diff options
Diffstat (limited to 'net/rxrpc/ar-security.c')
-rw-r--r-- | net/rxrpc/ar-security.c | 166 |
1 files changed, 35 insertions, 131 deletions
diff --git a/net/rxrpc/ar-security.c b/net/rxrpc/ar-security.c index ceff6394a65f..d223253b22fa 100644 --- a/net/rxrpc/ar-security.c +++ b/net/rxrpc/ar-security.c | |||
@@ -22,109 +22,60 @@ | |||
22 | static LIST_HEAD(rxrpc_security_methods); | 22 | static LIST_HEAD(rxrpc_security_methods); |
23 | static DECLARE_RWSEM(rxrpc_security_sem); | 23 | static DECLARE_RWSEM(rxrpc_security_sem); |
24 | 24 | ||
25 | /* | 25 | static const struct rxrpc_security *rxrpc_security_types[] = { |
26 | * get an RxRPC security module | 26 | [RXRPC_SECURITY_NONE] = &rxrpc_no_security, |
27 | */ | 27 | #ifdef CONFIG_RXKAD |
28 | static struct rxrpc_security *rxrpc_security_get(struct rxrpc_security *sec) | 28 | [RXRPC_SECURITY_RXKAD] = &rxkad, |
29 | { | 29 | #endif |
30 | return try_module_get(sec->owner) ? sec : NULL; | 30 | }; |
31 | } | 31 | |
32 | 32 | int __init rxrpc_init_security(void) | |
33 | /* | ||
34 | * release an RxRPC security module | ||
35 | */ | ||
36 | static void rxrpc_security_put(struct rxrpc_security *sec) | ||
37 | { | 33 | { |
38 | module_put(sec->owner); | 34 | int i, ret; |
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 | 35 | ||
50 | down_read(&rxrpc_security_sem); | 36 | for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) { |
51 | 37 | if (rxrpc_security_types[i]) { | |
52 | list_for_each_entry(sec, &rxrpc_security_methods, link) { | 38 | ret = rxrpc_security_types[i]->init(); |
53 | if (sec->security_index == security_index) { | 39 | if (ret < 0) |
54 | if (unlikely(!rxrpc_security_get(sec))) | 40 | goto failed; |
55 | break; | ||
56 | goto out; | ||
57 | } | 41 | } |
58 | } | 42 | } |
59 | 43 | ||
60 | sec = NULL; | 44 | return 0; |
61 | out: | 45 | |
62 | up_read(&rxrpc_security_sem); | 46 | failed: |
63 | _leave(" = %p [%s]", sec, sec ? sec->name : ""); | 47 | for (i--; i >= 0; i--) |
64 | return sec; | 48 | if (rxrpc_security_types[i]) |
49 | rxrpc_security_types[i]->exit(); | ||
50 | return ret; | ||
65 | } | 51 | } |
66 | 52 | ||
67 | /** | 53 | void rxrpc_exit_security(void) |
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 | { | 54 | { |
75 | struct rxrpc_security *psec; | 55 | int i; |
76 | int ret; | ||
77 | 56 | ||
78 | _enter(""); | 57 | for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) |
79 | down_write(&rxrpc_security_sem); | 58 | if (rxrpc_security_types[i]) |
80 | 59 | rxrpc_security_types[i]->exit(); | |
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 | } | 60 | } |
98 | 61 | ||
99 | EXPORT_SYMBOL_GPL(rxrpc_register_security); | 62 | /* |
100 | 63 | * look up an rxrpc security module | |
101 | /** | ||
102 | * rxrpc_unregister_security - unregister an RxRPC security handler | ||
103 | * @sec: security module | ||
104 | * | ||
105 | * unregister an RxRPC security handler | ||
106 | */ | 64 | */ |
107 | void rxrpc_unregister_security(struct rxrpc_security *sec) | 65 | static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) |
108 | { | 66 | { |
109 | 67 | if (security_index >= ARRAY_SIZE(rxrpc_security_types)) | |
110 | _enter(""); | 68 | return NULL; |
111 | down_write(&rxrpc_security_sem); | 69 | return rxrpc_security_types[security_index]; |
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 | } | 70 | } |
118 | 71 | ||
119 | EXPORT_SYMBOL_GPL(rxrpc_unregister_security); | ||
120 | |||
121 | /* | 72 | /* |
122 | * initialise the security on a client connection | 73 | * initialise the security on a client connection |
123 | */ | 74 | */ |
124 | int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) | 75 | int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) |
125 | { | 76 | { |
77 | const struct rxrpc_security *sec; | ||
126 | struct rxrpc_key_token *token; | 78 | struct rxrpc_key_token *token; |
127 | struct rxrpc_security *sec; | ||
128 | struct key *key = conn->key; | 79 | struct key *key = conn->key; |
129 | int ret; | 80 | int ret; |
130 | 81 | ||
@@ -148,8 +99,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) | |||
148 | 99 | ||
149 | ret = conn->security->init_connection_security(conn); | 100 | ret = conn->security->init_connection_security(conn); |
150 | if (ret < 0) { | 101 | if (ret < 0) { |
151 | rxrpc_security_put(conn->security); | 102 | conn->security = &rxrpc_no_security; |
152 | conn->security = NULL; | ||
153 | return ret; | 103 | return ret; |
154 | } | 104 | } |
155 | 105 | ||
@@ -162,7 +112,7 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) | |||
162 | */ | 112 | */ |
163 | int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) | 113 | int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) |
164 | { | 114 | { |
165 | struct rxrpc_security *sec; | 115 | const struct rxrpc_security *sec; |
166 | struct rxrpc_local *local = conn->trans->local; | 116 | struct rxrpc_local *local = conn->trans->local; |
167 | struct rxrpc_sock *rx; | 117 | struct rxrpc_sock *rx; |
168 | struct key *key; | 118 | struct key *key; |
@@ -188,14 +138,12 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) | |||
188 | 138 | ||
189 | /* the service appears to have died */ | 139 | /* the service appears to have died */ |
190 | read_unlock_bh(&local->services_lock); | 140 | read_unlock_bh(&local->services_lock); |
191 | rxrpc_security_put(sec); | ||
192 | _leave(" = -ENOENT"); | 141 | _leave(" = -ENOENT"); |
193 | return -ENOENT; | 142 | return -ENOENT; |
194 | 143 | ||
195 | found_service: | 144 | found_service: |
196 | if (!rx->securities) { | 145 | if (!rx->securities) { |
197 | read_unlock_bh(&local->services_lock); | 146 | read_unlock_bh(&local->services_lock); |
198 | rxrpc_security_put(sec); | ||
199 | _leave(" = -ENOKEY"); | 147 | _leave(" = -ENOKEY"); |
200 | return -ENOKEY; | 148 | return -ENOKEY; |
201 | } | 149 | } |
@@ -205,7 +153,6 @@ found_service: | |||
205 | &key_type_rxrpc_s, kdesc); | 153 | &key_type_rxrpc_s, kdesc); |
206 | if (IS_ERR(kref)) { | 154 | if (IS_ERR(kref)) { |
207 | read_unlock_bh(&local->services_lock); | 155 | read_unlock_bh(&local->services_lock); |
208 | rxrpc_security_put(sec); | ||
209 | _leave(" = %ld [search]", PTR_ERR(kref)); | 156 | _leave(" = %ld [search]", PTR_ERR(kref)); |
210 | return PTR_ERR(kref); | 157 | return PTR_ERR(kref); |
211 | } | 158 | } |
@@ -219,46 +166,3 @@ found_service: | |||
219 | _leave(" = 0"); | 166 | _leave(" = 0"); |
220 | return 0; | 167 | return 0; |
221 | } | 168 | } |
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 | } | ||