|
@@ -3,16 +3,23 @@
|
|
===================
|
|
===================
|
|
|
|
|
|
The key request service is part of the key retention service (refer to
|
|
The key request service is part of the key retention service (refer to
|
|
-Documentation/keys.txt). This document explains more fully how that the
|
|
|
|
-requesting algorithm works.
|
|
|
|
|
|
+Documentation/keys.txt). This document explains more fully how the requesting
|
|
|
|
+algorithm works.
|
|
|
|
|
|
The process starts by either the kernel requesting a service by calling
|
|
The process starts by either the kernel requesting a service by calling
|
|
-request_key():
|
|
|
|
|
|
+request_key*():
|
|
|
|
|
|
struct key *request_key(const struct key_type *type,
|
|
struct key *request_key(const struct key_type *type,
|
|
const char *description,
|
|
const char *description,
|
|
const char *callout_string);
|
|
const char *callout_string);
|
|
|
|
|
|
|
|
+or:
|
|
|
|
+
|
|
|
|
+ struct key *request_key_with_auxdata(const struct key_type *type,
|
|
|
|
+ const char *description,
|
|
|
|
+ const char *callout_string,
|
|
|
|
+ void *aux);
|
|
|
|
+
|
|
Or by userspace invoking the request_key system call:
|
|
Or by userspace invoking the request_key system call:
|
|
|
|
|
|
key_serial_t request_key(const char *type,
|
|
key_serial_t request_key(const char *type,
|
|
@@ -20,16 +27,26 @@ Or by userspace invoking the request_key system call:
|
|
const char *callout_info,
|
|
const char *callout_info,
|
|
key_serial_t dest_keyring);
|
|
key_serial_t dest_keyring);
|
|
|
|
|
|
-The main difference between the two access points is that the in-kernel
|
|
|
|
-interface does not need to link the key to a keyring to prevent it from being
|
|
|
|
-immediately destroyed. The kernel interface returns a pointer directly to the
|
|
|
|
-key, and it's up to the caller to destroy the key.
|
|
|
|
|
|
+The main difference between the access points is that the in-kernel interface
|
|
|
|
+does not need to link the key to a keyring to prevent it from being immediately
|
|
|
|
+destroyed. The kernel interface returns a pointer directly to the key, and
|
|
|
|
+it's up to the caller to destroy the key.
|
|
|
|
+
|
|
|
|
+The request_key_with_auxdata() call is like the in-kernel request_key() call,
|
|
|
|
+except that it permits auxiliary data to be passed to the upcaller (the default
|
|
|
|
+is NULL). This is only useful for those key types that define their own upcall
|
|
|
|
+mechanism rather than using /sbin/request-key.
|
|
|
|
|
|
The userspace interface links the key to a keyring associated with the process
|
|
The userspace interface links the key to a keyring associated with the process
|
|
to prevent the key from going away, and returns the serial number of the key to
|
|
to prevent the key from going away, and returns the serial number of the key to
|
|
the caller.
|
|
the caller.
|
|
|
|
|
|
|
|
|
|
|
|
+The following example assumes that the key types involved don't define their
|
|
|
|
+own upcall mechanisms. If they do, then those should be substituted for the
|
|
|
|
+forking and execution of /sbin/request-key.
|
|
|
|
+
|
|
|
|
+
|
|
===========
|
|
===========
|
|
THE PROCESS
|
|
THE PROCESS
|
|
===========
|
|
===========
|
|
@@ -40,8 +57,8 @@ A request proceeds in the following manner:
|
|
interface].
|
|
interface].
|
|
|
|
|
|
(2) request_key() searches the process's subscribed keyrings to see if there's
|
|
(2) request_key() searches the process's subscribed keyrings to see if there's
|
|
- a suitable key there. If there is, it returns the key. If there isn't, and
|
|
|
|
- callout_info is not set, an error is returned. Otherwise the process
|
|
|
|
|
|
+ a suitable key there. If there is, it returns the key. If there isn't,
|
|
|
|
+ and callout_info is not set, an error is returned. Otherwise the process
|
|
proceeds to the next step.
|
|
proceeds to the next step.
|
|
|
|
|
|
(3) request_key() sees that A doesn't have the desired key yet, so it creates
|
|
(3) request_key() sees that A doesn't have the desired key yet, so it creates
|
|
@@ -62,7 +79,7 @@ A request proceeds in the following manner:
|
|
instantiation.
|
|
instantiation.
|
|
|
|
|
|
(7) The program may want to access another key from A's context (say a
|
|
(7) The program may want to access another key from A's context (say a
|
|
- Kerberos TGT key). It just requests the appropriate key, and the keyring
|
|
|
|
|
|
+ Kerberos TGT key). It just requests the appropriate key, and the keyring
|
|
search notes that the session keyring has auth key V in its bottom level.
|
|
search notes that the session keyring has auth key V in its bottom level.
|
|
|
|
|
|
This will permit it to then search the keyrings of process A with the
|
|
This will permit it to then search the keyrings of process A with the
|
|
@@ -79,10 +96,11 @@ A request proceeds in the following manner:
|
|
(10) The program then exits 0 and request_key() deletes key V and returns key
|
|
(10) The program then exits 0 and request_key() deletes key V and returns key
|
|
U to the caller.
|
|
U to the caller.
|
|
|
|
|
|
-This also extends further. If key W (step 7 above) didn't exist, key W would be
|
|
|
|
-created uninstantiated, another auth key (X) would be created (as per step 3)
|
|
|
|
-and another copy of /sbin/request-key spawned (as per step 4); but the context
|
|
|
|
-specified by auth key X will still be process A, as it was in auth key V.
|
|
|
|
|
|
+This also extends further. If key W (step 7 above) didn't exist, key W would
|
|
|
|
+be created uninstantiated, another auth key (X) would be created (as per step
|
|
|
|
+3) and another copy of /sbin/request-key spawned (as per step 4); but the
|
|
|
|
+context specified by auth key X will still be process A, as it was in auth key
|
|
|
|
+V.
|
|
|
|
|
|
This is because process A's keyrings can't simply be attached to
|
|
This is because process A's keyrings can't simply be attached to
|
|
/sbin/request-key at the appropriate places because (a) execve will discard two
|
|
/sbin/request-key at the appropriate places because (a) execve will discard two
|
|
@@ -118,17 +136,17 @@ A search of any particular keyring proceeds in the following fashion:
|
|
|
|
|
|
(2) It considers all the non-keyring keys within that keyring and, if any key
|
|
(2) It considers all the non-keyring keys within that keyring and, if any key
|
|
matches the criteria specified, calls key_permission(SEARCH) on it to see
|
|
matches the criteria specified, calls key_permission(SEARCH) on it to see
|
|
- if the key is allowed to be found. If it is, that key is returned; if
|
|
|
|
|
|
+ if the key is allowed to be found. If it is, that key is returned; if
|
|
not, the search continues, and the error code is retained if of higher
|
|
not, the search continues, and the error code is retained if of higher
|
|
priority than the one currently set.
|
|
priority than the one currently set.
|
|
|
|
|
|
(3) It then considers all the keyring-type keys in the keyring it's currently
|
|
(3) It then considers all the keyring-type keys in the keyring it's currently
|
|
- searching. It calls key_permission(SEARCH) on each keyring, and if this
|
|
|
|
|
|
+ searching. It calls key_permission(SEARCH) on each keyring, and if this
|
|
grants permission, it recurses, executing steps (2) and (3) on that
|
|
grants permission, it recurses, executing steps (2) and (3) on that
|
|
keyring.
|
|
keyring.
|
|
|
|
|
|
The process stops immediately a valid key is found with permission granted to
|
|
The process stops immediately a valid key is found with permission granted to
|
|
-use it. Any error from a previous match attempt is discarded and the key is
|
|
|
|
|
|
+use it. Any error from a previous match attempt is discarded and the key is
|
|
returned.
|
|
returned.
|
|
|
|
|
|
When search_process_keyrings() is invoked, it performs the following searches
|
|
When search_process_keyrings() is invoked, it performs the following searches
|
|
@@ -153,7 +171,7 @@ The moment one succeeds, all pending errors are discarded and the found key is
|
|
returned.
|
|
returned.
|
|
|
|
|
|
Only if all these fail does the whole thing fail with the highest priority
|
|
Only if all these fail does the whole thing fail with the highest priority
|
|
-error. Note that several errors may have come from LSM.
|
|
|
|
|
|
+error. Note that several errors may have come from LSM.
|
|
|
|
|
|
The error priority is:
|
|
The error priority is:
|
|
|
|
|