コード例 #1
0
ファイル: reauthorize.c プロジェクト: AmartC/cockpit
int
reauthorize_perform (const char *user,
                     const char *response,
                     char **challenge)
{
  char *secret = NULL;
  int ret;

  if (!user || !challenge)
    {
      message ("bad arguments");
      ret = -EINVAL;
      goto out;
    }

  if (response != NULL &&
      strcmp (response, "") == 0)
    {
      debug ("reauthorize was cancelled");
      *challenge = NULL;
      ret = REAUTHORIZE_NO;
      goto out;
    }

  ret = lookup_reauthorize_secret (user, &secret);
  if (ret < 0)
    goto out;

  if (secret == NULL)
    {
      ret = lookup_shadow_secret (user, &secret);
      if (ret < 0)
        goto out;
    }

  /* This is where we'll plug in GSSAPI auth */
  if (secret == NULL)
    {
      debug ("no reauthorize secret available");
      *challenge = NULL;
      ret = REAUTHORIZE_NO;
    }
  else if (response == NULL)
    {
      ret = build_reauthorize_challenge (user, secret, challenge);
    }
  else if (strcmp (response, ""))
    {
      ret = perform_reauthorize_validate (user, secret, response);
    }

out:
  secfree (secret, -1);
  return ret;
}
コード例 #2
0
ファイル: reauthorize.c プロジェクト: BillTheBest/cockpit
int
reauthorize_crypt1 (const char *challenge,
                    const char *password,
                    char **response)
{
  struct crypt_data *cd = NULL;
  char *nonce = NULL;
  char *salt = NULL;
  const char *npos;
  const char *spos;
  char *secret;
  char *resp;
  int ret;

  if (strncmp (challenge, "crypt1:", 7) != 0)
    {
      message ("reauthorize challenge is not a crypt1");
      ret = -EINVAL;
      goto out;
    }
  challenge += 7;

  spos = NULL;
  npos = strchr (challenge, ':');
  if (npos != NULL)
    {
      npos++;
      spos = strchr (npos, ':');
    }

  if (npos == NULL || spos == NULL)
    {
      ret = -EINVAL;
      message ("couldn't parse reauthorize challenge");
      goto out;
    }

  nonce = strndup (npos, spos - npos);
  salt = strdup (spos + 1);
  if (!nonce || !salt)
    {
      ret = -ENOMEM;
      message ("couldn't allocate memory for challenge fields");
      goto out;
    }

  if (parse_salt (nonce) < 0 ||
      parse_salt (salt) < 0)
    {
      message ("reauthorize challenge has bad nonce or salt");
      ret = -EINVAL;
      goto out;
    }

  cd = calloc (2, sizeof (struct crypt_data));
  if (cd == NULL)
    {
      message ("couldn't allocate crypt data");
      ret = -ENOMEM;
      goto out;
    }

  /*
   * This is what we're generating here:
   *
   * response = "crypt1:" crypt(crypt(password, salt), nonce)
   */

  secret = crypt_r (password, salt, cd + 0);
  if (secret == NULL)
    {
      ret = -errno;
      message ("couldn't hash password via crypt: %m");
      goto out;
    }

  resp = crypt_r (secret, nonce, cd + 1);
  if (resp == NULL)
    {
      ret = -errno;
      message ("couldn't hash secret via crypt: %m");
      goto out;
    }

  if (asprintf (response, "crypt1:%s", resp) < 0)
    {
      ret = -ENOMEM;
      message ("couldn't allocate response");
      goto out;
    }

  ret = 0;

out:
  free (nonce);
  free (salt);
  secfree (cd, sizeof (struct crypt_data) * 2);

  return ret;
}
コード例 #3
0
ファイル: reauthorize.c プロジェクト: BillTheBest/cockpit
static int
perform_reauthorize_validate (const char *user,
                              const char *secret,
                              const char *response)
{
  struct crypt_data *cd = NULL;
  char *nonce = NULL;
  const char *check;
  ssize_t nonce_len;
  int ret;

  assert (user != NULL);
  assert (secret != NULL);
  assert (response != NULL);

  if (strncmp (response, "crypt1:", 7) != 0)
    {
      message ("received invalid response");
      ret = -EINVAL;
      goto out;
    }
  response += 7;

  nonce_len = parse_salt (response);
  if (nonce_len < 0)
    {
      message ("ignoring invalid reauthorize response");
      ret = -EINVAL;
      goto out;
    }

  nonce = strndup (response, nonce_len);
  if (!nonce)
    {
      message ("couldn't allocate memory for nonce");
      ret = -ENOMEM;
      goto out;
    }

  cd = calloc (1, sizeof (struct crypt_data));
  if (cd == NULL)
    {
      message ("couldn't allocate crypt data context");
      ret = -ENOMEM;
      goto out;
    }

  check = crypt_r (secret, nonce, cd);
  if (check == NULL)
    {
      ret = -errno;
      message ("couldn't crypt data: %m");
      goto out;
    }

  debug ("expected response is: %s", check);

  if (strcmp (check, response) != 0)
    {
      ret = REAUTHORIZE_NO;
      message ("user %s reauthorization failed", user);
      goto out;
    }

  message ("user %s was reauthorized", user);
  ret = REAUTHORIZE_YES;

out:
  free (nonce);
  secfree (cd, sizeof (struct crypt_data));
  return ret;
}
コード例 #4
0
ファイル: reauthorize.c プロジェクト: BillTheBest/cockpit
int
reauthorize_prepare (const char *user,
                     const char *password,
                     long keyring,
                     long *out_key)
{
  struct crypt_data *cd = NULL;
  key_serial_t key;
  const char *secret;
  char *salt = NULL;
  ssize_t salt_len;
  char *name = NULL;
  key_perm_t perm;
  int ret;

  if (password == NULL)
    {
      debug ("no password available for user %s", user);
      return 0;
    }

  /* The salt already contains algorithm prefix and suffix */
  ret = generate_salt (&salt);
  if (ret < 0)
    {
      message ("couldn't generate crypt salt: %m");
      goto out;
    }

  cd = calloc (1, sizeof (struct crypt_data));
  if (!cd)
    {
      message ("couldn't allocate crypt data");
      ret = -ENOMEM;
      goto out;
    }

  secret = crypt_r (password, salt, cd);
  if (!secret)
    {
      ret = -errno;
      message ("couldn't crypt reauthorize secret: %m");
      goto out;
    }

  /*
   * Double check that our assumptions about crypt() work
   * as expected. We're later going to be sending away the
   * salt as a challenge, so guarantee that it works.
   */

  salt_len = parse_salt (secret);
  if (salt_len != strlen (salt) || memcmp (secret, salt, salt_len) != 0)
    {
      ret = -EINVAL;
      message ("got invalid result from crypt");
      goto out;
    }

  if (asprintf (&name, "reauthorize/secret/%s", user) < 0)
    {
      ret = -ENOMEM;
      message ("couldn't allocate keyring name");
      goto out;
    }

  /*
   * Don't put our secret into the session keyring until the permissions
   * are strong enough. Since we want that to be atomic, first store in
   * our thread keyring, and then link below.
   */
  if (keyring == 0)
    keyring = KEY_SPEC_SESSION_KEYRING;

  key = add_key ("user", name, "xxx", 3, keyring);
  if (key < 0)
    {
      ret = -errno;
      message ("couldn't create key in kernel session keyring: %s: %m", name);
      goto out;
    }

  /* Set permissions, and double check that what we expect happened */
  perm = KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH | KEY_USR_LINK;
  if (keyctl_setperm (key, perm) < 0)
    {
      ret = -errno;
      message ("couldn't set permissions on kernel key: %s: %m", name);
      goto out;
    }

  if (keyctl_update (key, secret, strlen (secret)))
    {
      ret = -errno;
      message ("couldn't update secret reauthorize key in kernel keyring: %s: %m", name);
      goto out;
    }

  debug ("placed secret in kernel session keyring");
  *out_key = key;
  ret = 0;

out:
  secfree (cd, sizeof (struct crypt_data));
  free (name);
  free (salt);
  return ret;
}