1 /*
2 * RADIUS authentication server
3 * Copyright (c) 2005-2009, 2011-2019, 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 #ifdef CONFIG_SQLITE
12 #include <sqlite3.h>
13 #endif /* CONFIG_SQLITE */
14
15 #include "common.h"
16 #include "radius.h"
17 #include "eloop.h"
18 #include "eap_server/eap.h"
19 #include "ap/ap_config.h"
20 #include "crypto/tls.h"
21 #include "radius_server.h"
22
23 /**
24 * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
25 */
26 #define RADIUS_SESSION_TIMEOUT 60
27
28 /**
29 * RADIUS_SESSION_MAINTAIN - Completed session expiration timeout in seconds
30 */
31 #define RADIUS_SESSION_MAINTAIN 5
32
33 /**
34 * RADIUS_MAX_SESSION - Maximum number of active sessions
35 */
36 #define RADIUS_MAX_SESSION 1000
37
38 /**
39 * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
40 */
41 #define RADIUS_MAX_MSG_LEN 3000
42
43 static const struct eapol_callbacks radius_server_eapol_cb;
44
45 struct radius_client;
46 struct radius_server_data;
47
48 /**
49 * struct radius_server_counters - RADIUS server statistics counters
50 */
51 struct radius_server_counters {
52 u32 access_requests;
53 u32 invalid_requests;
54 u32 dup_access_requests;
55 u32 access_accepts;
56 u32 access_rejects;
57 u32 access_challenges;
58 u32 malformed_access_requests;
59 u32 bad_authenticators;
60 u32 packets_dropped;
61 u32 unknown_types;
62
63 u32 acct_requests;
64 u32 invalid_acct_requests;
65 u32 acct_responses;
66 u32 malformed_acct_requests;
67 u32 acct_bad_authenticators;
68 u32 unknown_acct_types;
69 };
70
71 /**
72 * struct radius_session - Internal RADIUS server data for a session
73 */
74 struct radius_session {
75 struct radius_session *next;
76 struct radius_client *client;
77 struct radius_server_data *server;
78 unsigned int sess_id;
79 struct eap_sm *eap;
80 struct eap_eapol_interface *eap_if;
81 char *username; /* from User-Name attribute */
82 char *nas_ip;
83 u8 mac_addr[ETH_ALEN]; /* from Calling-Station-Id attribute */
84
85 struct radius_msg *last_msg;
86 char *last_from_addr;
87 int last_from_port;
88 struct sockaddr_storage last_from;
89 socklen_t last_fromlen;
90 u8 last_identifier;
91 struct radius_msg *last_reply;
92 u8 last_authenticator[16];
93
94 unsigned int remediation:1;
95 unsigned int macacl:1;
96 unsigned int t_c_filtering:1;
97
98 struct hostapd_radius_attr *accept_attr;
99
100 u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
101 };
102
103 /**
104 * struct radius_client - Internal RADIUS server data for a client
105 */
106 struct radius_client {
107 struct radius_client *next;
108 struct in_addr addr;
109 struct in_addr mask;
110 #ifdef CONFIG_IPV6
111 struct in6_addr addr6;
112 struct in6_addr mask6;
113 #endif /* CONFIG_IPV6 */
114 char *shared_secret;
115 int shared_secret_len;
116 struct radius_session *sessions;
117 struct radius_server_counters counters;
118
119 u8 next_dac_identifier;
120 struct radius_msg *pending_dac_coa_req;
121 u8 pending_dac_coa_id;
122 u8 pending_dac_coa_addr[ETH_ALEN];
123 struct radius_msg *pending_dac_disconnect_req;
124 u8 pending_dac_disconnect_id;
125 u8 pending_dac_disconnect_addr[ETH_ALEN];
126 };
127
128 /**
129 * struct radius_server_data - Internal RADIUS server data
130 */
131 struct radius_server_data {
132 /**
133 * auth_sock - Socket for RADIUS authentication messages
134 */
135 int auth_sock;
136
137 /**
138 * acct_sock - Socket for RADIUS accounting messages
139 */
140 int acct_sock;
141
142 /**
143 * clients - List of authorized RADIUS clients
144 */
145 struct radius_client *clients;
146
147 /**
148 * next_sess_id - Next session identifier
149 */
150 unsigned int next_sess_id;
151
152 /**
153 * conf_ctx - Context pointer for callbacks
154 *
155 * This is used as the ctx argument in get_eap_user() calls.
156 */
157 void *conf_ctx;
158
159 /**
160 * num_sess - Number of active sessions
161 */
162 int num_sess;
163
164 const char *erp_domain;
165
166 struct dl_list erp_keys; /* struct eap_server_erp_key */
167
168 /**
169 * ipv6 - Whether to enable IPv6 support in the RADIUS server
170 */
171 int ipv6;
172
173 /**
174 * start_time - Timestamp of server start
175 */
176 struct os_reltime start_time;
177
178 /**
179 * counters - Statistics counters for server operations
180 *
181 * These counters are the sum over all clients.
182 */
183 struct radius_server_counters counters;
184
185 /**
186 * get_eap_user - Callback for fetching EAP user information
187 * @ctx: Context data from conf_ctx
188 * @identity: User identity
189 * @identity_len: identity buffer length in octets
190 * @phase2: Whether this is for Phase 2 identity
191 * @user: Data structure for filling in the user information
192 * Returns: 0 on success, -1 on failure
193 *
194 * This is used to fetch information from user database. The callback
195 * will fill in information about allowed EAP methods and the user
196 * password. The password field will be an allocated copy of the
197 * password data and RADIUS server will free it after use.
198 */
199 int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
200 int phase2, struct eap_user *user);
201
202 /**
203 * eap_req_id_text - Optional data for EAP-Request/Identity
204 *
205 * This can be used to configure an optional, displayable message that
206 * will be sent in EAP-Request/Identity. This string can contain an
207 * ASCII-0 character (nul) to separate network infromation per RFC
208 * 4284. The actual string length is explicit provided in
209 * eap_req_id_text_len since nul character will not be used as a string
210 * terminator.
211 */
212 char *eap_req_id_text;
213
214 /**
215 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
216 */
217 size_t eap_req_id_text_len;
218
219 #ifdef CONFIG_RADIUS_TEST
220 char *dump_msk_file;
221 #endif /* CONFIG_RADIUS_TEST */
222
223 char *subscr_remediation_url;
224 u8 subscr_remediation_method;
225 char *hs20_sim_provisioning_url;
226
227 char *t_c_server_url;
228
229 #ifdef CONFIG_SQLITE
230 sqlite3 *db;
231 #endif /* CONFIG_SQLITE */
232
233 const struct eap_config *eap_cfg;
234 };
235
236
237 #define RADIUS_DEBUG(args...) \
238 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
239 #define RADIUS_ERROR(args...) \
240 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
241 #define RADIUS_DUMP(args...) \
242 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
243 #define RADIUS_DUMP_ASCII(args...) \
244 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
245
246
247 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
248 static void radius_server_session_remove_timeout(void *eloop_ctx,
249 void *timeout_ctx);
250
251 #ifdef CONFIG_SQLITE
252 #ifdef CONFIG_HS20
253
db_table_exists(sqlite3 * db,const char * name)254 static int db_table_exists(sqlite3 *db, const char *name)
255 {
256 char cmd[128];
257
258 os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
259 return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
260 }
261
262
db_table_create_sim_provisioning(sqlite3 * db)263 static int db_table_create_sim_provisioning(sqlite3 *db)
264 {
265 char *err = NULL;
266 const char *sql =
267 "CREATE TABLE sim_provisioning("
268 " mobile_identifier_hash TEXT PRIMARY KEY,"
269 " imsi TEXT,"
270 " mac_addr TEXT,"
271 " eap_method TEXT,"
272 " timestamp TEXT"
273 ");";
274
275 RADIUS_DEBUG("Adding database table for SIM provisioning information");
276 if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
277 RADIUS_ERROR("SQLite error: %s", err);
278 sqlite3_free(err);
279 return -1;
280 }
281
282 return 0;
283 }
284
285 #endif /* CONFIG_HS20 */
286 #endif /* CONFIG_SQLITE */
287
288
289 void srv_log(struct radius_session *sess, const char *fmt, ...)
290 PRINTF_FORMAT(2, 3);
291
srv_log(struct radius_session * sess,const char * fmt,...)292 void srv_log(struct radius_session *sess, const char *fmt, ...)
293 {
294 va_list ap;
295 char *buf;
296 int buflen;
297
298 va_start(ap, fmt);
299 buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
300 va_end(ap);
301
302 buf = os_malloc(buflen);
303 if (buf == NULL)
304 return;
305 va_start(ap, fmt);
306 vsnprintf(buf, buflen, fmt, ap);
307 va_end(ap);
308
309 RADIUS_DEBUG("[0x%x %s] %s", sess->sess_id, sess->nas_ip, buf);
310
311 #ifdef CONFIG_SQLITE
312 if (sess->server->db) {
313 char *sql;
314 sql = sqlite3_mprintf("INSERT INTO authlog"
315 "(timestamp,session,nas_ip,username,note)"
316 " VALUES ("
317 "strftime('%%Y-%%m-%%d %%H:%%M:%%f',"
318 "'now'),%u,%Q,%Q,%Q)",
319 sess->sess_id, sess->nas_ip,
320 sess->username, buf);
321 if (sql) {
322 if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
323 NULL) != SQLITE_OK) {
324 RADIUS_ERROR("Failed to add authlog entry into sqlite database: %s",
325 sqlite3_errmsg(sess->server->db));
326 }
327 sqlite3_free(sql);
328 }
329 }
330 #endif /* CONFIG_SQLITE */
331
332 os_free(buf);
333 }
334
335
336 static struct radius_client *
radius_server_get_client(struct radius_server_data * data,struct in_addr * addr,int ipv6)337 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
338 int ipv6)
339 {
340 struct radius_client *client = data->clients;
341
342 while (client) {
343 #ifdef CONFIG_IPV6
344 if (ipv6) {
345 struct in6_addr *addr6;
346 int i;
347
348 addr6 = (struct in6_addr *) addr;
349 for (i = 0; i < 16; i++) {
350 if ((addr6->s6_addr[i] &
351 client->mask6.s6_addr[i]) !=
352 (client->addr6.s6_addr[i] &
353 client->mask6.s6_addr[i])) {
354 i = 17;
355 break;
356 }
357 }
358 if (i == 16) {
359 break;
360 }
361 }
362 #endif /* CONFIG_IPV6 */
363 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
364 (addr->s_addr & client->mask.s_addr)) {
365 break;
366 }
367
368 client = client->next;
369 }
370
371 return client;
372 }
373
374
375 static struct radius_session *
radius_server_get_session(struct radius_client * client,unsigned int sess_id)376 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
377 {
378 struct radius_session *sess = client->sessions;
379
380 while (sess) {
381 if (sess->sess_id == sess_id) {
382 break;
383 }
384 sess = sess->next;
385 }
386
387 return sess;
388 }
389
390
radius_server_session_free(struct radius_server_data * data,struct radius_session * sess)391 static void radius_server_session_free(struct radius_server_data *data,
392 struct radius_session *sess)
393 {
394 eloop_cancel_timeout(radius_server_session_timeout, data, sess);
395 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
396 eap_server_sm_deinit(sess->eap);
397 radius_msg_free(sess->last_msg);
398 os_free(sess->last_from_addr);
399 radius_msg_free(sess->last_reply);
400 os_free(sess->username);
401 os_free(sess->nas_ip);
402 os_free(sess);
403 data->num_sess--;
404 }
405
406
radius_server_session_remove(struct radius_server_data * data,struct radius_session * sess)407 static void radius_server_session_remove(struct radius_server_data *data,
408 struct radius_session *sess)
409 {
410 struct radius_client *client = sess->client;
411 struct radius_session *session, *prev;
412
413 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
414
415 prev = NULL;
416 session = client->sessions;
417 while (session) {
418 if (session == sess) {
419 if (prev == NULL) {
420 client->sessions = sess->next;
421 } else {
422 prev->next = sess->next;
423 }
424 radius_server_session_free(data, sess);
425 break;
426 }
427 prev = session;
428 session = session->next;
429 }
430 }
431
432
radius_server_session_remove_timeout(void * eloop_ctx,void * timeout_ctx)433 static void radius_server_session_remove_timeout(void *eloop_ctx,
434 void *timeout_ctx)
435 {
436 struct radius_server_data *data = eloop_ctx;
437 struct radius_session *sess = timeout_ctx;
438 RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
439 radius_server_session_remove(data, sess);
440 }
441
442
radius_server_session_timeout(void * eloop_ctx,void * timeout_ctx)443 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
444 {
445 struct radius_server_data *data = eloop_ctx;
446 struct radius_session *sess = timeout_ctx;
447
448 RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
449 radius_server_session_remove(data, sess);
450 }
451
452
453 static struct radius_session *
radius_server_new_session(struct radius_server_data * data,struct radius_client * client)454 radius_server_new_session(struct radius_server_data *data,
455 struct radius_client *client)
456 {
457 struct radius_session *sess;
458
459 if (data->num_sess >= RADIUS_MAX_SESSION) {
460 RADIUS_DEBUG("Maximum number of existing session - no room "
461 "for a new session");
462 return NULL;
463 }
464
465 sess = os_zalloc(sizeof(*sess));
466 if (sess == NULL)
467 return NULL;
468
469 sess->server = data;
470 sess->client = client;
471 sess->sess_id = data->next_sess_id++;
472 sess->next = client->sessions;
473 client->sessions = sess;
474 eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
475 radius_server_session_timeout, data, sess);
476 data->num_sess++;
477 return sess;
478 }
479
480
481 #ifdef CONFIG_TESTING_OPTIONS
radius_server_testing_options_tls(struct radius_session * sess,const char * tls,struct eap_session_data * eap_conf)482 static void radius_server_testing_options_tls(struct radius_session *sess,
483 const char *tls,
484 struct eap_session_data *eap_conf)
485 {
486 int test = atoi(tls);
487
488 switch (test) {
489 case 1:
490 srv_log(sess, "TLS test - break VerifyData");
491 eap_conf->tls_test_flags = TLS_BREAK_VERIFY_DATA;
492 break;
493 case 2:
494 srv_log(sess, "TLS test - break ServerKeyExchange ServerParams hash");
495 eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_HASH;
496 break;
497 case 3:
498 srv_log(sess, "TLS test - break ServerKeyExchange ServerParams Signature");
499 eap_conf->tls_test_flags = TLS_BREAK_SRV_KEY_X_SIGNATURE;
500 break;
501 case 4:
502 srv_log(sess, "TLS test - RSA-DHE using a short 511-bit prime");
503 eap_conf->tls_test_flags = TLS_DHE_PRIME_511B;
504 break;
505 case 5:
506 srv_log(sess, "TLS test - RSA-DHE using a short 767-bit prime");
507 eap_conf->tls_test_flags = TLS_DHE_PRIME_767B;
508 break;
509 case 6:
510 srv_log(sess, "TLS test - RSA-DHE using a bogus 15 \"prime\"");
511 eap_conf->tls_test_flags = TLS_DHE_PRIME_15;
512 break;
513 case 7:
514 srv_log(sess, "TLS test - RSA-DHE using a short 58-bit prime in long container");
515 eap_conf->tls_test_flags = TLS_DHE_PRIME_58B;
516 break;
517 case 8:
518 srv_log(sess, "TLS test - RSA-DHE using a non-prime");
519 eap_conf->tls_test_flags = TLS_DHE_NON_PRIME;
520 break;
521 default:
522 srv_log(sess, "Unrecognized TLS test");
523 break;
524 }
525 }
526 #endif /* CONFIG_TESTING_OPTIONS */
527
radius_server_testing_options(struct radius_session * sess,struct eap_session_data * eap_conf)528 static void radius_server_testing_options(struct radius_session *sess,
529 struct eap_session_data *eap_conf)
530 {
531 #ifdef CONFIG_TESTING_OPTIONS
532 const char *pos;
533
534 pos = os_strstr(sess->username, "@test-");
535 if (pos == NULL)
536 return;
537 pos += 6;
538 if (os_strncmp(pos, "tls-", 4) == 0)
539 radius_server_testing_options_tls(sess, pos + 4, eap_conf);
540 else
541 srv_log(sess, "Unrecognized test: %s", pos);
542 #endif /* CONFIG_TESTING_OPTIONS */
543 }
544
545
546 #ifdef CONFIG_ERP
547 static struct eap_server_erp_key *
radius_server_erp_find_key(struct radius_server_data * data,const char * keyname)548 radius_server_erp_find_key(struct radius_server_data *data, const char *keyname)
549 {
550 struct eap_server_erp_key *erp;
551
552 dl_list_for_each(erp, &data->erp_keys, struct eap_server_erp_key,
553 list) {
554 if (os_strcmp(erp->keyname_nai, keyname) == 0)
555 return erp;
556 }
557
558 return NULL;
559 }
560 #endif /* CONFIG_ERP */
561
562
563 static struct radius_session *
radius_server_get_new_session(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,const char * from_addr)564 radius_server_get_new_session(struct radius_server_data *data,
565 struct radius_client *client,
566 struct radius_msg *msg, const char *from_addr)
567 {
568 u8 *user, *id;
569 size_t user_len, id_len;
570 int res;
571 struct radius_session *sess;
572 struct eap_session_data eap_sess;
573 struct eap_user *tmp;
574
575 RADIUS_DEBUG("Creating a new session");
576
577 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &user,
578 &user_len, NULL) < 0) {
579 RADIUS_DEBUG("Could not get User-Name");
580 return NULL;
581 }
582 RADIUS_DUMP_ASCII("User-Name", user, user_len);
583
584 tmp = os_zalloc(sizeof(*tmp));
585 if (!tmp)
586 return NULL;
587
588 res = data->get_eap_user(data->conf_ctx, user, user_len, 0, tmp);
589 #ifdef CONFIG_ERP
590 if (res != 0 && data->eap_cfg->erp) {
591 char *username;
592
593 username = os_zalloc(user_len + 1);
594 if (username) {
595 os_memcpy(username, user, user_len);
596 if (radius_server_erp_find_key(data, username))
597 res = 0;
598 os_free(username);
599 }
600 }
601 #endif /* CONFIG_ERP */
602 if (res != 0) {
603 RADIUS_DEBUG("User-Name not found from user database");
604 eap_user_free(tmp);
605 return NULL;
606 }
607
608 RADIUS_DEBUG("Matching user entry found");
609 sess = radius_server_new_session(data, client);
610 if (sess == NULL) {
611 RADIUS_DEBUG("Failed to create a new session");
612 eap_user_free(tmp);
613 return NULL;
614 }
615 sess->accept_attr = tmp->accept_attr;
616 sess->macacl = tmp->macacl;
617 eap_user_free(tmp);
618
619 sess->username = os_malloc(user_len * 4 + 1);
620 if (sess->username == NULL) {
621 radius_server_session_remove(data, sess);
622 return NULL;
623 }
624 printf_encode(sess->username, user_len * 4 + 1, user, user_len);
625
626 sess->nas_ip = os_strdup(from_addr);
627 if (sess->nas_ip == NULL) {
628 radius_server_session_remove(data, sess);
629 return NULL;
630 }
631
632 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, &id,
633 &id_len, NULL) == 0) {
634 char buf[3 * ETH_ALEN];
635
636 os_memset(buf, 0, sizeof(buf));
637 if (id_len >= sizeof(buf))
638 id_len = sizeof(buf) - 1;
639 os_memcpy(buf, id, id_len);
640 if (hwaddr_aton2(buf, sess->mac_addr) < 0)
641 os_memset(sess->mac_addr, 0, ETH_ALEN);
642 else
643 RADIUS_DEBUG("Calling-Station-Id: " MACSTR,
644 MAC2STR(sess->mac_addr));
645 }
646
647 srv_log(sess, "New session created");
648
649 os_memset(&eap_sess, 0, sizeof(eap_sess));
650 radius_server_testing_options(sess, &eap_sess);
651 sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
652 data->eap_cfg, &eap_sess);
653 if (sess->eap == NULL) {
654 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
655 "new session");
656 radius_server_session_remove(data, sess);
657 return NULL;
658 }
659 sess->eap_if = eap_get_interface(sess->eap);
660 sess->eap_if->eapRestart = true;
661 sess->eap_if->portEnabled = true;
662
663 RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
664
665 return sess;
666 }
667
668
669 #ifdef CONFIG_HS20
radius_srv_hs20_t_c_pending(struct radius_session * sess)670 static void radius_srv_hs20_t_c_pending(struct radius_session *sess)
671 {
672 #ifdef CONFIG_SQLITE
673 char *sql;
674 char addr[3 * ETH_ALEN], *id_str;
675 const u8 *id;
676 size_t id_len;
677
678 if (!sess->server->db || !sess->eap ||
679 is_zero_ether_addr(sess->mac_addr))
680 return;
681
682 os_snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sess->mac_addr));
683
684 id = eap_get_identity(sess->eap, &id_len);
685 if (!id)
686 return;
687 id_str = os_malloc(id_len + 1);
688 if (!id_str)
689 return;
690 os_memcpy(id_str, id, id_len);
691 id_str[id_len] = '\0';
692
693 sql = sqlite3_mprintf("INSERT OR REPLACE INTO pending_tc (mac_addr,identity) VALUES (%Q,%Q)",
694 addr, id_str);
695 os_free(id_str);
696 if (!sql)
697 return;
698
699 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
700 SQLITE_OK) {
701 RADIUS_ERROR("Failed to add pending_tc entry into sqlite database: %s",
702 sqlite3_errmsg(sess->server->db));
703 }
704 sqlite3_free(sql);
705 #endif /* CONFIG_SQLITE */
706 }
707 #endif /* CONFIG_HS20 */
708
709
radius_server_add_session(struct radius_session * sess)710 static void radius_server_add_session(struct radius_session *sess)
711 {
712 #ifdef CONFIG_SQLITE
713 char *sql;
714 char addr_txt[ETH_ALEN * 3];
715 struct os_time now;
716
717 if (!sess->server->db)
718 return;
719
720
721 os_snprintf(addr_txt, sizeof(addr_txt), MACSTR,
722 MAC2STR(sess->mac_addr));
723
724 os_get_time(&now);
725 sql = sqlite3_mprintf("INSERT OR REPLACE INTO current_sessions(mac_addr,identity,start_time,nas,hs20_t_c_filtering) VALUES (%Q,%Q,%d,%Q,%u)",
726 addr_txt, sess->username, now.sec,
727 sess->nas_ip, sess->t_c_filtering);
728 if (sql) {
729 if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
730 NULL) != SQLITE_OK) {
731 RADIUS_ERROR("Failed to add current_sessions entry into sqlite database: %s",
732 sqlite3_errmsg(sess->server->db));
733 }
734 sqlite3_free(sql);
735 }
736 #endif /* CONFIG_SQLITE */
737 }
738
739
db_update_last_msk(struct radius_session * sess,const char * msk)740 static void db_update_last_msk(struct radius_session *sess, const char *msk)
741 {
742 #ifdef CONFIG_RADIUS_TEST
743 #ifdef CONFIG_SQLITE
744 char *sql = NULL;
745 char *id_str = NULL;
746 const u8 *id;
747 size_t id_len;
748 const char *serial_num;
749
750 if (!sess->server->db)
751 return;
752
753 serial_num = eap_get_serial_num(sess->eap);
754 if (serial_num) {
755 id_len = 5 + os_strlen(serial_num) + 1;
756 id_str = os_malloc(id_len);
757 if (!id_str)
758 return;
759 os_snprintf(id_str, id_len, "cert-%s", serial_num);
760 } else {
761 id = eap_get_identity(sess->eap, &id_len);
762 if (!id)
763 return;
764 id_str = os_malloc(id_len + 1);
765 if (!id_str)
766 return;
767 os_memcpy(id_str, id, id_len);
768 id_str[id_len] = '\0';
769 }
770
771 sql = sqlite3_mprintf("UPDATE users SET last_msk=%Q WHERE identity=%Q",
772 msk, id_str);
773 os_free(id_str);
774 if (!sql)
775 return;
776
777 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
778 SQLITE_OK) {
779 RADIUS_DEBUG("Failed to update last_msk: %s",
780 sqlite3_errmsg(sess->server->db));
781 }
782 sqlite3_free(sql);
783 #endif /* CONFIG_SQLITE */
784 #endif /* CONFIG_RADIUS_TEST */
785 }
786
787
788 #ifdef CONFIG_HS20
789
radius_server_is_sim_method(struct radius_session * sess)790 static int radius_server_is_sim_method(struct radius_session *sess)
791 {
792 const char *name;
793
794 name = eap_get_method(sess->eap);
795 return name &&
796 (os_strcmp(name, "SIM") == 0 ||
797 os_strcmp(name, "AKA") == 0 ||
798 os_strcmp(name, "AKA'") == 0);
799 }
800
801
radius_server_hs20_missing_sim_pps(struct radius_msg * request)802 static int radius_server_hs20_missing_sim_pps(struct radius_msg *request)
803 {
804 u8 *buf, *pos, *end, type, sublen;
805 size_t len;
806
807 buf = NULL;
808 for (;;) {
809 if (radius_msg_get_attr_ptr(request,
810 RADIUS_ATTR_VENDOR_SPECIFIC,
811 &buf, &len, buf) < 0)
812 return 0;
813 if (len < 6)
814 continue;
815 pos = buf;
816 end = buf + len;
817 if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
818 continue;
819 pos += 4;
820
821 type = *pos++;
822 sublen = *pos++;
823 if (sublen < 2)
824 continue; /* invalid length */
825 sublen -= 2; /* skip header */
826 if (pos + sublen > end)
827 continue; /* invalid WFA VSA */
828
829 if (type != RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION)
830 continue;
831
832 RADIUS_DUMP("HS2.0 mobile device version", pos, sublen);
833 if (sublen < 1 + 2)
834 continue;
835 if (pos[0] == 0)
836 continue; /* Release 1 STA does not support provisioning
837
838 */
839 /* UpdateIdentifier 0 indicates no PPS MO */
840 return WPA_GET_BE16(pos + 1) == 0;
841 }
842 }
843
844
845 #define HS20_MOBILE_ID_HASH_LEN 16
846
radius_server_sim_provisioning_session(struct radius_session * sess,const u8 * hash)847 static int radius_server_sim_provisioning_session(struct radius_session *sess,
848 const u8 *hash)
849 {
850 #ifdef CONFIG_SQLITE
851 char *sql;
852 char addr_txt[ETH_ALEN * 3];
853 char hash_txt[2 * HS20_MOBILE_ID_HASH_LEN + 1];
854 struct os_time now;
855 int res;
856 const char *imsi, *eap_method;
857
858 if (!sess->server->db ||
859 (!db_table_exists(sess->server->db, "sim_provisioning") &&
860 db_table_create_sim_provisioning(sess->server->db) < 0))
861 return -1;
862
863 imsi = eap_get_imsi(sess->eap);
864 if (!imsi)
865 return -1;
866
867 eap_method = eap_get_method(sess->eap);
868 if (!eap_method)
869 return -1;
870
871 os_snprintf(addr_txt, sizeof(addr_txt), MACSTR,
872 MAC2STR(sess->mac_addr));
873 wpa_snprintf_hex(hash_txt, sizeof(hash_txt), hash,
874 HS20_MOBILE_ID_HASH_LEN);
875
876 os_get_time(&now);
877 sql = sqlite3_mprintf("INSERT INTO sim_provisioning(mobile_identifier_hash,imsi,mac_addr,eap_method,timestamp) VALUES (%Q,%Q,%Q,%Q,%u)",
878 hash_txt, imsi, addr_txt, eap_method, now.sec);
879 if (!sql)
880 return -1;
881
882 if (sqlite3_exec(sess->server->db, sql, NULL, NULL, NULL) !=
883 SQLITE_OK) {
884 RADIUS_ERROR("Failed to add SIM provisioning entry into sqlite database: %s",
885 sqlite3_errmsg(sess->server->db));
886 res = -1;
887 } else {
888 res = 0;
889 }
890 sqlite3_free(sql);
891 return res;
892 #endif /* CONFIG_SQLITE */
893 return -1;
894 }
895
896 #endif /* CONFIG_HS20 */
897
898
899 static struct radius_msg *
radius_server_encapsulate_eap(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)900 radius_server_encapsulate_eap(struct radius_server_data *data,
901 struct radius_client *client,
902 struct radius_session *sess,
903 struct radius_msg *request)
904 {
905 struct radius_msg *msg;
906 int code;
907 unsigned int sess_id;
908 struct radius_hdr *hdr = radius_msg_get_hdr(request);
909 u16 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
910
911 if (sess->eap_if->eapFail) {
912 sess->eap_if->eapFail = false;
913 code = RADIUS_CODE_ACCESS_REJECT;
914 } else if (sess->eap_if->eapSuccess) {
915 sess->eap_if->eapSuccess = false;
916 code = RADIUS_CODE_ACCESS_ACCEPT;
917 } else {
918 sess->eap_if->eapReq = false;
919 code = RADIUS_CODE_ACCESS_CHALLENGE;
920 }
921
922 msg = radius_msg_new(code, hdr->identifier);
923 if (msg == NULL) {
924 RADIUS_DEBUG("Failed to allocate reply message");
925 return NULL;
926 }
927
928 sess_id = htonl(sess->sess_id);
929 if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
930 !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
931 (u8 *) &sess_id, sizeof(sess_id))) {
932 RADIUS_DEBUG("Failed to add State attribute");
933 }
934
935 if (sess->eap_if->eapReqData &&
936 !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
937 wpabuf_len(sess->eap_if->eapReqData))) {
938 RADIUS_DEBUG("Failed to add EAP-Message attribute");
939 }
940
941 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
942 int len;
943 #ifdef CONFIG_RADIUS_TEST
944 char buf[2 * 64 + 1];
945
946 len = sess->eap_if->eapKeyDataLen;
947 if (len > 64)
948 len = 64;
949 len = wpa_snprintf_hex(buf, sizeof(buf),
950 sess->eap_if->eapKeyData, len);
951 buf[len] = '\0';
952
953 if (data->dump_msk_file) {
954 FILE *f;
955
956 f = fopen(data->dump_msk_file, "a");
957 if (f) {
958 len = sess->eap_if->eapKeyDataLen;
959 if (len > 64)
960 len = 64;
961 len = wpa_snprintf_hex(
962 buf, sizeof(buf),
963 sess->eap_if->eapKeyData, len);
964 buf[len] = '\0';
965 fprintf(f, "%s\n", buf);
966 fclose(f);
967 }
968 }
969
970 db_update_last_msk(sess, buf);
971 #endif /* CONFIG_RADIUS_TEST */
972 if (sess->eap_if->eapKeyDataLen > 64) {
973 len = 32;
974 } else {
975 len = sess->eap_if->eapKeyDataLen / 2;
976 }
977 if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
978 (u8 *) client->shared_secret,
979 client->shared_secret_len,
980 sess->eap_if->eapKeyData + len,
981 len, sess->eap_if->eapKeyData,
982 len)) {
983 RADIUS_DEBUG("Failed to add MPPE key attributes");
984 }
985
986 if (sess->eap_if->eapSessionId &&
987 !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME,
988 sess->eap_if->eapSessionId,
989 sess->eap_if->eapSessionIdLen)) {
990 RADIUS_DEBUG("Failed to add EAP-Key-Name attribute");
991 }
992 }
993
994 #ifdef CONFIG_HS20
995 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation &&
996 data->subscr_remediation_url) {
997 u8 *buf;
998 size_t url_len = os_strlen(data->subscr_remediation_url);
999 buf = os_malloc(1 + url_len);
1000 if (buf == NULL) {
1001 radius_msg_free(msg);
1002 return NULL;
1003 }
1004 buf[0] = data->subscr_remediation_method;
1005 os_memcpy(&buf[1], data->subscr_remediation_url, url_len);
1006 if (!radius_msg_add_wfa(
1007 msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1008 buf, 1 + url_len)) {
1009 RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1010 }
1011 os_free(buf);
1012 } else if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->remediation) {
1013 u8 buf[1];
1014 if (!radius_msg_add_wfa(
1015 msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1016 buf, 0)) {
1017 RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1018 }
1019 } else if (code == RADIUS_CODE_ACCESS_ACCEPT &&
1020 data->hs20_sim_provisioning_url &&
1021 radius_server_is_sim_method(sess) &&
1022 radius_server_hs20_missing_sim_pps(request)) {
1023 u8 *buf, *pos, hash[HS20_MOBILE_ID_HASH_LEN];
1024 size_t prefix_len, url_len;
1025
1026 RADIUS_DEBUG("Device needs HS 2.0 SIM provisioning");
1027
1028 if (os_get_random(hash, HS20_MOBILE_ID_HASH_LEN) < 0) {
1029 radius_msg_free(msg);
1030 return NULL;
1031 }
1032 RADIUS_DUMP("hotspot2dot0-mobile-identifier-hash",
1033 hash, HS20_MOBILE_ID_HASH_LEN);
1034
1035 if (radius_server_sim_provisioning_session(sess, hash) < 0) {
1036 radius_msg_free(msg);
1037 return NULL;
1038 }
1039
1040 prefix_len = os_strlen(data->hs20_sim_provisioning_url);
1041 url_len = prefix_len + 2 * HS20_MOBILE_ID_HASH_LEN;
1042 buf = os_malloc(1 + url_len + 1);
1043 if (!buf) {
1044 radius_msg_free(msg);
1045 return NULL;
1046 }
1047 pos = buf;
1048 *pos++ = data->subscr_remediation_method;
1049 os_memcpy(pos, data->hs20_sim_provisioning_url, prefix_len);
1050 pos += prefix_len;
1051 wpa_snprintf_hex((char *) pos, 2 * HS20_MOBILE_ID_HASH_LEN + 1,
1052 hash, HS20_MOBILE_ID_HASH_LEN);
1053 RADIUS_DEBUG("HS 2.0 subscription remediation URL: %s",
1054 (char *) &buf[1]);
1055 if (!radius_msg_add_wfa(
1056 msg, RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION,
1057 buf, 1 + url_len)) {
1058 RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
1059 }
1060 os_free(buf);
1061 }
1062
1063 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) {
1064 u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */
1065 const char *url = data->t_c_server_url, *pos;
1066 char *url2, *end2, *pos2;
1067 size_t url_len;
1068
1069 if (!radius_msg_add_wfa(
1070 msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
1071 buf, sizeof(buf))) {
1072 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
1073 radius_msg_free(msg);
1074 return NULL;
1075 }
1076
1077 if (!url) {
1078 RADIUS_DEBUG("No t_c_server_url configured");
1079 radius_msg_free(msg);
1080 return NULL;
1081 }
1082
1083 pos = os_strstr(url, "@1@");
1084 if (!pos) {
1085 RADIUS_DEBUG("No @1@ macro in t_c_server_url");
1086 radius_msg_free(msg);
1087 return NULL;
1088 }
1089
1090 url_len = os_strlen(url) + ETH_ALEN * 3 - 1 - 3;
1091 url2 = os_malloc(url_len + 1);
1092 if (!url2) {
1093 RADIUS_DEBUG("Failed to allocate room for T&C Server URL");
1094 os_free(url2);
1095 radius_msg_free(msg);
1096 return NULL;
1097 }
1098 pos2 = url2;
1099 end2 = url2 + url_len + 1;
1100 os_memcpy(pos2, url, pos - url);
1101 pos2 += pos - url;
1102 os_snprintf(pos2, end2 - pos2, MACSTR, MAC2STR(sess->mac_addr));
1103 pos2 += ETH_ALEN * 3 - 1;
1104 os_memcpy(pos2, pos + 3, os_strlen(pos + 3));
1105 if (!radius_msg_add_wfa(msg,
1106 RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL,
1107 (const u8 *) url2, url_len)) {
1108 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-URL");
1109 os_free(url2);
1110 radius_msg_free(msg);
1111 return NULL;
1112 }
1113 os_free(url2);
1114
1115 radius_srv_hs20_t_c_pending(sess);
1116 }
1117 #endif /* CONFIG_HS20 */
1118
1119 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1120 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1121 radius_msg_free(msg);
1122 return NULL;
1123 }
1124
1125 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
1126 struct hostapd_radius_attr *attr;
1127 for (attr = sess->accept_attr; attr; attr = attr->next) {
1128 if (!radius_msg_add_attr(msg, attr->type,
1129 wpabuf_head(attr->val),
1130 wpabuf_len(attr->val))) {
1131 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
1132 radius_msg_free(msg);
1133 return NULL;
1134 }
1135 }
1136 }
1137
1138 if (code == RADIUS_CODE_ACCESS_REJECT) {
1139 if (radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
1140 reason) < 0) {
1141 RADIUS_DEBUG("Failed to add WLAN-Reason-Code attribute");
1142 radius_msg_free(msg);
1143 return NULL;
1144 }
1145 }
1146
1147 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1148 client->shared_secret_len,
1149 hdr->authenticator) < 0) {
1150 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1151 }
1152
1153 if (code == RADIUS_CODE_ACCESS_ACCEPT)
1154 radius_server_add_session(sess);
1155
1156 return msg;
1157 }
1158
1159
1160 static struct radius_msg *
radius_server_macacl(struct radius_server_data * data,struct radius_client * client,struct radius_session * sess,struct radius_msg * request)1161 radius_server_macacl(struct radius_server_data *data,
1162 struct radius_client *client,
1163 struct radius_session *sess,
1164 struct radius_msg *request)
1165 {
1166 struct radius_msg *msg;
1167 int code;
1168 struct radius_hdr *hdr = radius_msg_get_hdr(request);
1169 u8 *pw;
1170 size_t pw_len;
1171
1172 code = RADIUS_CODE_ACCESS_ACCEPT;
1173
1174 if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw,
1175 &pw_len, NULL) < 0) {
1176 RADIUS_DEBUG("Could not get User-Password");
1177 code = RADIUS_CODE_ACCESS_REJECT;
1178 } else {
1179 int res;
1180 struct eap_user tmp;
1181
1182 os_memset(&tmp, 0, sizeof(tmp));
1183 res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username,
1184 os_strlen(sess->username), 0, &tmp);
1185 if (res || !tmp.macacl || tmp.password == NULL) {
1186 RADIUS_DEBUG("No MAC ACL user entry");
1187 bin_clear_free(tmp.password, tmp.password_len);
1188 code = RADIUS_CODE_ACCESS_REJECT;
1189 } else {
1190 u8 buf[128];
1191 res = radius_user_password_hide(
1192 request, tmp.password, tmp.password_len,
1193 (u8 *) client->shared_secret,
1194 client->shared_secret_len,
1195 buf, sizeof(buf));
1196 bin_clear_free(tmp.password, tmp.password_len);
1197
1198 if (res < 0 || pw_len != (size_t) res ||
1199 os_memcmp_const(pw, buf, res) != 0) {
1200 RADIUS_DEBUG("Incorrect User-Password");
1201 code = RADIUS_CODE_ACCESS_REJECT;
1202 }
1203 }
1204 }
1205
1206 msg = radius_msg_new(code, hdr->identifier);
1207 if (msg == NULL) {
1208 RADIUS_DEBUG("Failed to allocate reply message");
1209 return NULL;
1210 }
1211
1212 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1213 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1214 radius_msg_free(msg);
1215 return NULL;
1216 }
1217
1218 if (code == RADIUS_CODE_ACCESS_ACCEPT) {
1219 struct hostapd_radius_attr *attr;
1220 for (attr = sess->accept_attr; attr; attr = attr->next) {
1221 if (!radius_msg_add_attr(msg, attr->type,
1222 wpabuf_head(attr->val),
1223 wpabuf_len(attr->val))) {
1224 wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
1225 radius_msg_free(msg);
1226 return NULL;
1227 }
1228 }
1229 }
1230
1231 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1232 client->shared_secret_len,
1233 hdr->authenticator) < 0) {
1234 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1235 }
1236
1237 return msg;
1238 }
1239
1240
radius_server_reject(struct radius_server_data * data,struct radius_client * client,struct radius_msg * request,struct sockaddr * from,socklen_t fromlen,const char * from_addr,int from_port)1241 static int radius_server_reject(struct radius_server_data *data,
1242 struct radius_client *client,
1243 struct radius_msg *request,
1244 struct sockaddr *from, socklen_t fromlen,
1245 const char *from_addr, int from_port)
1246 {
1247 struct radius_msg *msg;
1248 int ret = 0;
1249 struct eap_hdr eapfail;
1250 struct wpabuf *buf;
1251 struct radius_hdr *hdr = radius_msg_get_hdr(request);
1252
1253 RADIUS_DEBUG("Reject invalid request from %s:%d",
1254 from_addr, from_port);
1255
1256 msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
1257 if (msg == NULL) {
1258 return -1;
1259 }
1260
1261 os_memset(&eapfail, 0, sizeof(eapfail));
1262 eapfail.code = EAP_CODE_FAILURE;
1263 eapfail.identifier = 0;
1264 eapfail.length = host_to_be16(sizeof(eapfail));
1265
1266 if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
1267 RADIUS_DEBUG("Failed to add EAP-Message attribute");
1268 }
1269
1270 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
1271 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
1272 radius_msg_free(msg);
1273 return -1;
1274 }
1275
1276 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
1277 client->shared_secret_len,
1278 hdr->authenticator) <
1279 0) {
1280 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
1281 }
1282
1283 if (wpa_debug_level <= MSG_MSGDUMP) {
1284 radius_msg_dump(msg);
1285 }
1286
1287 data->counters.access_rejects++;
1288 client->counters.access_rejects++;
1289 buf = radius_msg_get_buf(msg);
1290 if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
1291 (struct sockaddr *) from, sizeof(*from)) < 0) {
1292 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno));
1293 ret = -1;
1294 }
1295
1296 radius_msg_free(msg);
1297
1298 return ret;
1299 }
1300
1301
radius_server_hs20_t_c_check(struct radius_session * sess,struct radius_msg * msg)1302 static void radius_server_hs20_t_c_check(struct radius_session *sess,
1303 struct radius_msg *msg)
1304 {
1305 #ifdef CONFIG_HS20
1306 u8 *buf, *pos, *end, type, sublen, *timestamp = NULL;
1307 size_t len;
1308
1309 buf = NULL;
1310 for (;;) {
1311 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
1312 &buf, &len, buf) < 0)
1313 break;
1314 if (len < 6)
1315 continue;
1316 pos = buf;
1317 end = buf + len;
1318 if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
1319 continue;
1320 pos += 4;
1321
1322 type = *pos++;
1323 sublen = *pos++;
1324 if (sublen < 2)
1325 continue; /* invalid length */
1326 sublen -= 2; /* skip header */
1327 if (pos + sublen > end)
1328 continue; /* invalid WFA VSA */
1329
1330 if (type == RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP && len >= 4) {
1331 timestamp = pos;
1332 break;
1333 }
1334 }
1335
1336 if (!timestamp)
1337 return;
1338 RADIUS_DEBUG("HS20-Timestamp: %u", WPA_GET_BE32(timestamp));
1339 if (sess->t_c_timestamp != WPA_GET_BE32(timestamp)) {
1340 RADIUS_DEBUG("Last read T&C timestamp does not match HS20-Timestamp --> require filtering");
1341 sess->t_c_filtering = 1;
1342 }
1343 #endif /* CONFIG_HS20 */
1344 }
1345
1346
radius_server_request(struct radius_server_data * data,struct radius_msg * msg,struct sockaddr * from,socklen_t fromlen,struct radius_client * client,const char * from_addr,int from_port,struct radius_session * force_sess)1347 static int radius_server_request(struct radius_server_data *data,
1348 struct radius_msg *msg,
1349 struct sockaddr *from, socklen_t fromlen,
1350 struct radius_client *client,
1351 const char *from_addr, int from_port,
1352 struct radius_session *force_sess)
1353 {
1354 struct wpabuf *eap = NULL;
1355 int res, state_included = 0;
1356 u8 statebuf[4];
1357 unsigned int state;
1358 struct radius_session *sess;
1359 struct radius_msg *reply;
1360 int is_complete = 0;
1361
1362 if (force_sess)
1363 sess = force_sess;
1364 else {
1365 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
1366 sizeof(statebuf));
1367 state_included = res >= 0;
1368 if (res == sizeof(statebuf)) {
1369 state = WPA_GET_BE32(statebuf);
1370 sess = radius_server_get_session(client, state);
1371 } else {
1372 sess = NULL;
1373 }
1374 }
1375
1376 if (sess) {
1377 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
1378 } else if (state_included) {
1379 RADIUS_DEBUG("State attribute included but no session found");
1380 radius_server_reject(data, client, msg, from, fromlen,
1381 from_addr, from_port);
1382 return -1;
1383 } else {
1384 sess = radius_server_get_new_session(data, client, msg,
1385 from_addr);
1386 if (sess == NULL) {
1387 RADIUS_DEBUG("Could not create a new session");
1388 radius_server_reject(data, client, msg, from, fromlen,
1389 from_addr, from_port);
1390 return -1;
1391 }
1392 }
1393
1394 if (sess->last_from_port == from_port &&
1395 sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
1396 os_memcmp(sess->last_authenticator,
1397 radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
1398 RADIUS_DEBUG("Duplicate message from %s", from_addr);
1399 data->counters.dup_access_requests++;
1400 client->counters.dup_access_requests++;
1401
1402 if (sess->last_reply) {
1403 struct wpabuf *buf;
1404 buf = radius_msg_get_buf(sess->last_reply);
1405 res = sendto(data->auth_sock, wpabuf_head(buf),
1406 wpabuf_len(buf), 0,
1407 (struct sockaddr *) from, fromlen);
1408 if (res < 0) {
1409 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1410 strerror(errno));
1411 }
1412 return 0;
1413 }
1414
1415 RADIUS_DEBUG("No previous reply available for duplicate "
1416 "message");
1417 return -1;
1418 }
1419
1420 eap = radius_msg_get_eap(msg);
1421 if (eap == NULL && sess->macacl) {
1422 reply = radius_server_macacl(data, client, sess, msg);
1423 if (reply == NULL)
1424 return -1;
1425 goto send_reply;
1426 }
1427 if (eap == NULL) {
1428 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
1429 from_addr);
1430 data->counters.packets_dropped++;
1431 client->counters.packets_dropped++;
1432 return -1;
1433 }
1434
1435 RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap));
1436
1437 /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
1438 * RFC3579 Sect. 2.6.2.
1439 * Include EAP-Response/Nak with no preferred method if
1440 * code == request.
1441 * If code is not 1-4, discard the packet silently.
1442 * Or is this already done by the EAP state machine? */
1443
1444 wpabuf_free(sess->eap_if->eapRespData);
1445 sess->eap_if->eapRespData = eap;
1446 sess->eap_if->eapResp = true;
1447 eap_server_sm_step(sess->eap);
1448
1449 if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
1450 sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
1451 RADIUS_DUMP("EAP data from the state machine",
1452 wpabuf_head(sess->eap_if->eapReqData),
1453 wpabuf_len(sess->eap_if->eapReqData));
1454 } else if (sess->eap_if->eapFail) {
1455 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
1456 "set");
1457 } else if (eap_sm_method_pending(sess->eap)) {
1458 radius_msg_free(sess->last_msg);
1459 sess->last_msg = msg;
1460 sess->last_from_port = from_port;
1461 os_free(sess->last_from_addr);
1462 sess->last_from_addr = os_strdup(from_addr);
1463 sess->last_fromlen = fromlen;
1464 os_memcpy(&sess->last_from, from, fromlen);
1465 return -2;
1466 } else {
1467 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
1468 " Access-Request silently (assuming it was a "
1469 "duplicate)");
1470 data->counters.packets_dropped++;
1471 client->counters.packets_dropped++;
1472 return -1;
1473 }
1474
1475 if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
1476 is_complete = 1;
1477 if (sess->eap_if->eapFail) {
1478 srv_log(sess, "EAP authentication failed");
1479 db_update_last_msk(sess, "FAIL");
1480 } else if (sess->eap_if->eapSuccess) {
1481 srv_log(sess, "EAP authentication succeeded");
1482 }
1483
1484 if (sess->eap_if->eapSuccess)
1485 radius_server_hs20_t_c_check(sess, msg);
1486
1487 reply = radius_server_encapsulate_eap(data, client, sess, msg);
1488
1489 send_reply:
1490 if (reply) {
1491 struct wpabuf *buf;
1492 struct radius_hdr *hdr;
1493
1494 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
1495 if (wpa_debug_level <= MSG_MSGDUMP) {
1496 radius_msg_dump(reply);
1497 }
1498
1499 switch (radius_msg_get_hdr(reply)->code) {
1500 case RADIUS_CODE_ACCESS_ACCEPT:
1501 srv_log(sess, "Sending Access-Accept");
1502 data->counters.access_accepts++;
1503 client->counters.access_accepts++;
1504 break;
1505 case RADIUS_CODE_ACCESS_REJECT:
1506 srv_log(sess, "Sending Access-Reject");
1507 data->counters.access_rejects++;
1508 client->counters.access_rejects++;
1509 break;
1510 case RADIUS_CODE_ACCESS_CHALLENGE:
1511 data->counters.access_challenges++;
1512 client->counters.access_challenges++;
1513 break;
1514 }
1515 buf = radius_msg_get_buf(reply);
1516 res = sendto(data->auth_sock, wpabuf_head(buf),
1517 wpabuf_len(buf), 0,
1518 (struct sockaddr *) from, fromlen);
1519 if (res < 0) {
1520 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1521 strerror(errno));
1522 }
1523 radius_msg_free(sess->last_reply);
1524 sess->last_reply = reply;
1525 sess->last_from_port = from_port;
1526 hdr = radius_msg_get_hdr(msg);
1527 sess->last_identifier = hdr->identifier;
1528 os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
1529 } else {
1530 data->counters.packets_dropped++;
1531 client->counters.packets_dropped++;
1532 }
1533
1534 if (is_complete) {
1535 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
1536 sess->sess_id);
1537 eloop_cancel_timeout(radius_server_session_remove_timeout,
1538 data, sess);
1539 eloop_register_timeout(RADIUS_SESSION_MAINTAIN, 0,
1540 radius_server_session_remove_timeout,
1541 data, sess);
1542 }
1543
1544 return 0;
1545 }
1546
1547
1548 static void
radius_server_receive_disconnect_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1549 radius_server_receive_disconnect_resp(struct radius_server_data *data,
1550 struct radius_client *client,
1551 struct radius_msg *msg, int ack)
1552 {
1553 struct radius_hdr *hdr;
1554
1555 if (!client->pending_dac_disconnect_req) {
1556 RADIUS_DEBUG("Ignore unexpected Disconnect response");
1557 radius_msg_free(msg);
1558 return;
1559 }
1560
1561 hdr = radius_msg_get_hdr(msg);
1562 if (hdr->identifier != client->pending_dac_disconnect_id) {
1563 RADIUS_DEBUG("Ignore unexpected Disconnect response with unexpected identifier %u (expected %u)",
1564 hdr->identifier,
1565 client->pending_dac_disconnect_id);
1566 radius_msg_free(msg);
1567 return;
1568 }
1569
1570 if (radius_msg_verify(msg, (const u8 *) client->shared_secret,
1571 client->shared_secret_len,
1572 client->pending_dac_disconnect_req, 0)) {
1573 RADIUS_DEBUG("Ignore Disconnect response with invalid authenticator");
1574 radius_msg_free(msg);
1575 return;
1576 }
1577
1578 RADIUS_DEBUG("Disconnect-%s received for " MACSTR,
1579 ack ? "ACK" : "NAK",
1580 MAC2STR(client->pending_dac_disconnect_addr));
1581
1582 radius_msg_free(msg);
1583 radius_msg_free(client->pending_dac_disconnect_req);
1584 client->pending_dac_disconnect_req = NULL;
1585 }
1586
1587
radius_server_receive_coa_resp(struct radius_server_data * data,struct radius_client * client,struct radius_msg * msg,int ack)1588 static void radius_server_receive_coa_resp(struct radius_server_data *data,
1589 struct radius_client *client,
1590 struct radius_msg *msg, int ack)
1591 {
1592 struct radius_hdr *hdr;
1593 #ifdef CONFIG_SQLITE
1594 char addrtxt[3 * ETH_ALEN];
1595 char *sql;
1596 int res;
1597 #endif /* CONFIG_SQLITE */
1598
1599 if (!client->pending_dac_coa_req) {
1600 RADIUS_DEBUG("Ignore unexpected CoA response");
1601 radius_msg_free(msg);
1602 return;
1603 }
1604
1605 hdr = radius_msg_get_hdr(msg);
1606 if (hdr->identifier != client->pending_dac_coa_id) {
1607 RADIUS_DEBUG("Ignore unexpected CoA response with unexpected identifier %u (expected %u)",
1608 hdr->identifier,
1609 client->pending_dac_coa_id);
1610 radius_msg_free(msg);
1611 return;
1612 }
1613
1614 if (radius_msg_verify(msg, (const u8 *) client->shared_secret,
1615 client->shared_secret_len,
1616 client->pending_dac_coa_req, 0)) {
1617 RADIUS_DEBUG("Ignore CoA response with invalid authenticator");
1618 radius_msg_free(msg);
1619 return;
1620 }
1621
1622 RADIUS_DEBUG("CoA-%s received for " MACSTR,
1623 ack ? "ACK" : "NAK",
1624 MAC2STR(client->pending_dac_coa_addr));
1625
1626 radius_msg_free(msg);
1627 radius_msg_free(client->pending_dac_coa_req);
1628 client->pending_dac_coa_req = NULL;
1629
1630 #ifdef CONFIG_SQLITE
1631 if (!data->db)
1632 return;
1633
1634 os_snprintf(addrtxt, sizeof(addrtxt), MACSTR,
1635 MAC2STR(client->pending_dac_coa_addr));
1636
1637 if (ack) {
1638 sql = sqlite3_mprintf("UPDATE current_sessions SET hs20_t_c_filtering=0, waiting_coa_ack=0, coa_ack_received=1 WHERE mac_addr=%Q",
1639 addrtxt);
1640 } else {
1641 sql = sqlite3_mprintf("UPDATE current_sessions SET waiting_coa_ack=0 WHERE mac_addr=%Q",
1642 addrtxt);
1643 }
1644 if (!sql)
1645 return;
1646
1647 res = sqlite3_exec(data->db, sql, NULL, NULL, NULL);
1648 sqlite3_free(sql);
1649 if (res != SQLITE_OK) {
1650 RADIUS_ERROR("Failed to update current_sessions entry: %s",
1651 sqlite3_errmsg(data->db));
1652 return;
1653 }
1654 #endif /* CONFIG_SQLITE */
1655 }
1656
1657
radius_server_receive_auth(int sock,void * eloop_ctx,void * sock_ctx)1658 static void radius_server_receive_auth(int sock, void *eloop_ctx,
1659 void *sock_ctx)
1660 {
1661 struct radius_server_data *data = eloop_ctx;
1662 u8 *buf = NULL;
1663 union {
1664 struct sockaddr_storage ss;
1665 struct sockaddr_in sin;
1666 #ifdef CONFIG_IPV6
1667 struct sockaddr_in6 sin6;
1668 #endif /* CONFIG_IPV6 */
1669 } from;
1670 socklen_t fromlen;
1671 int len;
1672 struct radius_client *client = NULL;
1673 struct radius_msg *msg = NULL;
1674 char abuf[50];
1675 int from_port = 0;
1676
1677 buf = os_malloc(RADIUS_MAX_MSG_LEN);
1678 if (buf == NULL) {
1679 goto fail;
1680 }
1681
1682 fromlen = sizeof(from);
1683 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1684 (struct sockaddr *) &from.ss, &fromlen);
1685 if (len < 0) {
1686 wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1687 strerror(errno));
1688 goto fail;
1689 }
1690
1691 #ifdef CONFIG_IPV6
1692 if (data->ipv6) {
1693 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1694 sizeof(abuf)) == NULL)
1695 abuf[0] = '\0';
1696 from_port = ntohs(from.sin6.sin6_port);
1697 RADIUS_DEBUG("Received %d bytes from %s:%d",
1698 len, abuf, from_port);
1699
1700 client = radius_server_get_client(data,
1701 (struct in_addr *)
1702 &from.sin6.sin6_addr, 1);
1703 }
1704 #endif /* CONFIG_IPV6 */
1705
1706 if (!data->ipv6) {
1707 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1708 from_port = ntohs(from.sin.sin_port);
1709 RADIUS_DEBUG("Received %d bytes from %s:%d",
1710 len, abuf, from_port);
1711
1712 client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1713 }
1714
1715 RADIUS_DUMP("Received data", buf, len);
1716
1717 if (client == NULL) {
1718 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1719 data->counters.invalid_requests++;
1720 goto fail;
1721 }
1722
1723 msg = radius_msg_parse(buf, len);
1724 if (msg == NULL) {
1725 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1726 data->counters.malformed_access_requests++;
1727 client->counters.malformed_access_requests++;
1728 goto fail;
1729 }
1730
1731 os_free(buf);
1732 buf = NULL;
1733
1734 if (wpa_debug_level <= MSG_MSGDUMP) {
1735 radius_msg_dump(msg);
1736 }
1737
1738 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_ACK) {
1739 radius_server_receive_disconnect_resp(data, client, msg, 1);
1740 return;
1741 }
1742
1743 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_DISCONNECT_NAK) {
1744 radius_server_receive_disconnect_resp(data, client, msg, 0);
1745 return;
1746 }
1747
1748 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_ACK) {
1749 radius_server_receive_coa_resp(data, client, msg, 1);
1750 return;
1751 }
1752
1753 if (radius_msg_get_hdr(msg)->code == RADIUS_CODE_COA_NAK) {
1754 radius_server_receive_coa_resp(data, client, msg, 0);
1755 return;
1756 }
1757
1758 if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
1759 RADIUS_DEBUG("Unexpected RADIUS code %d",
1760 radius_msg_get_hdr(msg)->code);
1761 data->counters.unknown_types++;
1762 client->counters.unknown_types++;
1763 goto fail;
1764 }
1765
1766 data->counters.access_requests++;
1767 client->counters.access_requests++;
1768
1769 if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
1770 client->shared_secret_len, NULL)) {
1771 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
1772 data->counters.bad_authenticators++;
1773 client->counters.bad_authenticators++;
1774 goto fail;
1775 }
1776
1777 if (radius_server_request(data, msg, (struct sockaddr *) &from,
1778 fromlen, client, abuf, from_port, NULL) ==
1779 -2)
1780 return; /* msg was stored with the session */
1781
1782 fail:
1783 radius_msg_free(msg);
1784 os_free(buf);
1785 }
1786
1787
radius_server_receive_acct(int sock,void * eloop_ctx,void * sock_ctx)1788 static void radius_server_receive_acct(int sock, void *eloop_ctx,
1789 void *sock_ctx)
1790 {
1791 struct radius_server_data *data = eloop_ctx;
1792 u8 *buf = NULL;
1793 union {
1794 struct sockaddr_storage ss;
1795 struct sockaddr_in sin;
1796 #ifdef CONFIG_IPV6
1797 struct sockaddr_in6 sin6;
1798 #endif /* CONFIG_IPV6 */
1799 } from;
1800 socklen_t fromlen;
1801 int len, res;
1802 struct radius_client *client = NULL;
1803 struct radius_msg *msg = NULL, *resp = NULL;
1804 char abuf[50];
1805 int from_port = 0;
1806 struct radius_hdr *hdr;
1807 struct wpabuf *rbuf;
1808
1809 buf = os_malloc(RADIUS_MAX_MSG_LEN);
1810 if (buf == NULL) {
1811 goto fail;
1812 }
1813
1814 fromlen = sizeof(from);
1815 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
1816 (struct sockaddr *) &from.ss, &fromlen);
1817 if (len < 0) {
1818 wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
1819 strerror(errno));
1820 goto fail;
1821 }
1822
1823 #ifdef CONFIG_IPV6
1824 if (data->ipv6) {
1825 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
1826 sizeof(abuf)) == NULL)
1827 abuf[0] = '\0';
1828 from_port = ntohs(from.sin6.sin6_port);
1829 RADIUS_DEBUG("Received %d bytes from %s:%d",
1830 len, abuf, from_port);
1831
1832 client = radius_server_get_client(data,
1833 (struct in_addr *)
1834 &from.sin6.sin6_addr, 1);
1835 }
1836 #endif /* CONFIG_IPV6 */
1837
1838 if (!data->ipv6) {
1839 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
1840 from_port = ntohs(from.sin.sin_port);
1841 RADIUS_DEBUG("Received %d bytes from %s:%d",
1842 len, abuf, from_port);
1843
1844 client = radius_server_get_client(data, &from.sin.sin_addr, 0);
1845 }
1846
1847 RADIUS_DUMP("Received data", buf, len);
1848
1849 if (client == NULL) {
1850 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
1851 data->counters.invalid_acct_requests++;
1852 goto fail;
1853 }
1854
1855 msg = radius_msg_parse(buf, len);
1856 if (msg == NULL) {
1857 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
1858 data->counters.malformed_acct_requests++;
1859 client->counters.malformed_acct_requests++;
1860 goto fail;
1861 }
1862
1863 os_free(buf);
1864 buf = NULL;
1865
1866 if (wpa_debug_level <= MSG_MSGDUMP) {
1867 radius_msg_dump(msg);
1868 }
1869
1870 if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_REQUEST) {
1871 RADIUS_DEBUG("Unexpected RADIUS code %d",
1872 radius_msg_get_hdr(msg)->code);
1873 data->counters.unknown_acct_types++;
1874 client->counters.unknown_acct_types++;
1875 goto fail;
1876 }
1877
1878 data->counters.acct_requests++;
1879 client->counters.acct_requests++;
1880
1881 if (radius_msg_verify_acct_req(msg, (u8 *) client->shared_secret,
1882 client->shared_secret_len)) {
1883 RADIUS_DEBUG("Invalid Authenticator from %s", abuf);
1884 data->counters.acct_bad_authenticators++;
1885 client->counters.acct_bad_authenticators++;
1886 goto fail;
1887 }
1888
1889 /* TODO: Write accounting information to a file or database */
1890
1891 hdr = radius_msg_get_hdr(msg);
1892
1893 resp = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, hdr->identifier);
1894 if (resp == NULL)
1895 goto fail;
1896
1897 radius_msg_finish_acct_resp(resp, (u8 *) client->shared_secret,
1898 client->shared_secret_len,
1899 hdr->authenticator);
1900
1901 RADIUS_DEBUG("Reply to %s:%d", abuf, from_port);
1902 if (wpa_debug_level <= MSG_MSGDUMP) {
1903 radius_msg_dump(resp);
1904 }
1905 rbuf = radius_msg_get_buf(resp);
1906 data->counters.acct_responses++;
1907 client->counters.acct_responses++;
1908 res = sendto(data->acct_sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0,
1909 (struct sockaddr *) &from.ss, fromlen);
1910 if (res < 0) {
1911 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
1912 strerror(errno));
1913 }
1914
1915 fail:
1916 radius_msg_free(resp);
1917 radius_msg_free(msg);
1918 os_free(buf);
1919 }
1920
1921
radius_server_disable_pmtu_discovery(int s)1922 static int radius_server_disable_pmtu_discovery(int s)
1923 {
1924 int r = -1;
1925 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
1926 /* Turn off Path MTU discovery on IPv4/UDP sockets. */
1927 int action = IP_PMTUDISC_DONT;
1928 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
1929 sizeof(action));
1930 if (r == -1)
1931 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
1932 "%s", strerror(errno));
1933 #endif
1934 return r;
1935 }
1936
1937
radius_server_open_socket(int port)1938 static int radius_server_open_socket(int port)
1939 {
1940 int s;
1941 struct sockaddr_in addr;
1942
1943 s = socket(PF_INET, SOCK_DGRAM, 0);
1944 if (s < 0) {
1945 wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno));
1946 return -1;
1947 }
1948
1949 radius_server_disable_pmtu_discovery(s);
1950
1951 os_memset(&addr, 0, sizeof(addr));
1952 addr.sin_family = AF_INET;
1953 addr.sin_port = htons(port);
1954 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1955 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1956 close(s);
1957 return -1;
1958 }
1959
1960 return s;
1961 }
1962
1963
1964 #ifdef CONFIG_IPV6
radius_server_open_socket6(int port)1965 static int radius_server_open_socket6(int port)
1966 {
1967 int s;
1968 struct sockaddr_in6 addr;
1969
1970 s = socket(PF_INET6, SOCK_DGRAM, 0);
1971 if (s < 0) {
1972 wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s",
1973 strerror(errno));
1974 return -1;
1975 }
1976
1977 os_memset(&addr, 0, sizeof(addr));
1978 addr.sin6_family = AF_INET6;
1979 os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
1980 addr.sin6_port = htons(port);
1981 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1982 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1983 close(s);
1984 return -1;
1985 }
1986
1987 return s;
1988 }
1989 #endif /* CONFIG_IPV6 */
1990
1991
radius_server_free_sessions(struct radius_server_data * data,struct radius_session * sessions)1992 static void radius_server_free_sessions(struct radius_server_data *data,
1993 struct radius_session *sessions)
1994 {
1995 struct radius_session *session, *prev;
1996
1997 session = sessions;
1998 while (session) {
1999 prev = session;
2000 session = session->next;
2001 radius_server_session_free(data, prev);
2002 }
2003 }
2004
2005
radius_server_free_clients(struct radius_server_data * data,struct radius_client * clients)2006 static void radius_server_free_clients(struct radius_server_data *data,
2007 struct radius_client *clients)
2008 {
2009 struct radius_client *client, *prev;
2010
2011 client = clients;
2012 while (client) {
2013 prev = client;
2014 client = client->next;
2015
2016 radius_server_free_sessions(data, prev->sessions);
2017 os_free(prev->shared_secret);
2018 radius_msg_free(prev->pending_dac_coa_req);
2019 radius_msg_free(prev->pending_dac_disconnect_req);
2020 os_free(prev);
2021 }
2022 }
2023
2024
2025 static struct radius_client *
radius_server_read_clients(const char * client_file,int ipv6)2026 radius_server_read_clients(const char *client_file, int ipv6)
2027 {
2028 FILE *f;
2029 const int buf_size = 1024;
2030 char *buf, *pos;
2031 struct radius_client *clients, *tail, *entry;
2032 int line = 0, mask, failed = 0, i;
2033 struct in_addr addr;
2034 #ifdef CONFIG_IPV6
2035 struct in6_addr addr6;
2036 #endif /* CONFIG_IPV6 */
2037 unsigned int val;
2038
2039 f = fopen(client_file, "r");
2040 if (f == NULL) {
2041 RADIUS_ERROR("Could not open client file '%s'", client_file);
2042 return NULL;
2043 }
2044
2045 buf = os_malloc(buf_size);
2046 if (buf == NULL) {
2047 fclose(f);
2048 return NULL;
2049 }
2050
2051 clients = tail = NULL;
2052 while (fgets(buf, buf_size, f)) {
2053 /* Configuration file format:
2054 * 192.168.1.0/24 secret
2055 * 192.168.1.2 secret
2056 * fe80::211:22ff:fe33:4455/64 secretipv6
2057 */
2058 line++;
2059 buf[buf_size - 1] = '\0';
2060 pos = buf;
2061 while (*pos != '\0' && *pos != '\n')
2062 pos++;
2063 if (*pos == '\n')
2064 *pos = '\0';
2065 if (*buf == '\0' || *buf == '#')
2066 continue;
2067
2068 pos = buf;
2069 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
2070 (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
2071 (*pos >= 'A' && *pos <= 'F')) {
2072 pos++;
2073 }
2074
2075 if (*pos == '\0') {
2076 failed = 1;
2077 break;
2078 }
2079
2080 if (*pos == '/') {
2081 char *end;
2082 *pos++ = '\0';
2083 mask = strtol(pos, &end, 10);
2084 if ((pos == end) ||
2085 (mask < 0 || mask > (ipv6 ? 128 : 32))) {
2086 failed = 1;
2087 break;
2088 }
2089 pos = end;
2090 } else {
2091 mask = ipv6 ? 128 : 32;
2092 *pos++ = '\0';
2093 }
2094
2095 if (!ipv6 && inet_aton(buf, &addr) == 0) {
2096 failed = 1;
2097 break;
2098 }
2099 #ifdef CONFIG_IPV6
2100 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
2101 if (inet_pton(AF_INET, buf, &addr) <= 0) {
2102 failed = 1;
2103 break;
2104 }
2105 /* Convert IPv4 address to IPv6 */
2106 if (mask <= 32)
2107 mask += (128 - 32);
2108 os_memset(addr6.s6_addr, 0, 10);
2109 addr6.s6_addr[10] = 0xff;
2110 addr6.s6_addr[11] = 0xff;
2111 os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
2112 4);
2113 }
2114 #endif /* CONFIG_IPV6 */
2115
2116 while (*pos == ' ' || *pos == '\t') {
2117 pos++;
2118 }
2119
2120 if (*pos == '\0') {
2121 failed = 1;
2122 break;
2123 }
2124
2125 entry = os_zalloc(sizeof(*entry));
2126 if (entry == NULL) {
2127 failed = 1;
2128 break;
2129 }
2130 entry->shared_secret = os_strdup(pos);
2131 if (entry->shared_secret == NULL) {
2132 failed = 1;
2133 os_free(entry);
2134 break;
2135 }
2136 entry->shared_secret_len = os_strlen(entry->shared_secret);
2137 if (!ipv6) {
2138 entry->addr.s_addr = addr.s_addr;
2139 val = 0;
2140 for (i = 0; i < mask; i++)
2141 val |= 1U << (31 - i);
2142 entry->mask.s_addr = htonl(val);
2143 }
2144 #ifdef CONFIG_IPV6
2145 if (ipv6) {
2146 int offset = mask / 8;
2147
2148 os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
2149 os_memset(entry->mask6.s6_addr, 0xff, offset);
2150 val = 0;
2151 for (i = 0; i < (mask % 8); i++)
2152 val |= 1 << (7 - i);
2153 if (offset < 16)
2154 entry->mask6.s6_addr[offset] = val;
2155 }
2156 #endif /* CONFIG_IPV6 */
2157
2158 if (tail == NULL) {
2159 clients = tail = entry;
2160 } else {
2161 tail->next = entry;
2162 tail = entry;
2163 }
2164 }
2165
2166 if (failed) {
2167 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
2168 radius_server_free_clients(NULL, clients);
2169 clients = NULL;
2170 }
2171
2172 os_free(buf);
2173 fclose(f);
2174
2175 return clients;
2176 }
2177
2178
2179 /**
2180 * radius_server_init - Initialize RADIUS server
2181 * @conf: Configuration for the RADIUS server
2182 * Returns: Pointer to private RADIUS server context or %NULL on failure
2183 *
2184 * This initializes a RADIUS server instance and returns a context pointer that
2185 * will be used in other calls to the RADIUS server module. The server can be
2186 * deinitialize by calling radius_server_deinit().
2187 */
2188 struct radius_server_data *
radius_server_init(struct radius_server_conf * conf)2189 radius_server_init(struct radius_server_conf *conf)
2190 {
2191 struct radius_server_data *data;
2192
2193 #ifndef CONFIG_IPV6
2194 if (conf->ipv6) {
2195 wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support");
2196 return NULL;
2197 }
2198 #endif /* CONFIG_IPV6 */
2199
2200 data = os_zalloc(sizeof(*data));
2201 if (data == NULL)
2202 return NULL;
2203
2204 data->eap_cfg = conf->eap_cfg;
2205 data->auth_sock = -1;
2206 data->acct_sock = -1;
2207 dl_list_init(&data->erp_keys);
2208 os_get_reltime(&data->start_time);
2209 data->conf_ctx = conf->conf_ctx;
2210 conf->eap_cfg->backend_auth = true;
2211 conf->eap_cfg->eap_server = 1;
2212 data->ipv6 = conf->ipv6;
2213 data->get_eap_user = conf->get_eap_user;
2214 if (conf->eap_req_id_text) {
2215 data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
2216 if (!data->eap_req_id_text)
2217 goto fail;
2218 os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
2219 conf->eap_req_id_text_len);
2220 data->eap_req_id_text_len = conf->eap_req_id_text_len;
2221 }
2222 data->erp_domain = conf->erp_domain;
2223
2224 if (conf->subscr_remediation_url) {
2225 data->subscr_remediation_url =
2226 os_strdup(conf->subscr_remediation_url);
2227 if (!data->subscr_remediation_url)
2228 goto fail;
2229 }
2230 data->subscr_remediation_method = conf->subscr_remediation_method;
2231 if (conf->hs20_sim_provisioning_url) {
2232 data->hs20_sim_provisioning_url =
2233 os_strdup(conf->hs20_sim_provisioning_url);
2234 if (!data->hs20_sim_provisioning_url)
2235 goto fail;
2236 }
2237
2238 if (conf->t_c_server_url) {
2239 data->t_c_server_url = os_strdup(conf->t_c_server_url);
2240 if (!data->t_c_server_url)
2241 goto fail;
2242 }
2243
2244 #ifdef CONFIG_SQLITE
2245 if (conf->sqlite_file) {
2246 if (sqlite3_open(conf->sqlite_file, &data->db)) {
2247 RADIUS_ERROR("Could not open SQLite file '%s'",
2248 conf->sqlite_file);
2249 goto fail;
2250 }
2251 }
2252 #endif /* CONFIG_SQLITE */
2253
2254 #ifdef CONFIG_RADIUS_TEST
2255 if (conf->dump_msk_file)
2256 data->dump_msk_file = os_strdup(conf->dump_msk_file);
2257 #endif /* CONFIG_RADIUS_TEST */
2258
2259 data->clients = radius_server_read_clients(conf->client_file,
2260 conf->ipv6);
2261 if (data->clients == NULL) {
2262 wpa_printf(MSG_ERROR, "No RADIUS clients configured");
2263 goto fail;
2264 }
2265
2266 #ifdef CONFIG_IPV6
2267 if (conf->ipv6)
2268 data->auth_sock = radius_server_open_socket6(conf->auth_port);
2269 else
2270 #endif /* CONFIG_IPV6 */
2271 data->auth_sock = radius_server_open_socket(conf->auth_port);
2272 if (data->auth_sock < 0) {
2273 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server");
2274 goto fail;
2275 }
2276 if (eloop_register_read_sock(data->auth_sock,
2277 radius_server_receive_auth,
2278 data, NULL)) {
2279 goto fail;
2280 }
2281
2282 if (conf->acct_port) {
2283 #ifdef CONFIG_IPV6
2284 if (conf->ipv6)
2285 data->acct_sock = radius_server_open_socket6(
2286 conf->acct_port);
2287 else
2288 #endif /* CONFIG_IPV6 */
2289 data->acct_sock = radius_server_open_socket(conf->acct_port);
2290 if (data->acct_sock < 0) {
2291 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS accounting server");
2292 goto fail;
2293 }
2294 if (eloop_register_read_sock(data->acct_sock,
2295 radius_server_receive_acct,
2296 data, NULL))
2297 goto fail;
2298 } else {
2299 data->acct_sock = -1;
2300 }
2301
2302 return data;
2303 fail:
2304 radius_server_deinit(data);
2305 return NULL;
2306 }
2307
2308
2309 /**
2310 * radius_server_erp_flush - Flush all ERP keys
2311 * @data: RADIUS server context from radius_server_init()
2312 */
radius_server_erp_flush(struct radius_server_data * data)2313 void radius_server_erp_flush(struct radius_server_data *data)
2314 {
2315 struct eap_server_erp_key *erp;
2316
2317 if (data == NULL)
2318 return;
2319 while ((erp = dl_list_first(&data->erp_keys, struct eap_server_erp_key,
2320 list)) != NULL) {
2321 dl_list_del(&erp->list);
2322 bin_clear_free(erp, sizeof(*erp));
2323 }
2324 }
2325
2326
2327 /**
2328 * radius_server_deinit - Deinitialize RADIUS server
2329 * @data: RADIUS server context from radius_server_init()
2330 */
radius_server_deinit(struct radius_server_data * data)2331 void radius_server_deinit(struct radius_server_data *data)
2332 {
2333 if (data == NULL)
2334 return;
2335
2336 if (data->auth_sock >= 0) {
2337 eloop_unregister_read_sock(data->auth_sock);
2338 close(data->auth_sock);
2339 }
2340
2341 if (data->acct_sock >= 0) {
2342 eloop_unregister_read_sock(data->acct_sock);
2343 close(data->acct_sock);
2344 }
2345
2346 radius_server_free_clients(data, data->clients);
2347
2348 os_free(data->eap_req_id_text);
2349 #ifdef CONFIG_RADIUS_TEST
2350 os_free(data->dump_msk_file);
2351 #endif /* CONFIG_RADIUS_TEST */
2352 os_free(data->subscr_remediation_url);
2353 os_free(data->hs20_sim_provisioning_url);
2354 os_free(data->t_c_server_url);
2355
2356 #ifdef CONFIG_SQLITE
2357 if (data->db)
2358 sqlite3_close(data->db);
2359 #endif /* CONFIG_SQLITE */
2360
2361 radius_server_erp_flush(data);
2362
2363 os_free(data);
2364 }
2365
2366
2367 /**
2368 * radius_server_get_mib - Get RADIUS server MIB information
2369 * @data: RADIUS server context from radius_server_init()
2370 * @buf: Buffer for returning the MIB data in text format
2371 * @buflen: buf length in octets
2372 * Returns: Number of octets written into buf
2373 */
radius_server_get_mib(struct radius_server_data * data,char * buf,size_t buflen)2374 int radius_server_get_mib(struct radius_server_data *data, char *buf,
2375 size_t buflen)
2376 {
2377 int ret, uptime;
2378 unsigned int idx;
2379 char *end, *pos;
2380 struct os_reltime now;
2381 struct radius_client *cli;
2382
2383 /* RFC 2619 - RADIUS Authentication Server MIB */
2384
2385 if (data == NULL || buflen == 0)
2386 return 0;
2387
2388 pos = buf;
2389 end = buf + buflen;
2390
2391 os_get_reltime(&now);
2392 uptime = (now.sec - data->start_time.sec) * 100 +
2393 ((now.usec - data->start_time.usec) / 10000) % 100;
2394 ret = os_snprintf(pos, end - pos,
2395 "RADIUS-AUTH-SERVER-MIB\n"
2396 "radiusAuthServIdent=hostapd\n"
2397 "radiusAuthServUpTime=%d\n"
2398 "radiusAuthServResetTime=0\n"
2399 "radiusAuthServConfigReset=4\n",
2400 uptime);
2401 if (os_snprintf_error(end - pos, ret)) {
2402 *pos = '\0';
2403 return pos - buf;
2404 }
2405 pos += ret;
2406
2407 ret = os_snprintf(pos, end - pos,
2408 "radiusAuthServTotalAccessRequests=%u\n"
2409 "radiusAuthServTotalInvalidRequests=%u\n"
2410 "radiusAuthServTotalDupAccessRequests=%u\n"
2411 "radiusAuthServTotalAccessAccepts=%u\n"
2412 "radiusAuthServTotalAccessRejects=%u\n"
2413 "radiusAuthServTotalAccessChallenges=%u\n"
2414 "radiusAuthServTotalMalformedAccessRequests=%u\n"
2415 "radiusAuthServTotalBadAuthenticators=%u\n"
2416 "radiusAuthServTotalPacketsDropped=%u\n"
2417 "radiusAuthServTotalUnknownTypes=%u\n"
2418 "radiusAccServTotalRequests=%u\n"
2419 "radiusAccServTotalInvalidRequests=%u\n"
2420 "radiusAccServTotalResponses=%u\n"
2421 "radiusAccServTotalMalformedRequests=%u\n"
2422 "radiusAccServTotalBadAuthenticators=%u\n"
2423 "radiusAccServTotalUnknownTypes=%u\n",
2424 data->counters.access_requests,
2425 data->counters.invalid_requests,
2426 data->counters.dup_access_requests,
2427 data->counters.access_accepts,
2428 data->counters.access_rejects,
2429 data->counters.access_challenges,
2430 data->counters.malformed_access_requests,
2431 data->counters.bad_authenticators,
2432 data->counters.packets_dropped,
2433 data->counters.unknown_types,
2434 data->counters.acct_requests,
2435 data->counters.invalid_acct_requests,
2436 data->counters.acct_responses,
2437 data->counters.malformed_acct_requests,
2438 data->counters.acct_bad_authenticators,
2439 data->counters.unknown_acct_types);
2440 if (os_snprintf_error(end - pos, ret)) {
2441 *pos = '\0';
2442 return pos - buf;
2443 }
2444 pos += ret;
2445
2446 for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
2447 char abuf[50], mbuf[50];
2448 #ifdef CONFIG_IPV6
2449 if (data->ipv6) {
2450 if (inet_ntop(AF_INET6, &cli->addr6, abuf,
2451 sizeof(abuf)) == NULL)
2452 abuf[0] = '\0';
2453 if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
2454 sizeof(mbuf)) == NULL)
2455 mbuf[0] = '\0';
2456 }
2457 #endif /* CONFIG_IPV6 */
2458 if (!data->ipv6) {
2459 os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
2460 os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
2461 }
2462
2463 ret = os_snprintf(pos, end - pos,
2464 "radiusAuthClientIndex=%u\n"
2465 "radiusAuthClientAddress=%s/%s\n"
2466 "radiusAuthServAccessRequests=%u\n"
2467 "radiusAuthServDupAccessRequests=%u\n"
2468 "radiusAuthServAccessAccepts=%u\n"
2469 "radiusAuthServAccessRejects=%u\n"
2470 "radiusAuthServAccessChallenges=%u\n"
2471 "radiusAuthServMalformedAccessRequests=%u\n"
2472 "radiusAuthServBadAuthenticators=%u\n"
2473 "radiusAuthServPacketsDropped=%u\n"
2474 "radiusAuthServUnknownTypes=%u\n"
2475 "radiusAccServTotalRequests=%u\n"
2476 "radiusAccServTotalInvalidRequests=%u\n"
2477 "radiusAccServTotalResponses=%u\n"
2478 "radiusAccServTotalMalformedRequests=%u\n"
2479 "radiusAccServTotalBadAuthenticators=%u\n"
2480 "radiusAccServTotalUnknownTypes=%u\n",
2481 idx,
2482 abuf, mbuf,
2483 cli->counters.access_requests,
2484 cli->counters.dup_access_requests,
2485 cli->counters.access_accepts,
2486 cli->counters.access_rejects,
2487 cli->counters.access_challenges,
2488 cli->counters.malformed_access_requests,
2489 cli->counters.bad_authenticators,
2490 cli->counters.packets_dropped,
2491 cli->counters.unknown_types,
2492 cli->counters.acct_requests,
2493 cli->counters.invalid_acct_requests,
2494 cli->counters.acct_responses,
2495 cli->counters.malformed_acct_requests,
2496 cli->counters.acct_bad_authenticators,
2497 cli->counters.unknown_acct_types);
2498 if (os_snprintf_error(end - pos, ret)) {
2499 *pos = '\0';
2500 return pos - buf;
2501 }
2502 pos += ret;
2503 }
2504
2505 return pos - buf;
2506 }
2507
2508
radius_server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)2509 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
2510 size_t identity_len, int phase2,
2511 struct eap_user *user)
2512 {
2513 struct radius_session *sess = ctx;
2514 struct radius_server_data *data = sess->server;
2515 int ret;
2516
2517 ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
2518 phase2, user);
2519 if (ret == 0 && user) {
2520 sess->accept_attr = user->accept_attr;
2521 sess->remediation = user->remediation;
2522 sess->macacl = user->macacl;
2523 sess->t_c_timestamp = user->t_c_timestamp;
2524 }
2525
2526 if (ret) {
2527 RADIUS_DEBUG("%s: User-Name not found from user database",
2528 __func__);
2529 }
2530
2531 return ret;
2532 }
2533
2534
radius_server_get_eap_req_id_text(void * ctx,size_t * len)2535 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
2536 {
2537 struct radius_session *sess = ctx;
2538 struct radius_server_data *data = sess->server;
2539 *len = data->eap_req_id_text_len;
2540 return data->eap_req_id_text;
2541 }
2542
2543
radius_server_log_msg(void * ctx,const char * msg)2544 static void radius_server_log_msg(void *ctx, const char *msg)
2545 {
2546 struct radius_session *sess = ctx;
2547 srv_log(sess, "EAP: %s", msg);
2548 }
2549
2550
2551 #ifdef CONFIG_ERP
2552
radius_server_get_erp_domain(void * ctx)2553 static const char * radius_server_get_erp_domain(void *ctx)
2554 {
2555 struct radius_session *sess = ctx;
2556 struct radius_server_data *data = sess->server;
2557
2558 return data->erp_domain;
2559 }
2560
2561
2562 static struct eap_server_erp_key *
radius_server_erp_get_key(void * ctx,const char * keyname)2563 radius_server_erp_get_key(void *ctx, const char *keyname)
2564 {
2565 struct radius_session *sess = ctx;
2566 struct radius_server_data *data = sess->server;
2567
2568 return radius_server_erp_find_key(data, keyname);
2569 }
2570
2571
radius_server_erp_add_key(void * ctx,struct eap_server_erp_key * erp)2572 static int radius_server_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
2573 {
2574 struct radius_session *sess = ctx;
2575 struct radius_server_data *data = sess->server;
2576
2577 dl_list_add(&data->erp_keys, &erp->list);
2578 return 0;
2579 }
2580
2581 #endif /* CONFIG_ERP */
2582
2583
2584 static const struct eapol_callbacks radius_server_eapol_cb =
2585 {
2586 .get_eap_user = radius_server_get_eap_user,
2587 .get_eap_req_id_text = radius_server_get_eap_req_id_text,
2588 .log_msg = radius_server_log_msg,
2589 #ifdef CONFIG_ERP
2590 .get_erp_send_reauth_start = NULL,
2591 .get_erp_domain = radius_server_get_erp_domain,
2592 .erp_get_key = radius_server_erp_get_key,
2593 .erp_add_key = radius_server_erp_add_key,
2594 #endif /* CONFIG_ERP */
2595 };
2596
2597
2598 /**
2599 * radius_server_eap_pending_cb - Pending EAP data notification
2600 * @data: RADIUS server context from radius_server_init()
2601 * @ctx: Pending EAP context pointer
2602 *
2603 * This function is used to notify EAP server module that a pending operation
2604 * has been completed and processing of the EAP session can proceed.
2605 */
radius_server_eap_pending_cb(struct radius_server_data * data,void * ctx)2606 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
2607 {
2608 struct radius_client *cli;
2609 struct radius_session *s, *sess = NULL;
2610 struct radius_msg *msg;
2611
2612 if (data == NULL)
2613 return;
2614
2615 for (cli = data->clients; cli; cli = cli->next) {
2616 for (s = cli->sessions; s; s = s->next) {
2617 if (s->eap == ctx && s->last_msg) {
2618 sess = s;
2619 break;
2620 }
2621 }
2622 if (sess)
2623 break;
2624 }
2625
2626 if (sess == NULL) {
2627 RADIUS_DEBUG("No session matched callback ctx");
2628 return;
2629 }
2630
2631 msg = sess->last_msg;
2632 sess->last_msg = NULL;
2633 eap_sm_pending_cb(sess->eap);
2634 if (radius_server_request(data, msg,
2635 (struct sockaddr *) &sess->last_from,
2636 sess->last_fromlen, cli,
2637 sess->last_from_addr,
2638 sess->last_from_port, sess) == -2)
2639 return; /* msg was stored with the session */
2640
2641 radius_msg_free(msg);
2642 }
2643
2644
2645 #ifdef CONFIG_SQLITE
2646
2647 struct db_session_fields {
2648 char *identity;
2649 char *nas;
2650 int hs20_t_c_filtering;
2651 int waiting_coa_ack;
2652 int coa_ack_received;
2653 };
2654
2655
get_db_session_fields(void * ctx,int argc,char * argv[],char * col[])2656 static int get_db_session_fields(void *ctx, int argc, char *argv[], char *col[])
2657 {
2658 struct db_session_fields *fields = ctx;
2659 int i;
2660
2661 for (i = 0; i < argc; i++) {
2662 if (!argv[i])
2663 continue;
2664
2665 RADIUS_DEBUG("Session DB: %s=%s", col[i], argv[i]);
2666
2667 if (os_strcmp(col[i], "identity") == 0) {
2668 os_free(fields->identity);
2669 fields->identity = os_strdup(argv[i]);
2670 } else if (os_strcmp(col[i], "nas") == 0) {
2671 os_free(fields->nas);
2672 fields->nas = os_strdup(argv[i]);
2673 } else if (os_strcmp(col[i], "hs20_t_c_filtering") == 0) {
2674 fields->hs20_t_c_filtering = atoi(argv[i]);
2675 } else if (os_strcmp(col[i], "waiting_coa_ack") == 0) {
2676 fields->waiting_coa_ack = atoi(argv[i]);
2677 } else if (os_strcmp(col[i], "coa_ack_received") == 0) {
2678 fields->coa_ack_received = atoi(argv[i]);
2679 }
2680 }
2681
2682 return 0;
2683 }
2684
2685
free_db_session_fields(struct db_session_fields * fields)2686 static void free_db_session_fields(struct db_session_fields *fields)
2687 {
2688 os_free(fields->identity);
2689 fields->identity = NULL;
2690 os_free(fields->nas);
2691 fields->nas = NULL;
2692 }
2693
2694 #endif /* CONFIG_SQLITE */
2695
2696
radius_server_dac_request(struct radius_server_data * data,const char * req)2697 int radius_server_dac_request(struct radius_server_data *data, const char *req)
2698 {
2699 #ifdef CONFIG_SQLITE
2700 char *sql;
2701 int res;
2702 int disconnect;
2703 const char *pos = req;
2704 u8 addr[ETH_ALEN];
2705 char addrtxt[3 * ETH_ALEN];
2706 int t_c_clear = 0;
2707 struct db_session_fields fields;
2708 struct sockaddr_in das;
2709 struct radius_client *client;
2710 struct radius_msg *msg;
2711 struct wpabuf *buf;
2712 u8 identifier;
2713 struct os_time now;
2714
2715 if (!data)
2716 return -1;
2717
2718 /* req: <disconnect|coa> <MAC Address> [t_c_clear] */
2719
2720 if (os_strncmp(pos, "disconnect ", 11) == 0) {
2721 disconnect = 1;
2722 pos += 11;
2723 } else if (os_strncmp(req, "coa ", 4) == 0) {
2724 disconnect = 0;
2725 pos += 4;
2726 } else {
2727 return -1;
2728 }
2729
2730 if (hwaddr_aton(pos, addr))
2731 return -1;
2732 pos = os_strchr(pos, ' ');
2733 if (pos) {
2734 if (os_strstr(pos, "t_c_clear"))
2735 t_c_clear = 1;
2736 }
2737
2738 if (!disconnect && !t_c_clear) {
2739 RADIUS_ERROR("DAC request for CoA without any authorization change");
2740 return -1;
2741 }
2742
2743 if (!data->db) {
2744 RADIUS_ERROR("SQLite database not in use");
2745 return -1;
2746 }
2747
2748 os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, MAC2STR(addr));
2749
2750 sql = sqlite3_mprintf("SELECT * FROM current_sessions WHERE mac_addr=%Q",
2751 addrtxt);
2752 if (!sql)
2753 return -1;
2754
2755 os_memset(&fields, 0, sizeof(fields));
2756 res = sqlite3_exec(data->db, sql, get_db_session_fields, &fields, NULL);
2757 sqlite3_free(sql);
2758 if (res != SQLITE_OK) {
2759 RADIUS_ERROR("Failed to find matching current_sessions entry from sqlite database: %s",
2760 sqlite3_errmsg(data->db));
2761 free_db_session_fields(&fields);
2762 return -1;
2763 }
2764
2765 if (!fields.nas) {
2766 RADIUS_ERROR("No NAS information found from current_sessions");
2767 free_db_session_fields(&fields);
2768 return -1;
2769 }
2770
2771 os_memset(&das, 0, sizeof(das));
2772 das.sin_family = AF_INET;
2773 das.sin_addr.s_addr = inet_addr(fields.nas);
2774 das.sin_port = htons(3799);
2775
2776 free_db_session_fields(&fields);
2777
2778 client = radius_server_get_client(data, &das.sin_addr, 0);
2779 if (!client) {
2780 RADIUS_ERROR("No NAS information available to protect the packet");
2781 return -1;
2782 }
2783
2784 identifier = client->next_dac_identifier++;
2785
2786 msg = radius_msg_new(disconnect ? RADIUS_CODE_DISCONNECT_REQUEST :
2787 RADIUS_CODE_COA_REQUEST, identifier);
2788 if (!msg)
2789 return -1;
2790
2791 os_snprintf(addrtxt, sizeof(addrtxt), RADIUS_802_1X_ADDR_FORMAT,
2792 MAC2STR(addr));
2793 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
2794 (u8 *) addrtxt, os_strlen(addrtxt))) {
2795 RADIUS_ERROR("Could not add Calling-Station-Id");
2796 radius_msg_free(msg);
2797 return -1;
2798 }
2799
2800 if (!disconnect && t_c_clear) {
2801 u8 val[4] = { 0x00, 0x00, 0x00, 0x00 }; /* E=0 */
2802
2803 if (!radius_msg_add_wfa(
2804 msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
2805 val, sizeof(val))) {
2806 RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
2807 radius_msg_free(msg);
2808 return -1;
2809 }
2810 }
2811
2812 os_get_time(&now);
2813 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
2814 now.sec)) {
2815 RADIUS_ERROR("Failed to add Event-Timestamp attribute");
2816 radius_msg_free(msg);
2817 return -1;
2818 }
2819
2820 radius_msg_finish_acct(msg, (u8 *) client->shared_secret,
2821 client->shared_secret_len);
2822
2823 if (wpa_debug_level <= MSG_MSGDUMP)
2824 radius_msg_dump(msg);
2825
2826 buf = radius_msg_get_buf(msg);
2827 if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
2828 (struct sockaddr *) &das, sizeof(das)) < 0) {
2829 RADIUS_ERROR("Failed to send packet - sendto: %s",
2830 strerror(errno));
2831 radius_msg_free(msg);
2832 return -1;
2833 }
2834
2835 if (disconnect) {
2836 radius_msg_free(client->pending_dac_disconnect_req);
2837 client->pending_dac_disconnect_req = msg;
2838 client->pending_dac_disconnect_id = identifier;
2839 os_memcpy(client->pending_dac_disconnect_addr, addr, ETH_ALEN);
2840 } else {
2841 radius_msg_free(client->pending_dac_coa_req);
2842 client->pending_dac_coa_req = msg;
2843 client->pending_dac_coa_id = identifier;
2844 os_memcpy(client->pending_dac_coa_addr, addr, ETH_ALEN);
2845 }
2846
2847 return 0;
2848 #else /* CONFIG_SQLITE */
2849 return -1;
2850 #endif /* CONFIG_SQLITE */
2851 }
2852