1 /* request_key_auth.c: request key authorisation controlling key def 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/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 22 static int request_key_auth_instantiate(struct key *, const void *, size_t); 23 static void request_key_auth_describe(const struct key *, struct seq_file *); 24 static void request_key_auth_revoke(struct key *); 25 static void request_key_auth_destroy(struct key *); 26 static long request_key_auth_read(const struct key *, char __user *, size_t); 27 28 /* 29 * the request-key authorisation key type definition 30 */ 31 struct 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 /* 43 * instantiate a request-key authorisation key 44 */ 45 static int request_key_auth_instantiate(struct key *key, 46 const void *data, 47 size_t datalen) 48 { 49 key->payload.data = (struct request_key_auth *) data; 50 return 0; 51 52 } /* end request_key_auth_instantiate() */ 53 54 /*****************************************************************************/ 55 /* 56 * reading a request-key authorisation key retrieves the callout information 57 */ 58 static void request_key_auth_describe(const struct key *key, 59 struct seq_file *m) 60 { 61 struct request_key_auth *rka = key->payload.data; 62 63 seq_puts(m, "key:"); 64 seq_puts(m, key->description); 65 seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); 66 67 } /* end request_key_auth_describe() */ 68 69 /*****************************************************************************/ 70 /* 71 * read the callout_info data 72 * - the key's semaphore is read-locked 73 */ 74 static long request_key_auth_read(const struct key *key, 75 char __user *buffer, size_t buflen) 76 { 77 struct request_key_auth *rka = key->payload.data; 78 size_t datalen; 79 long ret; 80 81 datalen = rka->callout_len; 82 ret = datalen; 83 84 /* we can return the data as is */ 85 if (buffer && buflen > 0) { 86 if (buflen > datalen) 87 buflen = datalen; 88 89 if (copy_to_user(buffer, rka->callout_info, buflen) != 0) 90 ret = -EFAULT; 91 } 92 93 return ret; 94 95 } /* end request_key_auth_read() */ 96 97 /*****************************************************************************/ 98 /* 99 * handle revocation of an authorisation token key 100 * - called with the key sem write-locked 101 */ 102 static void request_key_auth_revoke(struct key *key) 103 { 104 struct request_key_auth *rka = key->payload.data; 105 106 kenter("{%d}", key->serial); 107 108 if (rka->cred) { 109 put_cred(rka->cred); 110 rka->cred = NULL; 111 } 112 113 } /* end request_key_auth_revoke() */ 114 115 /*****************************************************************************/ 116 /* 117 * destroy an instantiation authorisation token key 118 */ 119 static void request_key_auth_destroy(struct key *key) 120 { 121 struct request_key_auth *rka = key->payload.data; 122 123 kenter("{%d}", key->serial); 124 125 if (rka->cred) { 126 put_cred(rka->cred); 127 rka->cred = NULL; 128 } 129 130 key_put(rka->target_key); 131 key_put(rka->dest_keyring); 132 kfree(rka->callout_info); 133 kfree(rka); 134 135 } /* end request_key_auth_destroy() */ 136 137 /*****************************************************************************/ 138 /* 139 * create an authorisation token for /sbin/request-key or whoever to gain 140 * access to the caller's security data 141 */ 142 struct key *request_key_auth_new(struct key *target, const void *callout_info, 143 size_t callout_len, struct key *dest_keyring) 144 { 145 struct request_key_auth *rka, *irka; 146 const struct cred *cred = current->cred; 147 struct key *authkey = NULL; 148 char desc[20]; 149 int ret; 150 151 kenter("%d,", target->serial); 152 153 /* allocate a auth record */ 154 rka = kmalloc(sizeof(*rka), GFP_KERNEL); 155 if (!rka) { 156 kleave(" = -ENOMEM"); 157 return ERR_PTR(-ENOMEM); 158 } 159 rka->callout_info = kmalloc(callout_len, GFP_KERNEL); 160 if (!rka->callout_info) { 161 kleave(" = -ENOMEM"); 162 kfree(rka); 163 return ERR_PTR(-ENOMEM); 164 } 165 166 /* see if the calling process is already servicing the key request of 167 * another process */ 168 if (cred->request_key_auth) { 169 /* it is - use that instantiation context here too */ 170 down_read(&cred->request_key_auth->sem); 171 172 /* if the auth key has been revoked, then the key we're 173 * servicing is already instantiated */ 174 if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags)) 175 goto auth_key_revoked; 176 177 irka = cred->request_key_auth->payload.data; 178 rka->cred = get_cred(irka->cred); 179 rka->pid = irka->pid; 180 181 up_read(&cred->request_key_auth->sem); 182 } 183 else { 184 /* it isn't - use this process as the context */ 185 rka->cred = get_cred(cred); 186 rka->pid = current->pid; 187 } 188 189 rka->target_key = key_get(target); 190 rka->dest_keyring = key_get(dest_keyring); 191 memcpy(rka->callout_info, callout_info, callout_len); 192 rka->callout_len = callout_len; 193 194 /* allocate the auth key */ 195 sprintf(desc, "%x", target->serial); 196 197 authkey = key_alloc(&key_type_request_key_auth, desc, 198 cred->fsuid, cred->fsgid, cred, 199 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | 200 KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); 201 if (IS_ERR(authkey)) { 202 ret = PTR_ERR(authkey); 203 goto error_alloc; 204 } 205 206 /* construct the auth key */ 207 ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); 208 if (ret < 0) 209 goto error_inst; 210 211 kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage)); 212 return authkey; 213 214 auth_key_revoked: 215 up_read(&cred->request_key_auth->sem); 216 kfree(rka->callout_info); 217 kfree(rka); 218 kleave("= -EKEYREVOKED"); 219 return ERR_PTR(-EKEYREVOKED); 220 221 error_inst: 222 key_revoke(authkey); 223 key_put(authkey); 224 error_alloc: 225 key_put(rka->target_key); 226 key_put(rka->dest_keyring); 227 kfree(rka->callout_info); 228 kfree(rka); 229 kleave("= %d", ret); 230 return ERR_PTR(ret); 231 232 } /* end request_key_auth_new() */ 233 234 /*****************************************************************************/ 235 /* 236 * see if an authorisation key is associated with a particular key 237 */ 238 static int key_get_instantiation_authkey_match(const struct key *key, 239 const void *_id) 240 { 241 struct request_key_auth *rka = key->payload.data; 242 key_serial_t id = (key_serial_t)(unsigned long) _id; 243 244 return rka->target_key->serial == id; 245 246 } /* end key_get_instantiation_authkey_match() */ 247 248 /*****************************************************************************/ 249 /* 250 * get the authorisation key for instantiation of a specific key if attached to 251 * the current process's keyrings 252 * - this key is inserted into a keyring and that is set as /sbin/request-key's 253 * session keyring 254 * - a target_id of zero specifies any valid token 255 */ 256 struct key *key_get_instantiation_authkey(key_serial_t target_id) 257 { 258 const struct cred *cred = current_cred(); 259 struct key *authkey; 260 key_ref_t authkey_ref; 261 262 authkey_ref = search_process_keyrings( 263 &key_type_request_key_auth, 264 (void *) (unsigned long) target_id, 265 key_get_instantiation_authkey_match, 266 cred); 267 268 if (IS_ERR(authkey_ref)) { 269 authkey = ERR_CAST(authkey_ref); 270 goto error; 271 } 272 273 authkey = key_ref_to_ptr(authkey_ref); 274 if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) { 275 key_put(authkey); 276 authkey = ERR_PTR(-EKEYREVOKED); 277 } 278 279 error: 280 return authkey; 281 282 } /* end key_get_instantiation_authkey() */ 283