an, awi, cue and kue don't use the miibus interface.
[dragonfly.git] / contrib / hostapd-0.4.9 / radius_server.c
1 /*
2  * hostapd / RADIUS authentication server
3  * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <netinet/in.h>
20 #include <sys/socket.h>
21 #include <arpa/inet.h>
22 #include <net/if.h>
23
24 #include "common.h"
25 #include "radius.h"
26 #include "eloop.h"
27 #include "config.h"
28 #include "eap.h"
29 #include "radius_server.h"
30
31 #define RADIUS_SESSION_TIMEOUT 60
32 #define RADIUS_MAX_SESSION 100
33 #define RADIUS_MAX_MSG_LEN 3000
34
35 static struct eapol_callbacks radius_server_eapol_cb;
36
37 struct radius_client;
38 struct radius_server_data;
39
40 struct radius_session {
41         struct radius_session *next;
42         struct radius_client *client;
43         struct radius_server_data *server;
44         unsigned int sess_id;
45         struct eap_sm *eap;
46         u8 *eapKeyData, *eapReqData;
47         size_t eapKeyDataLen, eapReqDataLen;
48         Boolean eapSuccess, eapRestart, eapFail, eapResp, eapReq, eapNoReq;
49         Boolean portEnabled, eapTimeout;
50 };
51
52 struct radius_client {
53         struct radius_client *next;
54         struct in_addr addr;
55         struct in_addr mask;
56 #ifdef CONFIG_IPV6
57         struct in6_addr addr6;
58         struct in6_addr mask6;
59 #endif /* CONFIG_IPV6 */
60         char *shared_secret;
61         int shared_secret_len;
62         struct radius_session *sessions;
63 };
64
65 struct radius_server_data {
66         int auth_sock;
67         struct radius_client *clients;
68         struct radius_server_session *sessions;
69         unsigned int next_sess_id;
70         void *hostapd_conf;
71         int num_sess;
72         void *eap_sim_db_priv;
73         void *ssl_ctx;
74         int ipv6;
75 };
76
77
78 extern int wpa_debug_level;
79
80 #define RADIUS_DEBUG(args...) \
81 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
82 #define RADIUS_ERROR(args...) \
83 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
84 #define RADIUS_DUMP(args...) \
85 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
86 #define RADIUS_DUMP_ASCII(args...) \
87 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
88
89
90 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
91
92
93
94 static struct radius_client *
95 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
96                          int ipv6)
97 {
98         struct radius_client *client = data->clients;
99
100         while (client) {
101 #ifdef CONFIG_IPV6
102                 if (ipv6) {
103                         struct in6_addr *addr6;
104                         int i;
105
106                         addr6 = (struct in6_addr *) addr;
107                         for (i = 0; i < 16; i++) {
108                                 if ((addr6->s6_addr[i] &
109                                      client->mask6.s6_addr[i]) !=
110                                     (client->addr6.s6_addr[i] &
111                                      client->mask6.s6_addr[i])) {
112                                         i = 17;
113                                         break;
114                                 }
115                         }
116                         if (i == 16) {
117                                 break;
118                         }
119                 }
120 #endif /* CONFIG_IPV6 */
121                 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
122                     (addr->s_addr & client->mask.s_addr)) {
123                         break;
124                 }
125
126                 client = client->next;
127         }
128
129         return client;
130 }
131
132
133 static struct radius_session *
134 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
135 {
136         struct radius_session *sess = client->sessions;
137
138         while (sess) {
139                 if (sess->sess_id == sess_id) {
140                         break;
141                 }
142                 sess = sess->next;
143         }
144
145         return sess;
146 }
147
148
149 static void radius_server_session_free(struct radius_server_data *data,
150                                        struct radius_session *sess)
151 {
152         eloop_cancel_timeout(radius_server_session_timeout, data, sess);
153         free(sess->eapKeyData);
154         free(sess->eapReqData);
155         eap_sm_deinit(sess->eap);
156         free(sess);
157         data->num_sess--;
158 }
159
160
161 static void radius_server_session_remove(struct radius_server_data *data,
162                                          struct radius_session *sess)
163 {
164         struct radius_client *client = sess->client;
165         struct radius_session *session, *prev;
166
167         prev = NULL;
168         session = client->sessions;
169         while (session) {
170                 if (session == sess) {
171                         if (prev == NULL) {
172                                 client->sessions = sess->next;
173                         } else {
174                                 prev->next = sess->next;
175                         }
176                         radius_server_session_free(data, sess);
177                         break;
178                 }
179                 prev = session;
180                 session = session->next;
181         }
182 }
183
184
185 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
186 {
187         struct radius_server_data *data = eloop_ctx;
188         struct radius_session *sess = timeout_ctx;
189
190         RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
191         radius_server_session_remove(data, sess);
192 }
193
194
195 static struct radius_session *
196 radius_server_new_session(struct radius_server_data *data,
197                           struct radius_client *client)
198 {
199         struct radius_session *sess;
200
201         if (data->num_sess >= RADIUS_MAX_SESSION) {
202                 RADIUS_DEBUG("Maximum number of existing session - no room "
203                              "for a new session");
204                 return NULL;
205         }
206
207         sess = malloc(sizeof(*sess));
208         if (sess == NULL) {
209                 return NULL;
210         }
211         memset(sess, 0, sizeof(*sess));
212         sess->server = data;
213         sess->client = client;
214         sess->sess_id = data->next_sess_id++;
215         sess->next = client->sessions;
216         client->sessions = sess;
217         eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
218                                radius_server_session_timeout, data, sess);
219         data->num_sess++;
220         return sess;
221 }
222
223
224 static struct radius_session *
225 radius_server_get_new_session(struct radius_server_data *data,
226                               struct radius_client *client,
227                               struct radius_msg *msg)
228 {
229         u8 *user;
230         size_t user_len;
231         const struct hostapd_eap_user *eap_user;
232         int res;
233         struct radius_session *sess;
234         struct eap_config eap_conf;
235
236         RADIUS_DEBUG("Creating a new session");
237
238         user = malloc(256);
239         if (user == NULL) {
240                 return NULL;
241         }
242         res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
243         if (res < 0 || res > 256) {
244                 RADIUS_DEBUG("Could not get User-Name");
245                 free(user);
246                 return NULL;
247         }
248         user_len = res;
249         RADIUS_DUMP_ASCII("User-Name", user, user_len);
250
251         eap_user = hostapd_get_eap_user(data->hostapd_conf, user, user_len, 0);
252         free(user);
253
254         if (eap_user) {
255                 RADIUS_DEBUG("Matching user entry found");
256                 sess = radius_server_new_session(data, client);
257                 if (sess == NULL) {
258                         RADIUS_DEBUG("Failed to create a new session");
259                         return NULL;
260                 }
261         } else {
262                 RADIUS_DEBUG("User-Name not found from user database");
263                 return NULL;
264         }
265
266         memset(&eap_conf, 0, sizeof(eap_conf));
267         eap_conf.ssl_ctx = data->ssl_ctx;
268         eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
269         eap_conf.backend_auth = TRUE;
270         sess->eap = eap_sm_init(sess, &radius_server_eapol_cb, &eap_conf);
271         if (sess->eap == NULL) {
272                 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
273                              "new session");
274                 radius_server_session_free(data, sess);
275                 return NULL;
276         }
277         sess->eapRestart = TRUE;
278         sess->portEnabled = TRUE;
279
280         RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
281
282         return sess;
283 }
284
285
286 static struct radius_msg *
287 radius_server_encapsulate_eap(struct radius_server_data *data,
288                               struct radius_client *client,
289                               struct radius_session *sess,
290                               struct radius_msg *request)
291 {
292         struct radius_msg *msg;
293         int code;
294         unsigned int sess_id;
295
296         if (sess->eapFail) {
297                 code = RADIUS_CODE_ACCESS_REJECT;
298         } else if (sess->eapSuccess) {
299                 code = RADIUS_CODE_ACCESS_ACCEPT;
300         } else {
301                 code = RADIUS_CODE_ACCESS_CHALLENGE;
302         }
303
304         msg = radius_msg_new(code, request->hdr->identifier);
305         if (msg == NULL) {
306                 return NULL;
307         }
308
309         sess_id = htonl(sess->sess_id);
310         if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
311             !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
312                                  (u8 *) &sess_id, sizeof(sess_id))) {
313                 RADIUS_DEBUG("Failed to add State attribute");
314         }
315
316         if (sess->eapReqData &&
317             !radius_msg_add_eap(msg, sess->eapReqData, sess->eapReqDataLen)) {
318                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
319         }
320
321         if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eapKeyData) {
322                 int len;
323                 if (sess->eapKeyDataLen > 64) {
324                         len = 32;
325                 } else {
326                         len = sess->eapKeyDataLen / 2;
327                 }
328                 if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
329                                               (u8 *) client->shared_secret,
330                                               client->shared_secret_len,
331                                               sess->eapKeyData + len, len,
332                                               sess->eapKeyData, len)) {
333                         RADIUS_DEBUG("Failed to add MPPE key attributes");
334                 }
335         }
336
337         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
338                                   client->shared_secret_len,
339                                   request->hdr->authenticator) < 0) {
340                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
341         }
342
343         return msg;
344 }
345
346
347 static int radius_server_reject(struct radius_server_data *data,
348                                 struct radius_client *client,
349                                 struct radius_msg *request,
350                                 struct sockaddr *from, socklen_t fromlen,
351                                 const char *from_addr, int from_port)
352 {
353         struct radius_msg *msg;
354         int ret = 0;
355         struct eap_hdr eapfail;
356
357         RADIUS_DEBUG("Reject invalid request from %s:%d",
358                      from_addr, from_port);
359
360         msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
361                              request->hdr->identifier);
362         if (msg == NULL) {
363                 return -1;
364         }
365
366         memset(&eapfail, 0, sizeof(eapfail));
367         eapfail.code = EAP_CODE_FAILURE;
368         eapfail.identifier = 0;
369         eapfail.length = htons(sizeof(eapfail));
370
371         if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
372                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
373         }
374
375
376         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
377                                   client->shared_secret_len,
378                                   request->hdr->authenticator) < 0) {
379                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
380         }
381
382         if (wpa_debug_level <= MSG_MSGDUMP) {
383                 radius_msg_dump(msg);
384         }
385
386         if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
387                    (struct sockaddr *) from, sizeof(*from)) < 0) {
388                 perror("sendto[RADIUS SRV]");
389                 ret = -1;
390         }
391
392         radius_msg_free(msg);
393         free(msg);
394
395         return ret;
396 }
397
398
399 static int radius_server_request(struct radius_server_data *data,
400                                  struct radius_msg *msg,
401                                  struct sockaddr *from, socklen_t fromlen,
402                                  struct radius_client *client,
403                                  const char *from_addr, int from_port)
404 {
405         u8 *eap = NULL;
406         size_t eap_len;
407         int res, state_included = 0;
408         u8 statebuf[4], resp_id;
409         unsigned int state;
410         struct radius_session *sess;
411         struct radius_msg *reply;
412         struct eap_hdr *hdr;
413
414         /* TODO: Implement duplicate packet processing */
415
416         res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
417                                   sizeof(statebuf));
418         state_included = res >= 0;
419         if (res == sizeof(statebuf)) {
420                 state = (statebuf[0] << 24) | (statebuf[1] << 16) |
421                         (statebuf[2] << 8) | statebuf[3];
422                 sess = radius_server_get_session(client, state);
423         } else {
424                 sess = NULL;
425         }
426
427         if (sess) {
428                 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
429         } else if (state_included) {
430                 RADIUS_DEBUG("State attribute included but no session found");
431                 radius_server_reject(data, client, msg, from, fromlen,
432                                      from_addr, from_port);
433                 return -1;
434         } else {
435                 sess = radius_server_get_new_session(data, client, msg);
436                 if (sess == NULL) {
437                         RADIUS_DEBUG("Could not create a new session");
438                         radius_server_reject(data, client, msg, from, fromlen,
439                                              from_addr, from_port);
440                         return -1;
441                 }
442         }
443
444         eap = radius_msg_get_eap(msg, &eap_len);
445         if (eap == NULL) {
446                 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
447                              from_addr);
448                 return -1;
449         }
450
451         RADIUS_DUMP("Received EAP data", eap, eap_len);
452         if (eap_len >= sizeof(*hdr)) {
453                 hdr = (struct eap_hdr *) eap;
454                 resp_id = hdr->identifier;
455         } else {
456                 resp_id = 0;
457         }
458
459         /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
460          * RFC3579 Sect. 2.6.2.
461          * Include EAP-Response/Nak with no preferred method if
462          * code == request.
463          * If code is not 1-4, discard the packet silently.
464          * Or is this already done by the EAP state machine? */
465
466         eap_set_eapRespData(sess->eap, eap, eap_len);
467         free(eap);
468         eap = NULL;
469         sess->eapResp = TRUE;
470         eap_sm_step(sess->eap);
471
472         if (sess->eapReqData) {
473                 RADIUS_DUMP("EAP data from the state machine",
474                             sess->eapReqData, sess->eapReqDataLen);
475         } else if (sess->eapFail) {
476                 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
477                              "set - generate EAP-Failure");
478                 hdr = malloc(sizeof(*hdr));
479                 if (hdr) {
480                         memset(hdr, 0, sizeof(*hdr));
481                         hdr->identifier = resp_id;
482                         hdr->length = htons(sizeof(*hdr));
483                         sess->eapReqData = (u8 *) hdr;
484                         sess->eapReqDataLen = sizeof(*hdr);
485                 }
486         } else {
487                 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
488                              " Access-Request silently (assuming it was a "
489                              "duplicate)");
490                 return -1;
491         }
492
493         reply = radius_server_encapsulate_eap(data, client, sess, msg);
494
495         free(sess->eapReqData);
496         sess->eapReqData = NULL;
497         sess->eapReqDataLen = 0;
498
499         if (reply) {
500                 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
501                 if (wpa_debug_level <= MSG_MSGDUMP) {
502                         radius_msg_dump(reply);
503                 }
504
505                 res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
506                              (struct sockaddr *) from, fromlen);
507                 if (res < 0) {
508                         perror("sendto[RADIUS SRV]");
509                 }
510                 radius_msg_free(reply);
511                 free(reply);
512         }
513
514         if (sess->eapSuccess || sess->eapFail) {
515                 RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
516                 radius_server_session_remove(data, sess);
517         }
518
519         return 0;
520 }
521
522
523 static void radius_server_receive_auth(int sock, void *eloop_ctx,
524                                        void *sock_ctx)
525 {
526         struct radius_server_data *data = eloop_ctx;
527         u8 *buf = NULL;
528         struct sockaddr_storage from;
529         socklen_t fromlen;
530         int len;
531         struct radius_client *client = NULL;
532         struct radius_msg *msg = NULL;
533         char abuf[50];
534         int from_port = 0;
535
536         buf = malloc(RADIUS_MAX_MSG_LEN);
537         if (buf == NULL) {
538                 goto fail;
539         }
540
541         fromlen = sizeof(from);
542         len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
543                        (struct sockaddr *) &from, &fromlen);
544         if (len < 0) {
545                 perror("recvfrom[radius_server]");
546                 goto fail;
547         }
548
549 #ifdef CONFIG_IPV6
550         if (data->ipv6) {
551                 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from;
552                 if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf))
553                     == NULL)
554                         abuf[0] = '\0';
555                 from_port = ntohs(from6->sin6_port);
556                 RADIUS_DEBUG("Received %d bytes from %s:%d",
557                              len, abuf, from_port);
558
559                 client = radius_server_get_client(data,
560                                                   (struct in_addr *)
561                                                   &from6->sin6_addr, 1);
562         }
563 #endif /* CONFIG_IPV6 */
564
565         if (!data->ipv6) {
566                 struct sockaddr_in *from4 = (struct sockaddr_in *) &from;
567                 snprintf(abuf, sizeof(abuf), "%s", inet_ntoa(from4->sin_addr));
568                 from_port = ntohs(from4->sin_port);
569                 RADIUS_DEBUG("Received %d bytes from %s:%d",
570                              len, abuf, from_port);
571
572                 client = radius_server_get_client(data, &from4->sin_addr, 0);
573         }
574
575         RADIUS_DUMP("Received data", buf, len);
576
577         if (client == NULL) {
578                 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
579                 goto fail;
580         }
581
582         msg = radius_msg_parse(buf, len);
583         if (msg == NULL) {
584                 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
585                 goto fail;
586         }
587
588         free(buf);
589         buf = NULL;
590
591         if (wpa_debug_level <= MSG_MSGDUMP) {
592                 radius_msg_dump(msg);
593         }
594
595         if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
596                 RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
597                 goto fail;
598         }
599
600         if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
601                                        client->shared_secret_len, NULL)) {
602                 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
603                 goto fail;
604         }
605
606         radius_server_request(data, msg, (struct sockaddr *) &from, fromlen,
607                               client, abuf, from_port);
608
609 fail:
610         if (msg) {
611                 radius_msg_free(msg);
612                 free(msg);
613         }
614         free(buf);
615 }
616
617
618 static int radius_server_open_socket(int port)
619 {
620         int s;
621         struct sockaddr_in addr;
622
623         s = socket(PF_INET, SOCK_DGRAM, 0);
624         if (s < 0) {
625                 perror("socket");
626                 return -1;
627         }
628
629         memset(&addr, 0, sizeof(addr));
630         addr.sin_family = AF_INET;
631         addr.sin_port = htons(port);
632         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
633                 perror("bind");
634                 close(s);
635                 return -1;
636         }
637
638         return s;
639 }
640
641
642 #ifdef CONFIG_IPV6
643 static int radius_server_open_socket6(int port)
644 {
645         int s;
646         struct sockaddr_in6 addr;
647
648         s = socket(PF_INET6, SOCK_DGRAM, 0);
649         if (s < 0) {
650                 perror("socket[IPv6]");
651                 return -1;
652         }
653
654         memset(&addr, 0, sizeof(addr));
655         addr.sin6_family = AF_INET6;
656         memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
657         addr.sin6_port = htons(port);
658         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
659                 perror("bind");
660                 close(s);
661                 return -1;
662         }
663
664         return s;
665 }
666 #endif /* CONFIG_IPV6 */
667
668
669 static void radius_server_free_sessions(struct radius_server_data *data,
670                                         struct radius_session *sessions)
671 {
672         struct radius_session *session, *prev;
673
674         session = sessions;
675         while (session) {
676                 prev = session;
677                 session = session->next;
678                 radius_server_session_free(data, prev);
679         }
680 }
681
682
683 static void radius_server_free_clients(struct radius_server_data *data,
684                                        struct radius_client *clients)
685 {
686         struct radius_client *client, *prev;
687
688         client = clients;
689         while (client) {
690                 prev = client;
691                 client = client->next;
692
693                 radius_server_free_sessions(data, prev->sessions);
694                 free(prev->shared_secret);
695                 free(prev);
696         }
697 }
698
699
700 static struct radius_client *
701 radius_server_read_clients(const char *client_file, int ipv6)
702 {
703         FILE *f;
704         const int buf_size = 1024;
705         char *buf, *pos;
706         struct radius_client *clients, *tail, *entry;
707         int line = 0, mask, failed = 0, i;
708         struct in_addr addr;
709 #ifdef CONFIG_IPV6
710         struct in6_addr addr6;
711 #endif /* CONFIG_IPV6 */
712         unsigned int val;
713
714         f = fopen(client_file, "r");
715         if (f == NULL) {
716                 RADIUS_ERROR("Could not open client file '%s'", client_file);
717                 return NULL;
718         }
719
720         buf = malloc(buf_size);
721         if (buf == NULL) {
722                 fclose(f);
723                 return NULL;
724         }
725
726         clients = tail = NULL;
727         while (fgets(buf, buf_size, f)) {
728                 /* Configuration file format:
729                  * 192.168.1.0/24 secret
730                  * 192.168.1.2 secret
731                  * fe80::211:22ff:fe33:4455/64 secretipv6
732                  */
733                 line++;
734                 buf[buf_size - 1] = '\0';
735                 pos = buf;
736                 while (*pos != '\0' && *pos != '\n')
737                         pos++;
738                 if (*pos == '\n')
739                         *pos = '\0';
740                 if (*buf == '\0' || *buf == '#')
741                         continue;
742
743                 pos = buf;
744                 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
745                        (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
746                        (*pos >= 'A' && *pos <= 'F')) {
747                         pos++;
748                 }
749
750                 if (*pos == '\0') {
751                         failed = 1;
752                         break;
753                 }
754
755                 if (*pos == '/') {
756                         char *end;
757                         *pos++ = '\0';
758                         mask = strtol(pos, &end, 10);
759                         if ((pos == end) ||
760                             (mask < 0 || mask > (ipv6 ? 128 : 32))) {
761                                 failed = 1;
762                                 break;
763                         }
764                         pos = end;
765                 } else {
766                         mask = ipv6 ? 128 : 32;
767                         *pos++ = '\0';
768                 }
769
770                 if (!ipv6 && inet_aton(buf, &addr) == 0) {
771                         failed = 1;
772                         break;
773                 }
774 #ifdef CONFIG_IPV6
775                 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
776                         if (inet_pton(AF_INET, buf, &addr) <= 0) {
777                                 failed = 1;
778                                 break;
779                         }
780                         /* Convert IPv4 address to IPv6 */
781                         if (mask <= 32)
782                                 mask += (128 - 32);
783                         memset(addr6.s6_addr, 0, 10);
784                         addr6.s6_addr[10] = 0xff;
785                         addr6.s6_addr[11] = 0xff;
786                         memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, 4);
787                 }
788 #endif /* CONFIG_IPV6 */
789
790                 while (*pos == ' ' || *pos == '\t') {
791                         pos++;
792                 }
793
794                 if (*pos == '\0') {
795                         failed = 1;
796                         break;
797                 }
798
799                 entry = malloc(sizeof(*entry));
800                 if (entry == NULL) {
801                         failed = 1;
802                         break;
803                 }
804                 memset(entry, 0, sizeof(*entry));
805                 entry->shared_secret = strdup(pos);
806                 if (entry->shared_secret == NULL) {
807                         failed = 1;
808                         free(entry);
809                         break;
810                 }
811                 entry->shared_secret_len = strlen(entry->shared_secret);
812                 entry->addr.s_addr = addr.s_addr;
813                 if (!ipv6) {
814                         val = 0;
815                         for (i = 0; i < mask; i++)
816                                 val |= 1 << (31 - i);
817                         entry->mask.s_addr = htonl(val);
818                 }
819 #ifdef CONFIG_IPV6
820                 if (ipv6) {
821                         int offset = mask / 8;
822
823                         memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
824                         memset(entry->mask6.s6_addr, 0xff, offset);
825                         val = 0;
826                         for (i = 0; i < (mask % 8); i++)
827                                 val |= 1 << (7 - i);
828                         if (offset < 16)
829                                 entry->mask6.s6_addr[offset] = val;
830                 }
831 #endif /* CONFIG_IPV6 */
832
833                 if (tail == NULL) {
834                         clients = tail = entry;
835                 } else {
836                         tail->next = entry;
837                         tail = entry;
838                 }
839         }
840
841         if (failed) {
842                 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
843                 radius_server_free_clients(NULL, clients);
844                 clients = NULL;
845         }
846
847         free(buf);
848         fclose(f);
849
850         return clients;
851 }
852
853
854 struct radius_server_data *
855 radius_server_init(struct radius_server_conf *conf)
856 {
857         struct radius_server_data *data;
858
859 #ifndef CONFIG_IPV6
860         if (conf->ipv6) {
861                 fprintf(stderr, "RADIUS server compiled without IPv6 "
862                         "support.\n");
863                 return NULL;
864         }
865 #endif /* CONFIG_IPV6 */
866
867         data = malloc(sizeof(*data));
868         if (data == NULL) {
869                 return NULL;
870         }
871         memset(data, 0, sizeof(*data));
872         data->hostapd_conf = conf->hostapd_conf;
873         data->eap_sim_db_priv = conf->eap_sim_db_priv;
874         data->ssl_ctx = conf->ssl_ctx;
875         data->ipv6 = conf->ipv6;
876
877         data->clients = radius_server_read_clients(conf->client_file,
878                                                    conf->ipv6);
879         if (data->clients == NULL) {
880                 printf("No RADIUS clients configured.\n");
881                 radius_server_deinit(data);
882                 return NULL;
883         }
884
885 #ifdef CONFIG_IPV6
886         if (conf->ipv6)
887                 data->auth_sock = radius_server_open_socket6(conf->auth_port);
888         else
889 #endif /* CONFIG_IPV6 */
890         data->auth_sock = radius_server_open_socket(conf->auth_port);
891         if (data->auth_sock < 0) {
892                 printf("Failed to open UDP socket for RADIUS authentication "
893                        "server\n");
894                 radius_server_deinit(data);
895                 return NULL;
896         }
897         if (eloop_register_read_sock(data->auth_sock,
898                                      radius_server_receive_auth,
899                                      data, NULL)) {
900                 radius_server_deinit(data);
901                 return NULL;
902         }
903
904         return data;
905 }
906
907
908 void radius_server_deinit(struct radius_server_data *data)
909 {
910         if (data == NULL)
911                 return;
912
913         if (data->auth_sock >= 0) {
914                 eloop_unregister_read_sock(data->auth_sock);
915                 close(data->auth_sock);
916         }
917
918         radius_server_free_clients(data, data->clients);
919
920         free(data);
921 }
922
923
924 int radius_server_get_mib(struct radius_server_data *data, char *buf,
925                           size_t buflen)
926 {
927         /* TODO: add support for RADIUS authentication server MIB */
928         return 0;
929 }
930
931
932 static Boolean radius_server_get_bool(void *ctx, enum eapol_bool_var variable)
933 {
934         struct radius_session *sess = ctx;
935         if (sess == NULL)
936                 return FALSE;
937         switch (variable) {
938         case EAPOL_eapSuccess:
939                 return sess->eapSuccess;
940         case EAPOL_eapRestart:
941                 return sess->eapRestart;
942         case EAPOL_eapFail:
943                 return sess->eapFail;
944         case EAPOL_eapResp:
945                 return sess->eapResp;
946         case EAPOL_eapReq:
947                 return sess->eapReq;
948         case EAPOL_eapNoReq:
949                 return sess->eapNoReq;
950         case EAPOL_portEnabled:
951                 return sess->portEnabled;
952         case EAPOL_eapTimeout:
953                 return sess->eapTimeout;
954         }
955         return FALSE;
956 }
957
958
959 static void radius_server_set_bool(void *ctx, enum eapol_bool_var variable,
960                               Boolean value)
961 {
962         struct radius_session *sess = ctx;
963         if (sess == NULL)
964                 return;
965         switch (variable) {
966         case EAPOL_eapSuccess:
967                 sess->eapSuccess = value;
968                 break;
969         case EAPOL_eapRestart:
970                 sess->eapRestart = value;
971                 break;
972         case EAPOL_eapFail:
973                 sess->eapFail = value;
974                 break;
975         case EAPOL_eapResp:
976                 sess->eapResp = value;
977                 break;
978         case EAPOL_eapReq:
979                 sess->eapReq = value;
980                 break;
981         case EAPOL_eapNoReq:
982                 sess->eapNoReq = value;
983                 break;
984         case EAPOL_portEnabled:
985                 sess->portEnabled = value;
986                 break;
987         case EAPOL_eapTimeout:
988                 sess->eapTimeout = value;
989                 break;
990         }
991 }
992
993
994 static void radius_server_set_eapReqData(void *ctx, const u8 *eapReqData,
995                                     size_t eapReqDataLen)
996 {
997         struct radius_session *sess = ctx;
998         if (sess == NULL)
999                 return;
1000
1001         free(sess->eapReqData);
1002         sess->eapReqData = malloc(eapReqDataLen);
1003         if (sess->eapReqData) {
1004                 memcpy(sess->eapReqData, eapReqData, eapReqDataLen);
1005                 sess->eapReqDataLen = eapReqDataLen;
1006         } else {
1007                 sess->eapReqDataLen = 0;
1008         }
1009 }
1010
1011
1012 static void radius_server_set_eapKeyData(void *ctx, const u8 *eapKeyData,
1013                                     size_t eapKeyDataLen)
1014 {
1015         struct radius_session *sess = ctx;
1016
1017         if (sess == NULL)
1018                 return;
1019
1020         free(sess->eapKeyData);
1021         if (eapKeyData) {
1022                 sess->eapKeyData = malloc(eapKeyDataLen);
1023                 if (sess->eapKeyData) {
1024                         memcpy(sess->eapKeyData, eapKeyData, eapKeyDataLen);
1025                         sess->eapKeyDataLen = eapKeyDataLen;
1026                 } else {
1027                         sess->eapKeyDataLen = 0;
1028                 }
1029         } else {
1030                 sess->eapKeyData = NULL;
1031                 sess->eapKeyDataLen = 0;
1032         }
1033 }
1034
1035
1036 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1037                                       size_t identity_len, int phase2,
1038                                       struct eap_user *user)
1039 {
1040         struct radius_session *sess = ctx;
1041         const struct hostapd_eap_user *eap_user;
1042
1043         eap_user = hostapd_get_eap_user(sess->server->hostapd_conf, identity,
1044                                         identity_len, phase2);
1045         if (eap_user == NULL)
1046                 return -1;
1047
1048         memset(user, 0, sizeof(*user));
1049         memcpy(user->methods, eap_user->methods,
1050                EAP_USER_MAX_METHODS > EAP_MAX_METHODS ?
1051                EAP_USER_MAX_METHODS : EAP_MAX_METHODS);
1052
1053         if (eap_user->password) {
1054                 user->password = malloc(eap_user->password_len);
1055                 if (user->password == NULL)
1056                         return -1;
1057                 memcpy(user->password, eap_user->password,
1058                        eap_user->password_len);
1059                 user->password_len = eap_user->password_len;
1060         }
1061         user->force_version = eap_user->force_version;
1062
1063         return 0;
1064 }
1065
1066
1067 static struct eapol_callbacks radius_server_eapol_cb =
1068 {
1069         .get_bool = radius_server_get_bool,
1070         .set_bool = radius_server_set_bool,
1071         .set_eapReqData = radius_server_set_eapReqData,
1072         .set_eapKeyData = radius_server_set_eapKeyData,
1073         .get_eap_user = radius_server_get_eap_user,
1074 };