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