]> asedeno.scripts.mit.edu Git - linux.git/blob - net/rxrpc/security.c
drm/modes: parse_cmdline: Rework drm_mode_parse_cmdline_options()
[linux.git] / net / rxrpc / security.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* RxRPC security handling
3  *
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7
8 #include <linux/module.h>
9 #include <linux/net.h>
10 #include <linux/skbuff.h>
11 #include <linux/udp.h>
12 #include <linux/crypto.h>
13 #include <net/sock.h>
14 #include <net/af_rxrpc.h>
15 #include <keys/rxrpc-type.h>
16 #include "ar-internal.h"
17
18 static const struct rxrpc_security *rxrpc_security_types[] = {
19         [RXRPC_SECURITY_NONE]   = &rxrpc_no_security,
20 #ifdef CONFIG_RXKAD
21         [RXRPC_SECURITY_RXKAD]  = &rxkad,
22 #endif
23 };
24
25 int __init rxrpc_init_security(void)
26 {
27         int i, ret;
28
29         for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
30                 if (rxrpc_security_types[i]) {
31                         ret = rxrpc_security_types[i]->init();
32                         if (ret < 0)
33                                 goto failed;
34                 }
35         }
36
37         return 0;
38
39 failed:
40         for (i--; i >= 0; i--)
41                 if (rxrpc_security_types[i])
42                         rxrpc_security_types[i]->exit();
43         return ret;
44 }
45
46 void rxrpc_exit_security(void)
47 {
48         int i;
49
50         for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
51                 if (rxrpc_security_types[i])
52                         rxrpc_security_types[i]->exit();
53 }
54
55 /*
56  * look up an rxrpc security module
57  */
58 static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
59 {
60         if (security_index >= ARRAY_SIZE(rxrpc_security_types))
61                 return NULL;
62         return rxrpc_security_types[security_index];
63 }
64
65 /*
66  * initialise the security on a client connection
67  */
68 int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
69 {
70         const struct rxrpc_security *sec;
71         struct rxrpc_key_token *token;
72         struct key *key = conn->params.key;
73         int ret;
74
75         _enter("{%d},{%x}", conn->debug_id, key_serial(key));
76
77         if (!key)
78                 return 0;
79
80         ret = key_validate(key);
81         if (ret < 0)
82                 return ret;
83
84         token = key->payload.data[0];
85         if (!token)
86                 return -EKEYREJECTED;
87
88         sec = rxrpc_security_lookup(token->security_index);
89         if (!sec)
90                 return -EKEYREJECTED;
91         conn->security = sec;
92
93         ret = conn->security->init_connection_security(conn);
94         if (ret < 0) {
95                 conn->security = &rxrpc_no_security;
96                 return ret;
97         }
98
99         _leave(" = 0");
100         return 0;
101 }
102
103 /*
104  * initialise the security on a server connection
105  */
106 int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
107 {
108         const struct rxrpc_security *sec;
109         struct rxrpc_local *local = conn->params.local;
110         struct rxrpc_sock *rx;
111         struct key *key;
112         key_ref_t kref;
113         char kdesc[5 + 1 + 3 + 1];
114
115         _enter("");
116
117         sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix);
118
119         sec = rxrpc_security_lookup(conn->security_ix);
120         if (!sec) {
121                 _leave(" = -ENOKEY [lookup]");
122                 return -ENOKEY;
123         }
124
125         /* find the service */
126         read_lock(&local->services_lock);
127         rx = rcu_dereference_protected(local->service,
128                                        lockdep_is_held(&local->services_lock));
129         if (rx && (rx->srx.srx_service == conn->service_id ||
130                    rx->second_service == conn->service_id))
131                 goto found_service;
132
133         /* the service appears to have died */
134         read_unlock(&local->services_lock);
135         _leave(" = -ENOENT");
136         return -ENOENT;
137
138 found_service:
139         if (!rx->securities) {
140                 read_unlock(&local->services_lock);
141                 _leave(" = -ENOKEY");
142                 return -ENOKEY;
143         }
144
145         /* look through the service's keyring */
146         kref = keyring_search(make_key_ref(rx->securities, 1UL),
147                               &key_type_rxrpc_s, kdesc, true);
148         if (IS_ERR(kref)) {
149                 read_unlock(&local->services_lock);
150                 _leave(" = %ld [search]", PTR_ERR(kref));
151                 return PTR_ERR(kref);
152         }
153
154         key = key_ref_to_ptr(kref);
155         read_unlock(&local->services_lock);
156
157         conn->server_key = key;
158         conn->security = sec;
159
160         _leave(" = 0");
161         return 0;
162 }