Example #1
0
static
int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error)
{
        int      seqwin = 0;
        char     buf[32];
        char    *p, *end;

        logmsg(LL_TRACE, "revoking kernel key %08x\n", keyid);

        p = buf;
        end = buf + sizeof(buf);

        WRITE_BYTES(&p, end, seqwin);
        WRITE_BYTES(&p, end, rpc_error);
        WRITE_BYTES(&p, end, gss_error);

again:
        if (keyctl_update(keyid, buf, p - buf)) {
                if (errno != EAGAIN) {
                        logmsg(LL_ERR, "revoke key %08x: %s\n",
                               keyid, strerror(errno));
                        return -1;
                }

                logmsg(LL_WARN, "key %08x: revoking too soon, try again\n",
                       keyid);
                sleep(2);
                goto again;
        }

        logmsg(LL_INFO, "key %08x: revoked\n", keyid);
        return 0;
}
Example #2
0
static
int update_kernel_key(key_serial_t keyid,
                      struct lgss_nego_data *lnd,
                      gss_buffer_desc *ctx_token)
{
        char        *buf = NULL, *p = NULL, *end = NULL;
        unsigned int buf_size = 0;
        int          rc;

        logmsg(LL_TRACE, "updating kernel key %08x\n", keyid);

        buf_size = sizeof(lnd->lnd_seq_win) +
                   sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length +
                   sizeof(ctx_token->length) + ctx_token->length;
        buf = malloc(buf_size);
        if (buf == NULL) {
                logmsg(LL_ERR, "key %08x: can't alloc update buf: size %d\n",
                       keyid, buf_size);
                return 1;
        }

        p = buf;
        end = buf + buf_size;
        rc = -1;

        if (WRITE_BYTES(&p, end, lnd->lnd_seq_win))
                goto out;
        if (write_buffer(&p, end, &lnd->lnd_rmt_ctx))
                goto out;
        if (write_buffer(&p, end, ctx_token))
                goto out;

again:
        if (keyctl_update(keyid, buf, p - buf)) {
                if (errno != EAGAIN) {
                        logmsg(LL_ERR, "update key %08x: %s\n",
                               keyid, strerror(errno));
                        goto out;
                }

                logmsg(LL_DEBUG, "key %08x: updating too soon, try again\n",
                       keyid);
                sleep(2);
                goto again;
        }

        rc = 0;
        logmsg(LL_DEBUG, "key %08x: updated\n", keyid);
out:
        free(buf);
        return rc;
}
Example #3
0
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;
}