X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=security%2Fkeys%2Frequest_key.c;h=f573ac189a0a6595b2184b43a9d54c3b01e0d5a0;hb=64106104dd2d4a6280777e88c1cbf9f7a52c30bd;hp=5cc4bba70db61eab5157bb0bb7ffe6b673a11ab3;hpb=c87ff94333642ce3db4fc0857ad1f723cb42c1dd;p=powerpc.git diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 5cc4bba70d..f573ac189a 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -1,6 +1,6 @@ /* request_key.c: request a key from userspace * - * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -29,28 +29,38 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); /*****************************************************************************/ /* * request userspace finish the construction of a key - * - execute "/sbin/request-key " + * - execute "/sbin/request-key " */ -static int call_request_key(struct key *key, - const char *op, - const char *callout_info) +static int call_sbin_request_key(struct key *key, + struct key *authkey, + const char *op, + void *aux) { struct task_struct *tsk = current; key_serial_t prkey, sskey; - struct key *session_keyring, *rkakey; - char *argv[10], *envp[3], uid_str[12], gid_str[12]; + struct key *keyring; + char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; + char desc[20]; int ret, i; - kenter("{%d},%s,%s", key->serial, op, callout_info); + kenter("{%d},{%d},%s", key->serial, authkey->serial, op); - /* generate a new session keyring with an auth key in it */ - session_keyring = request_key_auth_new(key, &rkakey); - if (IS_ERR(session_keyring)) { - ret = PTR_ERR(session_keyring); - goto error; + /* allocate a new session keyring */ + sprintf(desc, "_req.%u", key->serial); + + keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, + KEY_ALLOC_QUOTA_OVERRUN, NULL); + if (IS_ERR(keyring)) { + ret = PTR_ERR(keyring); + goto error_alloc; } + /* attach the auth key to the session keyring */ + ret = __key_link(keyring, authkey); + if (ret < 0) + goto error_link; + /* record the UID and GID */ sprintf(uid_str, "%d", current->fsuid); sprintf(gid_str, "%d", current->fsgid); @@ -95,22 +105,19 @@ static int call_request_key(struct key *key, argv[i++] = keyring_str[0]; argv[i++] = keyring_str[1]; argv[i++] = keyring_str[2]; - argv[i++] = (char *) callout_info; argv[i] = NULL; /* do it */ - ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1); + ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1); - /* dispose of the special keys */ - key_revoke(rkakey); - key_put(rkakey); - key_put(session_keyring); +error_link: + key_put(keyring); - error: +error_alloc: kleave(" = %d", ret); return ret; -} /* end call_request_key() */ +} /* end call_sbin_request_key() */ /*****************************************************************************/ /* @@ -120,18 +127,22 @@ static int call_request_key(struct key *key, */ static struct key *__request_key_construction(struct key_type *type, const char *description, - const char *callout_info) + const char *callout_info, + void *aux, + unsigned long flags) { + request_key_actor_t actor; struct key_construction cons; struct timespec now; - struct key *key; + struct key *key, *authkey; int ret, negated; - kenter("%s,%s,%s", type->name, description, callout_info); + kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); /* create a key and add it to the queue */ key = key_alloc(type, description, - current->fsuid, current->fsgid, KEY_POS_ALL, 0); + current->fsuid, current->fsgid, current, KEY_POS_ALL, + flags); if (IS_ERR(key)) goto alloc_failed; @@ -143,8 +154,19 @@ static struct key *__request_key_construction(struct key_type *type, /* we drop the construction sem here on behalf of the caller */ up_write(&key_construction_sem); + /* allocate an authorisation key */ + authkey = request_key_auth_new(key, callout_info); + if (IS_ERR(authkey)) { + ret = PTR_ERR(authkey); + authkey = NULL; + goto alloc_authkey_failed; + } + /* make the call */ - ret = call_request_key(key, "create", callout_info); + actor = call_sbin_request_key; + if (type->request_key) + actor = type->request_key; + ret = actor(key, authkey, "create", aux); if (ret < 0) goto request_failed; @@ -153,22 +175,29 @@ static struct key *__request_key_construction(struct key_type *type, if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) goto request_failed; + key_revoke(authkey); + key_put(authkey); + down_write(&key_construction_sem); list_del(&cons.link); up_write(&key_construction_sem); /* also give an error if the key was negatively instantiated */ - check_not_negative: +check_not_negative: if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { key_put(key); key = ERR_PTR(-ENOKEY); } - out: +out: kleave(" = %p", key); return key; - request_failed: +request_failed: + key_revoke(authkey); + key_put(authkey); + +alloc_authkey_failed: /* it wasn't instantiated * - remove from construction queue * - mark the key as dead @@ -217,7 +246,7 @@ static struct key *__request_key_construction(struct key_type *type, key = ERR_PTR(ret); goto out; - alloc_failed: +alloc_failed: up_write(&key_construction_sem); goto out; @@ -231,16 +260,18 @@ static struct key *__request_key_construction(struct key_type *type, */ static struct key *request_key_construction(struct key_type *type, const char *description, + const char *callout_info, + void *aux, struct key_user *user, - const char *callout_info) + unsigned long flags) { struct key_construction *pcons; struct key *key, *ckey; DECLARE_WAITQUEUE(myself, current); - kenter("%s,%s,{%d},%s", - type->name, description, user->uid, callout_info); + kenter("%s,%s,{%d},%s,%lx", + type->name, description, user->uid, callout_info, flags); /* see if there's such a key under construction already */ down_write(&key_construction_sem); @@ -256,7 +287,8 @@ static struct key *request_key_construction(struct key_type *type, } /* see about getting userspace to construct the key */ - key = __request_key_construction(type, description, callout_info); + key = __request_key_construction(type, description, callout_info, aux, + flags); error: kleave(" = %p", key); return key; @@ -363,14 +395,17 @@ static void request_key_link(struct key *key, struct key *dest_keyring) struct key *request_key_and_link(struct key_type *type, const char *description, const char *callout_info, - struct key *dest_keyring) + void *aux, + struct key *dest_keyring, + unsigned long flags) { struct key_user *user; struct key *key; key_ref_t key_ref; - kenter("%s,%s,%s,%p", - type->name, description, callout_info, dest_keyring); + kenter("%s,%s,%s,%p,%p,%lx", + type->name, description, callout_info, aux, + dest_keyring, flags); /* search all the process keyrings for a key */ key_ref = search_process_keyrings(type, description, type->match, @@ -403,7 +438,8 @@ struct key *request_key_and_link(struct key_type *type, /* ask userspace (returns NULL if it waited on a key * being constructed) */ key = request_key_construction(type, description, - user, callout_info); + callout_info, aux, + user, flags); if (key) break; @@ -459,7 +495,8 @@ struct key *request_key(struct key_type *type, const char *description, const char *callout_info) { - return request_key_and_link(type, description, callout_info, NULL); + return request_key_and_link(type, description, callout_info, NULL, + NULL, KEY_ALLOC_IN_QUOTA); } /* end request_key() */ @@ -467,32 +504,19 @@ EXPORT_SYMBOL(request_key); /*****************************************************************************/ /* - * validate a key + * request a key with auxiliary data for the upcaller + * - search the process's keyrings + * - check the list of keys being created or updated + * - call out to userspace for a key if supplementary info was provided */ -int key_validate(struct key *key) +struct key *request_key_with_auxdata(struct key_type *type, + const char *description, + const char *callout_info, + void *aux) { - struct timespec now; - int ret = 0; - - if (key) { - /* check it's still accessible */ - ret = -EKEYREVOKED; - if (test_bit(KEY_FLAG_REVOKED, &key->flags) || - test_bit(KEY_FLAG_DEAD, &key->flags)) - goto error; - - /* check it hasn't expired */ - ret = 0; - if (key->expiry) { - now = current_kernel_time(); - if (now.tv_sec >= key->expiry) - ret = -EKEYEXPIRED; - } - } - - error: - return ret; + return request_key_and_link(type, description, callout_info, aux, + NULL, KEY_ALLOC_IN_QUOTA); -} /* end key_validate() */ +} /* end request_key_with_auxdata() */ -EXPORT_SYMBOL(key_validate); +EXPORT_SYMBOL(request_key_with_auxdata);