Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/rxrpc/ar-security.c
15109 views
1
/* RxRPC security handling
2
*
3
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells ([email protected])
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/net.h>
14
#include <linux/skbuff.h>
15
#include <linux/udp.h>
16
#include <linux/crypto.h>
17
#include <net/sock.h>
18
#include <net/af_rxrpc.h>
19
#include <keys/rxrpc-type.h>
20
#include "ar-internal.h"
21
22
static LIST_HEAD(rxrpc_security_methods);
23
static DECLARE_RWSEM(rxrpc_security_sem);
24
25
/*
26
* get an RxRPC security module
27
*/
28
static struct rxrpc_security *rxrpc_security_get(struct rxrpc_security *sec)
29
{
30
return try_module_get(sec->owner) ? sec : NULL;
31
}
32
33
/*
34
* release an RxRPC security module
35
*/
36
static void rxrpc_security_put(struct rxrpc_security *sec)
37
{
38
module_put(sec->owner);
39
}
40
41
/*
42
* look up an rxrpc security module
43
*/
44
static struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
45
{
46
struct rxrpc_security *sec = NULL;
47
48
_enter("");
49
50
down_read(&rxrpc_security_sem);
51
52
list_for_each_entry(sec, &rxrpc_security_methods, link) {
53
if (sec->security_index == security_index) {
54
if (unlikely(!rxrpc_security_get(sec)))
55
break;
56
goto out;
57
}
58
}
59
60
sec = NULL;
61
out:
62
up_read(&rxrpc_security_sem);
63
_leave(" = %p [%s]", sec, sec ? sec->name : "");
64
return sec;
65
}
66
67
/**
68
* rxrpc_register_security - register an RxRPC security handler
69
* @sec: security module
70
*
71
* register an RxRPC security handler for use by RxRPC
72
*/
73
int rxrpc_register_security(struct rxrpc_security *sec)
74
{
75
struct rxrpc_security *psec;
76
int ret;
77
78
_enter("");
79
down_write(&rxrpc_security_sem);
80
81
ret = -EEXIST;
82
list_for_each_entry(psec, &rxrpc_security_methods, link) {
83
if (psec->security_index == sec->security_index)
84
goto out;
85
}
86
87
list_add(&sec->link, &rxrpc_security_methods);
88
89
printk(KERN_NOTICE "RxRPC: Registered security type %d '%s'\n",
90
sec->security_index, sec->name);
91
ret = 0;
92
93
out:
94
up_write(&rxrpc_security_sem);
95
_leave(" = %d", ret);
96
return ret;
97
}
98
99
EXPORT_SYMBOL_GPL(rxrpc_register_security);
100
101
/**
102
* rxrpc_unregister_security - unregister an RxRPC security handler
103
* @sec: security module
104
*
105
* unregister an RxRPC security handler
106
*/
107
void rxrpc_unregister_security(struct rxrpc_security *sec)
108
{
109
110
_enter("");
111
down_write(&rxrpc_security_sem);
112
list_del_init(&sec->link);
113
up_write(&rxrpc_security_sem);
114
115
printk(KERN_NOTICE "RxRPC: Unregistered security type %d '%s'\n",
116
sec->security_index, sec->name);
117
}
118
119
EXPORT_SYMBOL_GPL(rxrpc_unregister_security);
120
121
/*
122
* initialise the security on a client connection
123
*/
124
int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
125
{
126
struct rxrpc_key_token *token;
127
struct rxrpc_security *sec;
128
struct key *key = conn->key;
129
int ret;
130
131
_enter("{%d},{%x}", conn->debug_id, key_serial(key));
132
133
if (!key)
134
return 0;
135
136
ret = key_validate(key);
137
if (ret < 0)
138
return ret;
139
140
if (!key->payload.data)
141
return -EKEYREJECTED;
142
token = key->payload.data;
143
144
sec = rxrpc_security_lookup(token->security_index);
145
if (!sec)
146
return -EKEYREJECTED;
147
conn->security = sec;
148
149
ret = conn->security->init_connection_security(conn);
150
if (ret < 0) {
151
rxrpc_security_put(conn->security);
152
conn->security = NULL;
153
return ret;
154
}
155
156
_leave(" = 0");
157
return 0;
158
}
159
160
/*
161
* initialise the security on a server connection
162
*/
163
int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
164
{
165
struct rxrpc_security *sec;
166
struct rxrpc_local *local = conn->trans->local;
167
struct rxrpc_sock *rx;
168
struct key *key;
169
key_ref_t kref;
170
char kdesc[5+1+3+1];
171
172
_enter("");
173
174
sprintf(kdesc, "%u:%u", ntohs(conn->service_id), conn->security_ix);
175
176
sec = rxrpc_security_lookup(conn->security_ix);
177
if (!sec) {
178
_leave(" = -ENOKEY [lookup]");
179
return -ENOKEY;
180
}
181
182
/* find the service */
183
read_lock_bh(&local->services_lock);
184
list_for_each_entry(rx, &local->services, listen_link) {
185
if (rx->service_id == conn->service_id)
186
goto found_service;
187
}
188
189
/* the service appears to have died */
190
read_unlock_bh(&local->services_lock);
191
rxrpc_security_put(sec);
192
_leave(" = -ENOENT");
193
return -ENOENT;
194
195
found_service:
196
if (!rx->securities) {
197
read_unlock_bh(&local->services_lock);
198
rxrpc_security_put(sec);
199
_leave(" = -ENOKEY");
200
return -ENOKEY;
201
}
202
203
/* look through the service's keyring */
204
kref = keyring_search(make_key_ref(rx->securities, 1UL),
205
&key_type_rxrpc_s, kdesc);
206
if (IS_ERR(kref)) {
207
read_unlock_bh(&local->services_lock);
208
rxrpc_security_put(sec);
209
_leave(" = %ld [search]", PTR_ERR(kref));
210
return PTR_ERR(kref);
211
}
212
213
key = key_ref_to_ptr(kref);
214
read_unlock_bh(&local->services_lock);
215
216
conn->server_key = key;
217
conn->security = sec;
218
219
_leave(" = 0");
220
return 0;
221
}
222
223
/*
224
* secure a packet prior to transmission
225
*/
226
int rxrpc_secure_packet(const struct rxrpc_call *call,
227
struct sk_buff *skb,
228
size_t data_size,
229
void *sechdr)
230
{
231
if (call->conn->security)
232
return call->conn->security->secure_packet(
233
call, skb, data_size, sechdr);
234
return 0;
235
}
236
237
/*
238
* secure a packet prior to transmission
239
*/
240
int rxrpc_verify_packet(const struct rxrpc_call *call, struct sk_buff *skb,
241
u32 *_abort_code)
242
{
243
if (call->conn->security)
244
return call->conn->security->verify_packet(
245
call, skb, _abort_code);
246
return 0;
247
}
248
249
/*
250
* clear connection security
251
*/
252
void rxrpc_clear_conn_security(struct rxrpc_connection *conn)
253
{
254
_enter("{%d}", conn->debug_id);
255
256
if (conn->security) {
257
conn->security->clear(conn);
258
rxrpc_security_put(conn->security);
259
conn->security = NULL;
260
}
261
262
key_put(conn->key);
263
key_put(conn->server_key);
264
}
265
266