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