Blame view

security/keys/request_key_auth.c 7.56 KB
3e30148c3   David Howells   [PATCH] Keys: Mak...
1
2
3
4
5
6
7
8
9
  /* request_key_auth.c: request key authorisation controlling key def
   *
   * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
f1a9badcf   David Howells   [PATCH] Keys: Add...
10
11
   *
   * See Documentation/keys-request-key.txt
3e30148c3   David Howells   [PATCH] Keys: Mak...
12
13
14
15
16
17
   */
  
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/err.h>
  #include <linux/seq_file.h>
fdb89bce6   Robert P. J. Day   keys: explicitly ...
18
  #include <linux/slab.h>
b5f545c88   David Howells   [PATCH] keys: Per...
19
  #include <asm/uaccess.h>
3e30148c3   David Howells   [PATCH] Keys: Mak...
20
21
22
23
  #include "internal.h"
  
  static int request_key_auth_instantiate(struct key *, const void *, size_t);
  static void request_key_auth_describe(const struct key *, struct seq_file *);
04c567d93   David Howells   [PATCH] Keys: Fix...
24
  static void request_key_auth_revoke(struct key *);
3e30148c3   David Howells   [PATCH] Keys: Mak...
25
  static void request_key_auth_destroy(struct key *);
b5f545c88   David Howells   [PATCH] keys: Per...
26
  static long request_key_auth_read(const struct key *, char __user *, size_t);
3e30148c3   David Howells   [PATCH] Keys: Mak...
27
28
29
30
31
32
33
34
35
  
  /*
   * the request-key authorisation key type definition
   */
  struct key_type key_type_request_key_auth = {
  	.name		= ".request_key_auth",
  	.def_datalen	= sizeof(struct request_key_auth),
  	.instantiate	= request_key_auth_instantiate,
  	.describe	= request_key_auth_describe,
04c567d93   David Howells   [PATCH] Keys: Fix...
36
  	.revoke		= request_key_auth_revoke,
3e30148c3   David Howells   [PATCH] Keys: Mak...
37
  	.destroy	= request_key_auth_destroy,
b5f545c88   David Howells   [PATCH] keys: Per...
38
  	.read		= request_key_auth_read,
3e30148c3   David Howells   [PATCH] Keys: Mak...
39
40
41
42
  };
  
  /*****************************************************************************/
  /*
b5f545c88   David Howells   [PATCH] keys: Per...
43
   * instantiate a request-key authorisation key
3e30148c3   David Howells   [PATCH] Keys: Mak...
44
45
46
47
48
   */
  static int request_key_auth_instantiate(struct key *key,
  					const void *data,
  					size_t datalen)
  {
b5f545c88   David Howells   [PATCH] keys: Per...
49
50
  	key->payload.data = (struct request_key_auth *) data;
  	return 0;
3e30148c3   David Howells   [PATCH] Keys: Mak...
51
52
53
54
55
  
  } /* end request_key_auth_instantiate() */
  
  /*****************************************************************************/
  /*
b5f545c88   David Howells   [PATCH] keys: Per...
56
   * reading a request-key authorisation key retrieves the callout information
3e30148c3   David Howells   [PATCH] Keys: Mak...
57
58
59
60
61
62
63
64
   */
  static void request_key_auth_describe(const struct key *key,
  				      struct seq_file *m)
  {
  	struct request_key_auth *rka = key->payload.data;
  
  	seq_puts(m, "key:");
  	seq_puts(m, key->description);
4a38e122e   David Howells   keys: allow the c...
65
  	seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
3e30148c3   David Howells   [PATCH] Keys: Mak...
66
67
68
69
70
  
  } /* end request_key_auth_describe() */
  
  /*****************************************************************************/
  /*
b5f545c88   David Howells   [PATCH] keys: Per...
71
72
73
74
75
76
77
78
79
   * read the callout_info data
   * - the key's semaphore is read-locked
   */
  static long request_key_auth_read(const struct key *key,
  				  char __user *buffer, size_t buflen)
  {
  	struct request_key_auth *rka = key->payload.data;
  	size_t datalen;
  	long ret;
4a38e122e   David Howells   keys: allow the c...
80
  	datalen = rka->callout_len;
b5f545c88   David Howells   [PATCH] keys: Per...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  	ret = datalen;
  
  	/* we can return the data as is */
  	if (buffer && buflen > 0) {
  		if (buflen > datalen)
  			buflen = datalen;
  
  		if (copy_to_user(buffer, rka->callout_info, buflen) != 0)
  			ret = -EFAULT;
  	}
  
  	return ret;
  
  } /* end request_key_auth_read() */
  
  /*****************************************************************************/
  /*
04c567d93   David Howells   [PATCH] Keys: Fix...
98
99
100
101
102
103
104
105
   * handle revocation of an authorisation token key
   * - called with the key sem write-locked
   */
  static void request_key_auth_revoke(struct key *key)
  {
  	struct request_key_auth *rka = key->payload.data;
  
  	kenter("{%d}", key->serial);
d84f4f992   David Howells   CRED: Inaugurate ...
106
107
108
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
109
110
111
112
113
114
  	}
  
  } /* end request_key_auth_revoke() */
  
  /*****************************************************************************/
  /*
3e30148c3   David Howells   [PATCH] Keys: Mak...
115
116
117
118
119
120
121
   * destroy an instantiation authorisation token key
   */
  static void request_key_auth_destroy(struct key *key)
  {
  	struct request_key_auth *rka = key->payload.data;
  
  	kenter("{%d}", key->serial);
d84f4f992   David Howells   CRED: Inaugurate ...
122
123
124
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
125
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
126
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
127
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
128
  	kfree(rka->callout_info);
74fd92c51   David Howells   [PATCH] key: plug...
129
  	kfree(rka);
3e30148c3   David Howells   [PATCH] Keys: Mak...
130
131
132
133
134
  
  } /* end request_key_auth_destroy() */
  
  /*****************************************************************************/
  /*
b5f545c88   David Howells   [PATCH] keys: Per...
135
136
   * create an authorisation token for /sbin/request-key or whoever to gain
   * access to the caller's security data
3e30148c3   David Howells   [PATCH] Keys: Mak...
137
   */
4a38e122e   David Howells   keys: allow the c...
138
  struct key *request_key_auth_new(struct key *target, const void *callout_info,
8bbf4976b   David Howells   KEYS: Alter use o...
139
  				 size_t callout_len, struct key *dest_keyring)
3e30148c3   David Howells   [PATCH] Keys: Mak...
140
  {
b5f545c88   David Howells   [PATCH] keys: Per...
141
  	struct request_key_auth *rka, *irka;
d84f4f992   David Howells   CRED: Inaugurate ...
142
  	const struct cred *cred = current->cred;
b5f545c88   David Howells   [PATCH] keys: Per...
143
  	struct key *authkey = NULL;
3e30148c3   David Howells   [PATCH] Keys: Mak...
144
145
146
147
  	char desc[20];
  	int ret;
  
  	kenter("%d,", target->serial);
b5f545c88   David Howells   [PATCH] keys: Per...
148
149
150
151
152
153
  	/* allocate a auth record */
  	rka = kmalloc(sizeof(*rka), GFP_KERNEL);
  	if (!rka) {
  		kleave(" = -ENOMEM");
  		return ERR_PTR(-ENOMEM);
  	}
4a38e122e   David Howells   keys: allow the c...
154
  	rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
76181c134   David Howells   KEYS: Make reques...
155
156
157
158
159
  	if (!rka->callout_info) {
  		kleave(" = -ENOMEM");
  		kfree(rka);
  		return ERR_PTR(-ENOMEM);
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
160

b5f545c88   David Howells   [PATCH] keys: Per...
161
162
  	/* see if the calling process is already servicing the key request of
  	 * another process */
d84f4f992   David Howells   CRED: Inaugurate ...
163
  	if (cred->request_key_auth) {
b5f545c88   David Howells   [PATCH] keys: Per...
164
  		/* it is - use that instantiation context here too */
d84f4f992   David Howells   CRED: Inaugurate ...
165
  		down_read(&cred->request_key_auth->sem);
04c567d93   David Howells   [PATCH] Keys: Fix...
166
167
168
  
  		/* if the auth key has been revoked, then the key we're
  		 * servicing is already instantiated */
d84f4f992   David Howells   CRED: Inaugurate ...
169
  		if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
04c567d93   David Howells   [PATCH] Keys: Fix...
170
  			goto auth_key_revoked;
d84f4f992   David Howells   CRED: Inaugurate ...
171
172
  		irka = cred->request_key_auth->payload.data;
  		rka->cred = get_cred(irka->cred);
b5f545c88   David Howells   [PATCH] keys: Per...
173
  		rka->pid = irka->pid;
04c567d93   David Howells   [PATCH] Keys: Fix...
174

d84f4f992   David Howells   CRED: Inaugurate ...
175
  		up_read(&cred->request_key_auth->sem);
3e30148c3   David Howells   [PATCH] Keys: Mak...
176
  	}
b5f545c88   David Howells   [PATCH] keys: Per...
177
178
  	else {
  		/* it isn't - use this process as the context */
d84f4f992   David Howells   CRED: Inaugurate ...
179
  		rka->cred = get_cred(cred);
b5f545c88   David Howells   [PATCH] keys: Per...
180
181
182
183
  		rka->pid = current->pid;
  	}
  
  	rka->target_key = key_get(target);
8bbf4976b   David Howells   KEYS: Alter use o...
184
  	rka->dest_keyring = key_get(dest_keyring);
4a38e122e   David Howells   keys: allow the c...
185
186
  	memcpy(rka->callout_info, callout_info, callout_len);
  	rka->callout_len = callout_len;
3e30148c3   David Howells   [PATCH] Keys: Mak...
187
188
189
  
  	/* allocate the auth key */
  	sprintf(desc, "%x", target->serial);
b5f545c88   David Howells   [PATCH] keys: Per...
190
  	authkey = key_alloc(&key_type_request_key_auth, desc,
d84f4f992   David Howells   CRED: Inaugurate ...
191
  			    cred->fsuid, cred->fsgid, cred,
b5f545c88   David Howells   [PATCH] keys: Per...
192
  			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
7e047ef5f   David Howells   [PATCH] keys: sor...
193
  			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
b5f545c88   David Howells   [PATCH] keys: Per...
194
195
196
  	if (IS_ERR(authkey)) {
  		ret = PTR_ERR(authkey);
  		goto error_alloc;
3e30148c3   David Howells   [PATCH] Keys: Mak...
197
  	}
d84f4f992   David Howells   CRED: Inaugurate ...
198
  	/* construct the auth key */
b5f545c88   David Howells   [PATCH] keys: Per...
199
200
201
  	ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
  	if (ret < 0)
  		goto error_inst;
3e30148c3   David Howells   [PATCH] Keys: Mak...
202

d84f4f992   David Howells   CRED: Inaugurate ...
203
  	kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
b5f545c88   David Howells   [PATCH] keys: Per...
204
  	return authkey;
04c567d93   David Howells   [PATCH] Keys: Fix...
205
  auth_key_revoked:
d84f4f992   David Howells   CRED: Inaugurate ...
206
  	up_read(&cred->request_key_auth->sem);
76181c134   David Howells   KEYS: Make reques...
207
  	kfree(rka->callout_info);
04c567d93   David Howells   [PATCH] Keys: Fix...
208
209
210
  	kfree(rka);
  	kleave("= -EKEYREVOKED");
  	return ERR_PTR(-EKEYREVOKED);
b5f545c88   David Howells   [PATCH] keys: Per...
211
212
213
214
215
  error_inst:
  	key_revoke(authkey);
  	key_put(authkey);
  error_alloc:
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
216
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
217
  	kfree(rka->callout_info);
b5f545c88   David Howells   [PATCH] keys: Per...
218
219
220
  	kfree(rka);
  	kleave("= %d", ret);
  	return ERR_PTR(ret);
3e30148c3   David Howells   [PATCH] Keys: Mak...
221
222
223
224
225
  
  } /* end request_key_auth_new() */
  
  /*****************************************************************************/
  /*
b5f545c88   David Howells   [PATCH] keys: Per...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
   * see if an authorisation key is associated with a particular key
   */
  static int key_get_instantiation_authkey_match(const struct key *key,
  					       const void *_id)
  {
  	struct request_key_auth *rka = key->payload.data;
  	key_serial_t id = (key_serial_t)(unsigned long) _id;
  
  	return rka->target_key->serial == id;
  
  } /* end key_get_instantiation_authkey_match() */
  
  /*****************************************************************************/
  /*
3e30148c3   David Howells   [PATCH] Keys: Mak...
240
241
242
243
244
245
246
247
   * get the authorisation key for instantiation of a specific key if attached to
   * the current process's keyrings
   * - this key is inserted into a keyring and that is set as /sbin/request-key's
   *   session keyring
   * - a target_id of zero specifies any valid token
   */
  struct key *key_get_instantiation_authkey(key_serial_t target_id)
  {
d84f4f992   David Howells   CRED: Inaugurate ...
248
  	const struct cred *cred = current_cred();
b5f545c88   David Howells   [PATCH] keys: Per...
249
250
251
252
253
254
255
  	struct key *authkey;
  	key_ref_t authkey_ref;
  
  	authkey_ref = search_process_keyrings(
  		&key_type_request_key_auth,
  		(void *) (unsigned long) target_id,
  		key_get_instantiation_authkey_match,
d84f4f992   David Howells   CRED: Inaugurate ...
256
  		cred);
b5f545c88   David Howells   [PATCH] keys: Per...
257
258
  
  	if (IS_ERR(authkey_ref)) {
e231c2ee6   David Howells   Convert ERR_PTR(P...
259
  		authkey = ERR_CAST(authkey_ref);
b5f545c88   David Howells   [PATCH] keys: Per...
260
261
  		goto error;
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
262

b5f545c88   David Howells   [PATCH] keys: Per...
263
264
265
266
267
  	authkey = key_ref_to_ptr(authkey_ref);
  	if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {
  		key_put(authkey);
  		authkey = ERR_PTR(-EKEYREVOKED);
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
268

b5f545c88   David Howells   [PATCH] keys: Per...
269
270
  error:
  	return authkey;
3e30148c3   David Howells   [PATCH] Keys: Mak...
271
272
  
  } /* end key_get_instantiation_authkey() */