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