diff options
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r-- | security/keys/request_key.c | 108 |
1 files changed, 50 insertions, 58 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 5cc4bba70db6..f030a0ccbb93 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -29,28 +29,36 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); | |||
29 | /*****************************************************************************/ | 29 | /*****************************************************************************/ |
30 | /* | 30 | /* |
31 | * request userspace finish the construction of a key | 31 | * request userspace finish the construction of a key |
32 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>" | 32 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" |
33 | */ | 33 | */ |
34 | static int call_request_key(struct key *key, | 34 | static int call_sbin_request_key(struct key *key, |
35 | const char *op, | 35 | struct key *authkey, |
36 | const char *callout_info) | 36 | const char *op) |
37 | { | 37 | { |
38 | struct task_struct *tsk = current; | 38 | struct task_struct *tsk = current; |
39 | key_serial_t prkey, sskey; | 39 | key_serial_t prkey, sskey; |
40 | struct key *session_keyring, *rkakey; | 40 | struct key *keyring; |
41 | char *argv[10], *envp[3], uid_str[12], gid_str[12]; | 41 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; |
42 | char key_str[12], keyring_str[3][12]; | 42 | char key_str[12], keyring_str[3][12]; |
43 | char desc[20]; | ||
43 | int ret, i; | 44 | int ret, i; |
44 | 45 | ||
45 | kenter("{%d},%s,%s", key->serial, op, callout_info); | 46 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); |
46 | 47 | ||
47 | /* generate a new session keyring with an auth key in it */ | 48 | /* allocate a new session keyring */ |
48 | session_keyring = request_key_auth_new(key, &rkakey); | 49 | sprintf(desc, "_req.%u", key->serial); |
49 | if (IS_ERR(session_keyring)) { | 50 | |
50 | ret = PTR_ERR(session_keyring); | 51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); |
51 | goto error; | 52 | if (IS_ERR(keyring)) { |
53 | ret = PTR_ERR(keyring); | ||
54 | goto error_alloc; | ||
52 | } | 55 | } |
53 | 56 | ||
57 | /* attach the auth key to the session keyring */ | ||
58 | ret = __key_link(keyring, authkey); | ||
59 | if (ret < 0) | ||
60 | goto error_link; | ||
61 | |||
54 | /* record the UID and GID */ | 62 | /* record the UID and GID */ |
55 | sprintf(uid_str, "%d", current->fsuid); | 63 | sprintf(uid_str, "%d", current->fsuid); |
56 | sprintf(gid_str, "%d", current->fsgid); | 64 | sprintf(gid_str, "%d", current->fsgid); |
@@ -95,22 +103,19 @@ static int call_request_key(struct key *key, | |||
95 | argv[i++] = keyring_str[0]; | 103 | argv[i++] = keyring_str[0]; |
96 | argv[i++] = keyring_str[1]; | 104 | argv[i++] = keyring_str[1]; |
97 | argv[i++] = keyring_str[2]; | 105 | argv[i++] = keyring_str[2]; |
98 | argv[i++] = (char *) callout_info; | ||
99 | argv[i] = NULL; | 106 | argv[i] = NULL; |
100 | 107 | ||
101 | /* do it */ | 108 | /* do it */ |
102 | ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1); | 109 | ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1); |
103 | 110 | ||
104 | /* dispose of the special keys */ | 111 | error_link: |
105 | key_revoke(rkakey); | 112 | key_put(keyring); |
106 | key_put(rkakey); | ||
107 | key_put(session_keyring); | ||
108 | 113 | ||
109 | error: | 114 | error_alloc: |
110 | kleave(" = %d", ret); | 115 | kleave(" = %d", ret); |
111 | return ret; | 116 | return ret; |
112 | 117 | ||
113 | } /* end call_request_key() */ | 118 | } /* end call_sbin_request_key() */ |
114 | 119 | ||
115 | /*****************************************************************************/ | 120 | /*****************************************************************************/ |
116 | /* | 121 | /* |
@@ -122,9 +127,10 @@ static struct key *__request_key_construction(struct key_type *type, | |||
122 | const char *description, | 127 | const char *description, |
123 | const char *callout_info) | 128 | const char *callout_info) |
124 | { | 129 | { |
130 | request_key_actor_t actor; | ||
125 | struct key_construction cons; | 131 | struct key_construction cons; |
126 | struct timespec now; | 132 | struct timespec now; |
127 | struct key *key; | 133 | struct key *key, *authkey; |
128 | int ret, negated; | 134 | int ret, negated; |
129 | 135 | ||
130 | kenter("%s,%s,%s", type->name, description, callout_info); | 136 | kenter("%s,%s,%s", type->name, description, callout_info); |
@@ -143,8 +149,19 @@ static struct key *__request_key_construction(struct key_type *type, | |||
143 | /* we drop the construction sem here on behalf of the caller */ | 149 | /* we drop the construction sem here on behalf of the caller */ |
144 | up_write(&key_construction_sem); | 150 | up_write(&key_construction_sem); |
145 | 151 | ||
152 | /* allocate an authorisation key */ | ||
153 | authkey = request_key_auth_new(key, callout_info); | ||
154 | if (IS_ERR(authkey)) { | ||
155 | ret = PTR_ERR(authkey); | ||
156 | authkey = NULL; | ||
157 | goto alloc_authkey_failed; | ||
158 | } | ||
159 | |||
146 | /* make the call */ | 160 | /* make the call */ |
147 | ret = call_request_key(key, "create", callout_info); | 161 | actor = call_sbin_request_key; |
162 | if (type->request_key) | ||
163 | actor = type->request_key; | ||
164 | ret = actor(key, authkey, "create"); | ||
148 | if (ret < 0) | 165 | if (ret < 0) |
149 | goto request_failed; | 166 | goto request_failed; |
150 | 167 | ||
@@ -153,22 +170,29 @@ static struct key *__request_key_construction(struct key_type *type, | |||
153 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 170 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
154 | goto request_failed; | 171 | goto request_failed; |
155 | 172 | ||
173 | key_revoke(authkey); | ||
174 | key_put(authkey); | ||
175 | |||
156 | down_write(&key_construction_sem); | 176 | down_write(&key_construction_sem); |
157 | list_del(&cons.link); | 177 | list_del(&cons.link); |
158 | up_write(&key_construction_sem); | 178 | up_write(&key_construction_sem); |
159 | 179 | ||
160 | /* also give an error if the key was negatively instantiated */ | 180 | /* also give an error if the key was negatively instantiated */ |
161 | check_not_negative: | 181 | check_not_negative: |
162 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | 182 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { |
163 | key_put(key); | 183 | key_put(key); |
164 | key = ERR_PTR(-ENOKEY); | 184 | key = ERR_PTR(-ENOKEY); |
165 | } | 185 | } |
166 | 186 | ||
167 | out: | 187 | out: |
168 | kleave(" = %p", key); | 188 | kleave(" = %p", key); |
169 | return key; | 189 | return key; |
170 | 190 | ||
171 | request_failed: | 191 | request_failed: |
192 | key_revoke(authkey); | ||
193 | key_put(authkey); | ||
194 | |||
195 | alloc_authkey_failed: | ||
172 | /* it wasn't instantiated | 196 | /* it wasn't instantiated |
173 | * - remove from construction queue | 197 | * - remove from construction queue |
174 | * - mark the key as dead | 198 | * - mark the key as dead |
@@ -217,7 +241,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
217 | key = ERR_PTR(ret); | 241 | key = ERR_PTR(ret); |
218 | goto out; | 242 | goto out; |
219 | 243 | ||
220 | alloc_failed: | 244 | alloc_failed: |
221 | up_write(&key_construction_sem); | 245 | up_write(&key_construction_sem); |
222 | goto out; | 246 | goto out; |
223 | 247 | ||
@@ -464,35 +488,3 @@ struct key *request_key(struct key_type *type, | |||
464 | } /* end request_key() */ | 488 | } /* end request_key() */ |
465 | 489 | ||
466 | EXPORT_SYMBOL(request_key); | 490 | 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); | ||