]>
Commit | Line | Data |
---|---|---|
f1a9badc DH |
1 | =================== |
2 | KEY REQUEST SERVICE | |
3 | =================== | |
4 | ||
5 | The key request service is part of the key retention service (refer to | |
4e54f085 DH |
6 | Documentation/keys.txt). This document explains more fully how the requesting |
7 | algorithm works. | |
f1a9badc DH |
8 | |
9 | The process starts by either the kernel requesting a service by calling | |
4e54f085 | 10 | request_key*(): |
f1a9badc DH |
11 | |
12 | struct key *request_key(const struct key_type *type, | |
13 | const char *description, | |
14 | const char *callout_string); | |
15 | ||
4e54f085 DH |
16 | or: |
17 | ||
18 | struct key *request_key_with_auxdata(const struct key_type *type, | |
19 | const char *description, | |
20 | const char *callout_string, | |
21 | void *aux); | |
22 | ||
76181c13 DH |
23 | or: |
24 | ||
25 | struct key *request_key_async(const struct key_type *type, | |
26 | const char *description, | |
27 | const char *callout_string); | |
28 | ||
29 | or: | |
30 | ||
31 | struct key *request_key_async_with_auxdata(const struct key_type *type, | |
32 | const char *description, | |
33 | const char *callout_string, | |
34 | void *aux); | |
35 | ||
f1a9badc DH |
36 | Or by userspace invoking the request_key system call: |
37 | ||
38 | key_serial_t request_key(const char *type, | |
39 | const char *description, | |
40 | const char *callout_info, | |
41 | key_serial_t dest_keyring); | |
42 | ||
4e54f085 DH |
43 | The main difference between the access points is that the in-kernel interface |
44 | does not need to link the key to a keyring to prevent it from being immediately | |
45 | destroyed. The kernel interface returns a pointer directly to the key, and | |
46 | it's up to the caller to destroy the key. | |
47 | ||
76181c13 DH |
48 | The request_key*_with_auxdata() calls are like the in-kernel request_key*() |
49 | calls, except that they permit auxiliary data to be passed to the upcaller (the | |
50 | default is NULL). This is only useful for those key types that define their | |
51 | own upcall mechanism rather than using /sbin/request-key. | |
52 | ||
53 | The two async in-kernel calls may return keys that are still in the process of | |
54 | being constructed. The two non-async ones will wait for construction to | |
55 | complete first. | |
f1a9badc DH |
56 | |
57 | The userspace interface links the key to a keyring associated with the process | |
58 | to prevent the key from going away, and returns the serial number of the key to | |
59 | the caller. | |
60 | ||
61 | ||
4e54f085 DH |
62 | The following example assumes that the key types involved don't define their |
63 | own upcall mechanisms. If they do, then those should be substituted for the | |
64 | forking and execution of /sbin/request-key. | |
65 | ||
66 | ||
f1a9badc DH |
67 | =========== |
68 | THE PROCESS | |
69 | =========== | |
70 | ||
71 | A request proceeds in the following manner: | |
72 | ||
73 | (1) Process A calls request_key() [the userspace syscall calls the kernel | |
74 | interface]. | |
75 | ||
76 | (2) request_key() searches the process's subscribed keyrings to see if there's | |
4e54f085 DH |
77 | a suitable key there. If there is, it returns the key. If there isn't, |
78 | and callout_info is not set, an error is returned. Otherwise the process | |
f1a9badc DH |
79 | proceeds to the next step. |
80 | ||
81 | (3) request_key() sees that A doesn't have the desired key yet, so it creates | |
82 | two things: | |
83 | ||
84 | (a) An uninstantiated key U of requested type and description. | |
85 | ||
86 | (b) An authorisation key V that refers to key U and notes that process A | |
87 | is the context in which key U should be instantiated and secured, and | |
88 | from which associated key requests may be satisfied. | |
89 | ||
90 | (4) request_key() then forks and executes /sbin/request-key with a new session | |
91 | keyring that contains a link to auth key V. | |
92 | ||
b5f545c8 DH |
93 | (5) /sbin/request-key assumes the authority associated with key U. |
94 | ||
95 | (6) /sbin/request-key execs an appropriate program to perform the actual | |
f1a9badc DH |
96 | instantiation. |
97 | ||
b5f545c8 | 98 | (7) The program may want to access another key from A's context (say a |
4e54f085 | 99 | Kerberos TGT key). It just requests the appropriate key, and the keyring |
f1a9badc DH |
100 | search notes that the session keyring has auth key V in its bottom level. |
101 | ||
102 | This will permit it to then search the keyrings of process A with the | |
103 | UID, GID, groups and security info of process A as if it was process A, | |
104 | and come up with key W. | |
105 | ||
b5f545c8 | 106 | (8) The program then does what it must to get the data with which to |
f1a9badc DH |
107 | instantiate key U, using key W as a reference (perhaps it contacts a |
108 | Kerberos server using the TGT) and then instantiates key U. | |
109 | ||
b5f545c8 | 110 | (9) Upon instantiating key U, auth key V is automatically revoked so that it |
f1a9badc DH |
111 | may not be used again. |
112 | ||
b5f545c8 | 113 | (10) The program then exits 0 and request_key() deletes key V and returns key |
f1a9badc DH |
114 | U to the caller. |
115 | ||
4e54f085 DH |
116 | This also extends further. If key W (step 7 above) didn't exist, key W would |
117 | be created uninstantiated, another auth key (X) would be created (as per step | |
118 | 3) and another copy of /sbin/request-key spawned (as per step 4); but the | |
119 | context specified by auth key X will still be process A, as it was in auth key | |
120 | V. | |
f1a9badc DH |
121 | |
122 | This is because process A's keyrings can't simply be attached to | |
123 | /sbin/request-key at the appropriate places because (a) execve will discard two | |
124 | of them, and (b) it requires the same UID/GID/Groups all the way through. | |
125 | ||
126 | ||
127 | ====================== | |
128 | NEGATIVE INSTANTIATION | |
129 | ====================== | |
130 | ||
131 | Rather than instantiating a key, it is possible for the possessor of an | |
132 | authorisation key to negatively instantiate a key that's under construction. | |
133 | This is a short duration placeholder that causes any attempt at re-requesting | |
134 | the key whilst it exists to fail with error ENOKEY. | |
135 | ||
136 | This is provided to prevent excessive repeated spawning of /sbin/request-key | |
137 | processes for a key that will never be obtainable. | |
138 | ||
139 | Should the /sbin/request-key process exit anything other than 0 or die on a | |
140 | signal, the key under construction will be automatically negatively | |
141 | instantiated for a short amount of time. | |
142 | ||
143 | ||
144 | ==================== | |
145 | THE SEARCH ALGORITHM | |
146 | ==================== | |
147 | ||
148 | A search of any particular keyring proceeds in the following fashion: | |
149 | ||
150 | (1) When the key management code searches for a key (keyring_search_aux) it | |
151 | firstly calls key_permission(SEARCH) on the keyring it's starting with, | |
152 | if this denies permission, it doesn't search further. | |
153 | ||
154 | (2) It considers all the non-keyring keys within that keyring and, if any key | |
155 | matches the criteria specified, calls key_permission(SEARCH) on it to see | |
4e54f085 | 156 | if the key is allowed to be found. If it is, that key is returned; if |
f1a9badc DH |
157 | not, the search continues, and the error code is retained if of higher |
158 | priority than the one currently set. | |
159 | ||
160 | (3) It then considers all the keyring-type keys in the keyring it's currently | |
4e54f085 | 161 | searching. It calls key_permission(SEARCH) on each keyring, and if this |
f1a9badc DH |
162 | grants permission, it recurses, executing steps (2) and (3) on that |
163 | keyring. | |
164 | ||
165 | The process stops immediately a valid key is found with permission granted to | |
4e54f085 | 166 | use it. Any error from a previous match attempt is discarded and the key is |
f1a9badc DH |
167 | returned. |
168 | ||
169 | When search_process_keyrings() is invoked, it performs the following searches | |
170 | until one succeeds: | |
171 | ||
172 | (1) If extant, the process's thread keyring is searched. | |
173 | ||
174 | (2) If extant, the process's process keyring is searched. | |
175 | ||
176 | (3) The process's session keyring is searched. | |
177 | ||
b5f545c8 DH |
178 | (4) If the process has assumed the authority associated with a request_key() |
179 | authorisation key then: | |
f1a9badc DH |
180 | |
181 | (a) If extant, the calling process's thread keyring is searched. | |
182 | ||
183 | (b) If extant, the calling process's process keyring is searched. | |
184 | ||
185 | (c) The calling process's session keyring is searched. | |
186 | ||
187 | The moment one succeeds, all pending errors are discarded and the found key is | |
188 | returned. | |
189 | ||
190 | Only if all these fail does the whole thing fail with the highest priority | |
4e54f085 | 191 | error. Note that several errors may have come from LSM. |
f1a9badc DH |
192 | |
193 | The error priority is: | |
194 | ||
195 | EKEYREVOKED > EKEYEXPIRED > ENOKEY | |
196 | ||
197 | EACCES/EPERM are only returned on a direct search of a specific keyring where | |
198 | the basal keyring does not grant Search permission. |