Blame view

security/keys/request_key_auth.c 6.95 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>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
19
  #include <linux/uaccess.h>
3e30148c3   David Howells   [PATCH] Keys: Mak...
20
  #include "internal.h"
d0a059cac   David Howells   KEYS: Search for ...
21
  #include <keys/user-type.h>
3e30148c3   David Howells   [PATCH] Keys: Mak...
22

f1dcde91a   David Howells   KEYS: request_key...
23
24
  static int request_key_auth_preparse(struct key_preparsed_payload *);
  static void request_key_auth_free_preparse(struct key_preparsed_payload *);
cf7f601c0   David Howells   KEYS: Add payload...
25
26
  static int request_key_auth_instantiate(struct key *,
  					struct key_preparsed_payload *);
3e30148c3   David Howells   [PATCH] Keys: Mak...
27
  static void request_key_auth_describe(const struct key *, struct seq_file *);
04c567d93   David Howells   [PATCH] Keys: Fix...
28
  static void request_key_auth_revoke(struct key *);
3e30148c3   David Howells   [PATCH] Keys: Mak...
29
  static void request_key_auth_destroy(struct key *);
b5f545c88   David Howells   [PATCH] keys: Per...
30
  static long request_key_auth_read(const struct key *, char __user *, size_t);
3e30148c3   David Howells   [PATCH] Keys: Mak...
31
32
  
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
33
   * The request-key authorisation key type definition.
3e30148c3   David Howells   [PATCH] Keys: Mak...
34
35
36
37
   */
  struct key_type key_type_request_key_auth = {
  	.name		= ".request_key_auth",
  	.def_datalen	= sizeof(struct request_key_auth),
f1dcde91a   David Howells   KEYS: request_key...
38
39
  	.preparse	= request_key_auth_preparse,
  	.free_preparse	= request_key_auth_free_preparse,
3e30148c3   David Howells   [PATCH] Keys: Mak...
40
41
  	.instantiate	= request_key_auth_instantiate,
  	.describe	= request_key_auth_describe,
04c567d93   David Howells   [PATCH] Keys: Fix...
42
  	.revoke		= request_key_auth_revoke,
3e30148c3   David Howells   [PATCH] Keys: Mak...
43
  	.destroy	= request_key_auth_destroy,
b5f545c88   David Howells   [PATCH] keys: Per...
44
  	.read		= request_key_auth_read,
3e30148c3   David Howells   [PATCH] Keys: Mak...
45
  };
8da79b643   David Howells   KEYS: Fix missing...
46
  static int request_key_auth_preparse(struct key_preparsed_payload *prep)
f1dcde91a   David Howells   KEYS: request_key...
47
48
49
  {
  	return 0;
  }
8da79b643   David Howells   KEYS: Fix missing...
50
  static void request_key_auth_free_preparse(struct key_preparsed_payload *prep)
f1dcde91a   David Howells   KEYS: request_key...
51
52
  {
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
53
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
54
   * Instantiate a request-key authorisation key.
3e30148c3   David Howells   [PATCH] Keys: Mak...
55
56
   */
  static int request_key_auth_instantiate(struct key *key,
cf7f601c0   David Howells   KEYS: Add payload...
57
  					struct key_preparsed_payload *prep)
3e30148c3   David Howells   [PATCH] Keys: Mak...
58
  {
146aa8b14   David Howells   KEYS: Merge the t...
59
  	key->payload.data[0] = (struct request_key_auth *)prep->data;
b5f545c88   David Howells   [PATCH] keys: Per...
60
  	return 0;
a8b17ed01   David Howells   KEYS: Do some sty...
61
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
62

3e30148c3   David Howells   [PATCH] Keys: Mak...
63
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
64
   * Describe an authorisation token.
3e30148c3   David Howells   [PATCH] Keys: Mak...
65
66
67
68
   */
  static void request_key_auth_describe(const struct key *key,
  				      struct seq_file *m)
  {
146aa8b14   David Howells   KEYS: Merge the t...
69
  	struct request_key_auth *rka = key->payload.data[0];
3e30148c3   David Howells   [PATCH] Keys: Mak...
70
71
72
  
  	seq_puts(m, "key:");
  	seq_puts(m, key->description);
78b7280cc   David Howells   KEYS: Improve /pr...
73
74
  	if (key_is_instantiated(key))
  		seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
a8b17ed01   David Howells   KEYS: Do some sty...
75
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
76

3e30148c3   David Howells   [PATCH] Keys: Mak...
77
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
78
   * Read the callout_info data (retrieves the callout information).
b5f545c88   David Howells   [PATCH] keys: Per...
79
80
81
82
83
   * - the key's semaphore is read-locked
   */
  static long request_key_auth_read(const struct key *key,
  				  char __user *buffer, size_t buflen)
  {
146aa8b14   David Howells   KEYS: Merge the t...
84
  	struct request_key_auth *rka = key->payload.data[0];
b5f545c88   David Howells   [PATCH] keys: Per...
85
86
  	size_t datalen;
  	long ret;
4a38e122e   David Howells   keys: allow the c...
87
  	datalen = rka->callout_len;
b5f545c88   David Howells   [PATCH] keys: Per...
88
89
90
91
92
93
94
95
96
97
98
99
  	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...
100
  }
b5f545c88   David Howells   [PATCH] keys: Per...
101

b5f545c88   David Howells   [PATCH] keys: Per...
102
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
103
104
105
   * Handle revocation of an authorisation token key.
   *
   * Called with the key sem write-locked.
04c567d93   David Howells   [PATCH] Keys: Fix...
106
107
108
   */
  static void request_key_auth_revoke(struct key *key)
  {
146aa8b14   David Howells   KEYS: Merge the t...
109
  	struct request_key_auth *rka = key->payload.data[0];
04c567d93   David Howells   [PATCH] Keys: Fix...
110
111
  
  	kenter("{%d}", key->serial);
d84f4f992   David Howells   CRED: Inaugurate ...
112
113
114
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
115
  	}
a8b17ed01   David Howells   KEYS: Do some sty...
116
  }
04c567d93   David Howells   [PATCH] Keys: Fix...
117

04c567d93   David Howells   [PATCH] Keys: Fix...
118
  /*
973c9f4f4   David Howells   KEYS: Fix up comm...
119
   * Destroy an instantiation authorisation token key.
3e30148c3   David Howells   [PATCH] Keys: Mak...
120
121
122
   */
  static void request_key_auth_destroy(struct key *key)
  {
146aa8b14   David Howells   KEYS: Merge the t...
123
  	struct request_key_auth *rka = key->payload.data[0];
3e30148c3   David Howells   [PATCH] Keys: Mak...
124
125
  
  	kenter("{%d}", key->serial);
d84f4f992   David Howells   CRED: Inaugurate ...
126
127
128
  	if (rka->cred) {
  		put_cred(rka->cred);
  		rka->cred = NULL;
04c567d93   David Howells   [PATCH] Keys: Fix...
129
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
130
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
131
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
132
  	kfree(rka->callout_info);
74fd92c51   David Howells   [PATCH] key: plug...
133
  	kfree(rka);
a8b17ed01   David Howells   KEYS: Do some sty...
134
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
135

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

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

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

fff292914   Elena Reshetova   security, keys: c...
205
  	kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage));
b5f545c88   David Howells   [PATCH] keys: Per...
206
  	return authkey;
04c567d93   David Howells   [PATCH] Keys: Fix...
207
  auth_key_revoked:
d84f4f992   David Howells   CRED: Inaugurate ...
208
  	up_read(&cred->request_key_auth->sem);
76181c134   David Howells   KEYS: Make reques...
209
  	kfree(rka->callout_info);
04c567d93   David Howells   [PATCH] Keys: Fix...
210
211
212
  	kfree(rka);
  	kleave("= -EKEYREVOKED");
  	return ERR_PTR(-EKEYREVOKED);
b5f545c88   David Howells   [PATCH] keys: Per...
213
214
215
216
217
  error_inst:
  	key_revoke(authkey);
  	key_put(authkey);
  error_alloc:
  	key_put(rka->target_key);
8bbf4976b   David Howells   KEYS: Alter use o...
218
  	key_put(rka->dest_keyring);
76181c134   David Howells   KEYS: Make reques...
219
  	kfree(rka->callout_info);
b5f545c88   David Howells   [PATCH] keys: Per...
220
221
222
  	kfree(rka);
  	kleave("= %d", ret);
  	return ERR_PTR(ret);
a8b17ed01   David Howells   KEYS: Do some sty...
223
  }
3e30148c3   David Howells   [PATCH] Keys: Mak...
224

3e30148c3   David Howells   [PATCH] Keys: Mak...
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)
  {
d0a059cac   David Howells   KEYS: Search for ...
231
  	char description[16];
4bdf0bc30   David Howells   KEYS: Introduce a...
232
233
  	struct keyring_search_context ctx = {
  		.index_key.type		= &key_type_request_key_auth,
d0a059cac   David Howells   KEYS: Search for ...
234
  		.index_key.description	= description,
4bdf0bc30   David Howells   KEYS: Introduce a...
235
  		.cred			= current_cred(),
c06cfb08b   David Howells   KEYS: Remove key_...
236
  		.match_data.cmp		= key_default_cmp,
462919591   David Howells   KEYS: Preparse ma...
237
238
  		.match_data.raw_data	= description,
  		.match_data.lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
054f6180d   David Howells   KEYS: Simplify KE...
239
  		.flags			= KEYRING_SEARCH_DO_STATE_CHECK,
4bdf0bc30   David Howells   KEYS: Introduce a...
240
  	};
b5f545c88   David Howells   [PATCH] keys: Per...
241
242
  	struct key *authkey;
  	key_ref_t authkey_ref;
d0a059cac   David Howells   KEYS: Search for ...
243
  	sprintf(description, "%x", target_id);
4bdf0bc30   David Howells   KEYS: Introduce a...
244
  	authkey_ref = search_process_keyrings(&ctx);
b5f545c88   David Howells   [PATCH] keys: Per...
245
246
  
  	if (IS_ERR(authkey_ref)) {
e231c2ee6   David Howells   Convert ERR_PTR(P...
247
  		authkey = ERR_CAST(authkey_ref);
4d67431f8   David Howells   KEYS: Don't retur...
248
249
  		if (authkey == ERR_PTR(-EAGAIN))
  			authkey = ERR_PTR(-ENOKEY);
b5f545c88   David Howells   [PATCH] keys: Per...
250
251
  		goto error;
  	}
3e30148c3   David Howells   [PATCH] Keys: Mak...
252

b5f545c88   David Howells   [PATCH] keys: Per...
253
254
255
256
257
  	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...
258

b5f545c88   David Howells   [PATCH] keys: Per...
259
260
  error:
  	return authkey;
a8b17ed01   David Howells   KEYS: Do some sty...
261
  }