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 <asm/uaccess.h> 19 #include "internal.h" 20 21 static int request_key_auth_instantiate(struct key *, const void *, size_t); 22 static void request_key_auth_describe(const struct key *, struct seq_file *); 23 static void request_key_auth_destroy(struct key *); 24 static long request_key_auth_read(const struct key *, char __user *, size_t); 25 26 /* 27 * the request-key authorisation key type definition 28 */ 29 struct key_type key_type_request_key_auth = { 30 .name = ".request_key_auth", 31 .def_datalen = sizeof(struct request_key_auth), 32 .instantiate = request_key_auth_instantiate, 33 .describe = request_key_auth_describe, 34 .destroy = request_key_auth_destroy, 35 .read = request_key_auth_read, 36 }; 37 38 /*****************************************************************************/ 39 /* 40 * instantiate a request-key authorisation key 41 */ 42 static int request_key_auth_instantiate(struct key *key, 43 const void *data, 44 size_t datalen) 45 { 46 key->payload.data = (struct request_key_auth *) data; 47 return 0; 48 49 } /* end request_key_auth_instantiate() */ 50 51 /*****************************************************************************/ 52 /* 53 * reading a request-key authorisation key retrieves the callout information 54 */ 55 static 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 seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info)); 63 64 } /* end request_key_auth_describe() */ 65 66 /*****************************************************************************/ 67 /* 68 * read the callout_info data 69 * - the key's semaphore is read-locked 70 */ 71 static long request_key_auth_read(const struct key *key, 72 char __user *buffer, size_t buflen) 73 { 74 struct request_key_auth *rka = key->payload.data; 75 size_t datalen; 76 long ret; 77 78 datalen = strlen(rka->callout_info); 79 ret = datalen; 80 81 /* we can return the data as is */ 82 if (buffer && buflen > 0) { 83 if (buflen > datalen) 84 buflen = datalen; 85 86 if (copy_to_user(buffer, rka->callout_info, buflen) != 0) 87 ret = -EFAULT; 88 } 89 90 return ret; 91 92 } /* end request_key_auth_read() */ 93 94 /*****************************************************************************/ 95 /* 96 * destroy an instantiation authorisation token key 97 */ 98 static void request_key_auth_destroy(struct key *key) 99 { 100 struct request_key_auth *rka = key->payload.data; 101 102 kenter("{%d}", key->serial); 103 104 key_put(rka->target_key); 105 kfree(rka); 106 107 } /* end request_key_auth_destroy() */ 108 109 /*****************************************************************************/ 110 /* 111 * create an authorisation token for /sbin/request-key or whoever to gain 112 * access to the caller's security data 113 */ 114 struct key *request_key_auth_new(struct key *target, const char *callout_info) 115 { 116 struct request_key_auth *rka, *irka; 117 struct key *authkey = NULL; 118 char desc[20]; 119 int ret; 120 121 kenter("%d,", target->serial); 122 123 /* allocate a auth record */ 124 rka = kmalloc(sizeof(*rka), GFP_KERNEL); 125 if (!rka) { 126 kleave(" = -ENOMEM"); 127 return ERR_PTR(-ENOMEM); 128 } 129 130 /* see if the calling process is already servicing the key request of 131 * another process */ 132 if (current->request_key_auth) { 133 /* it is - use that instantiation context here too */ 134 irka = current->request_key_auth->payload.data; 135 rka->context = irka->context; 136 rka->pid = irka->pid; 137 } 138 else { 139 /* it isn't - use this process as the context */ 140 rka->context = current; 141 rka->pid = current->pid; 142 } 143 144 rka->target_key = key_get(target); 145 rka->callout_info = callout_info; 146 147 /* allocate the auth key */ 148 sprintf(desc, "%x", target->serial); 149 150 authkey = key_alloc(&key_type_request_key_auth, desc, 151 current->fsuid, current->fsgid, 152 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | 153 KEY_USR_VIEW, 1); 154 if (IS_ERR(authkey)) { 155 ret = PTR_ERR(authkey); 156 goto error_alloc; 157 } 158 159 /* construct and attach to the keyring */ 160 ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); 161 if (ret < 0) 162 goto error_inst; 163 164 kleave(" = {%d})", authkey->serial); 165 return authkey; 166 167 error_inst: 168 key_revoke(authkey); 169 key_put(authkey); 170 error_alloc: 171 key_put(rka->target_key); 172 kfree(rka); 173 kleave("= %d", ret); 174 return ERR_PTR(ret); 175 176 } /* end request_key_auth_new() */ 177 178 /*****************************************************************************/ 179 /* 180 * see if an authorisation key is associated with a particular key 181 */ 182 static int key_get_instantiation_authkey_match(const struct key *key, 183 const void *_id) 184 { 185 struct request_key_auth *rka = key->payload.data; 186 key_serial_t id = (key_serial_t)(unsigned long) _id; 187 188 return rka->target_key->serial == id; 189 190 } /* end key_get_instantiation_authkey_match() */ 191 192 /*****************************************************************************/ 193 /* 194 * get the authorisation key for instantiation of a specific key if attached to 195 * the current process's keyrings 196 * - this key is inserted into a keyring and that is set as /sbin/request-key's 197 * session keyring 198 * - a target_id of zero specifies any valid token 199 */ 200 struct key *key_get_instantiation_authkey(key_serial_t target_id) 201 { 202 struct key *authkey; 203 key_ref_t authkey_ref; 204 205 authkey_ref = search_process_keyrings( 206 &key_type_request_key_auth, 207 (void *) (unsigned long) target_id, 208 key_get_instantiation_authkey_match, 209 current); 210 211 if (IS_ERR(authkey_ref)) { 212 authkey = ERR_PTR(PTR_ERR(authkey_ref)); 213 goto error; 214 } 215 216 authkey = key_ref_to_ptr(authkey_ref); 217 if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) { 218 key_put(authkey); 219 authkey = ERR_PTR(-EKEYREVOKED); 220 } 221 222 error: 223 return authkey; 224 225 } /* end key_get_instantiation_authkey() */ 226