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  * See Documentation/keys-request-key.txt
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 <asm/uaccess.h>
19 #include "internal.h"
20 
21 static int request_key_auth_instantiate(struct key *, const void *, size_t);
22 static void request_key_auth_describe(const struct key *, struct seq_file *);
23 static void request_key_auth_destroy(struct key *);
24 static long request_key_auth_read(const struct key *, char __user *, size_t);
25 
26 /*
27  * the request-key authorisation key type definition
28  */
29 struct key_type key_type_request_key_auth = {
30 	.name		= ".request_key_auth",
31 	.def_datalen	= sizeof(struct request_key_auth),
32 	.instantiate	= request_key_auth_instantiate,
33 	.describe	= request_key_auth_describe,
34 	.destroy	= request_key_auth_destroy,
35 	.read		= request_key_auth_read,
36 };
37 
38 /*****************************************************************************/
39 /*
40  * instantiate a request-key authorisation key
41  */
42 static int request_key_auth_instantiate(struct key *key,
43 					const void *data,
44 					size_t datalen)
45 {
46 	key->payload.data = (struct request_key_auth *) data;
47 	return 0;
48 
49 } /* end request_key_auth_instantiate() */
50 
51 /*****************************************************************************/
52 /*
53  * reading a request-key authorisation key retrieves the callout information
54  */
55 static void request_key_auth_describe(const struct key *key,
56 				      struct seq_file *m)
57 {
58 	struct request_key_auth *rka = key->payload.data;
59 
60 	seq_puts(m, "key:");
61 	seq_puts(m, key->description);
62 	seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
63 
64 } /* end request_key_auth_describe() */
65 
66 /*****************************************************************************/
67 /*
68  * read the callout_info data
69  * - the key's semaphore is read-locked
70  */
71 static long request_key_auth_read(const struct key *key,
72 				  char __user *buffer, size_t buflen)
73 {
74 	struct request_key_auth *rka = key->payload.data;
75 	size_t datalen;
76 	long ret;
77 
78 	datalen = strlen(rka->callout_info);
79 	ret = datalen;
80 
81 	/* we can return the data as is */
82 	if (buffer && buflen > 0) {
83 		if (buflen > datalen)
84 			buflen = datalen;
85 
86 		if (copy_to_user(buffer, rka->callout_info, buflen) != 0)
87 			ret = -EFAULT;
88 	}
89 
90 	return ret;
91 
92 } /* end request_key_auth_read() */
93 
94 /*****************************************************************************/
95 /*
96  * destroy an instantiation authorisation token key
97  */
98 static void request_key_auth_destroy(struct key *key)
99 {
100 	struct request_key_auth *rka = key->payload.data;
101 
102 	kenter("{%d}", key->serial);
103 
104 	key_put(rka->target_key);
105 	kfree(rka);
106 
107 } /* end request_key_auth_destroy() */
108 
109 /*****************************************************************************/
110 /*
111  * create an authorisation token for /sbin/request-key or whoever to gain
112  * access to the caller's security data
113  */
114 struct key *request_key_auth_new(struct key *target, const char *callout_info)
115 {
116 	struct request_key_auth *rka, *irka;
117 	struct key *authkey = NULL;
118 	char desc[20];
119 	int ret;
120 
121 	kenter("%d,", target->serial);
122 
123 	/* allocate a auth record */
124 	rka = kmalloc(sizeof(*rka), GFP_KERNEL);
125 	if (!rka) {
126 		kleave(" = -ENOMEM");
127 		return ERR_PTR(-ENOMEM);
128 	}
129 
130 	/* see if the calling process is already servicing the key request of
131 	 * another process */
132 	if (current->request_key_auth) {
133 		/* it is - use that instantiation context here too */
134 		irka = current->request_key_auth->payload.data;
135 		rka->context = irka->context;
136 		rka->pid = irka->pid;
137 	}
138 	else {
139 		/* it isn't - use this process as the context */
140 		rka->context = current;
141 		rka->pid = current->pid;
142 	}
143 
144 	rka->target_key = key_get(target);
145 	rka->callout_info = callout_info;
146 
147 	/* allocate the auth key */
148 	sprintf(desc, "%x", target->serial);
149 
150 	authkey = key_alloc(&key_type_request_key_auth, desc,
151 			    current->fsuid, current->fsgid,
152 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
153 			    KEY_USR_VIEW, 1);
154 	if (IS_ERR(authkey)) {
155 		ret = PTR_ERR(authkey);
156 		goto error_alloc;
157 	}
158 
159 	/* construct and attach to the keyring */
160 	ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
161 	if (ret < 0)
162 		goto error_inst;
163 
164 	kleave(" = {%d})", authkey->serial);
165 	return authkey;
166 
167 error_inst:
168 	key_revoke(authkey);
169 	key_put(authkey);
170 error_alloc:
171 	key_put(rka->target_key);
172 	kfree(rka);
173 	kleave("= %d", ret);
174 	return ERR_PTR(ret);
175 
176 } /* end request_key_auth_new() */
177 
178 /*****************************************************************************/
179 /*
180  * see if an authorisation key is associated with a particular key
181  */
182 static int key_get_instantiation_authkey_match(const struct key *key,
183 					       const void *_id)
184 {
185 	struct request_key_auth *rka = key->payload.data;
186 	key_serial_t id = (key_serial_t)(unsigned long) _id;
187 
188 	return rka->target_key->serial == id;
189 
190 } /* end key_get_instantiation_authkey_match() */
191 
192 /*****************************************************************************/
193 /*
194  * get the authorisation key for instantiation of a specific key if attached to
195  * the current process's keyrings
196  * - this key is inserted into a keyring and that is set as /sbin/request-key's
197  *   session keyring
198  * - a target_id of zero specifies any valid token
199  */
200 struct key *key_get_instantiation_authkey(key_serial_t target_id)
201 {
202 	struct key *authkey;
203 	key_ref_t authkey_ref;
204 
205 	authkey_ref = search_process_keyrings(
206 		&key_type_request_key_auth,
207 		(void *) (unsigned long) target_id,
208 		key_get_instantiation_authkey_match,
209 		current);
210 
211 	if (IS_ERR(authkey_ref)) {
212 		authkey = ERR_PTR(PTR_ERR(authkey_ref));
213 		goto error;
214 	}
215 
216 	authkey = key_ref_to_ptr(authkey_ref);
217 	if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {
218 		key_put(authkey);
219 		authkey = ERR_PTR(-EKEYREVOKED);
220 	}
221 
222 error:
223 	return authkey;
224 
225 } /* end key_get_instantiation_authkey() */
226