]>
Commit | Line | Data |
---|---|---|
3e30148c DH |
1 | /* request_key_auth.c: request key authorisation controlling key def |
2 | * | |
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
f1a9badc DH |
10 | * |
11 | * See Documentation/keys-request-key.txt | |
3e30148c DH |
12 | */ |
13 | ||
14 | #include <linux/module.h> | |
15 | #include <linux/sched.h> | |
16 | #include <linux/err.h> | |
17 | #include <linux/seq_file.h> | |
18 | #include "internal.h" | |
19 | ||
20 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | |
21 | static void request_key_auth_describe(const struct key *, struct seq_file *); | |
22 | static void request_key_auth_destroy(struct key *); | |
23 | ||
24 | /* | |
25 | * the request-key authorisation key type definition | |
26 | */ | |
27 | struct key_type key_type_request_key_auth = { | |
28 | .name = ".request_key_auth", | |
29 | .def_datalen = sizeof(struct request_key_auth), | |
30 | .instantiate = request_key_auth_instantiate, | |
31 | .describe = request_key_auth_describe, | |
32 | .destroy = request_key_auth_destroy, | |
33 | }; | |
34 | ||
35 | /*****************************************************************************/ | |
36 | /* | |
37 | * instantiate a request-key authorisation record | |
38 | */ | |
39 | static int request_key_auth_instantiate(struct key *key, | |
40 | const void *data, | |
41 | size_t datalen) | |
42 | { | |
43 | struct request_key_auth *rka, *irka; | |
44 | struct key *instkey; | |
45 | int ret; | |
46 | ||
47 | ret = -ENOMEM; | |
48 | rka = kmalloc(sizeof(*rka), GFP_KERNEL); | |
49 | if (rka) { | |
50 | /* see if the calling process is already servicing the key | |
51 | * request of another process */ | |
52 | instkey = key_get_instantiation_authkey(0); | |
53 | if (!IS_ERR(instkey)) { | |
54 | /* it is - use that instantiation context here too */ | |
55 | irka = instkey->payload.data; | |
56 | rka->context = irka->context; | |
57 | rka->pid = irka->pid; | |
58 | key_put(instkey); | |
59 | } | |
60 | else { | |
61 | /* it isn't - use this process as the context */ | |
62 | rka->context = current; | |
63 | rka->pid = current->pid; | |
64 | } | |
65 | ||
66 | rka->target_key = key_get((struct key *) data); | |
67 | key->payload.data = rka; | |
68 | ret = 0; | |
69 | } | |
70 | ||
71 | return ret; | |
72 | ||
73 | } /* end request_key_auth_instantiate() */ | |
74 | ||
75 | /*****************************************************************************/ | |
76 | /* | |
77 | * | |
78 | */ | |
79 | static void request_key_auth_describe(const struct key *key, | |
80 | struct seq_file *m) | |
81 | { | |
82 | struct request_key_auth *rka = key->payload.data; | |
83 | ||
84 | seq_puts(m, "key:"); | |
85 | seq_puts(m, key->description); | |
86 | seq_printf(m, " pid:%d", rka->pid); | |
87 | ||
88 | } /* end request_key_auth_describe() */ | |
89 | ||
90 | /*****************************************************************************/ | |
91 | /* | |
92 | * destroy an instantiation authorisation token key | |
93 | */ | |
94 | static void request_key_auth_destroy(struct key *key) | |
95 | { | |
96 | struct request_key_auth *rka = key->payload.data; | |
97 | ||
98 | kenter("{%d}", key->serial); | |
99 | ||
100 | key_put(rka->target_key); | |
74fd92c5 | 101 | kfree(rka); |
3e30148c DH |
102 | |
103 | } /* end request_key_auth_destroy() */ | |
104 | ||
105 | /*****************************************************************************/ | |
106 | /* | |
107 | * create a session keyring to be for the invokation of /sbin/request-key and | |
108 | * stick an authorisation token in it | |
109 | */ | |
110 | struct key *request_key_auth_new(struct key *target, struct key **_rkakey) | |
111 | { | |
112 | struct key *keyring, *rkakey = NULL; | |
113 | char desc[20]; | |
114 | int ret; | |
115 | ||
116 | kenter("%d,", target->serial); | |
117 | ||
118 | /* allocate a new session keyring */ | |
119 | sprintf(desc, "_req.%u", target->serial); | |
120 | ||
121 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); | |
122 | if (IS_ERR(keyring)) { | |
123 | kleave("= %ld", PTR_ERR(keyring)); | |
124 | return keyring; | |
125 | } | |
126 | ||
127 | /* allocate the auth key */ | |
128 | sprintf(desc, "%x", target->serial); | |
129 | ||
130 | rkakey = key_alloc(&key_type_request_key_auth, desc, | |
131 | current->fsuid, current->fsgid, | |
664cceb0 | 132 | KEY_POS_VIEW | KEY_USR_VIEW, 1); |
3e30148c DH |
133 | if (IS_ERR(rkakey)) { |
134 | key_put(keyring); | |
135 | kleave("= %ld", PTR_ERR(rkakey)); | |
136 | return rkakey; | |
137 | } | |
138 | ||
139 | /* construct and attach to the keyring */ | |
140 | ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); | |
141 | if (ret < 0) { | |
142 | key_revoke(rkakey); | |
143 | key_put(rkakey); | |
144 | key_put(keyring); | |
145 | kleave("= %d", ret); | |
146 | return ERR_PTR(ret); | |
147 | } | |
148 | ||
149 | *_rkakey = rkakey; | |
150 | kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); | |
151 | return keyring; | |
152 | ||
153 | } /* end request_key_auth_new() */ | |
154 | ||
155 | /*****************************************************************************/ | |
156 | /* | |
157 | * get the authorisation key for instantiation of a specific key if attached to | |
158 | * the current process's keyrings | |
159 | * - this key is inserted into a keyring and that is set as /sbin/request-key's | |
160 | * session keyring | |
161 | * - a target_id of zero specifies any valid token | |
162 | */ | |
163 | struct key *key_get_instantiation_authkey(key_serial_t target_id) | |
164 | { | |
165 | struct task_struct *tsk = current; | |
166 | struct key *instkey; | |
167 | ||
168 | /* we must have our own personal session keyring */ | |
169 | if (!tsk->signal->session_keyring) | |
170 | return ERR_PTR(-EACCES); | |
171 | ||
172 | /* and it must contain a suitable request authorisation key | |
173 | * - lock RCU against session keyring changing | |
174 | */ | |
175 | rcu_read_lock(); | |
176 | ||
177 | instkey = keyring_search_instkey( | |
178 | rcu_dereference(tsk->signal->session_keyring), target_id); | |
179 | ||
180 | rcu_read_unlock(); | |
181 | return instkey; | |
182 | ||
183 | } /* end key_get_instantiation_authkey() */ |