xref: /linux/security/keys/request_key.c (revision 54a8a2220c936a47840c9a3d74910c5a56fae2ed)
1 /* request_key.c: request a key from userspace
2  *
3  * Copyright (C) 2004-5 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/kmod.h>
17 #include <linux/err.h>
18 #include <linux/keyctl.h>
19 #include "internal.h"
20 
21 struct key_construction {
22 	struct list_head	link;	/* link in construction queue */
23 	struct key		*key;	/* key being constructed */
24 };
25 
26 /* when waiting for someone else's keys, you get added to this */
27 DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
28 
29 /*****************************************************************************/
30 /*
31  * request userspace finish the construction of a key
32  * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
33  */
34 static int call_request_key(struct key *key,
35 			    const char *op,
36 			    const char *callout_info)
37 {
38 	struct task_struct *tsk = current;
39 	key_serial_t prkey, sskey;
40 	struct key *session_keyring, *rkakey;
41 	char *argv[10], *envp[3], uid_str[12], gid_str[12];
42 	char key_str[12], keyring_str[3][12];
43 	int ret, i;
44 
45 	kenter("{%d},%s,%s", key->serial, op, callout_info);
46 
47 	/* generate a new session keyring with an auth key in it */
48 	session_keyring = request_key_auth_new(key, &rkakey);
49 	if (IS_ERR(session_keyring)) {
50 		ret = PTR_ERR(session_keyring);
51 		goto error;
52 	}
53 
54 	/* record the UID and GID */
55 	sprintf(uid_str, "%d", current->fsuid);
56 	sprintf(gid_str, "%d", current->fsgid);
57 
58 	/* we say which key is under construction */
59 	sprintf(key_str, "%d", key->serial);
60 
61 	/* we specify the process's default keyrings */
62 	sprintf(keyring_str[0], "%d",
63 		tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
64 
65 	prkey = 0;
66 	if (tsk->signal->process_keyring)
67 		prkey = tsk->signal->process_keyring->serial;
68 
69 	sprintf(keyring_str[1], "%d", prkey);
70 
71 	if (tsk->signal->session_keyring) {
72 		rcu_read_lock();
73 		sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
74 		rcu_read_unlock();
75 	}
76 	else {
77 		sskey = tsk->user->session_keyring->serial;
78 	}
79 
80 	sprintf(keyring_str[2], "%d", sskey);
81 
82 	/* set up a minimal environment */
83 	i = 0;
84 	envp[i++] = "HOME=/";
85 	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
86 	envp[i] = NULL;
87 
88 	/* set up the argument list */
89 	i = 0;
90 	argv[i++] = "/sbin/request-key";
91 	argv[i++] = (char *) op;
92 	argv[i++] = key_str;
93 	argv[i++] = uid_str;
94 	argv[i++] = gid_str;
95 	argv[i++] = keyring_str[0];
96 	argv[i++] = keyring_str[1];
97 	argv[i++] = keyring_str[2];
98 	argv[i++] = (char *) callout_info;
99 	argv[i] = NULL;
100 
101 	/* do it */
102 	ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1);
103 
104 	/* dispose of the special keys */
105 	key_revoke(rkakey);
106 	key_put(rkakey);
107 	key_put(session_keyring);
108 
109  error:
110 	kleave(" = %d", ret);
111 	return ret;
112 
113 } /* end call_request_key() */
114 
115 /*****************************************************************************/
116 /*
117  * call out to userspace for the key
118  * - called with the construction sem held, but the sem is dropped here
119  * - we ignore program failure and go on key status instead
120  */
121 static struct key *__request_key_construction(struct key_type *type,
122 					      const char *description,
123 					      const char *callout_info)
124 {
125 	struct key_construction cons;
126 	struct timespec now;
127 	struct key *key;
128 	int ret, negated;
129 
130 	kenter("%s,%s,%s", type->name, description, callout_info);
131 
132 	/* create a key and add it to the queue */
133 	key = key_alloc(type, description,
134 			current->fsuid, current->fsgid, KEY_POS_ALL, 0);
135 	if (IS_ERR(key))
136 		goto alloc_failed;
137 
138 	set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
139 
140 	cons.key = key;
141 	list_add_tail(&cons.link, &key->user->consq);
142 
143 	/* we drop the construction sem here on behalf of the caller */
144 	up_write(&key_construction_sem);
145 
146 	/* make the call */
147 	ret = call_request_key(key, "create", callout_info);
148 	if (ret < 0)
149 		goto request_failed;
150 
151 	/* if the key wasn't instantiated, then we want to give an error */
152 	ret = -ENOKEY;
153 	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
154 		goto request_failed;
155 
156 	down_write(&key_construction_sem);
157 	list_del(&cons.link);
158 	up_write(&key_construction_sem);
159 
160 	/* also give an error if the key was negatively instantiated */
161  check_not_negative:
162 	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
163 		key_put(key);
164 		key = ERR_PTR(-ENOKEY);
165 	}
166 
167  out:
168 	kleave(" = %p", key);
169 	return key;
170 
171  request_failed:
172 	/* it wasn't instantiated
173 	 * - remove from construction queue
174 	 * - mark the key as dead
175 	 */
176 	negated = 0;
177 	down_write(&key_construction_sem);
178 
179 	list_del(&cons.link);
180 
181 	/* check it didn't get instantiated between the check and the down */
182 	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
183 		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
184 		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
185 		negated = 1;
186 	}
187 
188 	clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
189 
190 	up_write(&key_construction_sem);
191 
192 	if (!negated)
193 		goto check_not_negative; /* surprisingly, the key got
194 					  * instantiated */
195 
196 	/* set the timeout and store in the session keyring if we can */
197 	now = current_kernel_time();
198 	key->expiry = now.tv_sec + key_negative_timeout;
199 
200 	if (current->signal->session_keyring) {
201 		struct key *keyring;
202 
203 		rcu_read_lock();
204 		keyring = rcu_dereference(current->signal->session_keyring);
205 		atomic_inc(&keyring->usage);
206 		rcu_read_unlock();
207 
208 		key_link(keyring, key);
209 		key_put(keyring);
210 	}
211 
212 	key_put(key);
213 
214 	/* notify anyone who was waiting */
215 	wake_up_all(&request_key_conswq);
216 
217 	key = ERR_PTR(ret);
218 	goto out;
219 
220  alloc_failed:
221 	up_write(&key_construction_sem);
222 	goto out;
223 
224 } /* end __request_key_construction() */
225 
226 /*****************************************************************************/
227 /*
228  * call out to userspace to request the key
229  * - we check the construction queue first to see if an appropriate key is
230  *   already being constructed by userspace
231  */
232 static struct key *request_key_construction(struct key_type *type,
233 					    const char *description,
234 					    struct key_user *user,
235 					    const char *callout_info)
236 {
237 	struct key_construction *pcons;
238 	struct key *key, *ckey;
239 
240 	DECLARE_WAITQUEUE(myself, current);
241 
242 	kenter("%s,%s,{%d},%s",
243 	       type->name, description, user->uid, callout_info);
244 
245 	/* see if there's such a key under construction already */
246 	down_write(&key_construction_sem);
247 
248 	list_for_each_entry(pcons, &user->consq, link) {
249 		ckey = pcons->key;
250 
251 		if (ckey->type != type)
252 			continue;
253 
254 		if (type->match(ckey, description))
255 			goto found_key_under_construction;
256 	}
257 
258 	/* see about getting userspace to construct the key */
259 	key = __request_key_construction(type, description, callout_info);
260  error:
261 	kleave(" = %p", key);
262 	return key;
263 
264 	/* someone else has the same key under construction
265 	 * - we want to keep an eye on their key
266 	 */
267  found_key_under_construction:
268 	atomic_inc(&ckey->usage);
269 	up_write(&key_construction_sem);
270 
271 	/* wait for the key to be completed one way or another */
272 	add_wait_queue(&request_key_conswq, &myself);
273 
274 	for (;;) {
275 		set_current_state(TASK_INTERRUPTIBLE);
276 		if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
277 			break;
278 		if (signal_pending(current))
279 			break;
280 		schedule();
281 	}
282 
283 	set_current_state(TASK_RUNNING);
284 	remove_wait_queue(&request_key_conswq, &myself);
285 
286 	/* we'll need to search this process's keyrings to see if the key is
287 	 * now there since we can't automatically assume it's also available
288 	 * there */
289 	key_put(ckey);
290 	ckey = NULL;
291 
292 	key = NULL; /* request a retry */
293 	goto error;
294 
295 } /* end request_key_construction() */
296 
297 /*****************************************************************************/
298 /*
299  * link a freshly minted key to an appropriate destination keyring
300  */
301 static void request_key_link(struct key *key, struct key *dest_keyring)
302 {
303 	struct task_struct *tsk = current;
304 	struct key *drop = NULL;
305 
306 	kenter("{%d},%p", key->serial, dest_keyring);
307 
308 	/* find the appropriate keyring */
309 	if (!dest_keyring) {
310 		switch (tsk->jit_keyring) {
311 		case KEY_REQKEY_DEFL_DEFAULT:
312 		case KEY_REQKEY_DEFL_THREAD_KEYRING:
313 			dest_keyring = tsk->thread_keyring;
314 			if (dest_keyring)
315 				break;
316 
317 		case KEY_REQKEY_DEFL_PROCESS_KEYRING:
318 			dest_keyring = tsk->signal->process_keyring;
319 			if (dest_keyring)
320 				break;
321 
322 		case KEY_REQKEY_DEFL_SESSION_KEYRING:
323 			rcu_read_lock();
324 			dest_keyring = key_get(
325 				rcu_dereference(tsk->signal->session_keyring));
326 			rcu_read_unlock();
327 			drop = dest_keyring;
328 
329 			if (dest_keyring)
330 				break;
331 
332 		case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
333 			dest_keyring = current->user->session_keyring;
334 			break;
335 
336 		case KEY_REQKEY_DEFL_USER_KEYRING:
337 			dest_keyring = current->user->uid_keyring;
338 			break;
339 
340 		case KEY_REQKEY_DEFL_GROUP_KEYRING:
341 		default:
342 			BUG();
343 		}
344 	}
345 
346 	/* and attach the key to it */
347 	key_link(dest_keyring, key);
348 
349 	key_put(drop);
350 
351 	kleave("");
352 
353 } /* end request_key_link() */
354 
355 /*****************************************************************************/
356 /*
357  * request a key
358  * - search the process's keyrings
359  * - check the list of keys being created or updated
360  * - call out to userspace for a key if supplementary info was provided
361  * - cache the key in an appropriate keyring
362  */
363 struct key *request_key_and_link(struct key_type *type,
364 				 const char *description,
365 				 const char *callout_info,
366 				 struct key *dest_keyring)
367 {
368 	struct key_user *user;
369 	struct key *key;
370 	key_ref_t key_ref;
371 
372 	kenter("%s,%s,%s,%p",
373 	       type->name, description, callout_info, dest_keyring);
374 
375 	/* search all the process keyrings for a key */
376 	key_ref = search_process_keyrings(type, description, type->match,
377 					  current);
378 
379 	kdebug("search 1: %p", key_ref);
380 
381 	if (!IS_ERR(key_ref)) {
382 		key = key_ref_to_ptr(key_ref);
383 	}
384 	else if (PTR_ERR(key_ref) != -EAGAIN) {
385 		key = ERR_PTR(PTR_ERR(key_ref));
386 	}
387 	else  {
388 		/* the search failed, but the keyrings were searchable, so we
389 		 * should consult userspace if we can */
390 		key = ERR_PTR(-ENOKEY);
391 		if (!callout_info)
392 			goto error;
393 
394 		/* - get hold of the user's construction queue */
395 		user = key_user_lookup(current->fsuid);
396 		if (!user)
397 			goto nomem;
398 
399 		for (;;) {
400 			if (signal_pending(current))
401 				goto interrupted;
402 
403 			/* ask userspace (returns NULL if it waited on a key
404 			 * being constructed) */
405 			key = request_key_construction(type, description,
406 						       user, callout_info);
407 			if (key)
408 				break;
409 
410 			/* someone else made the key we want, so we need to
411 			 * search again as it might now be available to us */
412 			key_ref = search_process_keyrings(type, description,
413 							  type->match,
414 							  current);
415 
416 			kdebug("search 2: %p", key_ref);
417 
418 			if (!IS_ERR(key_ref)) {
419 				key = key_ref_to_ptr(key_ref);
420 				break;
421 			}
422 
423 			if (PTR_ERR(key_ref) != -EAGAIN) {
424 				key = ERR_PTR(PTR_ERR(key_ref));
425 				break;
426 			}
427 		}
428 
429 		key_user_put(user);
430 
431 		/* link the new key into the appropriate keyring */
432 		if (!IS_ERR(key))
433 			request_key_link(key, dest_keyring);
434 	}
435 
436 error:
437 	kleave(" = %p", key);
438 	return key;
439 
440 nomem:
441 	key = ERR_PTR(-ENOMEM);
442 	goto error;
443 
444 interrupted:
445 	key_user_put(user);
446 	key = ERR_PTR(-EINTR);
447 	goto error;
448 
449 } /* end request_key_and_link() */
450 
451 /*****************************************************************************/
452 /*
453  * request a key
454  * - search the process's keyrings
455  * - check the list of keys being created or updated
456  * - call out to userspace for a key if supplementary info was provided
457  */
458 struct key *request_key(struct key_type *type,
459 			const char *description,
460 			const char *callout_info)
461 {
462 	return request_key_and_link(type, description, callout_info, NULL);
463 
464 } /* end request_key() */
465 
466 EXPORT_SYMBOL(request_key);
467 
468 /*****************************************************************************/
469 /*
470  * validate a key
471  */
472 int key_validate(struct key *key)
473 {
474 	struct timespec now;
475 	int ret = 0;
476 
477 	if (key) {
478 		/* check it's still accessible */
479 		ret = -EKEYREVOKED;
480 		if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
481 		    test_bit(KEY_FLAG_DEAD, &key->flags))
482 			goto error;
483 
484 		/* check it hasn't expired */
485 		ret = 0;
486 		if (key->expiry) {
487 			now = current_kernel_time();
488 			if (now.tv_sec >= key->expiry)
489 				ret = -EKEYEXPIRED;
490 		}
491 	}
492 
493  error:
494 	return ret;
495 
496 } /* end key_validate() */
497 
498 EXPORT_SYMBOL(key_validate);
499