EAP-FAST: Added support for disabling anonymous/authenticated provisioning
[libeap.git] / src / radius / radius_server.c
1 /*
2  * hostapd / RADIUS authentication server
3  * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16 #include <net/if.h>
17
18 #include "common.h"
19 #include "radius.h"
20 #include "eloop.h"
21 #include "defs.h"
22 #include "eap_server/eap.h"
23 #include "radius_server.h"
24
25 #define RADIUS_SESSION_TIMEOUT 60
26 #define RADIUS_MAX_SESSION 100
27 #define RADIUS_MAX_MSG_LEN 3000
28
29 static struct eapol_callbacks radius_server_eapol_cb;
30
31 struct radius_client;
32 struct radius_server_data;
33
34 struct radius_server_counters {
35         u32 access_requests;
36         u32 invalid_requests;
37         u32 dup_access_requests;
38         u32 access_accepts;
39         u32 access_rejects;
40         u32 access_challenges;
41         u32 malformed_access_requests;
42         u32 bad_authenticators;
43         u32 packets_dropped;
44         u32 unknown_types;
45 };
46
47 struct radius_session {
48         struct radius_session *next;
49         struct radius_client *client;
50         struct radius_server_data *server;
51         unsigned int sess_id;
52         struct eap_sm *eap;
53         struct eap_eapol_interface *eap_if;
54
55         struct radius_msg *last_msg;
56         char *last_from_addr;
57         int last_from_port;
58         struct sockaddr_storage last_from;
59         socklen_t last_fromlen;
60         u8 last_identifier;
61         struct radius_msg *last_reply;
62         u8 last_authenticator[16];
63 };
64
65 struct radius_client {
66         struct radius_client *next;
67         struct in_addr addr;
68         struct in_addr mask;
69 #ifdef CONFIG_IPV6
70         struct in6_addr addr6;
71         struct in6_addr mask6;
72 #endif /* CONFIG_IPV6 */
73         char *shared_secret;
74         int shared_secret_len;
75         struct radius_session *sessions;
76         struct radius_server_counters counters;
77 };
78
79 struct radius_server_data {
80         int auth_sock;
81         struct radius_client *clients;
82         unsigned int next_sess_id;
83         void *conf_ctx;
84         int num_sess;
85         void *eap_sim_db_priv;
86         void *ssl_ctx;
87         u8 *pac_opaque_encr_key;
88         char *eap_fast_a_id;
89         int eap_fast_prov;
90         int eap_sim_aka_result_ind;
91         int tnc;
92         int ipv6;
93         struct os_time start_time;
94         struct radius_server_counters counters;
95         int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
96                             int phase2, struct eap_user *user);
97 };
98
99
100 extern int wpa_debug_level;
101
102 #define RADIUS_DEBUG(args...) \
103 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
104 #define RADIUS_ERROR(args...) \
105 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
106 #define RADIUS_DUMP(args...) \
107 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
108 #define RADIUS_DUMP_ASCII(args...) \
109 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
110
111
112 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
113
114
115
116 static struct radius_client *
117 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
118                          int ipv6)
119 {
120         struct radius_client *client = data->clients;
121
122         while (client) {
123 #ifdef CONFIG_IPV6
124                 if (ipv6) {
125                         struct in6_addr *addr6;
126                         int i;
127
128                         addr6 = (struct in6_addr *) addr;
129                         for (i = 0; i < 16; i++) {
130                                 if ((addr6->s6_addr[i] &
131                                      client->mask6.s6_addr[i]) !=
132                                     (client->addr6.s6_addr[i] &
133                                      client->mask6.s6_addr[i])) {
134                                         i = 17;
135                                         break;
136                                 }
137                         }
138                         if (i == 16) {
139                                 break;
140                         }
141                 }
142 #endif /* CONFIG_IPV6 */
143                 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
144                     (addr->s_addr & client->mask.s_addr)) {
145                         break;
146                 }
147
148                 client = client->next;
149         }
150
151         return client;
152 }
153
154
155 static struct radius_session *
156 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
157 {
158         struct radius_session *sess = client->sessions;
159
160         while (sess) {
161                 if (sess->sess_id == sess_id) {
162                         break;
163                 }
164                 sess = sess->next;
165         }
166
167         return sess;
168 }
169
170
171 static void radius_server_session_free(struct radius_server_data *data,
172                                        struct radius_session *sess)
173 {
174         eloop_cancel_timeout(radius_server_session_timeout, data, sess);
175         eap_server_sm_deinit(sess->eap);
176         if (sess->last_msg) {
177                 radius_msg_free(sess->last_msg);
178                 os_free(sess->last_msg);
179         }
180         os_free(sess->last_from_addr);
181         if (sess->last_reply) {
182                 radius_msg_free(sess->last_reply);
183                 os_free(sess->last_reply);
184         }
185         os_free(sess);
186         data->num_sess--;
187 }
188
189
190 static void radius_server_session_remove_timeout(void *eloop_ctx,
191                                                  void *timeout_ctx);
192
193 static void radius_server_session_remove(struct radius_server_data *data,
194                                          struct radius_session *sess)
195 {
196         struct radius_client *client = sess->client;
197         struct radius_session *session, *prev;
198
199         eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
200
201         prev = NULL;
202         session = client->sessions;
203         while (session) {
204                 if (session == sess) {
205                         if (prev == NULL) {
206                                 client->sessions = sess->next;
207                         } else {
208                                 prev->next = sess->next;
209                         }
210                         radius_server_session_free(data, sess);
211                         break;
212                 }
213                 prev = session;
214                 session = session->next;
215         }
216 }
217
218
219 static void radius_server_session_remove_timeout(void *eloop_ctx,
220                                                  void *timeout_ctx)
221 {
222         struct radius_server_data *data = eloop_ctx;
223         struct radius_session *sess = timeout_ctx;
224         RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
225         radius_server_session_remove(data, sess);
226 }
227
228
229 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
230 {
231         struct radius_server_data *data = eloop_ctx;
232         struct radius_session *sess = timeout_ctx;
233
234         RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
235         radius_server_session_remove(data, sess);
236 }
237
238
239 static struct radius_session *
240 radius_server_new_session(struct radius_server_data *data,
241                           struct radius_client *client)
242 {
243         struct radius_session *sess;
244
245         if (data->num_sess >= RADIUS_MAX_SESSION) {
246                 RADIUS_DEBUG("Maximum number of existing session - no room "
247                              "for a new session");
248                 return NULL;
249         }
250
251         sess = os_zalloc(sizeof(*sess));
252         if (sess == NULL)
253                 return NULL;
254
255         sess->server = data;
256         sess->client = client;
257         sess->sess_id = data->next_sess_id++;
258         sess->next = client->sessions;
259         client->sessions = sess;
260         eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
261                                radius_server_session_timeout, data, sess);
262         data->num_sess++;
263         return sess;
264 }
265
266
267 static struct radius_session *
268 radius_server_get_new_session(struct radius_server_data *data,
269                               struct radius_client *client,
270                               struct radius_msg *msg)
271 {
272         u8 *user;
273         size_t user_len;
274         int res;
275         struct radius_session *sess;
276         struct eap_config eap_conf;
277
278         RADIUS_DEBUG("Creating a new session");
279
280         user = os_malloc(256);
281         if (user == NULL) {
282                 return NULL;
283         }
284         res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
285         if (res < 0 || res > 256) {
286                 RADIUS_DEBUG("Could not get User-Name");
287                 os_free(user);
288                 return NULL;
289         }
290         user_len = res;
291         RADIUS_DUMP_ASCII("User-Name", user, user_len);
292
293         res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
294         os_free(user);
295
296         if (res == 0) {
297                 RADIUS_DEBUG("Matching user entry found");
298                 sess = radius_server_new_session(data, client);
299                 if (sess == NULL) {
300                         RADIUS_DEBUG("Failed to create a new session");
301                         return NULL;
302                 }
303         } else {
304                 RADIUS_DEBUG("User-Name not found from user database");
305                 return NULL;
306         }
307
308         os_memset(&eap_conf, 0, sizeof(eap_conf));
309         eap_conf.ssl_ctx = data->ssl_ctx;
310         eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
311         eap_conf.backend_auth = TRUE;
312         eap_conf.eap_server = 1;
313         eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
314         eap_conf.eap_fast_a_id = data->eap_fast_a_id;
315         eap_conf.eap_fast_prov = data->eap_fast_prov;
316         eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
317         eap_conf.tnc = data->tnc;
318         sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
319                                        &eap_conf);
320         if (sess->eap == NULL) {
321                 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
322                              "new session");
323                 radius_server_session_free(data, sess);
324                 return NULL;
325         }
326         sess->eap_if = eap_get_interface(sess->eap);
327         sess->eap_if->eapRestart = TRUE;
328         sess->eap_if->portEnabled = TRUE;
329
330         RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
331
332         return sess;
333 }
334
335
336 static struct radius_msg *
337 radius_server_encapsulate_eap(struct radius_server_data *data,
338                               struct radius_client *client,
339                               struct radius_session *sess,
340                               struct radius_msg *request)
341 {
342         struct radius_msg *msg;
343         int code;
344         unsigned int sess_id;
345
346         if (sess->eap_if->eapFail) {
347                 sess->eap_if->eapFail = FALSE;
348                 code = RADIUS_CODE_ACCESS_REJECT;
349         } else if (sess->eap_if->eapSuccess) {
350                 sess->eap_if->eapSuccess = FALSE;
351                 code = RADIUS_CODE_ACCESS_ACCEPT;
352         } else {
353                 sess->eap_if->eapReq = FALSE;
354                 code = RADIUS_CODE_ACCESS_CHALLENGE;
355         }
356
357         msg = radius_msg_new(code, request->hdr->identifier);
358         if (msg == NULL) {
359                 RADIUS_DEBUG("Failed to allocate reply message");
360                 return NULL;
361         }
362
363         sess_id = htonl(sess->sess_id);
364         if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
365             !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
366                                  (u8 *) &sess_id, sizeof(sess_id))) {
367                 RADIUS_DEBUG("Failed to add State attribute");
368         }
369
370         if (sess->eap_if->eapReqData &&
371             !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
372                                 wpabuf_len(sess->eap_if->eapReqData))) {
373                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
374         }
375
376         if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
377                 int len;
378                 if (sess->eap_if->eapKeyDataLen > 64) {
379                         len = 32;
380                 } else {
381                         len = sess->eap_if->eapKeyDataLen / 2;
382                 }
383                 if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
384                                               (u8 *) client->shared_secret,
385                                               client->shared_secret_len,
386                                               sess->eap_if->eapKeyData + len,
387                                               len, sess->eap_if->eapKeyData,
388                                               len)) {
389                         RADIUS_DEBUG("Failed to add MPPE key attributes");
390                 }
391         }
392
393         if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
394                 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
395                 radius_msg_free(msg);
396                 os_free(msg);
397                 return NULL;
398         }
399
400         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
401                                   client->shared_secret_len,
402                                   request->hdr->authenticator) < 0) {
403                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
404         }
405
406         return msg;
407 }
408
409
410 static int radius_server_reject(struct radius_server_data *data,
411                                 struct radius_client *client,
412                                 struct radius_msg *request,
413                                 struct sockaddr *from, socklen_t fromlen,
414                                 const char *from_addr, int from_port)
415 {
416         struct radius_msg *msg;
417         int ret = 0;
418         struct eap_hdr eapfail;
419
420         RADIUS_DEBUG("Reject invalid request from %s:%d",
421                      from_addr, from_port);
422
423         msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
424                              request->hdr->identifier);
425         if (msg == NULL) {
426                 return -1;
427         }
428
429         os_memset(&eapfail, 0, sizeof(eapfail));
430         eapfail.code = EAP_CODE_FAILURE;
431         eapfail.identifier = 0;
432         eapfail.length = host_to_be16(sizeof(eapfail));
433
434         if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
435                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
436         }
437
438         if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
439                 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
440                 radius_msg_free(msg);
441                 os_free(msg);
442                 return -1;
443         }
444
445         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
446                                   client->shared_secret_len,
447                                   request->hdr->authenticator) < 0) {
448                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
449         }
450
451         if (wpa_debug_level <= MSG_MSGDUMP) {
452                 radius_msg_dump(msg);
453         }
454
455         data->counters.access_rejects++;
456         client->counters.access_rejects++;
457         if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
458                    (struct sockaddr *) from, sizeof(*from)) < 0) {
459                 perror("sendto[RADIUS SRV]");
460                 ret = -1;
461         }
462
463         radius_msg_free(msg);
464         os_free(msg);
465
466         return ret;
467 }
468
469
470 static int radius_server_request(struct radius_server_data *data,
471                                  struct radius_msg *msg,
472                                  struct sockaddr *from, socklen_t fromlen,
473                                  struct radius_client *client,
474                                  const char *from_addr, int from_port,
475                                  struct radius_session *force_sess)
476 {
477         u8 *eap = NULL;
478         size_t eap_len;
479         int res, state_included = 0;
480         u8 statebuf[4];
481         unsigned int state;
482         struct radius_session *sess;
483         struct radius_msg *reply;
484
485         if (force_sess)
486                 sess = force_sess;
487         else {
488                 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
489                                           sizeof(statebuf));
490                 state_included = res >= 0;
491                 if (res == sizeof(statebuf)) {
492                         state = WPA_GET_BE32(statebuf);
493                         sess = radius_server_get_session(client, state);
494                 } else {
495                         sess = NULL;
496                 }
497         }
498
499         if (sess) {
500                 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
501         } else if (state_included) {
502                 RADIUS_DEBUG("State attribute included but no session found");
503                 radius_server_reject(data, client, msg, from, fromlen,
504                                      from_addr, from_port);
505                 return -1;
506         } else {
507                 sess = radius_server_get_new_session(data, client, msg);
508                 if (sess == NULL) {
509                         RADIUS_DEBUG("Could not create a new session");
510                         radius_server_reject(data, client, msg, from, fromlen,
511                                              from_addr, from_port);
512                         return -1;
513                 }
514         }
515
516         if (sess->last_from_port == from_port &&
517             sess->last_identifier == msg->hdr->identifier &&
518             os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
519             0) {
520                 RADIUS_DEBUG("Duplicate message from %s", from_addr);
521                 data->counters.dup_access_requests++;
522                 client->counters.dup_access_requests++;
523
524                 if (sess->last_reply) {
525                         res = sendto(data->auth_sock, sess->last_reply->buf,
526                                      sess->last_reply->buf_used, 0,
527                                      (struct sockaddr *) from, fromlen);
528                         if (res < 0) {
529                                 perror("sendto[RADIUS SRV]");
530                         }
531                         return 0;
532                 }
533
534                 RADIUS_DEBUG("No previous reply available for duplicate "
535                              "message");
536                 return -1;
537         }
538                       
539         eap = radius_msg_get_eap(msg, &eap_len);
540         if (eap == NULL) {
541                 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
542                              from_addr);
543                 data->counters.packets_dropped++;
544                 client->counters.packets_dropped++;
545                 return -1;
546         }
547
548         RADIUS_DUMP("Received EAP data", eap, eap_len);
549
550         /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
551          * RFC3579 Sect. 2.6.2.
552          * Include EAP-Response/Nak with no preferred method if
553          * code == request.
554          * If code is not 1-4, discard the packet silently.
555          * Or is this already done by the EAP state machine? */
556
557         wpabuf_free(sess->eap_if->eapRespData);
558         sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len);
559         if (sess->eap_if->eapRespData == NULL)
560                 os_free(eap);
561         eap = NULL;
562         sess->eap_if->eapResp = TRUE;
563         eap_server_sm_step(sess->eap);
564
565         if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
566              sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
567                 RADIUS_DUMP("EAP data from the state machine",
568                             wpabuf_head(sess->eap_if->eapReqData),
569                             wpabuf_len(sess->eap_if->eapReqData));
570         } else if (sess->eap_if->eapFail) {
571                 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
572                              "set");
573         } else if (eap_sm_method_pending(sess->eap)) {
574                 if (sess->last_msg) {
575                         radius_msg_free(sess->last_msg);
576                         os_free(sess->last_msg);
577                 }
578                 sess->last_msg = msg;
579                 sess->last_from_port = from_port;
580                 os_free(sess->last_from_addr);
581                 sess->last_from_addr = os_strdup(from_addr);
582                 sess->last_fromlen = fromlen;
583                 os_memcpy(&sess->last_from, from, fromlen);
584                 return -2;
585         } else {
586                 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
587                              " Access-Request silently (assuming it was a "
588                              "duplicate)");
589                 data->counters.packets_dropped++;
590                 client->counters.packets_dropped++;
591                 return -1;
592         }
593
594         reply = radius_server_encapsulate_eap(data, client, sess, msg);
595
596         if (reply) {
597                 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
598                 if (wpa_debug_level <= MSG_MSGDUMP) {
599                         radius_msg_dump(reply);
600                 }
601
602                 switch (reply->hdr->code) {
603                 case RADIUS_CODE_ACCESS_ACCEPT:
604                         data->counters.access_accepts++;
605                         client->counters.access_accepts++;
606                         break;
607                 case RADIUS_CODE_ACCESS_REJECT:
608                         data->counters.access_rejects++;
609                         client->counters.access_rejects++;
610                         break;
611                 case RADIUS_CODE_ACCESS_CHALLENGE:
612                         data->counters.access_challenges++;
613                         client->counters.access_challenges++;
614                         break;
615                 }
616                 res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
617                              (struct sockaddr *) from, fromlen);
618                 if (res < 0) {
619                         perror("sendto[RADIUS SRV]");
620                 }
621                 if (sess->last_reply) {
622                         radius_msg_free(sess->last_reply);
623                         os_free(sess->last_reply);
624                 }
625                 sess->last_reply = reply;
626                 sess->last_from_port = from_port;
627                 sess->last_identifier = msg->hdr->identifier;
628                 os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
629                           16);
630         } else {
631                 data->counters.packets_dropped++;
632                 client->counters.packets_dropped++;
633         }
634
635         if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) {
636                 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
637                              sess->sess_id);
638                 eloop_cancel_timeout(radius_server_session_remove_timeout,
639                                      data, sess);
640                 eloop_register_timeout(10, 0,
641                                        radius_server_session_remove_timeout,
642                                        data, sess);
643         }
644
645         return 0;
646 }
647
648
649 static void radius_server_receive_auth(int sock, void *eloop_ctx,
650                                        void *sock_ctx)
651 {
652         struct radius_server_data *data = eloop_ctx;
653         u8 *buf = NULL;
654         struct sockaddr_storage from;
655         socklen_t fromlen;
656         int len;
657         struct radius_client *client = NULL;
658         struct radius_msg *msg = NULL;
659         char abuf[50];
660         int from_port = 0;
661
662         buf = os_malloc(RADIUS_MAX_MSG_LEN);
663         if (buf == NULL) {
664                 goto fail;
665         }
666
667         fromlen = sizeof(from);
668         len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
669                        (struct sockaddr *) &from, &fromlen);
670         if (len < 0) {
671                 perror("recvfrom[radius_server]");
672                 goto fail;
673         }
674
675 #ifdef CONFIG_IPV6
676         if (data->ipv6) {
677                 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;
678                 if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf))
679                     == NULL)
680                         abuf[0] = '\0';
681                 from_port = ntohs(from6->sin6_port);
682                 RADIUS_DEBUG("Received %d bytes from %s:%d",
683                              len, abuf, from_port);
684
685                 client = radius_server_get_client(data,
686                                                   (struct in_addr *)
687                                                   &from6->sin6_addr, 1);
688         }
689 #endif /* CONFIG_IPV6 */
690
691         if (!data->ipv6) {
692                 struct sockaddr_in *from4 = (struct sockaddr_in *) &from;
693                 os_strlcpy(abuf, inet_ntoa(from4->sin_addr), sizeof(abuf));
694                 from_port = ntohs(from4->sin_port);
695                 RADIUS_DEBUG("Received %d bytes from %s:%d",
696                              len, abuf, from_port);
697
698                 client = radius_server_get_client(data, &from4->sin_addr, 0);
699         }
700
701         RADIUS_DUMP("Received data", buf, len);
702
703         if (client == NULL) {
704                 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
705                 data->counters.invalid_requests++;
706                 goto fail;
707         }
708
709         msg = radius_msg_parse(buf, len);
710         if (msg == NULL) {
711                 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
712                 data->counters.malformed_access_requests++;
713                 client->counters.malformed_access_requests++;
714                 goto fail;
715         }
716
717         os_free(buf);
718         buf = NULL;
719
720         if (wpa_debug_level <= MSG_MSGDUMP) {
721                 radius_msg_dump(msg);
722         }
723
724         if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
725                 RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
726                 data->counters.unknown_types++;
727                 client->counters.unknown_types++;
728                 goto fail;
729         }
730
731         data->counters.access_requests++;
732         client->counters.access_requests++;
733
734         if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
735                                        client->shared_secret_len, NULL)) {
736                 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
737                 data->counters.bad_authenticators++;
738                 client->counters.bad_authenticators++;
739                 goto fail;
740         }
741
742         if (radius_server_request(data, msg, (struct sockaddr *) &from,
743                                   fromlen, client, abuf, from_port, NULL) ==
744             -2)
745                 return; /* msg was stored with the session */
746
747 fail:
748         if (msg) {
749                 radius_msg_free(msg);
750                 os_free(msg);
751         }
752         os_free(buf);
753 }
754
755
756 static int radius_server_open_socket(int port)
757 {
758         int s;
759         struct sockaddr_in addr;
760
761         s = socket(PF_INET, SOCK_DGRAM, 0);
762         if (s < 0) {
763                 perror("socket");
764                 return -1;
765         }
766
767         os_memset(&addr, 0, sizeof(addr));
768         addr.sin_family = AF_INET;
769         addr.sin_port = htons(port);
770         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
771                 perror("bind");
772                 close(s);
773                 return -1;
774         }
775
776         return s;
777 }
778
779
780 #ifdef CONFIG_IPV6
781 static int radius_server_open_socket6(int port)
782 {
783         int s;
784         struct sockaddr_in6 addr;
785
786         s = socket(PF_INET6, SOCK_DGRAM, 0);
787         if (s < 0) {
788                 perror("socket[IPv6]");
789                 return -1;
790         }
791
792         os_memset(&addr, 0, sizeof(addr));
793         addr.sin6_family = AF_INET6;
794         os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
795         addr.sin6_port = htons(port);
796         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
797                 perror("bind");
798                 close(s);
799                 return -1;
800         }
801
802         return s;
803 }
804 #endif /* CONFIG_IPV6 */
805
806
807 static void radius_server_free_sessions(struct radius_server_data *data,
808                                         struct radius_session *sessions)
809 {
810         struct radius_session *session, *prev;
811
812         session = sessions;
813         while (session) {
814                 prev = session;
815                 session = session->next;
816                 radius_server_session_free(data, prev);
817         }
818 }
819
820
821 static void radius_server_free_clients(struct radius_server_data *data,
822                                        struct radius_client *clients)
823 {
824         struct radius_client *client, *prev;
825
826         client = clients;
827         while (client) {
828                 prev = client;
829                 client = client->next;
830
831                 radius_server_free_sessions(data, prev->sessions);
832                 os_free(prev->shared_secret);
833                 os_free(prev);
834         }
835 }
836
837
838 static struct radius_client *
839 radius_server_read_clients(const char *client_file, int ipv6)
840 {
841         FILE *f;
842         const int buf_size = 1024;
843         char *buf, *pos;
844         struct radius_client *clients, *tail, *entry;
845         int line = 0, mask, failed = 0, i;
846         struct in_addr addr;
847 #ifdef CONFIG_IPV6
848         struct in6_addr addr6;
849 #endif /* CONFIG_IPV6 */
850         unsigned int val;
851
852         f = fopen(client_file, "r");
853         if (f == NULL) {
854                 RADIUS_ERROR("Could not open client file '%s'", client_file);
855                 return NULL;
856         }
857
858         buf = os_malloc(buf_size);
859         if (buf == NULL) {
860                 fclose(f);
861                 return NULL;
862         }
863
864         clients = tail = NULL;
865         while (fgets(buf, buf_size, f)) {
866                 /* Configuration file format:
867                  * 192.168.1.0/24 secret
868                  * 192.168.1.2 secret
869                  * fe80::211:22ff:fe33:4455/64 secretipv6
870                  */
871                 line++;
872                 buf[buf_size - 1] = '\0';
873                 pos = buf;
874                 while (*pos != '\0' && *pos != '\n')
875                         pos++;
876                 if (*pos == '\n')
877                         *pos = '\0';
878                 if (*buf == '\0' || *buf == '#')
879                         continue;
880
881                 pos = buf;
882                 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
883                        (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
884                        (*pos >= 'A' && *pos <= 'F')) {
885                         pos++;
886                 }
887
888                 if (*pos == '\0') {
889                         failed = 1;
890                         break;
891                 }
892
893                 if (*pos == '/') {
894                         char *end;
895                         *pos++ = '\0';
896                         mask = strtol(pos, &end, 10);
897                         if ((pos == end) ||
898                             (mask < 0 || mask > (ipv6 ? 128 : 32))) {
899                                 failed = 1;
900                                 break;
901                         }
902                         pos = end;
903                 } else {
904                         mask = ipv6 ? 128 : 32;
905                         *pos++ = '\0';
906                 }
907
908                 if (!ipv6 && inet_aton(buf, &addr) == 0) {
909                         failed = 1;
910                         break;
911                 }
912 #ifdef CONFIG_IPV6
913                 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
914                         if (inet_pton(AF_INET, buf, &addr) <= 0) {
915                                 failed = 1;
916                                 break;
917                         }
918                         /* Convert IPv4 address to IPv6 */
919                         if (mask <= 32)
920                                 mask += (128 - 32);
921                         os_memset(addr6.s6_addr, 0, 10);
922                         addr6.s6_addr[10] = 0xff;
923                         addr6.s6_addr[11] = 0xff;
924                         os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
925                                   4);
926                 }
927 #endif /* CONFIG_IPV6 */
928
929                 while (*pos == ' ' || *pos == '\t') {
930                         pos++;
931                 }
932
933                 if (*pos == '\0') {
934                         failed = 1;
935                         break;
936                 }
937
938                 entry = os_zalloc(sizeof(*entry));
939                 if (entry == NULL) {
940                         failed = 1;
941                         break;
942                 }
943                 entry->shared_secret = os_strdup(pos);
944                 if (entry->shared_secret == NULL) {
945                         failed = 1;
946                         os_free(entry);
947                         break;
948                 }
949                 entry->shared_secret_len = os_strlen(entry->shared_secret);
950                 entry->addr.s_addr = addr.s_addr;
951                 if (!ipv6) {
952                         val = 0;
953                         for (i = 0; i < mask; i++)
954                                 val |= 1 << (31 - i);
955                         entry->mask.s_addr = htonl(val);
956                 }
957 #ifdef CONFIG_IPV6
958                 if (ipv6) {
959                         int offset = mask / 8;
960
961                         os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
962                         os_memset(entry->mask6.s6_addr, 0xff, offset);
963                         val = 0;
964                         for (i = 0; i < (mask % 8); i++)
965                                 val |= 1 << (7 - i);
966                         if (offset < 16)
967                                 entry->mask6.s6_addr[offset] = val;
968                 }
969 #endif /* CONFIG_IPV6 */
970
971                 if (tail == NULL) {
972                         clients = tail = entry;
973                 } else {
974                         tail->next = entry;
975                         tail = entry;
976                 }
977         }
978
979         if (failed) {
980                 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
981                 radius_server_free_clients(NULL, clients);
982                 clients = NULL;
983         }
984
985         os_free(buf);
986         fclose(f);
987
988         return clients;
989 }
990
991
992 struct radius_server_data *
993 radius_server_init(struct radius_server_conf *conf)
994 {
995         struct radius_server_data *data;
996
997 #ifndef CONFIG_IPV6
998         if (conf->ipv6) {
999                 fprintf(stderr, "RADIUS server compiled without IPv6 "
1000                         "support.\n");
1001                 return NULL;
1002         }
1003 #endif /* CONFIG_IPV6 */
1004
1005         data = os_zalloc(sizeof(*data));
1006         if (data == NULL)
1007                 return NULL;
1008
1009         os_get_time(&data->start_time);
1010         data->conf_ctx = conf->conf_ctx;
1011         data->eap_sim_db_priv = conf->eap_sim_db_priv;
1012         data->ssl_ctx = conf->ssl_ctx;
1013         data->ipv6 = conf->ipv6;
1014         if (conf->pac_opaque_encr_key) {
1015                 data->pac_opaque_encr_key = os_malloc(16);
1016                 os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1017                           16);
1018         }
1019         if (conf->eap_fast_a_id)
1020                 data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
1021         data->eap_fast_prov = conf->eap_fast_prov;
1022         data->get_eap_user = conf->get_eap_user;
1023         data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1024         data->tnc = conf->tnc;
1025
1026         data->clients = radius_server_read_clients(conf->client_file,
1027                                                    conf->ipv6);
1028         if (data->clients == NULL) {
1029                 printf("No RADIUS clients configured.\n");
1030                 radius_server_deinit(data);
1031                 return NULL;
1032         }
1033
1034 #ifdef CONFIG_IPV6
1035         if (conf->ipv6)
1036                 data->auth_sock = radius_server_open_socket6(conf->auth_port);
1037         else
1038 #endif /* CONFIG_IPV6 */
1039         data->auth_sock = radius_server_open_socket(conf->auth_port);
1040         if (data->auth_sock < 0) {
1041                 printf("Failed to open UDP socket for RADIUS authentication "
1042                        "server\n");
1043                 radius_server_deinit(data);
1044                 return NULL;
1045         }
1046         if (eloop_register_read_sock(data->auth_sock,
1047                                      radius_server_receive_auth,
1048                                      data, NULL)) {
1049                 radius_server_deinit(data);
1050                 return NULL;
1051         }
1052
1053         return data;
1054 }
1055
1056
1057 void radius_server_deinit(struct radius_server_data *data)
1058 {
1059         if (data == NULL)
1060                 return;
1061
1062         if (data->auth_sock >= 0) {
1063                 eloop_unregister_read_sock(data->auth_sock);
1064                 close(data->auth_sock);
1065         }
1066
1067         radius_server_free_clients(data, data->clients);
1068
1069         os_free(data->pac_opaque_encr_key);
1070         os_free(data->eap_fast_a_id);
1071         os_free(data);
1072 }
1073
1074
1075 int radius_server_get_mib(struct radius_server_data *data, char *buf,
1076                           size_t buflen)
1077 {
1078         int ret, uptime;
1079         unsigned int idx;
1080         char *end, *pos;
1081         struct os_time now;
1082         struct radius_client *cli;
1083
1084         /* RFC 2619 - RADIUS Authentication Server MIB */
1085
1086         if (data == NULL || buflen == 0)
1087                 return 0;
1088
1089         pos = buf;
1090         end = buf + buflen;
1091
1092         os_get_time(&now);
1093         uptime = (now.sec - data->start_time.sec) * 100 +
1094                 ((now.usec - data->start_time.usec) / 10000) % 100;
1095         ret = os_snprintf(pos, end - pos,
1096                           "RADIUS-AUTH-SERVER-MIB\n"
1097                           "radiusAuthServIdent=hostapd\n"
1098                           "radiusAuthServUpTime=%d\n"
1099                           "radiusAuthServResetTime=0\n"
1100                           "radiusAuthServConfigReset=4\n",
1101                           uptime);
1102         if (ret < 0 || ret >= end - pos) {
1103                 *pos = '\0';
1104                 return pos - buf;
1105         }
1106         pos += ret;
1107
1108         ret = os_snprintf(pos, end - pos,
1109                           "radiusAuthServTotalAccessRequests=%u\n"
1110                           "radiusAuthServTotalInvalidRequests=%u\n"
1111                           "radiusAuthServTotalDupAccessRequests=%u\n"
1112                           "radiusAuthServTotalAccessAccepts=%u\n"
1113                           "radiusAuthServTotalAccessRejects=%u\n"
1114                           "radiusAuthServTotalAccessChallenges=%u\n"
1115                           "radiusAuthServTotalMalformedAccessRequests=%u\n"
1116                           "radiusAuthServTotalBadAuthenticators=%u\n"
1117                           "radiusAuthServTotalPacketsDropped=%u\n"
1118                           "radiusAuthServTotalUnknownTypes=%u\n",
1119                           data->counters.access_requests,
1120                           data->counters.invalid_requests,
1121                           data->counters.dup_access_requests,
1122                           data->counters.access_accepts,
1123                           data->counters.access_rejects,
1124                           data->counters.access_challenges,
1125                           data->counters.malformed_access_requests,
1126                           data->counters.bad_authenticators,
1127                           data->counters.packets_dropped,
1128                           data->counters.unknown_types);
1129         if (ret < 0 || ret >= end - pos) {
1130                 *pos = '\0';
1131                 return pos - buf;
1132         }
1133         pos += ret;
1134
1135         for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1136                 char abuf[50], mbuf[50];
1137 #ifdef CONFIG_IPV6
1138                 if (data->ipv6) {
1139                         if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1140                                       sizeof(abuf)) == NULL)
1141                                 abuf[0] = '\0';
1142                         if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1143                                       sizeof(mbuf)) == NULL)
1144                                 mbuf[0] = '\0';
1145                 }
1146 #endif /* CONFIG_IPV6 */
1147                 if (!data->ipv6) {
1148                         os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1149                         os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1150                 }
1151
1152                 ret = os_snprintf(pos, end - pos,
1153                                   "radiusAuthClientIndex=%u\n"
1154                                   "radiusAuthClientAddress=%s/%s\n"
1155                                   "radiusAuthServAccessRequests=%u\n"
1156                                   "radiusAuthServDupAccessRequests=%u\n"
1157                                   "radiusAuthServAccessAccepts=%u\n"
1158                                   "radiusAuthServAccessRejects=%u\n"
1159                                   "radiusAuthServAccessChallenges=%u\n"
1160                                   "radiusAuthServMalformedAccessRequests=%u\n"
1161                                   "radiusAuthServBadAuthenticators=%u\n"
1162                                   "radiusAuthServPacketsDropped=%u\n"
1163                                   "radiusAuthServUnknownTypes=%u\n",
1164                                   idx,
1165                                   abuf, mbuf,
1166                                   cli->counters.access_requests,
1167                                   cli->counters.dup_access_requests,
1168                                   cli->counters.access_accepts,
1169                                   cli->counters.access_rejects,
1170                                   cli->counters.access_challenges,
1171                                   cli->counters.malformed_access_requests,
1172                                   cli->counters.bad_authenticators,
1173                                   cli->counters.packets_dropped,
1174                                   cli->counters.unknown_types);
1175                 if (ret < 0 || ret >= end - pos) {
1176                         *pos = '\0';
1177                         return pos - buf;
1178                 }
1179                 pos += ret;
1180         }
1181
1182         return pos - buf;
1183 }
1184
1185
1186 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1187                                       size_t identity_len, int phase2,
1188                                       struct eap_user *user)
1189 {
1190         struct radius_session *sess = ctx;
1191         struct radius_server_data *data = sess->server;
1192
1193         return data->get_eap_user(data->conf_ctx, identity, identity_len,
1194                                   phase2, user);
1195 }
1196
1197
1198 static struct eapol_callbacks radius_server_eapol_cb =
1199 {
1200         .get_eap_user = radius_server_get_eap_user,
1201 };
1202
1203
1204 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1205 {
1206         struct radius_client *cli;
1207         struct radius_session *s, *sess = NULL;
1208         struct radius_msg *msg;
1209
1210         if (data == NULL)
1211                 return;
1212
1213         for (cli = data->clients; cli; cli = cli->next) {
1214                 for (s = cli->sessions; s; s = s->next) {
1215                         if (s->eap == ctx && s->last_msg) {
1216                                 sess = s;
1217                                 break;
1218                         }
1219                         if (sess)
1220                                 break;
1221                 }
1222                 if (sess)
1223                         break;
1224         }
1225
1226         if (sess == NULL) {
1227                 RADIUS_DEBUG("No session matched callback ctx");
1228                 return;
1229         }
1230
1231         msg = sess->last_msg;
1232         sess->last_msg = NULL;
1233         eap_sm_pending_cb(sess->eap);
1234         if (radius_server_request(data, msg,
1235                                   (struct sockaddr *) &sess->last_from,
1236                                   sess->last_fromlen, cli,
1237                                   sess->last_from_addr,
1238                                   sess->last_from_port, sess) == -2)
1239                 return; /* msg was stored with the session */
1240
1241         radius_msg_free(msg);
1242         os_free(msg);
1243 }