xref: /linux/security/keys/request_key_auth.c (revision d67b569f5f620c0fb95d5212642746b7ba9d29e4)
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,
129 			   KEY_USR_VIEW, 1);
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() */
181