blob: f80a501e27f19d7e0e5cdd121647d93b719c418b [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.
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
18static int request_key_auth_instantiate(struct key *, const void *, size_t);
19static void request_key_auth_describe(const struct key *, struct seq_file *);
20static void request_key_auth_destroy(struct key *);
21
22/*
23 * the request-key authorisation key type definition
24 */
25struct 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 */
37static 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 */
77static 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 */
92static 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);
David Howells74fd92c2005-10-07 15:01:09 +010099 kfree(rka);
David Howells3e301482005-06-23 22:00:56 -0700100
101} /* end request_key_auth_destroy() */
102
103/*****************************************************************************/
104/*
105 * create a session keyring to be for the invokation of /sbin/request-key and
106 * stick an authorisation token in it
107 */
108struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
109{
110 struct key *keyring, *rkakey = NULL;
111 char desc[20];
112 int ret;
113
114 kenter("%d,", target->serial);
115
116 /* allocate a new session keyring */
117 sprintf(desc, "_req.%u", target->serial);
118
119 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
120 if (IS_ERR(keyring)) {
121 kleave("= %ld", PTR_ERR(keyring));
122 return keyring;
123 }
124
125 /* allocate the auth key */
126 sprintf(desc, "%x", target->serial);
127
128 rkakey = key_alloc(&key_type_request_key_auth, desc,
129 current->fsuid, current->fsgid,
David Howells664cceb2005-09-28 17:03:15 +0100130 KEY_POS_VIEW | KEY_USR_VIEW, 1);
David Howells3e301482005-06-23 22:00:56 -0700131 if (IS_ERR(rkakey)) {
132 key_put(keyring);
133 kleave("= %ld", PTR_ERR(rkakey));
134 return rkakey;
135 }
136
137 /* construct and attach to the keyring */
138 ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
139 if (ret < 0) {
140 key_revoke(rkakey);
141 key_put(rkakey);
142 key_put(keyring);
143 kleave("= %d", ret);
144 return ERR_PTR(ret);
145 }
146
147 *_rkakey = rkakey;
148 kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
149 return keyring;
150
151} /* end request_key_auth_new() */
152
153/*****************************************************************************/
154/*
155 * get the authorisation key for instantiation of a specific key if attached to
156 * the current process's keyrings
157 * - this key is inserted into a keyring and that is set as /sbin/request-key's
158 * session keyring
159 * - a target_id of zero specifies any valid token
160 */
161struct key *key_get_instantiation_authkey(key_serial_t target_id)
162{
163 struct task_struct *tsk = current;
164 struct key *instkey;
165
166 /* we must have our own personal session keyring */
167 if (!tsk->signal->session_keyring)
168 return ERR_PTR(-EACCES);
169
170 /* and it must contain a suitable request authorisation key
171 * - lock RCU against session keyring changing
172 */
173 rcu_read_lock();
174
175 instkey = keyring_search_instkey(
176 rcu_dereference(tsk->signal->session_keyring), target_id);
177
178 rcu_read_unlock();
179 return instkey;
180
181} /* end key_get_instantiation_authkey() */