1 /* request_key.c: request a key from userspace
3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <linux/kmod.h>
15 #include <linux/err.h>
16 #include <linux/keyctl.h>
19 struct key_construction
{
20 struct list_head link
; /* link in construction queue */
21 struct key
*key
; /* key being constructed */
24 /* when waiting for someone else's keys, you get added to this */
25 DECLARE_WAIT_QUEUE_HEAD(request_key_conswq
);
27 /*****************************************************************************/
29 * request userspace finish the construction of a key
30 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
32 static int call_request_key(struct key
*key
,
34 const char *callout_info
)
36 struct task_struct
*tsk
= current
;
37 key_serial_t prkey
, sskey
;
38 struct key
*session_keyring
, *rkakey
;
39 char *argv
[10], *envp
[3], uid_str
[12], gid_str
[12];
40 char key_str
[12], keyring_str
[3][12];
43 kenter("{%d},%s,%s", key
->serial
, op
, callout_info
);
45 /* generate a new session keyring with an auth key in it */
46 session_keyring
= request_key_auth_new(key
, &rkakey
);
47 if (IS_ERR(session_keyring
)) {
48 ret
= PTR_ERR(session_keyring
);
52 /* record the UID and GID */
53 sprintf(uid_str
, "%d", current
->fsuid
);
54 sprintf(gid_str
, "%d", current
->fsgid
);
56 /* we say which key is under construction */
57 sprintf(key_str
, "%d", key
->serial
);
59 /* we specify the process's default keyrings */
60 sprintf(keyring_str
[0], "%d",
61 tsk
->thread_keyring
? tsk
->thread_keyring
->serial
: 0);
64 if (tsk
->signal
->process_keyring
)
65 prkey
= tsk
->signal
->process_keyring
->serial
;
67 sprintf(keyring_str
[1], "%d", prkey
);
69 if (tsk
->signal
->session_keyring
) {
71 sskey
= rcu_dereference(tsk
->signal
->session_keyring
)->serial
;
75 sskey
= tsk
->user
->session_keyring
->serial
;
78 sprintf(keyring_str
[2], "%d", sskey
);
80 /* set up a minimal environment */
83 envp
[i
++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
86 /* set up the argument list */
88 argv
[i
++] = "/sbin/request-key";
89 argv
[i
++] = (char *) op
;
93 argv
[i
++] = keyring_str
[0];
94 argv
[i
++] = keyring_str
[1];
95 argv
[i
++] = keyring_str
[2];
96 argv
[i
++] = (char *) callout_info
;
100 ret
= call_usermodehelper_keys(argv
[0], argv
, envp
, session_keyring
, 1);
102 /* dispose of the special keys */
105 key_put(session_keyring
);
108 kleave(" = %d", ret
);
111 } /* end call_request_key() */
113 /*****************************************************************************/
115 * call out to userspace for the key
116 * - called with the construction sem held, but the sem is dropped here
117 * - we ignore program failure and go on key status instead
119 static struct key
*__request_key_construction(struct key_type
*type
,
120 const char *description
,
121 const char *callout_info
)
123 struct key_construction cons
;
128 kenter("%s,%s,%s", type
->name
, description
, callout_info
);
130 /* create a key and add it to the queue */
131 key
= key_alloc(type
, description
,
132 current
->fsuid
, current
->fsgid
, KEY_USR_ALL
, 0);
136 set_bit(KEY_FLAG_USER_CONSTRUCT
, &key
->flags
);
139 list_add_tail(&cons
.link
, &key
->user
->consq
);
141 /* we drop the construction sem here on behalf of the caller */
142 up_write(&key_construction_sem
);
145 ret
= call_request_key(key
, "create", callout_info
);
149 /* if the key wasn't instantiated, then we want to give an error */
151 if (!test_bit(KEY_FLAG_INSTANTIATED
, &key
->flags
))
154 down_write(&key_construction_sem
);
155 list_del(&cons
.link
);
156 up_write(&key_construction_sem
);
158 /* also give an error if the key was negatively instantiated */
160 if (test_bit(KEY_FLAG_NEGATIVE
, &key
->flags
)) {
162 key
= ERR_PTR(-ENOKEY
);
166 kleave(" = %p", key
);
170 /* it wasn't instantiated
171 * - remove from construction queue
172 * - mark the key as dead
175 down_write(&key_construction_sem
);
177 list_del(&cons
.link
);
179 /* check it didn't get instantiated between the check and the down */
180 if (!test_bit(KEY_FLAG_INSTANTIATED
, &key
->flags
)) {
181 set_bit(KEY_FLAG_NEGATIVE
, &key
->flags
);
182 set_bit(KEY_FLAG_INSTANTIATED
, &key
->flags
);
186 clear_bit(KEY_FLAG_USER_CONSTRUCT
, &key
->flags
);
188 up_write(&key_construction_sem
);
191 goto check_not_negative
; /* surprisingly, the key got
194 /* set the timeout and store in the session keyring if we can */
195 now
= current_kernel_time();
196 key
->expiry
= now
.tv_sec
+ key_negative_timeout
;
198 if (current
->signal
->session_keyring
) {
202 keyring
= rcu_dereference(current
->signal
->session_keyring
);
203 atomic_inc(&keyring
->usage
);
206 key_link(keyring
, key
);
212 /* notify anyone who was waiting */
213 wake_up_all(&request_key_conswq
);
219 up_write(&key_construction_sem
);
222 } /* end __request_key_construction() */
224 /*****************************************************************************/
226 * call out to userspace to request the key
227 * - we check the construction queue first to see if an appropriate key is
228 * already being constructed by userspace
230 static struct key
*request_key_construction(struct key_type
*type
,
231 const char *description
,
232 struct key_user
*user
,
233 const char *callout_info
)
235 struct key_construction
*pcons
;
236 struct key
*key
, *ckey
;
238 DECLARE_WAITQUEUE(myself
, current
);
240 kenter("%s,%s,{%d},%s",
241 type
->name
, description
, user
->uid
, callout_info
);
243 /* see if there's such a key under construction already */
244 down_write(&key_construction_sem
);
246 list_for_each_entry(pcons
, &user
->consq
, link
) {
249 if (ckey
->type
!= type
)
252 if (type
->match(ckey
, description
))
253 goto found_key_under_construction
;
256 /* see about getting userspace to construct the key */
257 key
= __request_key_construction(type
, description
, callout_info
);
259 kleave(" = %p", key
);
262 /* someone else has the same key under construction
263 * - we want to keep an eye on their key
265 found_key_under_construction
:
266 atomic_inc(&ckey
->usage
);
267 up_write(&key_construction_sem
);
269 /* wait for the key to be completed one way or another */
270 add_wait_queue(&request_key_conswq
, &myself
);
273 set_current_state(TASK_INTERRUPTIBLE
);
274 if (!test_bit(KEY_FLAG_USER_CONSTRUCT
, &ckey
->flags
))
276 if (signal_pending(current
))
281 set_current_state(TASK_RUNNING
);
282 remove_wait_queue(&request_key_conswq
, &myself
);
284 /* we'll need to search this process's keyrings to see if the key is
285 * now there since we can't automatically assume it's also available
290 key
= NULL
; /* request a retry */
293 } /* end request_key_construction() */
295 /*****************************************************************************/
297 * link a freshly minted key to an appropriate destination keyring
299 static void request_key_link(struct key
*key
, struct key
*dest_keyring
)
301 struct task_struct
*tsk
= current
;
302 struct key
*drop
= NULL
;
304 kenter("{%d},%p", key
->serial
, dest_keyring
);
306 /* find the appropriate keyring */
308 switch (tsk
->jit_keyring
) {
309 case KEY_REQKEY_DEFL_DEFAULT
:
310 case KEY_REQKEY_DEFL_THREAD_KEYRING
:
311 dest_keyring
= tsk
->thread_keyring
;
315 case KEY_REQKEY_DEFL_PROCESS_KEYRING
:
316 dest_keyring
= tsk
->signal
->process_keyring
;
320 case KEY_REQKEY_DEFL_SESSION_KEYRING
:
322 dest_keyring
= key_get(
323 rcu_dereference(tsk
->signal
->session_keyring
));
330 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING
:
331 dest_keyring
= current
->user
->session_keyring
;
334 case KEY_REQKEY_DEFL_USER_KEYRING
:
335 dest_keyring
= current
->user
->uid_keyring
;
338 case KEY_REQKEY_DEFL_GROUP_KEYRING
:
344 /* and attach the key to it */
345 key_link(dest_keyring
, key
);
351 } /* end request_key_link() */
353 /*****************************************************************************/
356 * - search the process's keyrings
357 * - check the list of keys being created or updated
358 * - call out to userspace for a key if supplementary info was provided
359 * - cache the key in an appropriate keyring
361 struct key
*request_key_and_link(struct key_type
*type
,
362 const char *description
,
363 const char *callout_info
,
364 struct key
*dest_keyring
)
366 struct key_user
*user
;
369 kenter("%s,%s,%s,%p",
370 type
->name
, description
, callout_info
, dest_keyring
);
372 /* search all the process keyrings for a key */
373 key
= search_process_keyrings(type
, description
, type
->match
, current
);
375 if (PTR_ERR(key
) == -EAGAIN
) {
376 /* the search failed, but the keyrings were searchable, so we
377 * should consult userspace if we can */
378 key
= ERR_PTR(-ENOKEY
);
382 /* - get hold of the user's construction queue */
383 user
= key_user_lookup(current
->fsuid
);
388 if (signal_pending(current
))
391 /* ask userspace (returns NULL if it waited on a key
392 * being constructed) */
393 key
= request_key_construction(type
, description
,
398 /* someone else made the key we want, so we need to
399 * search again as it might now be available to us */
400 key
= search_process_keyrings(type
, description
,
401 type
->match
, current
);
403 } while (PTR_ERR(key
) == -EAGAIN
);
407 /* link the new key into the appropriate keyring */
409 request_key_link(key
, dest_keyring
);
413 kleave(" = %p", key
);
417 key
= ERR_PTR(-ENOMEM
);
422 key
= ERR_PTR(-EINTR
);
425 } /* end request_key_and_link() */
427 /*****************************************************************************/
430 * - search the process's keyrings
431 * - check the list of keys being created or updated
432 * - call out to userspace for a key if supplementary info was provided
434 struct key
*request_key(struct key_type
*type
,
435 const char *description
,
436 const char *callout_info
)
438 return request_key_and_link(type
, description
, callout_info
, NULL
);
440 } /* end request_key() */
442 EXPORT_SYMBOL(request_key
);
444 /*****************************************************************************/
448 int key_validate(struct key
*key
)
454 /* check it's still accessible */
456 if (test_bit(KEY_FLAG_REVOKED
, &key
->flags
) ||
457 test_bit(KEY_FLAG_DEAD
, &key
->flags
))
460 /* check it hasn't expired */
463 now
= current_kernel_time();
464 if (now
.tv_sec
>= key
->expiry
)
472 } /* end key_validate() */
474 EXPORT_SYMBOL(key_validate
);