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