Branch data Line data Source code
1 : : /*
2 : : * RADIUS authentication server
3 : : * Copyright (c) 2005-2009, 2011-2014, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : : #include <net/if.h>
11 : :
12 : : #include "common.h"
13 : : #include "radius.h"
14 : : #include "eloop.h"
15 : : #include "eap_server/eap.h"
16 : : #include "radius_server.h"
17 : :
18 : : /**
19 : : * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
20 : : */
21 : : #define RADIUS_SESSION_TIMEOUT 60
22 : :
23 : : /**
24 : : * RADIUS_MAX_SESSION - Maximum number of active sessions
25 : : */
26 : : #define RADIUS_MAX_SESSION 100
27 : :
28 : : /**
29 : : * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
30 : : */
31 : : #define RADIUS_MAX_MSG_LEN 3000
32 : :
33 : : static struct eapol_callbacks radius_server_eapol_cb;
34 : :
35 : : struct radius_client;
36 : : struct radius_server_data;
37 : :
38 : : /**
39 : : * struct radius_server_counters - RADIUS server statistics counters
40 : : */
41 : : struct radius_server_counters {
42 : : u32 access_requests;
43 : : u32 invalid_requests;
44 : : u32 dup_access_requests;
45 : : u32 access_accepts;
46 : : u32 access_rejects;
47 : : u32 access_challenges;
48 : : u32 malformed_access_requests;
49 : : u32 bad_authenticators;
50 : : u32 packets_dropped;
51 : : u32 unknown_types;
52 : :
53 : : u32 acct_requests;
54 : : u32 invalid_acct_requests;
55 : : u32 acct_responses;
56 : : u32 malformed_acct_requests;
57 : : u32 acct_bad_authenticators;
58 : : u32 unknown_acct_types;
59 : : };
60 : :
61 : : /**
62 : : * struct radius_session - Internal RADIUS server data for a session
63 : : */
64 : : struct radius_session {
65 : : struct radius_session *next;
66 : : struct radius_client *client;
67 : : struct radius_server_data *server;
68 : : unsigned int sess_id;
69 : : struct eap_sm *eap;
70 : : struct eap_eapol_interface *eap_if;
71 : :
72 : : struct radius_msg *last_msg;
73 : : char *last_from_addr;
74 : : int last_from_port;
75 : : struct sockaddr_storage last_from;
76 : : socklen_t last_fromlen;
77 : : u8 last_identifier;
78 : : struct radius_msg *last_reply;
79 : : u8 last_authenticator[16];
80 : :
81 : : unsigned int remediation:1;
82 : : };
83 : :
84 : : /**
85 : : * struct radius_client - Internal RADIUS server data for a client
86 : : */
87 : : struct radius_client {
88 : : struct radius_client *next;
89 : : struct in_addr addr;
90 : : struct in_addr mask;
91 : : #ifdef CONFIG_IPV6
92 : : struct in6_addr addr6;
93 : : struct in6_addr mask6;
94 : : #endif /* CONFIG_IPV6 */
95 : : char *shared_secret;
96 : : int shared_secret_len;
97 : : struct radius_session *sessions;
98 : : struct radius_server_counters counters;
99 : : };
100 : :
101 : : /**
102 : : * struct radius_server_data - Internal RADIUS server data
103 : : */
104 : : struct radius_server_data {
105 : : /**
106 : : * auth_sock - Socket for RADIUS authentication messages
107 : : */
108 : : int auth_sock;
109 : :
110 : : /**
111 : : * acct_sock - Socket for RADIUS accounting messages
112 : : */
113 : : int acct_sock;
114 : :
115 : : /**
116 : : * clients - List of authorized RADIUS clients
117 : : */
118 : : struct radius_client *clients;
119 : :
120 : : /**
121 : : * next_sess_id - Next session identifier
122 : : */
123 : : unsigned int next_sess_id;
124 : :
125 : : /**
126 : : * conf_ctx - Context pointer for callbacks
127 : : *
128 : : * This is used as the ctx argument in get_eap_user() calls.
129 : : */
130 : : void *conf_ctx;
131 : :
132 : : /**
133 : : * num_sess - Number of active sessions
134 : : */
135 : : int num_sess;
136 : :
137 : : /**
138 : : * eap_sim_db_priv - EAP-SIM/AKA database context
139 : : *
140 : : * This is passed to the EAP-SIM/AKA server implementation as a
141 : : * callback context.
142 : : */
143 : : void *eap_sim_db_priv;
144 : :
145 : : /**
146 : : * ssl_ctx - TLS context
147 : : *
148 : : * This is passed to the EAP server implementation as a callback
149 : : * context for TLS operations.
150 : : */
151 : : void *ssl_ctx;
152 : :
153 : : /**
154 : : * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
155 : : *
156 : : * This parameter is used to set a key for EAP-FAST to encrypt the
157 : : * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
158 : : * set, must point to a 16-octet key.
159 : : */
160 : : u8 *pac_opaque_encr_key;
161 : :
162 : : /**
163 : : * eap_fast_a_id - EAP-FAST authority identity (A-ID)
164 : : *
165 : : * If EAP-FAST is not used, this can be set to %NULL. In theory, this
166 : : * is a variable length field, but due to some existing implementations
167 : : * requiring A-ID to be 16 octets in length, it is recommended to use
168 : : * that length for the field to provide interoperability with deployed
169 : : * peer implementations.
170 : : */
171 : : u8 *eap_fast_a_id;
172 : :
173 : : /**
174 : : * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
175 : : */
176 : : size_t eap_fast_a_id_len;
177 : :
178 : : /**
179 : : * eap_fast_a_id_info - EAP-FAST authority identifier information
180 : : *
181 : : * This A-ID-Info contains a user-friendly name for the A-ID. For
182 : : * example, this could be the enterprise and server names in
183 : : * human-readable format. This field is encoded as UTF-8. If EAP-FAST
184 : : * is not used, this can be set to %NULL.
185 : : */
186 : : char *eap_fast_a_id_info;
187 : :
188 : : /**
189 : : * eap_fast_prov - EAP-FAST provisioning modes
190 : : *
191 : : * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
192 : : * 2 = only authenticated provisioning allowed, 3 = both provisioning
193 : : * modes allowed.
194 : : */
195 : : int eap_fast_prov;
196 : :
197 : : /**
198 : : * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
199 : : *
200 : : * This is the hard limit on how long a provisioned PAC-Key can be
201 : : * used.
202 : : */
203 : : int pac_key_lifetime;
204 : :
205 : : /**
206 : : * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
207 : : *
208 : : * This is a soft limit on the PAC-Key. The server will automatically
209 : : * generate a new PAC-Key when this number of seconds (or fewer) of the
210 : : * lifetime remains.
211 : : */
212 : : int pac_key_refresh_time;
213 : :
214 : : /**
215 : : * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
216 : : *
217 : : * This controls whether the protected success/failure indication
218 : : * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
219 : : */
220 : : int eap_sim_aka_result_ind;
221 : :
222 : : /**
223 : : * tnc - Trusted Network Connect (TNC)
224 : : *
225 : : * This controls whether TNC is enabled and will be required before the
226 : : * peer is allowed to connect. Note: This is only used with EAP-TTLS
227 : : * and EAP-FAST. If any other EAP method is enabled, the peer will be
228 : : * allowed to connect without TNC.
229 : : */
230 : : int tnc;
231 : :
232 : : /**
233 : : * pwd_group - The D-H group assigned for EAP-pwd
234 : : *
235 : : * If EAP-pwd is not used it can be set to zero.
236 : : */
237 : : u16 pwd_group;
238 : :
239 : : /**
240 : : * server_id - Server identity
241 : : */
242 : : const char *server_id;
243 : :
244 : : /**
245 : : * wps - Wi-Fi Protected Setup context
246 : : *
247 : : * If WPS is used with an external RADIUS server (which is quite
248 : : * unlikely configuration), this is used to provide a pointer to WPS
249 : : * context data. Normally, this can be set to %NULL.
250 : : */
251 : : struct wps_context *wps;
252 : :
253 : : /**
254 : : * ipv6 - Whether to enable IPv6 support in the RADIUS server
255 : : */
256 : : int ipv6;
257 : :
258 : : /**
259 : : * start_time - Timestamp of server start
260 : : */
261 : : struct os_reltime start_time;
262 : :
263 : : /**
264 : : * counters - Statistics counters for server operations
265 : : *
266 : : * These counters are the sum over all clients.
267 : : */
268 : : struct radius_server_counters counters;
269 : :
270 : : /**
271 : : * get_eap_user - Callback for fetching EAP user information
272 : : * @ctx: Context data from conf_ctx
273 : : * @identity: User identity
274 : : * @identity_len: identity buffer length in octets
275 : : * @phase2: Whether this is for Phase 2 identity
276 : : * @user: Data structure for filling in the user information
277 : : * Returns: 0 on success, -1 on failure
278 : : *
279 : : * This is used to fetch information from user database. The callback
280 : : * will fill in information about allowed EAP methods and the user
281 : : * password. The password field will be an allocated copy of the
282 : : * password data and RADIUS server will free it after use.
283 : : */
284 : : int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
285 : : int phase2, struct eap_user *user);
286 : :
287 : : /**
288 : : * eap_req_id_text - Optional data for EAP-Request/Identity
289 : : *
290 : : * This can be used to configure an optional, displayable message that
291 : : * will be sent in EAP-Request/Identity. This string can contain an
292 : : * ASCII-0 character (nul) to separate network infromation per RFC
293 : : * 4284. The actual string length is explicit provided in
294 : : * eap_req_id_text_len since nul character will not be used as a string
295 : : * terminator.
296 : : */
297 : : char *eap_req_id_text;
298 : :
299 : : /**
300 : : * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
301 : : */
302 : : size_t eap_req_id_text_len;
303 : :
304 : : /*
305 : : * msg_ctx - Context data for wpa_msg() calls
306 : : */
307 : : void *msg_ctx;
308 : :
309 : : #ifdef CONFIG_RADIUS_TEST
310 : : char *dump_msk_file;
311 : : #endif /* CONFIG_RADIUS_TEST */
312 : :
313 : : char *subscr_remediation_url;
314 : : u8 subscr_remediation_method;
315 : : };
316 : :
317 : :
318 : : #define RADIUS_DEBUG(args...) \
319 : : wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
320 : : #define RADIUS_ERROR(args...) \
321 : : wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
322 : : #define RADIUS_DUMP(args...) \
323 : : wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
324 : : #define RADIUS_DUMP_ASCII(args...) \
325 : : wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
326 : :
327 : :
328 : : static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
329 : : static void radius_server_session_remove_timeout(void *eloop_ctx,
330 : : void *timeout_ctx);
331 : :
332 : :
333 : : static struct radius_client *
334 : 1057 : radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
335 : : int ipv6)
336 : : {
337 : 1057 : struct radius_client *client = data->clients;
338 : :
339 [ + - ]: 1057 : while (client) {
340 : : #ifdef CONFIG_IPV6
341 [ + + ]: 1057 : if (ipv6) {
342 : : struct in6_addr *addr6;
343 : : int i;
344 : :
345 : 7 : addr6 = (struct in6_addr *) addr;
346 [ + + ]: 119 : for (i = 0; i < 16; i++) {
347 [ - + ]: 112 : if ((addr6->s6_addr[i] &
348 : 112 : client->mask6.s6_addr[i]) !=
349 : 112 : (client->addr6.s6_addr[i] &
350 : : client->mask6.s6_addr[i])) {
351 : 0 : i = 17;
352 : 0 : break;
353 : : }
354 : : }
355 [ + - ]: 7 : if (i == 16) {
356 : 7 : break;
357 : : }
358 : : }
359 : : #endif /* CONFIG_IPV6 */
360 [ + - ][ + - ]: 1050 : if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
361 : 1050 : (addr->s_addr & client->mask.s_addr)) {
362 : 1050 : break;
363 : : }
364 : :
365 : 0 : client = client->next;
366 : : }
367 : :
368 : 1057 : return client;
369 : : }
370 : :
371 : :
372 : : static struct radius_session *
373 : 856 : radius_server_get_session(struct radius_client *client, unsigned int sess_id)
374 : : {
375 : 856 : struct radius_session *sess = client->sessions;
376 : :
377 [ + - ]: 856 : while (sess) {
378 [ + - ]: 856 : if (sess->sess_id == sess_id) {
379 : 856 : break;
380 : : }
381 : 0 : sess = sess->next;
382 : : }
383 : :
384 : 856 : return sess;
385 : : }
386 : :
387 : :
388 : 193 : static void radius_server_session_free(struct radius_server_data *data,
389 : : struct radius_session *sess)
390 : : {
391 : 193 : eloop_cancel_timeout(radius_server_session_timeout, data, sess);
392 : 193 : eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
393 : 193 : eap_server_sm_deinit(sess->eap);
394 : 193 : radius_msg_free(sess->last_msg);
395 : 193 : os_free(sess->last_from_addr);
396 : 193 : radius_msg_free(sess->last_reply);
397 : 193 : os_free(sess);
398 : 193 : data->num_sess--;
399 : 193 : }
400 : :
401 : :
402 : 192 : static void radius_server_session_remove(struct radius_server_data *data,
403 : : struct radius_session *sess)
404 : : {
405 : 192 : struct radius_client *client = sess->client;
406 : : struct radius_session *session, *prev;
407 : :
408 : 192 : eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
409 : :
410 : 192 : prev = NULL;
411 : 192 : session = client->sessions;
412 [ + - ]: 2070 : while (session) {
413 [ + + ]: 2070 : if (session == sess) {
414 [ + + ]: 192 : if (prev == NULL) {
415 : 9 : client->sessions = sess->next;
416 : : } else {
417 : 183 : prev->next = sess->next;
418 : : }
419 : 192 : radius_server_session_free(data, sess);
420 : 192 : break;
421 : : }
422 : 1878 : prev = session;
423 : 1878 : session = session->next;
424 : : }
425 : 192 : }
426 : :
427 : :
428 : 190 : static void radius_server_session_remove_timeout(void *eloop_ctx,
429 : : void *timeout_ctx)
430 : : {
431 : 190 : struct radius_server_data *data = eloop_ctx;
432 : 190 : struct radius_session *sess = timeout_ctx;
433 : 190 : RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
434 : 190 : radius_server_session_remove(data, sess);
435 : 190 : }
436 : :
437 : :
438 : 2 : static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
439 : : {
440 : 2 : struct radius_server_data *data = eloop_ctx;
441 : 2 : struct radius_session *sess = timeout_ctx;
442 : :
443 : 2 : RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
444 : 2 : radius_server_session_remove(data, sess);
445 : 2 : }
446 : :
447 : :
448 : : static struct radius_session *
449 : 193 : radius_server_new_session(struct radius_server_data *data,
450 : : struct radius_client *client)
451 : : {
452 : : struct radius_session *sess;
453 : :
454 [ - + ]: 193 : if (data->num_sess >= RADIUS_MAX_SESSION) {
455 : 0 : RADIUS_DEBUG("Maximum number of existing session - no room "
456 : : "for a new session");
457 : 0 : return NULL;
458 : : }
459 : :
460 : 193 : sess = os_zalloc(sizeof(*sess));
461 [ - + ]: 193 : if (sess == NULL)
462 : 0 : return NULL;
463 : :
464 : 193 : sess->server = data;
465 : 193 : sess->client = client;
466 : 193 : sess->sess_id = data->next_sess_id++;
467 : 193 : sess->next = client->sessions;
468 : 193 : client->sessions = sess;
469 : 193 : eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
470 : : radius_server_session_timeout, data, sess);
471 : 193 : data->num_sess++;
472 : 193 : return sess;
473 : : }
474 : :
475 : :
476 : : static struct radius_session *
477 : 193 : radius_server_get_new_session(struct radius_server_data *data,
478 : : struct radius_client *client,
479 : : struct radius_msg *msg)
480 : : {
481 : : u8 *user;
482 : : size_t user_len;
483 : : int res;
484 : : struct radius_session *sess;
485 : : struct eap_config eap_conf;
486 : :
487 : 193 : RADIUS_DEBUG("Creating a new session");
488 : :
489 : 193 : user = os_malloc(256);
490 [ - + ]: 193 : if (user == NULL) {
491 : 0 : return NULL;
492 : : }
493 : 193 : res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
494 [ - + ][ + - ]: 193 : if (res < 0 || res > 256) {
495 : 0 : RADIUS_DEBUG("Could not get User-Name");
496 : 0 : os_free(user);
497 : 0 : return NULL;
498 : : }
499 : 193 : user_len = res;
500 : 193 : RADIUS_DUMP_ASCII("User-Name", user, user_len);
501 : :
502 : 193 : res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
503 : 193 : os_free(user);
504 : :
505 [ + - ]: 193 : if (res == 0) {
506 : 193 : RADIUS_DEBUG("Matching user entry found");
507 : 193 : sess = radius_server_new_session(data, client);
508 [ - + ]: 193 : if (sess == NULL) {
509 : 0 : RADIUS_DEBUG("Failed to create a new session");
510 : 0 : return NULL;
511 : : }
512 : : } else {
513 : 0 : RADIUS_DEBUG("User-Name not found from user database");
514 : 0 : return NULL;
515 : : }
516 : :
517 : 193 : os_memset(&eap_conf, 0, sizeof(eap_conf));
518 : 193 : eap_conf.ssl_ctx = data->ssl_ctx;
519 : 193 : eap_conf.msg_ctx = data->msg_ctx;
520 : 193 : eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
521 : 193 : eap_conf.backend_auth = TRUE;
522 : 193 : eap_conf.eap_server = 1;
523 : 193 : eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
524 : 193 : eap_conf.eap_fast_a_id = data->eap_fast_a_id;
525 : 193 : eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
526 : 193 : eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
527 : 193 : eap_conf.eap_fast_prov = data->eap_fast_prov;
528 : 193 : eap_conf.pac_key_lifetime = data->pac_key_lifetime;
529 : 193 : eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
530 : 193 : eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
531 : 193 : eap_conf.tnc = data->tnc;
532 : 193 : eap_conf.wps = data->wps;
533 : 193 : eap_conf.pwd_group = data->pwd_group;
534 : 193 : eap_conf.server_id = (const u8 *) data->server_id;
535 : 193 : eap_conf.server_id_len = os_strlen(data->server_id);
536 : 193 : sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
537 : : &eap_conf);
538 [ - + ]: 193 : if (sess->eap == NULL) {
539 : 0 : RADIUS_DEBUG("Failed to initialize EAP state machine for the "
540 : : "new session");
541 : 0 : radius_server_session_free(data, sess);
542 : 0 : return NULL;
543 : : }
544 : 193 : sess->eap_if = eap_get_interface(sess->eap);
545 : 193 : sess->eap_if->eapRestart = TRUE;
546 : 193 : sess->eap_if->portEnabled = TRUE;
547 : :
548 : 193 : RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
549 : :
550 : 193 : return sess;
551 : : }
552 : :
553 : :
554 : : static struct radius_msg *
555 : 1049 : radius_server_encapsulate_eap(struct radius_server_data *data,
556 : : struct radius_client *client,
557 : : struct radius_session *sess,
558 : : struct radius_msg *request)
559 : : {
560 : : struct radius_msg *msg;
561 : : int code;
562 : : unsigned int sess_id;
563 : 1049 : struct radius_hdr *hdr = radius_msg_get_hdr(request);
564 : :
565 [ + + ]: 1049 : if (sess->eap_if->eapFail) {
566 : 21 : sess->eap_if->eapFail = FALSE;
567 : 21 : code = RADIUS_CODE_ACCESS_REJECT;
568 [ + + ]: 1028 : } else if (sess->eap_if->eapSuccess) {
569 : 170 : sess->eap_if->eapSuccess = FALSE;
570 : 170 : code = RADIUS_CODE_ACCESS_ACCEPT;
571 : : } else {
572 : 858 : sess->eap_if->eapReq = FALSE;
573 : 858 : code = RADIUS_CODE_ACCESS_CHALLENGE;
574 : : }
575 : :
576 : 1049 : msg = radius_msg_new(code, hdr->identifier);
577 [ - + ]: 1049 : if (msg == NULL) {
578 : 0 : RADIUS_DEBUG("Failed to allocate reply message");
579 : 0 : return NULL;
580 : : }
581 : :
582 : 1049 : sess_id = htonl(sess->sess_id);
583 [ + + - + ]: 1907 : if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
584 : 858 : !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
585 : : (u8 *) &sess_id, sizeof(sess_id))) {
586 : 0 : RADIUS_DEBUG("Failed to add State attribute");
587 : : }
588 : :
589 [ + - - + ]: 2098 : if (sess->eap_if->eapReqData &&
590 : 1049 : !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
591 : 1049 : wpabuf_len(sess->eap_if->eapReqData))) {
592 : 0 : RADIUS_DEBUG("Failed to add EAP-Message attribute");
593 : : }
594 : :
595 [ + + ][ + - ]: 1049 : if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
596 : : int len;
597 : : #ifdef CONFIG_RADIUS_TEST
598 : : if (data->dump_msk_file) {
599 : : FILE *f;
600 : : char buf[2 * 64 + 1];
601 : : f = fopen(data->dump_msk_file, "a");
602 : : if (f) {
603 : : len = sess->eap_if->eapKeyDataLen;
604 : : if (len > 64)
605 : : len = 64;
606 : : len = wpa_snprintf_hex(
607 : : buf, sizeof(buf),
608 : : sess->eap_if->eapKeyData, len);
609 : : buf[len] = '\0';
610 : : fprintf(f, "%s\n", buf);
611 : : fclose(f);
612 : : }
613 : : }
614 : : #endif /* CONFIG_RADIUS_TEST */
615 [ - + ]: 170 : if (sess->eap_if->eapKeyDataLen > 64) {
616 : 0 : len = 32;
617 : : } else {
618 : 170 : len = sess->eap_if->eapKeyDataLen / 2;
619 : : }
620 [ - + ]: 170 : if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
621 : 170 : (u8 *) client->shared_secret,
622 : 170 : client->shared_secret_len,
623 : 170 : sess->eap_if->eapKeyData + len,
624 : 170 : len, sess->eap_if->eapKeyData,
625 : : len)) {
626 : 0 : RADIUS_DEBUG("Failed to add MPPE key attributes");
627 : : }
628 : : }
629 : :
630 : : #ifdef CONFIG_HS20
631 [ + + ][ - + ]: 1049 : if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation &&
[ # # ]
632 : 0 : data->subscr_remediation_url) {
633 : : u8 *buf;
634 : 0 : size_t url_len = os_strlen(data->subscr_remediation_url);
635 : 0 : buf = os_malloc(1 + url_len);
636 [ # # ]: 0 : if (buf == NULL) {
637 : 0 : radius_msg_free(msg);
638 : 0 : return NULL;
639 : : }
640 : 0 : buf[0] = data->subscr_remediation_method;
641 : 0 : os_memcpy(&buf[1], data->subscr_remediation_url, url_len);
642 [ # # ]: 0 : if (!radius_msg_add_wfa(
643 : : msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
644 : : buf, 1 + url_len)) {
645 : 0 : RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
646 : : }
647 : 0 : os_free(buf);
648 [ + + ][ - + ]: 1049 : } else if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation) {
649 : : u8 buf[1];
650 [ # # ]: 0 : if (!radius_msg_add_wfa(
651 : : msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
652 : : buf, 0)) {
653 : 0 : RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
654 : : }
655 : : }
656 : : #endif /* CONFIG_HS20 */
657 : :
658 [ - + ]: 1049 : if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
659 : 0 : RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
660 : 0 : radius_msg_free(msg);
661 : 0 : return NULL;
662 : : }
663 : :
664 [ - + ]: 1049 : if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
665 : 1049 : client->shared_secret_len,
666 : 1049 : hdr->authenticator) < 0) {
667 : 0 : RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
668 : : }
669 : :
670 : 1049 : return msg;
671 : : }
672 : :
673 : :
674 : 0 : static int radius_server_reject(struct radius_server_data *data,
675 : : struct radius_client *client,
676 : : struct radius_msg *request,
677 : : struct sockaddr *from, socklen_t fromlen,
678 : : const char *from_addr, int from_port)
679 : : {
680 : : struct radius_msg *msg;
681 : 0 : int ret = 0;
682 : : struct eap_hdr eapfail;
683 : : struct wpabuf *buf;
684 : 0 : struct radius_hdr *hdr = radius_msg_get_hdr(request);
685 : :
686 : 0 : RADIUS_DEBUG("Reject invalid request from %s:%d",
687 : : from_addr, from_port);
688 : :
689 : 0 : msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
690 [ # # ]: 0 : if (msg == NULL) {
691 : 0 : return -1;
692 : : }
693 : :
694 : 0 : os_memset(&eapfail, 0, sizeof(eapfail));
695 : 0 : eapfail.code = EAP_CODE_FAILURE;
696 : 0 : eapfail.identifier = 0;
697 : 0 : eapfail.length = host_to_be16(sizeof(eapfail));
698 : :
699 [ # # ]: 0 : if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
700 : 0 : RADIUS_DEBUG("Failed to add EAP-Message attribute");
701 : : }
702 : :
703 [ # # ]: 0 : if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
704 : 0 : RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
705 : 0 : radius_msg_free(msg);
706 : 0 : return -1;
707 : : }
708 : :
709 [ # # ]: 0 : if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
710 : 0 : client->shared_secret_len,
711 : 0 : hdr->authenticator) <
712 : : 0) {
713 : 0 : RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
714 : : }
715 : :
716 [ # # ]: 0 : if (wpa_debug_level <= MSG_MSGDUMP) {
717 : 0 : radius_msg_dump(msg);
718 : : }
719 : :
720 : 0 : data->counters.access_rejects++;
721 : 0 : client->counters.access_rejects++;
722 : 0 : buf = radius_msg_get_buf(msg);
723 [ # # ]: 0 : if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
724 : : (struct sockaddr *) from, sizeof(*from)) < 0) {
725 : 0 : wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno));
726 : 0 : ret = -1;
727 : : }
728 : :
729 : 0 : radius_msg_free(msg);
730 : :
731 : 0 : return ret;
732 : : }
733 : :
734 : :
735 : 1065 : static int radius_server_request(struct radius_server_data *data,
736 : : struct radius_msg *msg,
737 : : struct sockaddr *from, socklen_t fromlen,
738 : : struct radius_client *client,
739 : : const char *from_addr, int from_port,
740 : : struct radius_session *force_sess)
741 : : {
742 : 1065 : struct wpabuf *eap = NULL;
743 : 1065 : int res, state_included = 0;
744 : : u8 statebuf[4];
745 : : unsigned int state;
746 : : struct radius_session *sess;
747 : : struct radius_msg *reply;
748 : 1065 : int is_complete = 0;
749 : :
750 [ + + ]: 1065 : if (force_sess)
751 : 16 : sess = force_sess;
752 : : else {
753 : 1049 : res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
754 : : sizeof(statebuf));
755 : 1049 : state_included = res >= 0;
756 [ + + ]: 1049 : if (res == sizeof(statebuf)) {
757 : 856 : state = WPA_GET_BE32(statebuf);
758 : 856 : sess = radius_server_get_session(client, state);
759 : : } else {
760 : 193 : sess = NULL;
761 : : }
762 : : }
763 : :
764 [ + + ]: 1065 : if (sess) {
765 : 872 : RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
766 [ - + ]: 193 : } else if (state_included) {
767 : 0 : RADIUS_DEBUG("State attribute included but no session found");
768 : 0 : radius_server_reject(data, client, msg, from, fromlen,
769 : : from_addr, from_port);
770 : 0 : return -1;
771 : : } else {
772 : 193 : sess = radius_server_get_new_session(data, client, msg);
773 [ - + ]: 193 : if (sess == NULL) {
774 : 0 : RADIUS_DEBUG("Could not create a new session");
775 : 0 : radius_server_reject(data, client, msg, from, fromlen,
776 : : from_addr, from_port);
777 : 0 : return -1;
778 : : }
779 : : }
780 : :
781 [ + + - + ]: 1937 : if (sess->last_from_port == from_port &&
782 [ # # ]: 872 : sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
783 : 0 : os_memcmp(sess->last_authenticator,
784 : : radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
785 : 0 : RADIUS_DEBUG("Duplicate message from %s", from_addr);
786 : 0 : data->counters.dup_access_requests++;
787 : 0 : client->counters.dup_access_requests++;
788 : :
789 [ # # ]: 0 : if (sess->last_reply) {
790 : : struct wpabuf *buf;
791 : 0 : buf = radius_msg_get_buf(sess->last_reply);
792 : 0 : res = sendto(data->auth_sock, wpabuf_head(buf),
793 : : wpabuf_len(buf), 0,
794 : : (struct sockaddr *) from, fromlen);
795 [ # # ]: 0 : if (res < 0) {
796 : 0 : wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
797 : 0 : strerror(errno));
798 : : }
799 : 0 : return 0;
800 : : }
801 : :
802 : 0 : RADIUS_DEBUG("No previous reply available for duplicate "
803 : : "message");
804 : 0 : return -1;
805 : : }
806 : :
807 : 1065 : eap = radius_msg_get_eap(msg);
808 [ - + ]: 1065 : if (eap == NULL) {
809 : 0 : RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
810 : : from_addr);
811 : 0 : data->counters.packets_dropped++;
812 : 0 : client->counters.packets_dropped++;
813 : 0 : return -1;
814 : : }
815 : :
816 : 1065 : RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap));
817 : :
818 : : /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
819 : : * RFC3579 Sect. 2.6.2.
820 : : * Include EAP-Response/Nak with no preferred method if
821 : : * code == request.
822 : : * If code is not 1-4, discard the packet silently.
823 : : * Or is this already done by the EAP state machine? */
824 : :
825 : 1065 : wpabuf_free(sess->eap_if->eapRespData);
826 : 1065 : sess->eap_if->eapRespData = eap;
827 : 1065 : sess->eap_if->eapResp = TRUE;
828 : 1065 : eap_server_sm_step(sess->eap);
829 : :
830 [ + + ][ + + ]: 1065 : if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
[ + + ]
831 [ + - ]: 1049 : sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
832 : 1049 : RADIUS_DUMP("EAP data from the state machine",
833 : : wpabuf_head(sess->eap_if->eapReqData),
834 : : wpabuf_len(sess->eap_if->eapReqData));
835 [ - + ]: 16 : } else if (sess->eap_if->eapFail) {
836 : 0 : RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
837 : : "set");
838 [ + - ]: 16 : } else if (eap_sm_method_pending(sess->eap)) {
839 : 16 : radius_msg_free(sess->last_msg);
840 : 16 : sess->last_msg = msg;
841 : 16 : sess->last_from_port = from_port;
842 : 16 : os_free(sess->last_from_addr);
843 : 16 : sess->last_from_addr = os_strdup(from_addr);
844 : 16 : sess->last_fromlen = fromlen;
845 : 16 : os_memcpy(&sess->last_from, from, fromlen);
846 : 16 : return -2;
847 : : } else {
848 : 0 : RADIUS_DEBUG("No EAP data from the state machine - ignore this"
849 : : " Access-Request silently (assuming it was a "
850 : : "duplicate)");
851 : 0 : data->counters.packets_dropped++;
852 : 0 : client->counters.packets_dropped++;
853 : 0 : return -1;
854 : : }
855 : :
856 [ + + ][ + + ]: 1049 : if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
857 : 191 : is_complete = 1;
858 : :
859 : 1049 : reply = radius_server_encapsulate_eap(data, client, sess, msg);
860 : :
861 [ + - ]: 1049 : if (reply) {
862 : : struct wpabuf *buf;
863 : : struct radius_hdr *hdr;
864 : :
865 : 1049 : RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
866 [ + - ]: 1049 : if (wpa_debug_level <= MSG_MSGDUMP) {
867 : 1049 : radius_msg_dump(reply);
868 : : }
869 : :
870 [ + + + - ]: 1049 : switch (radius_msg_get_hdr(reply)->code) {
871 : : case RADIUS_CODE_ACCESS_ACCEPT:
872 : 170 : data->counters.access_accepts++;
873 : 170 : client->counters.access_accepts++;
874 : 170 : break;
875 : : case RADIUS_CODE_ACCESS_REJECT:
876 : 21 : data->counters.access_rejects++;
877 : 21 : client->counters.access_rejects++;
878 : 21 : break;
879 : : case RADIUS_CODE_ACCESS_CHALLENGE:
880 : 858 : data->counters.access_challenges++;
881 : 858 : client->counters.access_challenges++;
882 : 858 : break;
883 : : }
884 : 1049 : buf = radius_msg_get_buf(reply);
885 : 1049 : res = sendto(data->auth_sock, wpabuf_head(buf),
886 : : wpabuf_len(buf), 0,
887 : : (struct sockaddr *) from, fromlen);
888 [ - + ]: 1049 : if (res < 0) {
889 : 0 : wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
890 : 0 : strerror(errno));
891 : : }
892 : 1049 : radius_msg_free(sess->last_reply);
893 : 1049 : sess->last_reply = reply;
894 : 1049 : sess->last_from_port = from_port;
895 : 1049 : hdr = radius_msg_get_hdr(msg);
896 : 1049 : sess->last_identifier = hdr->identifier;
897 : 1049 : os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
898 : : } else {
899 : 0 : data->counters.packets_dropped++;
900 : 0 : client->counters.packets_dropped++;
901 : : }
902 : :
903 [ + + ]: 1049 : if (is_complete) {
904 : 191 : RADIUS_DEBUG("Removing completed session 0x%x after timeout",
905 : : sess->sess_id);
906 : 191 : eloop_cancel_timeout(radius_server_session_remove_timeout,
907 : : data, sess);
908 : 191 : eloop_register_timeout(10, 0,
909 : : radius_server_session_remove_timeout,
910 : : data, sess);
911 : : }
912 : :
913 : 1065 : return 0;
914 : : }
915 : :
916 : :
917 : 1049 : static void radius_server_receive_auth(int sock, void *eloop_ctx,
918 : : void *sock_ctx)
919 : : {
920 : 1049 : struct radius_server_data *data = eloop_ctx;
921 : 1049 : u8 *buf = NULL;
922 : : union {
923 : : struct sockaddr_storage ss;
924 : : struct sockaddr_in sin;
925 : : #ifdef CONFIG_IPV6
926 : : struct sockaddr_in6 sin6;
927 : : #endif /* CONFIG_IPV6 */
928 : : } from;
929 : : socklen_t fromlen;
930 : : int len;
931 : 1049 : struct radius_client *client = NULL;
932 : 1049 : struct radius_msg *msg = NULL;
933 : : char abuf[50];
934 : 1049 : int from_port = 0;
935 : :
936 : 1049 : buf = os_malloc(RADIUS_MAX_MSG_LEN);
937 [ - + ]: 1049 : if (buf == NULL) {
938 : 0 : goto fail;
939 : : }
940 : :
941 : 1049 : fromlen = sizeof(from);
942 : 1049 : len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
943 : : (struct sockaddr *) &from.ss, &fromlen);
944 [ - + ]: 1049 : if (len < 0) {
945 : 0 : wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
946 : 0 : strerror(errno));
947 : 0 : goto fail;
948 : : }
949 : :
950 : : #ifdef CONFIG_IPV6
951 [ + + ]: 1049 : if (data->ipv6) {
952 [ - + ]: 3 : if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
953 : : sizeof(abuf)) == NULL)
954 : 0 : abuf[0] = '\0';
955 : 3 : from_port = ntohs(from.sin6.sin6_port);
956 : 3 : RADIUS_DEBUG("Received %d bytes from %s:%d",
957 : : len, abuf, from_port);
958 : :
959 : 3 : client = radius_server_get_client(data,
960 : : (struct in_addr *)
961 : : &from.sin6.sin6_addr, 1);
962 : : }
963 : : #endif /* CONFIG_IPV6 */
964 : :
965 [ + + ]: 1049 : if (!data->ipv6) {
966 : 1046 : os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
967 : 1046 : from_port = ntohs(from.sin.sin_port);
968 : 1046 : RADIUS_DEBUG("Received %d bytes from %s:%d",
969 : : len, abuf, from_port);
970 : :
971 : 1046 : client = radius_server_get_client(data, &from.sin.sin_addr, 0);
972 : : }
973 : :
974 : 1049 : RADIUS_DUMP("Received data", buf, len);
975 : :
976 [ - + ]: 1049 : if (client == NULL) {
977 : 0 : RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
978 : 0 : data->counters.invalid_requests++;
979 : 0 : goto fail;
980 : : }
981 : :
982 : 1049 : msg = radius_msg_parse(buf, len);
983 [ - + ]: 1049 : if (msg == NULL) {
984 : 0 : RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
985 : 0 : data->counters.malformed_access_requests++;
986 : 0 : client->counters.malformed_access_requests++;
987 : 0 : goto fail;
988 : : }
989 : :
990 : 1049 : os_free(buf);
991 : 1049 : buf = NULL;
992 : :
993 [ + - ]: 1049 : if (wpa_debug_level <= MSG_MSGDUMP) {
994 : 1049 : radius_msg_dump(msg);
995 : : }
996 : :
997 [ - + ]: 1049 : if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
998 : 0 : RADIUS_DEBUG("Unexpected RADIUS code %d",
999 : : radius_msg_get_hdr(msg)->code);
1000 : 0 : data->counters.unknown_types++;
1001 : 0 : client->counters.unknown_types++;
1002 : 0 : goto fail;
1003 : : }
1004 : :
1005 : 1049 : data->counters.access_requests++;
1006 : 1049 : client->counters.access_requests++;
1007 : :
1008 [ - + ]: 1049 : if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
1009 : 1049 : client->shared_secret_len, NULL)) {
1010 : 0 : RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
1011 : 0 : data->counters.bad_authenticators++;
1012 : 0 : client->counters.bad_authenticators++;
1013 : 0 : goto fail;
1014 : : }
1015 : :
1016 [ + + ]: 1049 : if (radius_server_request(data, msg, (struct sockaddr *) &from,
1017 : : fromlen, client, abuf, from_port, NULL) ==
1018 : : -2)
1019 : 1049 : return; /* msg was stored with the session */
1020 : :
1021 : : fail:
1022 : 1033 : radius_msg_free(msg);
1023 : 1033 : os_free(buf);
1024 : : }
1025 : :
1026 : :
1027 : 8 : static void radius_server_receive_acct(int sock, void *eloop_ctx,
1028 : : void *sock_ctx)
1029 : : {
1030 : 8 : struct radius_server_data *data = eloop_ctx;
1031 : 8 : u8 *buf = NULL;
1032 : : union {
1033 : : struct sockaddr_storage ss;
1034 : : struct sockaddr_in sin;
1035 : : #ifdef CONFIG_IPV6
1036 : : struct sockaddr_in6 sin6;
1037 : : #endif /* CONFIG_IPV6 */
1038 : : } from;
1039 : : socklen_t fromlen;
1040 : : int len, res;
1041 : 8 : struct radius_client *client = NULL;
1042 : 8 : struct radius_msg *msg = NULL, *resp = NULL;
1043 : : char abuf[50];
1044 : 8 : int from_port = 0;
1045 : : struct radius_hdr *hdr;
1046 : : struct wpabuf *rbuf;
1047 : :
1048 : 8 : buf = os_malloc(RADIUS_MAX_MSG_LEN);
1049 [ - + ]: 8 : if (buf == NULL) {
1050 : 0 : goto fail;
1051 : : }
1052 : :
1053 : 8 : fromlen = sizeof(from);
1054 : 8 : len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1055 : : (struct sockaddr *) &from.ss, &fromlen);
1056 [ - + ]: 8 : if (len < 0) {
1057 : 0 : wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1058 : 0 : strerror(errno));
1059 : 0 : goto fail;
1060 : : }
1061 : :
1062 : : #ifdef CONFIG_IPV6
1063 [ + + ]: 8 : if (data->ipv6) {
1064 [ - + ]: 4 : if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1065 : : sizeof(abuf)) == NULL)
1066 : 0 : abuf[0] = '\0';
1067 : 4 : from_port = ntohs(from.sin6.sin6_port);
1068 : 4 : RADIUS_DEBUG("Received %d bytes from %s:%d",
1069 : : len, abuf, from_port);
1070 : :
1071 : 4 : client = radius_server_get_client(data,
1072 : : (struct in_addr *)
1073 : : &from.sin6.sin6_addr, 1);
1074 : : }
1075 : : #endif /* CONFIG_IPV6 */
1076 : :
1077 [ + + ]: 8 : if (!data->ipv6) {
1078 : 4 : os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1079 : 4 : from_port = ntohs(from.sin.sin_port);
1080 : 4 : RADIUS_DEBUG("Received %d bytes from %s:%d",
1081 : : len, abuf, from_port);
1082 : :
1083 : 4 : client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1084 : : }
1085 : :
1086 : 8 : RADIUS_DUMP("Received data", buf, len);
1087 : :
1088 [ - + ]: 8 : if (client == NULL) {
1089 : 0 : RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1090 : 0 : data->counters.invalid_acct_requests++;
1091 : 0 : goto fail;
1092 : : }
1093 : :
1094 : 8 : msg = radius_msg_parse(buf, len);
1095 [ - + ]: 8 : if (msg == NULL) {
1096 : 0 : RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1097 : 0 : data->counters.malformed_acct_requests++;
1098 : 0 : client->counters.malformed_acct_requests++;
1099 : 0 : goto fail;
1100 : : }
1101 : :
1102 : 8 : os_free(buf);
1103 : 8 : buf = NULL;
1104 : :
1105 [ + - ]: 8 : if (wpa_debug_level <= MSG_MSGDUMP) {
1106 : 8 : radius_msg_dump(msg);
1107 : : }
1108 : :
1109 [ - + ]: 8 : if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_REQUEST) {
1110 : 0 : RADIUS_DEBUG("Unexpected RADIUS code %d",
1111 : : radius_msg_get_hdr(msg)->code);
1112 : 0 : data->counters.unknown_acct_types++;
1113 : 0 : client->counters.unknown_acct_types++;
1114 : 0 : goto fail;
1115 : : }
1116 : :
1117 : 8 : data->counters.acct_requests++;
1118 : 8 : client->counters.acct_requests++;
1119 : :
1120 [ - + ]: 8 : if (radius_msg_verify_acct_req(msg, (u8 *) client->shared_secret,
1121 : 8 : client->shared_secret_len)) {
1122 : 0 : RADIUS_DEBUG("Invalid Authenticator from %s", abuf);
1123 : 0 : data->counters.acct_bad_authenticators++;
1124 : 0 : client->counters.acct_bad_authenticators++;
1125 : 0 : goto fail;
1126 : : }
1127 : :
1128 : : /* TODO: Write accounting information to a file or database */
1129 : :
1130 : 8 : hdr = radius_msg_get_hdr(msg);
1131 : :
1132 : 8 : resp = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, hdr->identifier);
1133 [ - + ]: 8 : if (resp == NULL)
1134 : 0 : goto fail;
1135 : :
1136 : 8 : radius_msg_finish_acct_resp(resp, (u8 *) client->shared_secret,
1137 : 8 : client->shared_secret_len,
1138 : 8 : hdr->authenticator);
1139 : :
1140 : 8 : RADIUS_DEBUG("Reply to %s:%d", abuf, from_port);
1141 [ + - ]: 8 : if (wpa_debug_level <= MSG_MSGDUMP) {
1142 : 8 : radius_msg_dump(resp);
1143 : : }
1144 : 8 : rbuf = radius_msg_get_buf(resp);
1145 : 8 : data->counters.acct_responses++;
1146 : 8 : client->counters.acct_responses++;
1147 : 8 : res = sendto(data->acct_sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0,
1148 : : (struct sockaddr *) &from.ss, fromlen);
1149 [ - + ]: 8 : if (res < 0) {
1150 : 0 : wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1151 : 0 : strerror(errno));
1152 : : }
1153 : :
1154 : : fail:
1155 : 8 : radius_msg_free(resp);
1156 : 8 : radius_msg_free(msg);
1157 : 8 : os_free(buf);
1158 : 8 : }
1159 : :
1160 : :
1161 : 2 : static int radius_server_disable_pmtu_discovery(int s)
1162 : : {
1163 : 2 : int r = -1;
1164 : : #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1165 : : /* Turn off Path MTU discovery on IPv4/UDP sockets. */
1166 : 2 : int action = IP_PMTUDISC_DONT;
1167 : 2 : r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
1168 : : sizeof(action));
1169 [ - + ]: 2 : if (r == -1)
1170 : 0 : wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
1171 : 0 : "%s", strerror(errno));
1172 : : #endif
1173 : 2 : return r;
1174 : : }
1175 : :
1176 : :
1177 : 2 : static int radius_server_open_socket(int port)
1178 : : {
1179 : : int s;
1180 : : struct sockaddr_in addr;
1181 : :
1182 : 2 : s = socket(PF_INET, SOCK_DGRAM, 0);
1183 [ - + ]: 2 : if (s < 0) {
1184 : 0 : wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno));
1185 : 0 : return -1;
1186 : : }
1187 : :
1188 : 2 : radius_server_disable_pmtu_discovery(s);
1189 : :
1190 : 2 : os_memset(&addr, 0, sizeof(addr));
1191 : 2 : addr.sin_family = AF_INET;
1192 : 2 : addr.sin_port = htons(port);
1193 [ - + ]: 2 : if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1194 : 0 : wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1195 : 0 : close(s);
1196 : 0 : return -1;
1197 : : }
1198 : :
1199 : 2 : return s;
1200 : : }
1201 : :
1202 : :
1203 : : #ifdef CONFIG_IPV6
1204 : 2 : static int radius_server_open_socket6(int port)
1205 : : {
1206 : : int s;
1207 : : struct sockaddr_in6 addr;
1208 : :
1209 : 2 : s = socket(PF_INET6, SOCK_DGRAM, 0);
1210 [ - + ]: 2 : if (s < 0) {
1211 : 0 : wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s",
1212 : 0 : strerror(errno));
1213 : 0 : return -1;
1214 : : }
1215 : :
1216 : 2 : os_memset(&addr, 0, sizeof(addr));
1217 : 2 : addr.sin6_family = AF_INET6;
1218 : 2 : os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
1219 : 2 : addr.sin6_port = htons(port);
1220 [ - + ]: 2 : if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1221 : 0 : wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1222 : 0 : close(s);
1223 : 0 : return -1;
1224 : : }
1225 : :
1226 : 2 : return s;
1227 : : }
1228 : : #endif /* CONFIG_IPV6 */
1229 : :
1230 : :
1231 : 2 : static void radius_server_free_sessions(struct radius_server_data *data,
1232 : : struct radius_session *sessions)
1233 : : {
1234 : : struct radius_session *session, *prev;
1235 : :
1236 : 2 : session = sessions;
1237 [ + + ]: 3 : while (session) {
1238 : 1 : prev = session;
1239 : 1 : session = session->next;
1240 : 1 : radius_server_session_free(data, prev);
1241 : : }
1242 : 2 : }
1243 : :
1244 : :
1245 : 2 : static void radius_server_free_clients(struct radius_server_data *data,
1246 : : struct radius_client *clients)
1247 : : {
1248 : : struct radius_client *client, *prev;
1249 : :
1250 : 2 : client = clients;
1251 [ + + ]: 4 : while (client) {
1252 : 2 : prev = client;
1253 : 2 : client = client->next;
1254 : :
1255 : 2 : radius_server_free_sessions(data, prev->sessions);
1256 : 2 : os_free(prev->shared_secret);
1257 : 2 : os_free(prev);
1258 : : }
1259 : 2 : }
1260 : :
1261 : :
1262 : : static struct radius_client *
1263 : 2 : radius_server_read_clients(const char *client_file, int ipv6)
1264 : : {
1265 : : FILE *f;
1266 : 2 : const int buf_size = 1024;
1267 : : char *buf, *pos;
1268 : : struct radius_client *clients, *tail, *entry;
1269 : 2 : int line = 0, mask, failed = 0, i;
1270 : : struct in_addr addr;
1271 : : #ifdef CONFIG_IPV6
1272 : : struct in6_addr addr6;
1273 : : #endif /* CONFIG_IPV6 */
1274 : : unsigned int val;
1275 : :
1276 : 2 : f = fopen(client_file, "r");
1277 [ - + ]: 2 : if (f == NULL) {
1278 : 0 : RADIUS_ERROR("Could not open client file '%s'", client_file);
1279 : 0 : return NULL;
1280 : : }
1281 : :
1282 : 2 : buf = os_malloc(buf_size);
1283 [ - + ]: 2 : if (buf == NULL) {
1284 : 0 : fclose(f);
1285 : 0 : return NULL;
1286 : : }
1287 : :
1288 : 2 : clients = tail = NULL;
1289 [ + + ]: 4 : while (fgets(buf, buf_size, f)) {
1290 : : /* Configuration file format:
1291 : : * 192.168.1.0/24 secret
1292 : : * 192.168.1.2 secret
1293 : : * fe80::211:22ff:fe33:4455/64 secretipv6
1294 : : */
1295 : 2 : line++;
1296 : 2 : buf[buf_size - 1] = '\0';
1297 : 2 : pos = buf;
1298 [ + - ][ + + ]: 28 : while (*pos != '\0' && *pos != '\n')
1299 : 26 : pos++;
1300 [ + - ]: 2 : if (*pos == '\n')
1301 : 2 : *pos = '\0';
1302 [ + - ][ - + ]: 2 : if (*buf == '\0' || *buf == '#')
1303 : 0 : continue;
1304 : :
1305 : 2 : pos = buf;
1306 [ + + ][ + + ]: 12 : while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
[ + + ][ - + ]
1307 [ # # ][ + + ]: 4 : (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
[ - + ]
1308 [ # # ]: 0 : (*pos >= 'A' && *pos <= 'F')) {
1309 : 10 : pos++;
1310 : : }
1311 : :
1312 [ - + ]: 2 : if (*pos == '\0') {
1313 : 0 : failed = 1;
1314 : 0 : break;
1315 : : }
1316 : :
1317 [ + + ]: 2 : if (*pos == '/') {
1318 : : char *end;
1319 : 1 : *pos++ = '\0';
1320 : 1 : mask = strtol(pos, &end, 10);
1321 [ + - ][ + - ]: 1 : if ((pos == end) ||
1322 [ - + ][ - + ]: 1 : (mask < 0 || mask > (ipv6 ? 128 : 32))) {
1323 : 0 : failed = 1;
1324 : 0 : break;
1325 : : }
1326 : 1 : pos = end;
1327 : : } else {
1328 [ + - ]: 1 : mask = ipv6 ? 128 : 32;
1329 : 1 : *pos++ = '\0';
1330 : : }
1331 : :
1332 [ + + ][ - + ]: 2 : if (!ipv6 && inet_aton(buf, &addr) == 0) {
1333 : 0 : failed = 1;
1334 : 0 : break;
1335 : : }
1336 : : #ifdef CONFIG_IPV6
1337 [ + + ][ - + ]: 2 : if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
1338 [ # # ]: 0 : if (inet_pton(AF_INET, buf, &addr) <= 0) {
1339 : 0 : failed = 1;
1340 : 0 : break;
1341 : : }
1342 : : /* Convert IPv4 address to IPv6 */
1343 [ # # ]: 0 : if (mask <= 32)
1344 : 0 : mask += (128 - 32);
1345 : 0 : os_memset(addr6.s6_addr, 0, 10);
1346 : 0 : addr6.s6_addr[10] = 0xff;
1347 : 0 : addr6.s6_addr[11] = 0xff;
1348 : 0 : os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
1349 : : 4);
1350 : : }
1351 : : #endif /* CONFIG_IPV6 */
1352 : :
1353 [ - + ][ + + ]: 3 : while (*pos == ' ' || *pos == '\t') {
1354 : 1 : pos++;
1355 : : }
1356 : :
1357 [ - + ]: 2 : if (*pos == '\0') {
1358 : 0 : failed = 1;
1359 : 0 : break;
1360 : : }
1361 : :
1362 : 2 : entry = os_zalloc(sizeof(*entry));
1363 [ - + ]: 2 : if (entry == NULL) {
1364 : 0 : failed = 1;
1365 : 0 : break;
1366 : : }
1367 : 2 : entry->shared_secret = os_strdup(pos);
1368 [ - + ]: 2 : if (entry->shared_secret == NULL) {
1369 : 0 : failed = 1;
1370 : 0 : os_free(entry);
1371 : 0 : break;
1372 : : }
1373 : 2 : entry->shared_secret_len = os_strlen(entry->shared_secret);
1374 [ + + ]: 2 : if (!ipv6) {
1375 : 1 : entry->addr.s_addr = addr.s_addr;
1376 : 1 : val = 0;
1377 [ - + ]: 1 : for (i = 0; i < mask; i++)
1378 : 0 : val |= 1 << (31 - i);
1379 : 1 : entry->mask.s_addr = htonl(val);
1380 : : }
1381 : : #ifdef CONFIG_IPV6
1382 [ + + ]: 2 : if (ipv6) {
1383 : 1 : int offset = mask / 8;
1384 : :
1385 : 1 : os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
1386 : 1 : os_memset(entry->mask6.s6_addr, 0xff, offset);
1387 : 1 : val = 0;
1388 [ - + ]: 1 : for (i = 0; i < (mask % 8); i++)
1389 : 0 : val |= 1 << (7 - i);
1390 [ - + ]: 1 : if (offset < 16)
1391 : 0 : entry->mask6.s6_addr[offset] = val;
1392 : : }
1393 : : #endif /* CONFIG_IPV6 */
1394 : :
1395 [ + - ]: 2 : if (tail == NULL) {
1396 : 2 : clients = tail = entry;
1397 : : } else {
1398 : 0 : tail->next = entry;
1399 : 0 : tail = entry;
1400 : : }
1401 : : }
1402 : :
1403 [ - + ]: 2 : if (failed) {
1404 : 0 : RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
1405 : 0 : radius_server_free_clients(NULL, clients);
1406 : 0 : clients = NULL;
1407 : : }
1408 : :
1409 : 2 : os_free(buf);
1410 : 2 : fclose(f);
1411 : :
1412 : 2 : return clients;
1413 : : }
1414 : :
1415 : :
1416 : : /**
1417 : : * radius_server_init - Initialize RADIUS server
1418 : : * @conf: Configuration for the RADIUS server
1419 : : * Returns: Pointer to private RADIUS server context or %NULL on failure
1420 : : *
1421 : : * This initializes a RADIUS server instance and returns a context pointer that
1422 : : * will be used in other calls to the RADIUS server module. The server can be
1423 : : * deinitialize by calling radius_server_deinit().
1424 : : */
1425 : : struct radius_server_data *
1426 : 2 : radius_server_init(struct radius_server_conf *conf)
1427 : : {
1428 : : struct radius_server_data *data;
1429 : :
1430 : : #ifndef CONFIG_IPV6
1431 : : if (conf->ipv6) {
1432 : : wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support");
1433 : : return NULL;
1434 : : }
1435 : : #endif /* CONFIG_IPV6 */
1436 : :
1437 : 2 : data = os_zalloc(sizeof(*data));
1438 [ - + ]: 2 : if (data == NULL)
1439 : 0 : return NULL;
1440 : :
1441 : 2 : os_get_reltime(&data->start_time);
1442 : 2 : data->conf_ctx = conf->conf_ctx;
1443 : 2 : data->eap_sim_db_priv = conf->eap_sim_db_priv;
1444 : 2 : data->ssl_ctx = conf->ssl_ctx;
1445 : 2 : data->msg_ctx = conf->msg_ctx;
1446 : 2 : data->ipv6 = conf->ipv6;
1447 [ + + ]: 2 : if (conf->pac_opaque_encr_key) {
1448 : 1 : data->pac_opaque_encr_key = os_malloc(16);
1449 : 1 : os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1450 : : 16);
1451 : : }
1452 [ + + ]: 2 : if (conf->eap_fast_a_id) {
1453 : 1 : data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1454 [ + - ]: 1 : if (data->eap_fast_a_id) {
1455 : 1 : os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
1456 : : conf->eap_fast_a_id_len);
1457 : 1 : data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1458 : : }
1459 : : }
1460 [ + + ]: 2 : if (conf->eap_fast_a_id_info)
1461 : 1 : data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1462 : 2 : data->eap_fast_prov = conf->eap_fast_prov;
1463 : 2 : data->pac_key_lifetime = conf->pac_key_lifetime;
1464 : 2 : data->pac_key_refresh_time = conf->pac_key_refresh_time;
1465 : 2 : data->get_eap_user = conf->get_eap_user;
1466 : 2 : data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1467 : 2 : data->tnc = conf->tnc;
1468 : 2 : data->wps = conf->wps;
1469 : 2 : data->pwd_group = conf->pwd_group;
1470 : 2 : data->server_id = conf->server_id;
1471 [ - + ]: 2 : if (conf->eap_req_id_text) {
1472 : 0 : data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
1473 [ # # ]: 0 : if (data->eap_req_id_text) {
1474 : 0 : os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
1475 : : conf->eap_req_id_text_len);
1476 : 0 : data->eap_req_id_text_len = conf->eap_req_id_text_len;
1477 : : }
1478 : : }
1479 : :
1480 [ - + ]: 2 : if (conf->subscr_remediation_url) {
1481 : 0 : data->subscr_remediation_url =
1482 : 0 : os_strdup(conf->subscr_remediation_url);
1483 : : }
1484 : :
1485 : : #ifdef CONFIG_RADIUS_TEST
1486 : : if (conf->dump_msk_file)
1487 : : data->dump_msk_file = os_strdup(conf->dump_msk_file);
1488 : : #endif /* CONFIG_RADIUS_TEST */
1489 : :
1490 : 2 : data->clients = radius_server_read_clients(conf->client_file,
1491 : : conf->ipv6);
1492 [ - + ]: 2 : if (data->clients == NULL) {
1493 : 0 : wpa_printf(MSG_ERROR, "No RADIUS clients configured");
1494 : 0 : radius_server_deinit(data);
1495 : 0 : return NULL;
1496 : : }
1497 : :
1498 : : #ifdef CONFIG_IPV6
1499 [ + + ]: 2 : if (conf->ipv6)
1500 : 1 : data->auth_sock = radius_server_open_socket6(conf->auth_port);
1501 : : else
1502 : : #endif /* CONFIG_IPV6 */
1503 : 1 : data->auth_sock = radius_server_open_socket(conf->auth_port);
1504 [ - + ]: 2 : if (data->auth_sock < 0) {
1505 : 0 : wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server");
1506 : 0 : radius_server_deinit(data);
1507 : 0 : return NULL;
1508 : : }
1509 [ - + ]: 2 : if (eloop_register_read_sock(data->auth_sock,
1510 : : radius_server_receive_auth,
1511 : : data, NULL)) {
1512 : 0 : radius_server_deinit(data);
1513 : 0 : return NULL;
1514 : : }
1515 : :
1516 [ + - ]: 2 : if (conf->acct_port) {
1517 : : #ifdef CONFIG_IPV6
1518 [ + + ]: 2 : if (conf->ipv6)
1519 : 1 : data->acct_sock = radius_server_open_socket6(
1520 : : conf->acct_port);
1521 : : else
1522 : : #endif /* CONFIG_IPV6 */
1523 : 1 : data->acct_sock = radius_server_open_socket(conf->acct_port);
1524 [ - + ]: 2 : if (data->acct_sock < 0) {
1525 : 0 : wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS accounting server");
1526 : 0 : radius_server_deinit(data);
1527 : 0 : return NULL;
1528 : : }
1529 [ - + ]: 2 : if (eloop_register_read_sock(data->acct_sock,
1530 : : radius_server_receive_acct,
1531 : : data, NULL)) {
1532 : 0 : radius_server_deinit(data);
1533 : 0 : return NULL;
1534 : : }
1535 : : } else {
1536 : 0 : data->acct_sock = -1;
1537 : : }
1538 : :
1539 : 2 : return data;
1540 : : }
1541 : :
1542 : :
1543 : : /**
1544 : : * radius_server_deinit - Deinitialize RADIUS server
1545 : : * @data: RADIUS server context from radius_server_init()
1546 : : */
1547 : 343 : void radius_server_deinit(struct radius_server_data *data)
1548 : : {
1549 [ + + ]: 343 : if (data == NULL)
1550 : 343 : return;
1551 : :
1552 [ + - ]: 2 : if (data->auth_sock >= 0) {
1553 : 2 : eloop_unregister_read_sock(data->auth_sock);
1554 : 2 : close(data->auth_sock);
1555 : : }
1556 : :
1557 [ + - ]: 2 : if (data->acct_sock >= 0) {
1558 : 2 : eloop_unregister_read_sock(data->acct_sock);
1559 : 2 : close(data->acct_sock);
1560 : : }
1561 : :
1562 : 2 : radius_server_free_clients(data, data->clients);
1563 : :
1564 : 2 : os_free(data->pac_opaque_encr_key);
1565 : 2 : os_free(data->eap_fast_a_id);
1566 : 2 : os_free(data->eap_fast_a_id_info);
1567 : 2 : os_free(data->eap_req_id_text);
1568 : : #ifdef CONFIG_RADIUS_TEST
1569 : : os_free(data->dump_msk_file);
1570 : : #endif /* CONFIG_RADIUS_TEST */
1571 : 2 : os_free(data->subscr_remediation_url);
1572 : 2 : os_free(data);
1573 : : }
1574 : :
1575 : :
1576 : : /**
1577 : : * radius_server_get_mib - Get RADIUS server MIB information
1578 : : * @data: RADIUS server context from radius_server_init()
1579 : : * @buf: Buffer for returning the MIB data in text format
1580 : : * @buflen: buf length in octets
1581 : : * Returns: Number of octets written into buf
1582 : : */
1583 : 2 : int radius_server_get_mib(struct radius_server_data *data, char *buf,
1584 : : size_t buflen)
1585 : : {
1586 : : int ret, uptime;
1587 : : unsigned int idx;
1588 : : char *end, *pos;
1589 : : struct os_reltime now;
1590 : : struct radius_client *cli;
1591 : :
1592 : : /* RFC 2619 - RADIUS Authentication Server MIB */
1593 : :
1594 [ + - ][ - + ]: 2 : if (data == NULL || buflen == 0)
1595 : 0 : return 0;
1596 : :
1597 : 2 : pos = buf;
1598 : 2 : end = buf + buflen;
1599 : :
1600 : 2 : os_get_reltime(&now);
1601 : 4 : uptime = (now.sec - data->start_time.sec) * 100 +
1602 : 2 : ((now.usec - data->start_time.usec) / 10000) % 100;
1603 : 2 : ret = os_snprintf(pos, end - pos,
1604 : : "RADIUS-AUTH-SERVER-MIB\n"
1605 : : "radiusAuthServIdent=hostapd\n"
1606 : : "radiusAuthServUpTime=%d\n"
1607 : : "radiusAuthServResetTime=0\n"
1608 : : "radiusAuthServConfigReset=4\n",
1609 : : uptime);
1610 [ - + ][ + - ]: 2 : if (ret < 0 || ret >= end - pos) {
1611 : 0 : *pos = '\0';
1612 : 0 : return pos - buf;
1613 : : }
1614 : 2 : pos += ret;
1615 : :
1616 : 2 : ret = os_snprintf(pos, end - pos,
1617 : : "radiusAuthServTotalAccessRequests=%u\n"
1618 : : "radiusAuthServTotalInvalidRequests=%u\n"
1619 : : "radiusAuthServTotalDupAccessRequests=%u\n"
1620 : : "radiusAuthServTotalAccessAccepts=%u\n"
1621 : : "radiusAuthServTotalAccessRejects=%u\n"
1622 : : "radiusAuthServTotalAccessChallenges=%u\n"
1623 : : "radiusAuthServTotalMalformedAccessRequests=%u\n"
1624 : : "radiusAuthServTotalBadAuthenticators=%u\n"
1625 : : "radiusAuthServTotalPacketsDropped=%u\n"
1626 : : "radiusAuthServTotalUnknownTypes=%u\n"
1627 : : "radiusAccServTotalRequests=%u\n"
1628 : : "radiusAccServTotalInvalidRequests=%u\n"
1629 : : "radiusAccServTotalResponses=%u\n"
1630 : : "radiusAccServTotalMalformedRequests=%u\n"
1631 : : "radiusAccServTotalBadAuthenticators=%u\n"
1632 : : "radiusAccServTotalUnknownTypes=%u\n",
1633 : : data->counters.access_requests,
1634 : : data->counters.invalid_requests,
1635 : : data->counters.dup_access_requests,
1636 : : data->counters.access_accepts,
1637 : : data->counters.access_rejects,
1638 : : data->counters.access_challenges,
1639 : : data->counters.malformed_access_requests,
1640 : : data->counters.bad_authenticators,
1641 : : data->counters.packets_dropped,
1642 : : data->counters.unknown_types,
1643 : : data->counters.acct_requests,
1644 : : data->counters.invalid_acct_requests,
1645 : : data->counters.acct_responses,
1646 : : data->counters.malformed_acct_requests,
1647 : : data->counters.acct_bad_authenticators,
1648 : : data->counters.unknown_acct_types);
1649 [ + - ][ - + ]: 2 : if (ret < 0 || ret >= end - pos) {
1650 : 0 : *pos = '\0';
1651 : 0 : return pos - buf;
1652 : : }
1653 : 2 : pos += ret;
1654 : :
1655 [ + + ]: 4 : for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1656 : : char abuf[50], mbuf[50];
1657 : : #ifdef CONFIG_IPV6
1658 [ - + ]: 2 : if (data->ipv6) {
1659 [ # # ]: 0 : if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1660 : : sizeof(abuf)) == NULL)
1661 : 0 : abuf[0] = '\0';
1662 [ # # ]: 0 : if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1663 : : sizeof(mbuf)) == NULL)
1664 : 0 : mbuf[0] = '\0';
1665 : : }
1666 : : #endif /* CONFIG_IPV6 */
1667 [ + - ]: 2 : if (!data->ipv6) {
1668 : 2 : os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1669 : 2 : os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1670 : : }
1671 : :
1672 : 2 : ret = os_snprintf(pos, end - pos,
1673 : : "radiusAuthClientIndex=%u\n"
1674 : : "radiusAuthClientAddress=%s/%s\n"
1675 : : "radiusAuthServAccessRequests=%u\n"
1676 : : "radiusAuthServDupAccessRequests=%u\n"
1677 : : "radiusAuthServAccessAccepts=%u\n"
1678 : : "radiusAuthServAccessRejects=%u\n"
1679 : : "radiusAuthServAccessChallenges=%u\n"
1680 : : "radiusAuthServMalformedAccessRequests=%u\n"
1681 : : "radiusAuthServBadAuthenticators=%u\n"
1682 : : "radiusAuthServPacketsDropped=%u\n"
1683 : : "radiusAuthServUnknownTypes=%u\n"
1684 : : "radiusAccServTotalRequests=%u\n"
1685 : : "radiusAccServTotalInvalidRequests=%u\n"
1686 : : "radiusAccServTotalResponses=%u\n"
1687 : : "radiusAccServTotalMalformedRequests=%u\n"
1688 : : "radiusAccServTotalBadAuthenticators=%u\n"
1689 : : "radiusAccServTotalUnknownTypes=%u\n",
1690 : : idx,
1691 : : abuf, mbuf,
1692 : : cli->counters.access_requests,
1693 : : cli->counters.dup_access_requests,
1694 : : cli->counters.access_accepts,
1695 : : cli->counters.access_rejects,
1696 : : cli->counters.access_challenges,
1697 : : cli->counters.malformed_access_requests,
1698 : : cli->counters.bad_authenticators,
1699 : : cli->counters.packets_dropped,
1700 : : cli->counters.unknown_types,
1701 : : cli->counters.acct_requests,
1702 : : cli->counters.invalid_acct_requests,
1703 : : cli->counters.acct_responses,
1704 : : cli->counters.malformed_acct_requests,
1705 : : cli->counters.acct_bad_authenticators,
1706 : : cli->counters.unknown_acct_types);
1707 [ + - ][ - + ]: 2 : if (ret < 0 || ret >= end - pos) {
1708 : 0 : *pos = '\0';
1709 : 0 : return pos - buf;
1710 : : }
1711 : 2 : pos += ret;
1712 : : }
1713 : :
1714 : 2 : return pos - buf;
1715 : : }
1716 : :
1717 : :
1718 : 334 : static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1719 : : size_t identity_len, int phase2,
1720 : : struct eap_user *user)
1721 : : {
1722 : 334 : struct radius_session *sess = ctx;
1723 : 334 : struct radius_server_data *data = sess->server;
1724 : : int ret;
1725 : :
1726 : 334 : ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
1727 : : phase2, user);
1728 [ + - ][ + - ]: 334 : if (ret == 0 && user)
1729 : 334 : sess->remediation = user->remediation;
1730 : 334 : return ret;
1731 : : }
1732 : :
1733 : :
1734 : 25 : static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
1735 : : {
1736 : 25 : struct radius_session *sess = ctx;
1737 : 25 : struct radius_server_data *data = sess->server;
1738 : 25 : *len = data->eap_req_id_text_len;
1739 : 25 : return data->eap_req_id_text;
1740 : : }
1741 : :
1742 : :
1743 : : static struct eapol_callbacks radius_server_eapol_cb =
1744 : : {
1745 : : .get_eap_user = radius_server_get_eap_user,
1746 : : .get_eap_req_id_text = radius_server_get_eap_req_id_text,
1747 : : };
1748 : :
1749 : :
1750 : : /**
1751 : : * radius_server_eap_pending_cb - Pending EAP data notification
1752 : : * @data: RADIUS server context from radius_server_init()
1753 : : * @ctx: Pending EAP context pointer
1754 : : *
1755 : : * This function is used to notify EAP server module that a pending operation
1756 : : * has been completed and processing of the EAP session can proceed.
1757 : : */
1758 : 16 : void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1759 : : {
1760 : : struct radius_client *cli;
1761 : 16 : struct radius_session *s, *sess = NULL;
1762 : : struct radius_msg *msg;
1763 : :
1764 [ - + ]: 16 : if (data == NULL)
1765 : 0 : return;
1766 : :
1767 [ + - ]: 16 : for (cli = data->clients; cli; cli = cli->next) {
1768 [ + - ]: 16 : for (s = cli->sessions; s; s = s->next) {
1769 [ + - ][ + - ]: 16 : if (s->eap == ctx && s->last_msg) {
1770 : 16 : sess = s;
1771 : 16 : break;
1772 : : }
1773 [ # # ]: 0 : if (sess)
1774 : 0 : break;
1775 : : }
1776 [ + - ]: 16 : if (sess)
1777 : 16 : break;
1778 : : }
1779 : :
1780 [ - + ]: 16 : if (sess == NULL) {
1781 : 0 : RADIUS_DEBUG("No session matched callback ctx");
1782 : 0 : return;
1783 : : }
1784 : :
1785 : 16 : msg = sess->last_msg;
1786 : 16 : sess->last_msg = NULL;
1787 : 16 : eap_sm_pending_cb(sess->eap);
1788 [ - + ]: 16 : if (radius_server_request(data, msg,
1789 : 16 : (struct sockaddr *) &sess->last_from,
1790 : : sess->last_fromlen, cli,
1791 : 16 : sess->last_from_addr,
1792 : : sess->last_from_port, sess) == -2)
1793 : 0 : return; /* msg was stored with the session */
1794 : :
1795 : 16 : radius_msg_free(msg);
1796 : : }
|