blob: cce6ba6b032352aa4cd182db51a521242eea814a [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>
David Howellsb5f545c2006-01-08 01:02:47 -080018#include <asm/uaccess.h>
David Howells3e301482005-06-23 22:00:56 -070019#include "internal.h"
20
21static int request_key_auth_instantiate(struct key *, const void *, size_t);
22static void request_key_auth_describe(const struct key *, struct seq_file *);
23static void request_key_auth_destroy(struct key *);
David Howellsb5f545c2006-01-08 01:02:47 -080024static long request_key_auth_read(const struct key *, char __user *, size_t);
David Howells3e301482005-06-23 22:00:56 -070025
26/*
27 * the request-key authorisation key type definition
28 */
29struct 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,
David Howellsb5f545c2006-01-08 01:02:47 -080035 .read = request_key_auth_read,
David Howells3e301482005-06-23 22:00:56 -070036};
37
38/*****************************************************************************/
39/*
David Howellsb5f545c2006-01-08 01:02:47 -080040 * instantiate a request-key authorisation key
David Howells3e301482005-06-23 22:00:56 -070041 */
42static int request_key_auth_instantiate(struct key *key,
43 const void *data,
44 size_t datalen)
45{
David Howellsb5f545c2006-01-08 01:02:47 -080046 key->payload.data = (struct request_key_auth *) data;
47 return 0;
David Howells3e301482005-06-23 22:00:56 -070048
49} /* end request_key_auth_instantiate() */
50
51/*****************************************************************************/
52/*
David Howellsb5f545c2006-01-08 01:02:47 -080053 * reading a request-key authorisation key retrieves the callout information
David Howells3e301482005-06-23 22:00:56 -070054 */
55static 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);
David Howellsb5f545c2006-01-08 01:02:47 -080062 seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
David Howells3e301482005-06-23 22:00:56 -070063
64} /* end request_key_auth_describe() */
65
66/*****************************************************************************/
67/*
David Howellsb5f545c2006-01-08 01:02:47 -080068 * read the callout_info data
69 * - the key's semaphore is read-locked
70 */
71static 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/*
David Howells3e301482005-06-23 22:00:56 -070096 * destroy an instantiation authorisation token key
97 */
98static 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);
David Howells74fd92c2005-10-07 15:01:09 +0100105 kfree(rka);
David Howells3e301482005-06-23 22:00:56 -0700106
107} /* end request_key_auth_destroy() */
108
109/*****************************************************************************/
110/*
David Howellsb5f545c2006-01-08 01:02:47 -0800111 * create an authorisation token for /sbin/request-key or whoever to gain
112 * access to the caller's security data
David Howells3e301482005-06-23 22:00:56 -0700113 */
David Howellsb5f545c2006-01-08 01:02:47 -0800114struct key *request_key_auth_new(struct key *target, const char *callout_info)
David Howells3e301482005-06-23 22:00:56 -0700115{
David Howellsb5f545c2006-01-08 01:02:47 -0800116 struct request_key_auth *rka, *irka;
117 struct key *authkey = NULL;
David Howells3e301482005-06-23 22:00:56 -0700118 char desc[20];
119 int ret;
120
121 kenter("%d,", target->serial);
122
David Howellsb5f545c2006-01-08 01:02:47 -0800123 /* allocate a auth record */
124 rka = kmalloc(sizeof(*rka), GFP_KERNEL);
125 if (!rka) {
126 kleave(" = -ENOMEM");
127 return ERR_PTR(-ENOMEM);
David Howells3e301482005-06-23 22:00:56 -0700128 }
129
David Howellsb5f545c2006-01-08 01:02:47 -0800130 /* 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
David Howells3e301482005-06-23 22:00:56 -0700147 /* allocate the auth key */
148 sprintf(desc, "%x", target->serial);
149
David Howellsb5f545c2006-01-08 01:02:47 -0800150 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;
David Howells3e301482005-06-23 22:00:56 -0700157 }
158
159 /* construct and attach to the keyring */
David Howellsb5f545c2006-01-08 01:02:47 -0800160 ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
161 if (ret < 0)
162 goto error_inst;
David Howells3e301482005-06-23 22:00:56 -0700163
David Howellsb5f545c2006-01-08 01:02:47 -0800164 kleave(" = {%d})", authkey->serial);
165 return authkey;
166
167error_inst:
168 key_revoke(authkey);
169 key_put(authkey);
170error_alloc:
171 key_put(rka->target_key);
172 kfree(rka);
173 kleave("= %d", ret);
174 return ERR_PTR(ret);
David Howells3e301482005-06-23 22:00:56 -0700175
176} /* end request_key_auth_new() */
177
178/*****************************************************************************/
179/*
David Howellsb5f545c2006-01-08 01:02:47 -0800180 * see if an authorisation key is associated with a particular key
181 */
182static 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/*
David Howells3e301482005-06-23 22:00:56 -0700194 * 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 */
200struct key *key_get_instantiation_authkey(key_serial_t target_id)
201{
David Howellsb5f545c2006-01-08 01:02:47 -0800202 struct key *authkey;
203 key_ref_t authkey_ref;
David Howells3e301482005-06-23 22:00:56 -0700204
David Howellsb5f545c2006-01-08 01:02:47 -0800205 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);
David Howells3e301482005-06-23 22:00:56 -0700210
David Howellsb5f545c2006-01-08 01:02:47 -0800211 if (IS_ERR(authkey_ref)) {
212 authkey = ERR_PTR(PTR_ERR(authkey_ref));
213 goto error;
214 }
David Howells3e301482005-06-23 22:00:56 -0700215
David Howellsb5f545c2006-01-08 01:02:47 -0800216 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 }
David Howells3e301482005-06-23 22:00:56 -0700221
David Howellsb5f545c2006-01-08 01:02:47 -0800222error:
223 return authkey;
David Howells3e301482005-06-23 22:00:56 -0700224
225} /* end key_get_instantiation_authkey() */