xref: /linux/security/keys/request_key_auth.c (revision 54a8a2220c936a47840c9a3d74910c5a56fae2ed)
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