linux/security/keys/request_key_auth.c
<<
>>
Prefs
   1/* Request key authorisation token key definition.
   2 *
   3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 *
  11 * See Documentation/security/keys-request-key.txt
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/sched.h>
  16#include <linux/err.h>
  17#include <linux/seq_file.h>
  18#include <linux/slab.h>
  19#include <asm/uaccess.h>
  20#include "internal.h"
  21
  22static int request_key_auth_instantiate(struct key *, const void *, size_t);
  23static void request_key_auth_describe(const struct key *, struct seq_file *);
  24static void request_key_auth_revoke(struct key *);
  25static void request_key_auth_destroy(struct key *);
  26static long request_key_auth_read(const struct key *, char __user *, size_t);
  27
  28/*
  29 * The request-key authorisation key type definition.
  30 */
  31struct key_type key_type_request_key_auth = {
  32        .name           = ".request_key_auth",
  33        .def_datalen    = sizeof(struct request_key_auth),
  34        .instantiate    = request_key_auth_instantiate,
  35        .describe       = request_key_auth_describe,
  36        .revoke         = request_key_auth_revoke,
  37        .destroy        = request_key_auth_destroy,
  38        .read           = request_key_auth_read,
  39};
  40
  41/*
  42 * Instantiate a request-key authorisation key.
  43 */
  44static int request_key_auth_instantiate(struct key *key,
  45                                        const void *data,
  46                                        size_t datalen)
  47{
  48        key->payload.data = (struct request_key_auth *) data;
  49        return 0;
  50}
  51
  52/*
  53 * Describe an authorisation token.
  54 */
  55static void request_key_auth_describe(const struct key *key,
  56                                      struct seq_file *m)
  57{
  58        struct request_key_auth *rka = key->payload.data;
  59
  60        seq_puts(m, "key:");
  61        seq_puts(m, key->description);
  62        if (key_is_instantiated(key))
  63                seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
  64}
  65
  66/*
  67 * Read the callout_info data (retrieves the callout information).
  68 * - the key's semaphore is read-locked
  69 */
  70static long request_key_auth_read(const struct key *key,
  71                                  char __user *buffer, size_t buflen)
  72{
  73        struct request_key_auth *rka = key->payload.data;
  74        size_t datalen;
  75        long ret;
  76
  77        datalen = rka->callout_len;
  78        ret = datalen;
  79
  80        /* we can return the data as is */
  81        if (buffer && buflen > 0) {
  82                if (buflen > datalen)
  83                        buflen = datalen;
  84
  85                if (copy_to_user(buffer, rka->callout_info, buflen) != 0)
  86                        ret = -EFAULT;
  87        }
  88
  89        return ret;
  90}
  91
  92/*
  93 * Handle revocation of an authorisation token key.
  94 *
  95 * Called with the key sem write-locked.
  96 */
  97static void request_key_auth_revoke(struct key *key)
  98{
  99        struct request_key_auth *rka = key->payload.data;
 100
 101        kenter("{%d}", key->serial);
 102
 103        if (rka->cred) {
 104                put_cred(rka->cred);
 105                rka->cred = NULL;
 106        }
 107}
 108
 109/*
 110 * Destroy an instantiation authorisation token key.
 111 */
 112static void request_key_auth_destroy(struct key *key)
 113{
 114        struct request_key_auth *rka = key->payload.data;
 115
 116        kenter("{%d}", key->serial);
 117
 118        if (rka->cred) {
 119                put_cred(rka->cred);
 120                rka->cred = NULL;
 121        }
 122
 123        key_put(rka->target_key);
 124        key_put(rka->dest_keyring);
 125        kfree(rka->callout_info);
 126        kfree(rka);
 127}
 128
 129/*
 130 * Create an authorisation token for /sbin/request-key or whoever to gain
 131 * access to the caller's security data.
 132 */
 133struct key *request_key_auth_new(struct key *target, const void *callout_info,
 134                                 size_t callout_len, struct key *dest_keyring)
 135{
 136        struct request_key_auth *rka, *irka;
 137        const struct cred *cred = current->cred;
 138        struct key *authkey = NULL;
 139        char desc[20];
 140        int ret;
 141
 142        kenter("%d,", target->serial);
 143
 144        /* allocate a auth record */
 145        rka = kmalloc(sizeof(*rka), GFP_KERNEL);
 146        if (!rka) {
 147                kleave(" = -ENOMEM");
 148                return ERR_PTR(-ENOMEM);
 149        }
 150        rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
 151        if (!rka->callout_info) {
 152                kleave(" = -ENOMEM");
 153                kfree(rka);
 154                return ERR_PTR(-ENOMEM);
 155        }
 156
 157        /* see if the calling process is already servicing the key request of
 158         * another process */
 159        if (cred->request_key_auth) {
 160                /* it is - use that instantiation context here too */
 161                down_read(&cred->request_key_auth->sem);
 162
 163                /* if the auth key has been revoked, then the key we're
 164                 * servicing is already instantiated */
 165                if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
 166                        goto auth_key_revoked;
 167
 168                irka = cred->request_key_auth->payload.data;
 169                rka->cred = get_cred(irka->cred);
 170                rka->pid = irka->pid;
 171
 172                up_read(&cred->request_key_auth->sem);
 173        }
 174        else {
 175                /* it isn't - use this process as the context */
 176                rka->cred = get_cred(cred);
 177                rka->pid = current->pid;
 178        }
 179
 180        rka->target_key = key_get(target);
 181        rka->dest_keyring = key_get(dest_keyring);
 182        memcpy(rka->callout_info, callout_info, callout_len);
 183        rka->callout_len = callout_len;
 184
 185        /* allocate the auth key */
 186        sprintf(desc, "%x", target->serial);
 187
 188        authkey = key_alloc(&key_type_request_key_auth, desc,
 189                            cred->fsuid, cred->fsgid, cred,
 190                            KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
 191                            KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 192        if (IS_ERR(authkey)) {
 193                ret = PTR_ERR(authkey);
 194                goto error_alloc;
 195        }
 196
 197        /* construct the auth key */
 198        ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
 199        if (ret < 0)
 200                goto error_inst;
 201
 202        kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
 203        return authkey;
 204
 205auth_key_revoked:
 206        up_read(&cred->request_key_auth->sem);
 207        kfree(rka->callout_info);
 208        kfree(rka);
 209        kleave("= -EKEYREVOKED");
 210        return ERR_PTR(-EKEYREVOKED);
 211
 212error_inst:
 213        key_revoke(authkey);
 214        key_put(authkey);
 215error_alloc:
 216        key_put(rka->target_key);
 217        key_put(rka->dest_keyring);
 218        kfree(rka->callout_info);
 219        kfree(rka);
 220        kleave("= %d", ret);
 221        return ERR_PTR(ret);
 222}
 223
 224/*
 225 * See if an authorisation key is associated with a particular key.
 226 */
 227static int key_get_instantiation_authkey_match(const struct key *key,
 228                                               const void *_id)
 229{
 230        struct request_key_auth *rka = key->payload.data;
 231        key_serial_t id = (key_serial_t)(unsigned long) _id;
 232
 233        return rka->target_key->serial == id;
 234}
 235
 236/*
 237 * Search the current process's keyrings for the authorisation key for
 238 * instantiation of a key.
 239 */
 240struct key *key_get_instantiation_authkey(key_serial_t target_id)
 241{
 242        const struct cred *cred = current_cred();
 243        struct key *authkey;
 244        key_ref_t authkey_ref;
 245
 246        authkey_ref = search_process_keyrings(
 247                &key_type_request_key_auth,
 248                (void *) (unsigned long) target_id,
 249                key_get_instantiation_authkey_match,
 250                cred);
 251
 252        if (IS_ERR(authkey_ref)) {
 253                authkey = ERR_CAST(authkey_ref);
 254                if (authkey == ERR_PTR(-EAGAIN))
 255                        authkey = ERR_PTR(-ENOKEY);
 256                goto error;
 257        }
 258
 259        authkey = key_ref_to_ptr(authkey_ref);
 260        if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {
 261                key_put(authkey);
 262                authkey = ERR_PTR(-EKEYREVOKED);
 263        }
 264
 265error:
 266        return authkey;
 267}
 268
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.