blob: a8e4069d48cbf93d91b6bcab3ee173549139221c [file] [log] [blame]
David Howells3e301482005-06-23 22:00:56 -07001/* 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.
David Howellsf1a9bad2005-10-07 15:04:52 +010010 *
11 * See Documentation/keys-request-key.txt
David Howells3e301482005-06-23 22:00:56 -070012 */
13
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/err.h>
17#include <linux/seq_file.h>
18#include "internal.h"
19
20static int request_key_auth_instantiate(struct key *, const void *, size_t);
21static void request_key_auth_describe(const struct key *, struct seq_file *);
22static void request_key_auth_destroy(struct key *);
23
24/*
25 * the request-key authorisation key type definition
26 */
27struct key_type key_type_request_key_auth = {
28 .name = ".request_key_auth",
29 .def_datalen = sizeof(struct request_key_auth),
30 .instantiate = request_key_auth_instantiate,
31 .describe = request_key_auth_describe,
32 .destroy = request_key_auth_destroy,
33};
34
35/*****************************************************************************/
36/*
37 * instantiate a request-key authorisation record
38 */
39static int request_key_auth_instantiate(struct key *key,
40 const void *data,
41 size_t datalen)
42{
43 struct request_key_auth *rka, *irka;
44 struct key *instkey;
45 int ret;
46
47 ret = -ENOMEM;
48 rka = kmalloc(sizeof(*rka), GFP_KERNEL);
49 if (rka) {
50 /* see if the calling process is already servicing the key
51 * request of another process */
52 instkey = key_get_instantiation_authkey(0);
53 if (!IS_ERR(instkey)) {
54 /* it is - use that instantiation context here too */
55 irka = instkey->payload.data;
56 rka->context = irka->context;
57 rka->pid = irka->pid;
58 key_put(instkey);
59 }
60 else {
61 /* it isn't - use this process as the context */
62 rka->context = current;
63 rka->pid = current->pid;
64 }
65
66 rka->target_key = key_get((struct key *) data);
67 key->payload.data = rka;
68 ret = 0;
69 }
70
71 return ret;
72
73} /* end request_key_auth_instantiate() */
74
75/*****************************************************************************/
76/*
77 *
78 */
79static void request_key_auth_describe(const struct key *key,
80 struct seq_file *m)
81{
82 struct request_key_auth *rka = key->payload.data;
83
84 seq_puts(m, "key:");
85 seq_puts(m, key->description);
86 seq_printf(m, " pid:%d", rka->pid);
87
88} /* end request_key_auth_describe() */
89
90/*****************************************************************************/
91/*
92 * destroy an instantiation authorisation token key
93 */
94static void request_key_auth_destroy(struct key *key)
95{
96 struct request_key_auth *rka = key->payload.data;
97
98 kenter("{%d}", key->serial);
99
100 key_put(rka->target_key);
David Howells74fd92c2005-10-07 15:01:09 +0100101 kfree(rka);
David Howells3e301482005-06-23 22:00:56 -0700102
103} /* end request_key_auth_destroy() */
104
105/*****************************************************************************/
106/*
107 * create a session keyring to be for the invokation of /sbin/request-key and
108 * stick an authorisation token in it
109 */
110struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
111{
112 struct key *keyring, *rkakey = NULL;
113 char desc[20];
114 int ret;
115
116 kenter("%d,", target->serial);
117
118 /* allocate a new session keyring */
119 sprintf(desc, "_req.%u", target->serial);
120
121 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
122 if (IS_ERR(keyring)) {
123 kleave("= %ld", PTR_ERR(keyring));
124 return keyring;
125 }
126
127 /* allocate the auth key */
128 sprintf(desc, "%x", target->serial);
129
130 rkakey = key_alloc(&key_type_request_key_auth, desc,
131 current->fsuid, current->fsgid,
David Howells664cceb2005-09-28 17:03:15 +0100132 KEY_POS_VIEW | KEY_USR_VIEW, 1);
David Howells3e301482005-06-23 22:00:56 -0700133 if (IS_ERR(rkakey)) {
134 key_put(keyring);
135 kleave("= %ld", PTR_ERR(rkakey));
136 return rkakey;
137 }
138
139 /* construct and attach to the keyring */
140 ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
141 if (ret < 0) {
142 key_revoke(rkakey);
143 key_put(rkakey);
144 key_put(keyring);
145 kleave("= %d", ret);
146 return ERR_PTR(ret);
147 }
148
149 *_rkakey = rkakey;
150 kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
151 return keyring;
152
153} /* end request_key_auth_new() */
154
155/*****************************************************************************/
156/*
157 * get the authorisation key for instantiation of a specific key if attached to
158 * the current process's keyrings
159 * - this key is inserted into a keyring and that is set as /sbin/request-key's
160 * session keyring
161 * - a target_id of zero specifies any valid token
162 */
163struct key *key_get_instantiation_authkey(key_serial_t target_id)
164{
165 struct task_struct *tsk = current;
166 struct key *instkey;
167
168 /* we must have our own personal session keyring */
169 if (!tsk->signal->session_keyring)
170 return ERR_PTR(-EACCES);
171
172 /* and it must contain a suitable request authorisation key
173 * - lock RCU against session keyring changing
174 */
175 rcu_read_lock();
176
177 instkey = keyring_search_instkey(
178 rcu_dereference(tsk->signal->session_keyring), target_id);
179
180 rcu_read_unlock();
181 return instkey;
182
183} /* end key_get_instantiation_authkey() */