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