|
@@ -0,0 +1,161 @@
|
|
|
+ ===================
|
|
|
+ KEY REQUEST SERVICE
|
|
|
+ ===================
|
|
|
+
|
|
|
+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.
|
|
|
+
|
|
|
+The process starts by either the kernel requesting a service by calling
|
|
|
+request_key():
|
|
|
+
|
|
|
+ struct key *request_key(const struct key_type *type,
|
|
|
+ const char *description,
|
|
|
+ const char *callout_string);
|
|
|
+
|
|
|
+Or by userspace invoking the request_key system call:
|
|
|
+
|
|
|
+ key_serial_t request_key(const char *type,
|
|
|
+ const char *description,
|
|
|
+ const char *callout_info,
|
|
|
+ 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 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
|
|
|
+the caller.
|
|
|
+
|
|
|
+
|
|
|
+===========
|
|
|
+THE PROCESS
|
|
|
+===========
|
|
|
+
|
|
|
+A request proceeds in the following manner:
|
|
|
+
|
|
|
+ (1) Process A calls request_key() [the userspace syscall calls the kernel
|
|
|
+ interface].
|
|
|
+
|
|
|
+ (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
|
|
|
+ proceeds to the next step.
|
|
|
+
|
|
|
+ (3) request_key() sees that A doesn't have the desired key yet, so it creates
|
|
|
+ two things:
|
|
|
+
|
|
|
+ (a) An uninstantiated key U of requested type and description.
|
|
|
+
|
|
|
+ (b) An authorisation key V that refers to key U and notes that process A
|
|
|
+ is the context in which key U should be instantiated and secured, and
|
|
|
+ from which associated key requests may be satisfied.
|
|
|
+
|
|
|
+ (4) request_key() then forks and executes /sbin/request-key with a new session
|
|
|
+ keyring that contains a link to auth key V.
|
|
|
+
|
|
|
+ (5) /sbin/request-key execs an appropriate program to perform the actual
|
|
|
+ instantiation.
|
|
|
+
|
|
|
+ (6) 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
|
|
|
+ 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
|
|
|
+ UID, GID, groups and security info of process A as if it was process A,
|
|
|
+ and come up with key W.
|
|
|
+
|
|
|
+ (7) The program then does what it must to get the data with which to
|
|
|
+ instantiate key U, using key W as a reference (perhaps it contacts a
|
|
|
+ Kerberos server using the TGT) and then instantiates key U.
|
|
|
+
|
|
|
+ (8) Upon instantiating key U, auth key V is automatically revoked so that it
|
|
|
+ may not be used again.
|
|
|
+
|
|
|
+ (9) The program then exits 0 and request_key() deletes key V and returns key
|
|
|
+ U to the caller.
|
|
|
+
|
|
|
+This also extends further. If key W (step 5 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
|
|
|
+/sbin/request-key at the appropriate places because (a) execve will discard two
|
|
|
+of them, and (b) it requires the same UID/GID/Groups all the way through.
|
|
|
+
|
|
|
+
|
|
|
+======================
|
|
|
+NEGATIVE INSTANTIATION
|
|
|
+======================
|
|
|
+
|
|
|
+Rather than instantiating a key, it is possible for the possessor of an
|
|
|
+authorisation key to negatively instantiate a key that's under construction.
|
|
|
+This is a short duration placeholder that causes any attempt at re-requesting
|
|
|
+the key whilst it exists to fail with error ENOKEY.
|
|
|
+
|
|
|
+This is provided to prevent excessive repeated spawning of /sbin/request-key
|
|
|
+processes for a key that will never be obtainable.
|
|
|
+
|
|
|
+Should the /sbin/request-key process exit anything other than 0 or die on a
|
|
|
+signal, the key under construction will be automatically negatively
|
|
|
+instantiated for a short amount of time.
|
|
|
+
|
|
|
+
|
|
|
+====================
|
|
|
+THE SEARCH ALGORITHM
|
|
|
+====================
|
|
|
+
|
|
|
+A search of any particular keyring proceeds in the following fashion:
|
|
|
+
|
|
|
+ (1) When the key management code searches for a key (keyring_search_aux) it
|
|
|
+ firstly calls key_permission(SEARCH) on the keyring it's starting with,
|
|
|
+ if this denies permission, it doesn't search further.
|
|
|
+
|
|
|
+ (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
|
|
|
+ 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
|
|
|
+ priority than the one currently set.
|
|
|
+
|
|
|
+ (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
|
|
|
+ grants permission, it recurses, executing steps (2) and (3) on that
|
|
|
+ keyring.
|
|
|
+
|
|
|
+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
|
|
|
+returned.
|
|
|
+
|
|
|
+When search_process_keyrings() is invoked, it performs the following searches
|
|
|
+until one succeeds:
|
|
|
+
|
|
|
+ (1) If extant, the process's thread keyring is searched.
|
|
|
+
|
|
|
+ (2) If extant, the process's process keyring is searched.
|
|
|
+
|
|
|
+ (3) The process's session keyring is searched.
|
|
|
+
|
|
|
+ (4) If the process has a request_key() authorisation key in its session
|
|
|
+ keyring then:
|
|
|
+
|
|
|
+ (a) If extant, the calling process's thread keyring is searched.
|
|
|
+
|
|
|
+ (b) If extant, the calling process's process keyring is searched.
|
|
|
+
|
|
|
+ (c) The calling process's session keyring is searched.
|
|
|
+
|
|
|
+The moment one succeeds, all pending errors are discarded and the found key is
|
|
|
+returned.
|
|
|
+
|
|
|
+Only if all these fail does the whole thing fail with the highest priority
|
|
|
+error. Note that several errors may have come from LSM.
|
|
|
+
|
|
|
+The error priority is:
|
|
|
+
|
|
|
+ EKEYREVOKED > EKEYEXPIRED > ENOKEY
|
|
|
+
|
|
|
+EACCES/EPERM are only returned on a direct search of a specific keyring where
|
|
|
+the basal keyring does not grant Search permission.
|