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 "internal.h" 19 20 static int request_key_auth_instantiate(struct key *, const void *, size_t); 21 static void request_key_auth_describe(const struct key *, struct seq_file *); 22 static void request_key_auth_destroy(struct key *); 23 24 /* 25 * the request-key authorisation key type definition 26 */ 27 struct key_type key_type_request_key_auth = { 28 .name = ".request_key_auth", 29 .def_datalen = sizeof(struct request_key_auth), 30 .instantiate = request_key_auth_instantiate, 31 .describe = request_key_auth_describe, 32 .destroy = request_key_auth_destroy, 33 }; 34 35 /*****************************************************************************/ 36 /* 37 * instantiate a request-key authorisation record 38 */ 39 static int request_key_auth_instantiate(struct key *key, 40 const void *data, 41 size_t datalen) 42 { 43 struct request_key_auth *rka, *irka; 44 struct key *instkey; 45 int ret; 46 47 ret = -ENOMEM; 48 rka = kmalloc(sizeof(*rka), GFP_KERNEL); 49 if (rka) { 50 /* see if the calling process is already servicing the key 51 * request of another process */ 52 instkey = key_get_instantiation_authkey(0); 53 if (!IS_ERR(instkey)) { 54 /* it is - use that instantiation context here too */ 55 irka = instkey->payload.data; 56 rka->context = irka->context; 57 rka->pid = irka->pid; 58 key_put(instkey); 59 } 60 else { 61 /* it isn't - use this process as the context */ 62 rka->context = current; 63 rka->pid = current->pid; 64 } 65 66 rka->target_key = key_get((struct key *) data); 67 key->payload.data = rka; 68 ret = 0; 69 } 70 71 return ret; 72 73 } /* end request_key_auth_instantiate() */ 74 75 /*****************************************************************************/ 76 /* 77 * 78 */ 79 static void request_key_auth_describe(const struct key *key, 80 struct seq_file *m) 81 { 82 struct request_key_auth *rka = key->payload.data; 83 84 seq_puts(m, "key:"); 85 seq_puts(m, key->description); 86 seq_printf(m, " pid:%d", rka->pid); 87 88 } /* end request_key_auth_describe() */ 89 90 /*****************************************************************************/ 91 /* 92 * destroy an instantiation authorisation token key 93 */ 94 static void request_key_auth_destroy(struct key *key) 95 { 96 struct request_key_auth *rka = key->payload.data; 97 98 kenter("{%d}", key->serial); 99 100 key_put(rka->target_key); 101 kfree(rka); 102 103 } /* end request_key_auth_destroy() */ 104 105 /*****************************************************************************/ 106 /* 107 * create a session keyring to be for the invokation of /sbin/request-key and 108 * stick an authorisation token in it 109 */ 110 struct key *request_key_auth_new(struct key *target, struct key **_rkakey) 111 { 112 struct key *keyring, *rkakey = NULL; 113 char desc[20]; 114 int ret; 115 116 kenter("%d,", target->serial); 117 118 /* allocate a new session keyring */ 119 sprintf(desc, "_req.%u", target->serial); 120 121 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); 122 if (IS_ERR(keyring)) { 123 kleave("= %ld", PTR_ERR(keyring)); 124 return keyring; 125 } 126 127 /* allocate the auth key */ 128 sprintf(desc, "%x", target->serial); 129 130 rkakey = key_alloc(&key_type_request_key_auth, desc, 131 current->fsuid, current->fsgid, 132 KEY_POS_VIEW | KEY_USR_VIEW, 1); 133 if (IS_ERR(rkakey)) { 134 key_put(keyring); 135 kleave("= %ld", PTR_ERR(rkakey)); 136 return rkakey; 137 } 138 139 /* construct and attach to the keyring */ 140 ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); 141 if (ret < 0) { 142 key_revoke(rkakey); 143 key_put(rkakey); 144 key_put(keyring); 145 kleave("= %d", ret); 146 return ERR_PTR(ret); 147 } 148 149 *_rkakey = rkakey; 150 kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); 151 return keyring; 152 153 } /* end request_key_auth_new() */ 154 155 /*****************************************************************************/ 156 /* 157 * get the authorisation key for instantiation of a specific key if attached to 158 * the current process's keyrings 159 * - this key is inserted into a keyring and that is set as /sbin/request-key's 160 * session keyring 161 * - a target_id of zero specifies any valid token 162 */ 163 struct key *key_get_instantiation_authkey(key_serial_t target_id) 164 { 165 struct task_struct *tsk = current; 166 struct key *instkey; 167 168 /* we must have our own personal session keyring */ 169 if (!tsk->signal->session_keyring) 170 return ERR_PTR(-EACCES); 171 172 /* and it must contain a suitable request authorisation key 173 * - lock RCU against session keyring changing 174 */ 175 rcu_read_lock(); 176 177 instkey = keyring_search_instkey( 178 rcu_dereference(tsk->signal->session_keyring), target_id); 179 180 rcu_read_unlock(); 181 return instkey; 182 183 } /* end key_get_instantiation_authkey() */ 184