Blame view

security/keys/request_key_auth.c 6.56 KB
973c9f4f4   David Howells   KEYS: Fix up comm...
1
  /* Request key authorisation token key definition.
3e30148c3   David Howells   [PATCH] Keys: Mak...
2
3
4
5
6
7
8
9
   *
   * 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
   *
d410fa4ef   Randy Dunlap   Create Documentat...
11
   * See Documentation/security/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
  
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
29
   * The request-key authorisation key type definition.
3e30148c3   David Howells   [PATCH] Keys: Mak...
30
31
32
33
34
35
   */
  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
  };
3e30148c3   David Howells   [PATCH] Keys: Mak...
40
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
41
   * Instantiate a request-key authorisation key.
3e30148c3   David Howells   [PATCH] Keys: Mak...
42
43
44
45
46
   */
  static int request_key_auth_instantiate(struct key *key,
  					const void *data,
  					size_t datalen)
  {
b5f545c88   David Howells   [PATCH] keys: Per...
47
48
  	key->payload.data = (struct request_key_auth *) data;
  	return 0;
a8b17ed01   David Howells   KEYS: Do some sty...
49
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
50

3e30148c3   David Howells   [PATCH] Keys: Mak...
51
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
52
   * Describe an authorisation token.
3e30148c3   David Howells   [PATCH] Keys: Mak...
53
54
55
56
57
58
59
60
   */
  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);
78b7280cc   David Howells   KEYS: Improve /pr...
61
62
  	if (key_is_instantiated(key))
  		seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
a8b17ed01   David Howells   KEYS: Do some sty...
63
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
64

3e30148c3   David Howells   [PATCH] Keys: Mak...
65
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
66
   * Read the callout_info data (retrieves the callout information).
b5f545c88   David Howells   [PATCH] keys: Per...
67
68
69
70
71
72
73
74
   * - 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...
75
  	datalen = rka->callout_len;
b5f545c88   David Howells   [PATCH] keys: Per...
76
77
78
79
80
81
82
83
84
85
86
87
  	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;
a8b17ed01   David Howells   KEYS: Do some sty...
88
  }
b5f545c88   David Howells   [PATCH] keys: Per...
89

b5f545c88   David Howells   [PATCH] keys: Per...
90
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
91
92
93
   * Handle revocation of an authorisation token key.
   *
   * Called with the key sem write-locked.
04c567d93   David Howells   [PATCH] Keys: Fix...
94
95
96
97
98
99
   */
  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 ...
100
101
102
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
103
  	}
a8b17ed01   David Howells   KEYS: Do some sty...
104
  }
04c567d93   David Howells   [PATCH] Keys: Fix...
105

04c567d93   David Howells   [PATCH] Keys: Fix...
106
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
107
   * Destroy an instantiation authorisation token key.
3e30148c3   David Howells   [PATCH] Keys: Mak...
108
109
110
111
112
113
   */
  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 ...
114
115
116
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
117
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
118
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
119
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
120
  	kfree(rka->callout_info);
74fd92c51   David Howells   [PATCH] key: plug...
121
  	kfree(rka);
a8b17ed01   David Howells   KEYS: Do some sty...
122
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
123

3e30148c3   David Howells   [PATCH] Keys: Mak...
124
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
125
126
   * 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...
127
   */
4a38e122e   David Howells   keys: allow the c...
128
  struct key *request_key_auth_new(struct key *target, const void *callout_info,
8bbf4976b   David Howells   KEYS: Alter use o...
129
  				 size_t callout_len, struct key *dest_keyring)
3e30148c3   David Howells   [PATCH] Keys: Mak...
130
  {
b5f545c88   David Howells   [PATCH] keys: Per...
131
  	struct request_key_auth *rka, *irka;
d84f4f992   David Howells   CRED: Inaugurate ...
132
  	const struct cred *cred = current->cred;
b5f545c88   David Howells   [PATCH] keys: Per...
133
  	struct key *authkey = NULL;
3e30148c3   David Howells   [PATCH] Keys: Mak...
134
135
136
137
  	char desc[20];
  	int ret;
  
  	kenter("%d,", target->serial);
b5f545c88   David Howells   [PATCH] keys: Per...
138
139
140
141
142
143
  	/* 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...
144
  	rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
76181c134   David Howells   KEYS: Make reques...
145
146
147
148
149
  	if (!rka->callout_info) {
  		kleave(" = -ENOMEM");
  		kfree(rka);
  		return ERR_PTR(-ENOMEM);
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
150

b5f545c88   David Howells   [PATCH] keys: Per...
151
152
  	/* see if the calling process is already servicing the key request of
  	 * another process */
d84f4f992   David Howells   CRED: Inaugurate ...
153
  	if (cred->request_key_auth) {
b5f545c88   David Howells   [PATCH] keys: Per...
154
  		/* it is - use that instantiation context here too */
d84f4f992   David Howells   CRED: Inaugurate ...
155
  		down_read(&cred->request_key_auth->sem);
04c567d93   David Howells   [PATCH] Keys: Fix...
156
157
158
  
  		/* if the auth key has been revoked, then the key we're
  		 * servicing is already instantiated */
d84f4f992   David Howells   CRED: Inaugurate ...
159
  		if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
04c567d93   David Howells   [PATCH] Keys: Fix...
160
  			goto auth_key_revoked;
d84f4f992   David Howells   CRED: Inaugurate ...
161
162
  		irka = cred->request_key_auth->payload.data;
  		rka->cred = get_cred(irka->cred);
b5f545c88   David Howells   [PATCH] keys: Per...
163
  		rka->pid = irka->pid;
04c567d93   David Howells   [PATCH] Keys: Fix...
164

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

d84f4f992   David Howells   CRED: Inaugurate ...
193
  	kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
b5f545c88   David Howells   [PATCH] keys: Per...
194
  	return authkey;
04c567d93   David Howells   [PATCH] Keys: Fix...
195
  auth_key_revoked:
d84f4f992   David Howells   CRED: Inaugurate ...
196
  	up_read(&cred->request_key_auth->sem);
76181c134   David Howells   KEYS: Make reques...
197
  	kfree(rka->callout_info);
04c567d93   David Howells   [PATCH] Keys: Fix...
198
199
200
  	kfree(rka);
  	kleave("= -EKEYREVOKED");
  	return ERR_PTR(-EKEYREVOKED);
b5f545c88   David Howells   [PATCH] keys: Per...
201
202
203
204
205
  error_inst:
  	key_revoke(authkey);
  	key_put(authkey);
  error_alloc:
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
206
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
207
  	kfree(rka->callout_info);
b5f545c88   David Howells   [PATCH] keys: Per...
208
209
210
  	kfree(rka);
  	kleave("= %d", ret);
  	return ERR_PTR(ret);
a8b17ed01   David Howells   KEYS: Do some sty...
211
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
212

3e30148c3   David Howells   [PATCH] Keys: Mak...
213
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
214
   * See if an authorisation key is associated with a particular key.
b5f545c88   David Howells   [PATCH] keys: Per...
215
216
217
218
219
220
221
222
   */
  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;
a8b17ed01   David Howells   KEYS: Do some sty...
223
  }
b5f545c88   David Howells   [PATCH] keys: Per...
224

b5f545c88   David Howells   [PATCH] keys: Per...
225
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
226
227
   * Search the current process's keyrings for the authorisation key for
   * instantiation of a key.
3e30148c3   David Howells   [PATCH] Keys: Mak...
228
229
230
   */
  struct key *key_get_instantiation_authkey(key_serial_t target_id)
  {
d84f4f992   David Howells   CRED: Inaugurate ...
231
  	const struct cred *cred = current_cred();
b5f545c88   David Howells   [PATCH] keys: Per...
232
233
234
235
236
237
238
  	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 ...
239
  		cred);
b5f545c88   David Howells   [PATCH] keys: Per...
240
241
  
  	if (IS_ERR(authkey_ref)) {
e231c2ee6   David Howells   Convert ERR_PTR(P...
242
  		authkey = ERR_CAST(authkey_ref);
4d67431f8   David Howells   KEYS: Don't retur...
243
244
  		if (authkey == ERR_PTR(-EAGAIN))
  			authkey = ERR_PTR(-ENOKEY);
b5f545c88   David Howells   [PATCH] keys: Per...
245
246
  		goto error;
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
247

b5f545c88   David Howells   [PATCH] keys: Per...
248
249
250
251
252
  	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...
253

b5f545c88   David Howells   [PATCH] keys: Per...
254
255
  error:
  	return authkey;
a8b17ed01   David Howells   KEYS: Do some sty...
256
  }