ACPI: SBS: Simplify the code using module_acpi_driver()
[linux-2.6-microblaze.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  * Find the security key for a server connection.
105  */
106 bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx,
107                                    const struct rxrpc_security **_sec,
108                                    struct key **_key,
109                                    struct sk_buff *skb)
110 {
111         const struct rxrpc_security *sec;
112         struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
113         key_ref_t kref = NULL;
114         char kdesc[5 + 1 + 3 + 1];
115
116         _enter("");
117
118         sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex);
119
120         sec = rxrpc_security_lookup(sp->hdr.securityIndex);
121         if (!sec) {
122                 trace_rxrpc_abort(0, "SVS",
123                                   sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
124                                   RX_INVALID_OPERATION, EKEYREJECTED);
125                 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
126                 skb->priority = RX_INVALID_OPERATION;
127                 return false;
128         }
129
130         if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE)
131                 goto out;
132
133         if (!rx->securities) {
134                 trace_rxrpc_abort(0, "SVR",
135                                   sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
136                                   RX_INVALID_OPERATION, EKEYREJECTED);
137                 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
138                 skb->priority = RX_INVALID_OPERATION;
139                 return false;
140         }
141
142         /* look through the service's keyring */
143         kref = keyring_search(make_key_ref(rx->securities, 1UL),
144                               &key_type_rxrpc_s, kdesc, true);
145         if (IS_ERR(kref)) {
146                 trace_rxrpc_abort(0, "SVK",
147                                   sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
148                                   sec->no_key_abort, EKEYREJECTED);
149                 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
150                 skb->priority = sec->no_key_abort;
151                 return false;
152         }
153
154 out:
155         *_sec = sec;
156         *_key = key_ref_to_ptr(kref);
157         return true;
158 }