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