Disconnect hostapd from building in base
[dragonfly.git] / contrib / hostapd / src / radius / radius_server.c
1 /*
2  * RADIUS authentication server
3  * Copyright (c) 2005-2009, 2011, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10 #include <net/if.h>
11
12 #include "common.h"
13 #include "radius.h"
14 #include "eloop.h"
15 #include "eap_server/eap.h"
16 #include "radius_server.h"
17
18 /**
19  * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
20  */
21 #define RADIUS_SESSION_TIMEOUT 60
22
23 /**
24  * RADIUS_MAX_SESSION - Maximum number of active sessions
25  */
26 #define RADIUS_MAX_SESSION 100
27
28 /**
29  * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
30  */
31 #define RADIUS_MAX_MSG_LEN 3000
32
33 static struct eapol_callbacks radius_server_eapol_cb;
34
35 struct radius_client;
36 struct radius_server_data;
37
38 /**
39  * struct radius_server_counters - RADIUS server statistics counters
40  */
41 struct radius_server_counters {
42         u32 access_requests;
43         u32 invalid_requests;
44         u32 dup_access_requests;
45         u32 access_accepts;
46         u32 access_rejects;
47         u32 access_challenges;
48         u32 malformed_access_requests;
49         u32 bad_authenticators;
50         u32 packets_dropped;
51         u32 unknown_types;
52 };
53
54 /**
55  * struct radius_session - Internal RADIUS server data for a session
56  */
57 struct radius_session {
58         struct radius_session *next;
59         struct radius_client *client;
60         struct radius_server_data *server;
61         unsigned int sess_id;
62         struct eap_sm *eap;
63         struct eap_eapol_interface *eap_if;
64
65         struct radius_msg *last_msg;
66         char *last_from_addr;
67         int last_from_port;
68         struct sockaddr_storage last_from;
69         socklen_t last_fromlen;
70         u8 last_identifier;
71         struct radius_msg *last_reply;
72         u8 last_authenticator[16];
73 };
74
75 /**
76  * struct radius_client - Internal RADIUS server data for a client
77  */
78 struct radius_client {
79         struct radius_client *next;
80         struct in_addr addr;
81         struct in_addr mask;
82 #ifdef CONFIG_IPV6
83         struct in6_addr addr6;
84         struct in6_addr mask6;
85 #endif /* CONFIG_IPV6 */
86         char *shared_secret;
87         int shared_secret_len;
88         struct radius_session *sessions;
89         struct radius_server_counters counters;
90 };
91
92 /**
93  * struct radius_server_data - Internal RADIUS server data
94  */
95 struct radius_server_data {
96         /**
97          * auth_sock - Socket for RADIUS authentication messages
98          */
99         int auth_sock;
100
101         /**
102          * clients - List of authorized RADIUS clients
103          */
104         struct radius_client *clients;
105
106         /**
107          * next_sess_id - Next session identifier
108          */
109         unsigned int next_sess_id;
110
111         /**
112          * conf_ctx - Context pointer for callbacks
113          *
114          * This is used as the ctx argument in get_eap_user() calls.
115          */
116         void *conf_ctx;
117
118         /**
119          * num_sess - Number of active sessions
120          */
121         int num_sess;
122
123         /**
124          * eap_sim_db_priv - EAP-SIM/AKA database context
125          *
126          * This is passed to the EAP-SIM/AKA server implementation as a
127          * callback context.
128          */
129         void *eap_sim_db_priv;
130
131         /**
132          * ssl_ctx - TLS context
133          *
134          * This is passed to the EAP server implementation as a callback
135          * context for TLS operations.
136          */
137         void *ssl_ctx;
138
139         /**
140          * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
141          *
142          * This parameter is used to set a key for EAP-FAST to encrypt the
143          * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
144          * set, must point to a 16-octet key.
145          */
146         u8 *pac_opaque_encr_key;
147
148         /**
149          * eap_fast_a_id - EAP-FAST authority identity (A-ID)
150          *
151          * If EAP-FAST is not used, this can be set to %NULL. In theory, this
152          * is a variable length field, but due to some existing implementations
153          * requiring A-ID to be 16 octets in length, it is recommended to use
154          * that length for the field to provide interoperability with deployed
155          * peer implementations.
156          */
157         u8 *eap_fast_a_id;
158
159         /**
160          * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
161          */
162         size_t eap_fast_a_id_len;
163
164         /**
165          * eap_fast_a_id_info - EAP-FAST authority identifier information
166          *
167          * This A-ID-Info contains a user-friendly name for the A-ID. For
168          * example, this could be the enterprise and server names in
169          * human-readable format. This field is encoded as UTF-8. If EAP-FAST
170          * is not used, this can be set to %NULL.
171          */
172         char *eap_fast_a_id_info;
173
174         /**
175          * eap_fast_prov - EAP-FAST provisioning modes
176          *
177          * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
178          * 2 = only authenticated provisioning allowed, 3 = both provisioning
179          * modes allowed.
180          */
181         int eap_fast_prov;
182
183         /**
184          * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
185          *
186          * This is the hard limit on how long a provisioned PAC-Key can be
187          * used.
188          */
189         int pac_key_lifetime;
190
191         /**
192          * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
193          *
194          * This is a soft limit on the PAC-Key. The server will automatically
195          * generate a new PAC-Key when this number of seconds (or fewer) of the
196          * lifetime remains.
197          */
198         int pac_key_refresh_time;
199
200         /**
201          * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
202          *
203          * This controls whether the protected success/failure indication
204          * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
205          */
206         int eap_sim_aka_result_ind;
207
208         /**
209          * tnc - Trusted Network Connect (TNC)
210          *
211          * This controls whether TNC is enabled and will be required before the
212          * peer is allowed to connect. Note: This is only used with EAP-TTLS
213          * and EAP-FAST. If any other EAP method is enabled, the peer will be
214          * allowed to connect without TNC.
215          */
216         int tnc;
217
218         /**
219          * pwd_group - The D-H group assigned for EAP-pwd
220          *
221          * If EAP-pwd is not used it can be set to zero.
222          */
223         u16 pwd_group;
224
225         /**
226          * server_id - Server identity
227          */
228         const char *server_id;
229
230         /**
231          * wps - Wi-Fi Protected Setup context
232          *
233          * If WPS is used with an external RADIUS server (which is quite
234          * unlikely configuration), this is used to provide a pointer to WPS
235          * context data. Normally, this can be set to %NULL.
236          */
237         struct wps_context *wps;
238
239         /**
240          * ipv6 - Whether to enable IPv6 support in the RADIUS server
241          */
242         int ipv6;
243
244         /**
245          * start_time - Timestamp of server start
246          */
247         struct os_reltime start_time;
248
249         /**
250          * counters - Statistics counters for server operations
251          *
252          * These counters are the sum over all clients.
253          */
254         struct radius_server_counters counters;
255
256         /**
257          * get_eap_user - Callback for fetching EAP user information
258          * @ctx: Context data from conf_ctx
259          * @identity: User identity
260          * @identity_len: identity buffer length in octets
261          * @phase2: Whether this is for Phase 2 identity
262          * @user: Data structure for filling in the user information
263          * Returns: 0 on success, -1 on failure
264          *
265          * This is used to fetch information from user database. The callback
266          * will fill in information about allowed EAP methods and the user
267          * password. The password field will be an allocated copy of the
268          * password data and RADIUS server will free it after use.
269          */
270         int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
271                             int phase2, struct eap_user *user);
272
273         /**
274          * eap_req_id_text - Optional data for EAP-Request/Identity
275          *
276          * This can be used to configure an optional, displayable message that
277          * will be sent in EAP-Request/Identity. This string can contain an
278          * ASCII-0 character (nul) to separate network infromation per RFC
279          * 4284. The actual string length is explicit provided in
280          * eap_req_id_text_len since nul character will not be used as a string
281          * terminator.
282          */
283         char *eap_req_id_text;
284
285         /**
286          * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
287          */
288         size_t eap_req_id_text_len;
289
290         /*
291          * msg_ctx - Context data for wpa_msg() calls
292          */
293         void *msg_ctx;
294
295 #ifdef CONFIG_RADIUS_TEST
296         char *dump_msk_file;
297 #endif /* CONFIG_RADIUS_TEST */
298 };
299
300
301 #define RADIUS_DEBUG(args...) \
302 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
303 #define RADIUS_ERROR(args...) \
304 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
305 #define RADIUS_DUMP(args...) \
306 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
307 #define RADIUS_DUMP_ASCII(args...) \
308 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
309
310
311 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
312 static void radius_server_session_remove_timeout(void *eloop_ctx,
313                                                  void *timeout_ctx);
314
315
316 static struct radius_client *
317 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
318                          int ipv6)
319 {
320         struct radius_client *client = data->clients;
321
322         while (client) {
323 #ifdef CONFIG_IPV6
324                 if (ipv6) {
325                         struct in6_addr *addr6;
326                         int i;
327
328                         addr6 = (struct in6_addr *) addr;
329                         for (i = 0; i < 16; i++) {
330                                 if ((addr6->s6_addr[i] &
331                                      client->mask6.s6_addr[i]) !=
332                                     (client->addr6.s6_addr[i] &
333                                      client->mask6.s6_addr[i])) {
334                                         i = 17;
335                                         break;
336                                 }
337                         }
338                         if (i == 16) {
339                                 break;
340                         }
341                 }
342 #endif /* CONFIG_IPV6 */
343                 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
344                     (addr->s_addr & client->mask.s_addr)) {
345                         break;
346                 }
347
348                 client = client->next;
349         }
350
351         return client;
352 }
353
354
355 static struct radius_session *
356 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
357 {
358         struct radius_session *sess = client->sessions;
359
360         while (sess) {
361                 if (sess->sess_id == sess_id) {
362                         break;
363                 }
364                 sess = sess->next;
365         }
366
367         return sess;
368 }
369
370
371 static void radius_server_session_free(struct radius_server_data *data,
372                                        struct radius_session *sess)
373 {
374         eloop_cancel_timeout(radius_server_session_timeout, data, sess);
375         eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
376         eap_server_sm_deinit(sess->eap);
377         radius_msg_free(sess->last_msg);
378         os_free(sess->last_from_addr);
379         radius_msg_free(sess->last_reply);
380         os_free(sess);
381         data->num_sess--;
382 }
383
384
385 static void radius_server_session_remove(struct radius_server_data *data,
386                                          struct radius_session *sess)
387 {
388         struct radius_client *client = sess->client;
389         struct radius_session *session, *prev;
390
391         eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
392
393         prev = NULL;
394         session = client->sessions;
395         while (session) {
396                 if (session == sess) {
397                         if (prev == NULL) {
398                                 client->sessions = sess->next;
399                         } else {
400                                 prev->next = sess->next;
401                         }
402                         radius_server_session_free(data, sess);
403                         break;
404                 }
405                 prev = session;
406                 session = session->next;
407         }
408 }
409
410
411 static void radius_server_session_remove_timeout(void *eloop_ctx,
412                                                  void *timeout_ctx)
413 {
414         struct radius_server_data *data = eloop_ctx;
415         struct radius_session *sess = timeout_ctx;
416         RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
417         radius_server_session_remove(data, sess);
418 }
419
420
421 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
422 {
423         struct radius_server_data *data = eloop_ctx;
424         struct radius_session *sess = timeout_ctx;
425
426         RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
427         radius_server_session_remove(data, sess);
428 }
429
430
431 static struct radius_session *
432 radius_server_new_session(struct radius_server_data *data,
433                           struct radius_client *client)
434 {
435         struct radius_session *sess;
436
437         if (data->num_sess >= RADIUS_MAX_SESSION) {
438                 RADIUS_DEBUG("Maximum number of existing session - no room "
439                              "for a new session");
440                 return NULL;
441         }
442
443         sess = os_zalloc(sizeof(*sess));
444         if (sess == NULL)
445                 return NULL;
446
447         sess->server = data;
448         sess->client = client;
449         sess->sess_id = data->next_sess_id++;
450         sess->next = client->sessions;
451         client->sessions = sess;
452         eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
453                                radius_server_session_timeout, data, sess);
454         data->num_sess++;
455         return sess;
456 }
457
458
459 static struct radius_session *
460 radius_server_get_new_session(struct radius_server_data *data,
461                               struct radius_client *client,
462                               struct radius_msg *msg)
463 {
464         u8 *user;
465         size_t user_len;
466         int res;
467         struct radius_session *sess;
468         struct eap_config eap_conf;
469
470         RADIUS_DEBUG("Creating a new session");
471
472         user = os_malloc(256);
473         if (user == NULL) {
474                 return NULL;
475         }
476         res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
477         if (res < 0 || res > 256) {
478                 RADIUS_DEBUG("Could not get User-Name");
479                 os_free(user);
480                 return NULL;
481         }
482         user_len = res;
483         RADIUS_DUMP_ASCII("User-Name", user, user_len);
484
485         res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
486         os_free(user);
487
488         if (res == 0) {
489                 RADIUS_DEBUG("Matching user entry found");
490                 sess = radius_server_new_session(data, client);
491                 if (sess == NULL) {
492                         RADIUS_DEBUG("Failed to create a new session");
493                         return NULL;
494                 }
495         } else {
496                 RADIUS_DEBUG("User-Name not found from user database");
497                 return NULL;
498         }
499
500         os_memset(&eap_conf, 0, sizeof(eap_conf));
501         eap_conf.ssl_ctx = data->ssl_ctx;
502         eap_conf.msg_ctx = data->msg_ctx;
503         eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
504         eap_conf.backend_auth = TRUE;
505         eap_conf.eap_server = 1;
506         eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
507         eap_conf.eap_fast_a_id = data->eap_fast_a_id;
508         eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
509         eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
510         eap_conf.eap_fast_prov = data->eap_fast_prov;
511         eap_conf.pac_key_lifetime = data->pac_key_lifetime;
512         eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
513         eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
514         eap_conf.tnc = data->tnc;
515         eap_conf.wps = data->wps;
516         eap_conf.pwd_group = data->pwd_group;
517         eap_conf.server_id = (const u8 *) data->server_id;
518         eap_conf.server_id_len = os_strlen(data->server_id);
519         sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
520                                        &eap_conf);
521         if (sess->eap == NULL) {
522                 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
523                              "new session");
524                 radius_server_session_free(data, sess);
525                 return NULL;
526         }
527         sess->eap_if = eap_get_interface(sess->eap);
528         sess->eap_if->eapRestart = TRUE;
529         sess->eap_if->portEnabled = TRUE;
530
531         RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
532
533         return sess;
534 }
535
536
537 static struct radius_msg *
538 radius_server_encapsulate_eap(struct radius_server_data *data,
539                               struct radius_client *client,
540                               struct radius_session *sess,
541                               struct radius_msg *request)
542 {
543         struct radius_msg *msg;
544         int code;
545         unsigned int sess_id;
546         struct radius_hdr *hdr = radius_msg_get_hdr(request);
547
548         if (sess->eap_if->eapFail) {
549                 sess->eap_if->eapFail = FALSE;
550                 code = RADIUS_CODE_ACCESS_REJECT;
551         } else if (sess->eap_if->eapSuccess) {
552                 sess->eap_if->eapSuccess = FALSE;
553                 code = RADIUS_CODE_ACCESS_ACCEPT;
554         } else {
555                 sess->eap_if->eapReq = FALSE;
556                 code = RADIUS_CODE_ACCESS_CHALLENGE;
557         }
558
559         msg = radius_msg_new(code, hdr->identifier);
560         if (msg == NULL) {
561                 RADIUS_DEBUG("Failed to allocate reply message");
562                 return NULL;
563         }
564
565         sess_id = htonl(sess->sess_id);
566         if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
567             !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
568                                  (u8 *) &sess_id, sizeof(sess_id))) {
569                 RADIUS_DEBUG("Failed to add State attribute");
570         }
571
572         if (sess->eap_if->eapReqData &&
573             !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
574                                 wpabuf_len(sess->eap_if->eapReqData))) {
575                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
576         }
577
578         if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
579                 int len;
580 #ifdef CONFIG_RADIUS_TEST
581                 if (data->dump_msk_file) {
582                         FILE *f;
583                         char buf[2 * 64 + 1];
584                         f = fopen(data->dump_msk_file, "a");
585                         if (f) {
586                                 len = sess->eap_if->eapKeyDataLen;
587                                 if (len > 64)
588                                         len = 64;
589                                 len = wpa_snprintf_hex(
590                                         buf, sizeof(buf),
591                                         sess->eap_if->eapKeyData, len);
592                                 buf[len] = '\0';
593                                 fprintf(f, "%s\n", buf);
594                                 fclose(f);
595                         }
596                 }
597 #endif /* CONFIG_RADIUS_TEST */
598                 if (sess->eap_if->eapKeyDataLen > 64) {
599                         len = 32;
600                 } else {
601                         len = sess->eap_if->eapKeyDataLen / 2;
602                 }
603                 if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
604                                               (u8 *) client->shared_secret,
605                                               client->shared_secret_len,
606                                               sess->eap_if->eapKeyData + len,
607                                               len, sess->eap_if->eapKeyData,
608                                               len)) {
609                         RADIUS_DEBUG("Failed to add MPPE key attributes");
610                 }
611         }
612
613         if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
614                 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
615                 radius_msg_free(msg);
616                 return NULL;
617         }
618
619         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
620                                   client->shared_secret_len,
621                                   hdr->authenticator) < 0) {
622                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
623         }
624
625         return msg;
626 }
627
628
629 static int radius_server_reject(struct radius_server_data *data,
630                                 struct radius_client *client,
631                                 struct radius_msg *request,
632                                 struct sockaddr *from, socklen_t fromlen,
633                                 const char *from_addr, int from_port)
634 {
635         struct radius_msg *msg;
636         int ret = 0;
637         struct eap_hdr eapfail;
638         struct wpabuf *buf;
639         struct radius_hdr *hdr = radius_msg_get_hdr(request);
640
641         RADIUS_DEBUG("Reject invalid request from %s:%d",
642                      from_addr, from_port);
643
644         msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
645         if (msg == NULL) {
646                 return -1;
647         }
648
649         os_memset(&eapfail, 0, sizeof(eapfail));
650         eapfail.code = EAP_CODE_FAILURE;
651         eapfail.identifier = 0;
652         eapfail.length = host_to_be16(sizeof(eapfail));
653
654         if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
655                 RADIUS_DEBUG("Failed to add EAP-Message attribute");
656         }
657
658         if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
659                 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
660                 radius_msg_free(msg);
661                 return -1;
662         }
663
664         if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
665                                   client->shared_secret_len,
666                                   hdr->authenticator) <
667             0) {
668                 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
669         }
670
671         if (wpa_debug_level <= MSG_MSGDUMP) {
672                 radius_msg_dump(msg);
673         }
674
675         data->counters.access_rejects++;
676         client->counters.access_rejects++;
677         buf = radius_msg_get_buf(msg);
678         if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
679                    (struct sockaddr *) from, sizeof(*from)) < 0) {
680                 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno));
681                 ret = -1;
682         }
683
684         radius_msg_free(msg);
685
686         return ret;
687 }
688
689
690 static int radius_server_request(struct radius_server_data *data,
691                                  struct radius_msg *msg,
692                                  struct sockaddr *from, socklen_t fromlen,
693                                  struct radius_client *client,
694                                  const char *from_addr, int from_port,
695                                  struct radius_session *force_sess)
696 {
697         struct wpabuf *eap = NULL;
698         int res, state_included = 0;
699         u8 statebuf[4];
700         unsigned int state;
701         struct radius_session *sess;
702         struct radius_msg *reply;
703         int is_complete = 0;
704
705         if (force_sess)
706                 sess = force_sess;
707         else {
708                 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
709                                           sizeof(statebuf));
710                 state_included = res >= 0;
711                 if (res == sizeof(statebuf)) {
712                         state = WPA_GET_BE32(statebuf);
713                         sess = radius_server_get_session(client, state);
714                 } else {
715                         sess = NULL;
716                 }
717         }
718
719         if (sess) {
720                 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
721         } else if (state_included) {
722                 RADIUS_DEBUG("State attribute included but no session found");
723                 radius_server_reject(data, client, msg, from, fromlen,
724                                      from_addr, from_port);
725                 return -1;
726         } else {
727                 sess = radius_server_get_new_session(data, client, msg);
728                 if (sess == NULL) {
729                         RADIUS_DEBUG("Could not create a new session");
730                         radius_server_reject(data, client, msg, from, fromlen,
731                                              from_addr, from_port);
732                         return -1;
733                 }
734         }
735
736         if (sess->last_from_port == from_port &&
737             sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
738             os_memcmp(sess->last_authenticator,
739                       radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
740                 RADIUS_DEBUG("Duplicate message from %s", from_addr);
741                 data->counters.dup_access_requests++;
742                 client->counters.dup_access_requests++;
743
744                 if (sess->last_reply) {
745                         struct wpabuf *buf;
746                         buf = radius_msg_get_buf(sess->last_reply);
747                         res = sendto(data->auth_sock, wpabuf_head(buf),
748                                      wpabuf_len(buf), 0,
749                                      (struct sockaddr *) from, fromlen);
750                         if (res < 0) {
751                                 wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
752                                            strerror(errno));
753                         }
754                         return 0;
755                 }
756
757                 RADIUS_DEBUG("No previous reply available for duplicate "
758                              "message");
759                 return -1;
760         }
761                       
762         eap = radius_msg_get_eap(msg);
763         if (eap == NULL) {
764                 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
765                              from_addr);
766                 data->counters.packets_dropped++;
767                 client->counters.packets_dropped++;
768                 return -1;
769         }
770
771         RADIUS_DUMP("Received EAP data", wpabuf_head(eap), wpabuf_len(eap));
772
773         /* FIX: if Code is Request, Success, or Failure, send Access-Reject;
774          * RFC3579 Sect. 2.6.2.
775          * Include EAP-Response/Nak with no preferred method if
776          * code == request.
777          * If code is not 1-4, discard the packet silently.
778          * Or is this already done by the EAP state machine? */
779
780         wpabuf_free(sess->eap_if->eapRespData);
781         sess->eap_if->eapRespData = eap;
782         sess->eap_if->eapResp = TRUE;
783         eap_server_sm_step(sess->eap);
784
785         if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
786              sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
787                 RADIUS_DUMP("EAP data from the state machine",
788                             wpabuf_head(sess->eap_if->eapReqData),
789                             wpabuf_len(sess->eap_if->eapReqData));
790         } else if (sess->eap_if->eapFail) {
791                 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
792                              "set");
793         } else if (eap_sm_method_pending(sess->eap)) {
794                 radius_msg_free(sess->last_msg);
795                 sess->last_msg = msg;
796                 sess->last_from_port = from_port;
797                 os_free(sess->last_from_addr);
798                 sess->last_from_addr = os_strdup(from_addr);
799                 sess->last_fromlen = fromlen;
800                 os_memcpy(&sess->last_from, from, fromlen);
801                 return -2;
802         } else {
803                 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
804                              " Access-Request silently (assuming it was a "
805                              "duplicate)");
806                 data->counters.packets_dropped++;
807                 client->counters.packets_dropped++;
808                 return -1;
809         }
810
811         if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
812                 is_complete = 1;
813
814         reply = radius_server_encapsulate_eap(data, client, sess, msg);
815
816         if (reply) {
817                 struct wpabuf *buf;
818                 struct radius_hdr *hdr;
819
820                 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
821                 if (wpa_debug_level <= MSG_MSGDUMP) {
822                         radius_msg_dump(reply);
823                 }
824
825                 switch (radius_msg_get_hdr(reply)->code) {
826                 case RADIUS_CODE_ACCESS_ACCEPT:
827                         data->counters.access_accepts++;
828                         client->counters.access_accepts++;
829                         break;
830                 case RADIUS_CODE_ACCESS_REJECT:
831                         data->counters.access_rejects++;
832                         client->counters.access_rejects++;
833                         break;
834                 case RADIUS_CODE_ACCESS_CHALLENGE:
835                         data->counters.access_challenges++;
836                         client->counters.access_challenges++;
837                         break;
838                 }
839                 buf = radius_msg_get_buf(reply);
840                 res = sendto(data->auth_sock, wpabuf_head(buf),
841                              wpabuf_len(buf), 0,
842                              (struct sockaddr *) from, fromlen);
843                 if (res < 0) {
844                         wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s",
845                                    strerror(errno));
846                 }
847                 radius_msg_free(sess->last_reply);
848                 sess->last_reply = reply;
849                 sess->last_from_port = from_port;
850                 hdr = radius_msg_get_hdr(msg);
851                 sess->last_identifier = hdr->identifier;
852                 os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
853         } else {
854                 data->counters.packets_dropped++;
855                 client->counters.packets_dropped++;
856         }
857
858         if (is_complete) {
859                 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
860                              sess->sess_id);
861                 eloop_cancel_timeout(radius_server_session_remove_timeout,
862                                      data, sess);
863                 eloop_register_timeout(10, 0,
864                                        radius_server_session_remove_timeout,
865                                        data, sess);
866         }
867
868         return 0;
869 }
870
871
872 static void radius_server_receive_auth(int sock, void *eloop_ctx,
873                                        void *sock_ctx)
874 {
875         struct radius_server_data *data = eloop_ctx;
876         u8 *buf = NULL;
877         union {
878                 struct sockaddr_storage ss;
879                 struct sockaddr_in sin;
880 #ifdef CONFIG_IPV6
881                 struct sockaddr_in6 sin6;
882 #endif /* CONFIG_IPV6 */
883         } from;
884         socklen_t fromlen;
885         int len;
886         struct radius_client *client = NULL;
887         struct radius_msg *msg = NULL;
888         char abuf[50];
889         int from_port = 0;
890
891         buf = os_malloc(RADIUS_MAX_MSG_LEN);
892         if (buf == NULL) {
893                 goto fail;
894         }
895
896         fromlen = sizeof(from);
897         len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
898                        (struct sockaddr *) &from.ss, &fromlen);
899         if (len < 0) {
900                 wpa_printf(MSG_INFO, "recvfrom[radius_server]: %s",
901                            strerror(errno));
902                 goto fail;
903         }
904
905 #ifdef CONFIG_IPV6
906         if (data->ipv6) {
907                 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
908                               sizeof(abuf)) == NULL)
909                         abuf[0] = '\0';
910                 from_port = ntohs(from.sin6.sin6_port);
911                 RADIUS_DEBUG("Received %d bytes from %s:%d",
912                              len, abuf, from_port);
913
914                 client = radius_server_get_client(data,
915                                                   (struct in_addr *)
916                                                   &from.sin6.sin6_addr, 1);
917         }
918 #endif /* CONFIG_IPV6 */
919
920         if (!data->ipv6) {
921                 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
922                 from_port = ntohs(from.sin.sin_port);
923                 RADIUS_DEBUG("Received %d bytes from %s:%d",
924                              len, abuf, from_port);
925
926                 client = radius_server_get_client(data, &from.sin.sin_addr, 0);
927         }
928
929         RADIUS_DUMP("Received data", buf, len);
930
931         if (client == NULL) {
932                 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
933                 data->counters.invalid_requests++;
934                 goto fail;
935         }
936
937         msg = radius_msg_parse(buf, len);
938         if (msg == NULL) {
939                 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
940                 data->counters.malformed_access_requests++;
941                 client->counters.malformed_access_requests++;
942                 goto fail;
943         }
944
945         os_free(buf);
946         buf = NULL;
947
948         if (wpa_debug_level <= MSG_MSGDUMP) {
949                 radius_msg_dump(msg);
950         }
951
952         if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
953                 RADIUS_DEBUG("Unexpected RADIUS code %d",
954                              radius_msg_get_hdr(msg)->code);
955                 data->counters.unknown_types++;
956                 client->counters.unknown_types++;
957                 goto fail;
958         }
959
960         data->counters.access_requests++;
961         client->counters.access_requests++;
962
963         if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
964                                        client->shared_secret_len, NULL)) {
965                 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
966                 data->counters.bad_authenticators++;
967                 client->counters.bad_authenticators++;
968                 goto fail;
969         }
970
971         if (radius_server_request(data, msg, (struct sockaddr *) &from,
972                                   fromlen, client, abuf, from_port, NULL) ==
973             -2)
974                 return; /* msg was stored with the session */
975
976 fail:
977         radius_msg_free(msg);
978         os_free(buf);
979 }
980
981
982 static int radius_server_disable_pmtu_discovery(int s)
983 {
984         int r = -1;
985 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
986         /* Turn off Path MTU discovery on IPv4/UDP sockets. */
987         int action = IP_PMTUDISC_DONT;
988         r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
989                        sizeof(action));
990         if (r == -1)
991                 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
992                            "%s", strerror(errno));
993 #endif
994         return r;
995 }
996
997
998 static int radius_server_open_socket(int port)
999 {
1000         int s;
1001         struct sockaddr_in addr;
1002
1003         s = socket(PF_INET, SOCK_DGRAM, 0);
1004         if (s < 0) {
1005                 wpa_printf(MSG_INFO, "RADIUS: socket: %s", strerror(errno));
1006                 return -1;
1007         }
1008
1009         radius_server_disable_pmtu_discovery(s);
1010
1011         os_memset(&addr, 0, sizeof(addr));
1012         addr.sin_family = AF_INET;
1013         addr.sin_port = htons(port);
1014         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1015                 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1016                 close(s);
1017                 return -1;
1018         }
1019
1020         return s;
1021 }
1022
1023
1024 #ifdef CONFIG_IPV6
1025 static int radius_server_open_socket6(int port)
1026 {
1027         int s;
1028         struct sockaddr_in6 addr;
1029
1030         s = socket(PF_INET6, SOCK_DGRAM, 0);
1031         if (s < 0) {
1032                 wpa_printf(MSG_INFO, "RADIUS: socket[IPv6]: %s",
1033                            strerror(errno));
1034                 return -1;
1035         }
1036
1037         os_memset(&addr, 0, sizeof(addr));
1038         addr.sin6_family = AF_INET6;
1039         os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
1040         addr.sin6_port = htons(port);
1041         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1042                 wpa_printf(MSG_INFO, "RADIUS: bind: %s", strerror(errno));
1043                 close(s);
1044                 return -1;
1045         }
1046
1047         return s;
1048 }
1049 #endif /* CONFIG_IPV6 */
1050
1051
1052 static void radius_server_free_sessions(struct radius_server_data *data,
1053                                         struct radius_session *sessions)
1054 {
1055         struct radius_session *session, *prev;
1056
1057         session = sessions;
1058         while (session) {
1059                 prev = session;
1060                 session = session->next;
1061                 radius_server_session_free(data, prev);
1062         }
1063 }
1064
1065
1066 static void radius_server_free_clients(struct radius_server_data *data,
1067                                        struct radius_client *clients)
1068 {
1069         struct radius_client *client, *prev;
1070
1071         client = clients;
1072         while (client) {
1073                 prev = client;
1074                 client = client->next;
1075
1076                 radius_server_free_sessions(data, prev->sessions);
1077                 os_free(prev->shared_secret);
1078                 os_free(prev);
1079         }
1080 }
1081
1082
1083 static struct radius_client *
1084 radius_server_read_clients(const char *client_file, int ipv6)
1085 {
1086         FILE *f;
1087         const int buf_size = 1024;
1088         char *buf, *pos;
1089         struct radius_client *clients, *tail, *entry;
1090         int line = 0, mask, failed = 0, i;
1091         struct in_addr addr;
1092 #ifdef CONFIG_IPV6
1093         struct in6_addr addr6;
1094 #endif /* CONFIG_IPV6 */
1095         unsigned int val;
1096
1097         f = fopen(client_file, "r");
1098         if (f == NULL) {
1099                 RADIUS_ERROR("Could not open client file '%s'", client_file);
1100                 return NULL;
1101         }
1102
1103         buf = os_malloc(buf_size);
1104         if (buf == NULL) {
1105                 fclose(f);
1106                 return NULL;
1107         }
1108
1109         clients = tail = NULL;
1110         while (fgets(buf, buf_size, f)) {
1111                 /* Configuration file format:
1112                  * 192.168.1.0/24 secret
1113                  * 192.168.1.2 secret
1114                  * fe80::211:22ff:fe33:4455/64 secretipv6
1115                  */
1116                 line++;
1117                 buf[buf_size - 1] = '\0';
1118                 pos = buf;
1119                 while (*pos != '\0' && *pos != '\n')
1120                         pos++;
1121                 if (*pos == '\n')
1122                         *pos = '\0';
1123                 if (*buf == '\0' || *buf == '#')
1124                         continue;
1125
1126                 pos = buf;
1127                 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
1128                        (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
1129                        (*pos >= 'A' && *pos <= 'F')) {
1130                         pos++;
1131                 }
1132
1133                 if (*pos == '\0') {
1134                         failed = 1;
1135                         break;
1136                 }
1137
1138                 if (*pos == '/') {
1139                         char *end;
1140                         *pos++ = '\0';
1141                         mask = strtol(pos, &end, 10);
1142                         if ((pos == end) ||
1143                             (mask < 0 || mask > (ipv6 ? 128 : 32))) {
1144                                 failed = 1;
1145                                 break;
1146                         }
1147                         pos = end;
1148                 } else {
1149                         mask = ipv6 ? 128 : 32;
1150                         *pos++ = '\0';
1151                 }
1152
1153                 if (!ipv6 && inet_aton(buf, &addr) == 0) {
1154                         failed = 1;
1155                         break;
1156                 }
1157 #ifdef CONFIG_IPV6
1158                 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
1159                         if (inet_pton(AF_INET, buf, &addr) <= 0) {
1160                                 failed = 1;
1161                                 break;
1162                         }
1163                         /* Convert IPv4 address to IPv6 */
1164                         if (mask <= 32)
1165                                 mask += (128 - 32);
1166                         os_memset(addr6.s6_addr, 0, 10);
1167                         addr6.s6_addr[10] = 0xff;
1168                         addr6.s6_addr[11] = 0xff;
1169                         os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
1170                                   4);
1171                 }
1172 #endif /* CONFIG_IPV6 */
1173
1174                 while (*pos == ' ' || *pos == '\t') {
1175                         pos++;
1176                 }
1177
1178                 if (*pos == '\0') {
1179                         failed = 1;
1180                         break;
1181                 }
1182
1183                 entry = os_zalloc(sizeof(*entry));
1184                 if (entry == NULL) {
1185                         failed = 1;
1186                         break;
1187                 }
1188                 entry->shared_secret = os_strdup(pos);
1189                 if (entry->shared_secret == NULL) {
1190                         failed = 1;
1191                         os_free(entry);
1192                         break;
1193                 }
1194                 entry->shared_secret_len = os_strlen(entry->shared_secret);
1195                 entry->addr.s_addr = addr.s_addr;
1196                 if (!ipv6) {
1197                         val = 0;
1198                         for (i = 0; i < mask; i++)
1199                                 val |= 1 << (31 - i);
1200                         entry->mask.s_addr = htonl(val);
1201                 }
1202 #ifdef CONFIG_IPV6
1203                 if (ipv6) {
1204                         int offset = mask / 8;
1205
1206                         os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
1207                         os_memset(entry->mask6.s6_addr, 0xff, offset);
1208                         val = 0;
1209                         for (i = 0; i < (mask % 8); i++)
1210                                 val |= 1 << (7 - i);
1211                         if (offset < 16)
1212                                 entry->mask6.s6_addr[offset] = val;
1213                 }
1214 #endif /* CONFIG_IPV6 */
1215
1216                 if (tail == NULL) {
1217                         clients = tail = entry;
1218                 } else {
1219                         tail->next = entry;
1220                         tail = entry;
1221                 }
1222         }
1223
1224         if (failed) {
1225                 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
1226                 radius_server_free_clients(NULL, clients);
1227                 clients = NULL;
1228         }
1229
1230         os_free(buf);
1231         fclose(f);
1232
1233         return clients;
1234 }
1235
1236
1237 /**
1238  * radius_server_init - Initialize RADIUS server
1239  * @conf: Configuration for the RADIUS server
1240  * Returns: Pointer to private RADIUS server context or %NULL on failure
1241  *
1242  * This initializes a RADIUS server instance and returns a context pointer that
1243  * will be used in other calls to the RADIUS server module. The server can be
1244  * deinitialize by calling radius_server_deinit().
1245  */
1246 struct radius_server_data *
1247 radius_server_init(struct radius_server_conf *conf)
1248 {
1249         struct radius_server_data *data;
1250
1251 #ifndef CONFIG_IPV6
1252         if (conf->ipv6) {
1253                 wpa_printf(MSG_ERROR, "RADIUS server compiled without IPv6 support");
1254                 return NULL;
1255         }
1256 #endif /* CONFIG_IPV6 */
1257
1258         data = os_zalloc(sizeof(*data));
1259         if (data == NULL)
1260                 return NULL;
1261
1262         os_get_reltime(&data->start_time);
1263         data->conf_ctx = conf->conf_ctx;
1264         data->eap_sim_db_priv = conf->eap_sim_db_priv;
1265         data->ssl_ctx = conf->ssl_ctx;
1266         data->msg_ctx = conf->msg_ctx;
1267         data->ipv6 = conf->ipv6;
1268         if (conf->pac_opaque_encr_key) {
1269                 data->pac_opaque_encr_key = os_malloc(16);
1270                 os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
1271                           16);
1272         }
1273         if (conf->eap_fast_a_id) {
1274                 data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1275                 if (data->eap_fast_a_id) {
1276                         os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
1277                                   conf->eap_fast_a_id_len);
1278                         data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1279                 }
1280         }
1281         if (conf->eap_fast_a_id_info)
1282                 data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1283         data->eap_fast_prov = conf->eap_fast_prov;
1284         data->pac_key_lifetime = conf->pac_key_lifetime;
1285         data->pac_key_refresh_time = conf->pac_key_refresh_time;
1286         data->get_eap_user = conf->get_eap_user;
1287         data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1288         data->tnc = conf->tnc;
1289         data->wps = conf->wps;
1290         data->pwd_group = conf->pwd_group;
1291         data->server_id = conf->server_id;
1292         if (conf->eap_req_id_text) {
1293                 data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
1294                 if (data->eap_req_id_text) {
1295                         os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
1296                                   conf->eap_req_id_text_len);
1297                         data->eap_req_id_text_len = conf->eap_req_id_text_len;
1298                 }
1299         }
1300
1301 #ifdef CONFIG_RADIUS_TEST
1302         if (conf->dump_msk_file)
1303                 data->dump_msk_file = os_strdup(conf->dump_msk_file);
1304 #endif /* CONFIG_RADIUS_TEST */
1305
1306         data->clients = radius_server_read_clients(conf->client_file,
1307                                                    conf->ipv6);
1308         if (data->clients == NULL) {
1309                 wpa_printf(MSG_ERROR, "No RADIUS clients configured");
1310                 radius_server_deinit(data);
1311                 return NULL;
1312         }
1313
1314 #ifdef CONFIG_IPV6
1315         if (conf->ipv6)
1316                 data->auth_sock = radius_server_open_socket6(conf->auth_port);
1317         else
1318 #endif /* CONFIG_IPV6 */
1319         data->auth_sock = radius_server_open_socket(conf->auth_port);
1320         if (data->auth_sock < 0) {
1321                 wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS authentication server");
1322                 radius_server_deinit(data);
1323                 return NULL;
1324         }
1325         if (eloop_register_read_sock(data->auth_sock,
1326                                      radius_server_receive_auth,
1327                                      data, NULL)) {
1328                 radius_server_deinit(data);
1329                 return NULL;
1330         }
1331
1332         return data;
1333 }
1334
1335
1336 /**
1337  * radius_server_deinit - Deinitialize RADIUS server
1338  * @data: RADIUS server context from radius_server_init()
1339  */
1340 void radius_server_deinit(struct radius_server_data *data)
1341 {
1342         if (data == NULL)
1343                 return;
1344
1345         if (data->auth_sock >= 0) {
1346                 eloop_unregister_read_sock(data->auth_sock);
1347                 close(data->auth_sock);
1348         }
1349
1350         radius_server_free_clients(data, data->clients);
1351
1352         os_free(data->pac_opaque_encr_key);
1353         os_free(data->eap_fast_a_id);
1354         os_free(data->eap_fast_a_id_info);
1355         os_free(data->eap_req_id_text);
1356 #ifdef CONFIG_RADIUS_TEST
1357         os_free(data->dump_msk_file);
1358 #endif /* CONFIG_RADIUS_TEST */
1359         os_free(data);
1360 }
1361
1362
1363 /**
1364  * radius_server_get_mib - Get RADIUS server MIB information
1365  * @data: RADIUS server context from radius_server_init()
1366  * @buf: Buffer for returning the MIB data in text format
1367  * @buflen: buf length in octets
1368  * Returns: Number of octets written into buf
1369  */
1370 int radius_server_get_mib(struct radius_server_data *data, char *buf,
1371                           size_t buflen)
1372 {
1373         int ret, uptime;
1374         unsigned int idx;
1375         char *end, *pos;
1376         struct os_reltime now;
1377         struct radius_client *cli;
1378
1379         /* RFC 2619 - RADIUS Authentication Server MIB */
1380
1381         if (data == NULL || buflen == 0)
1382                 return 0;
1383
1384         pos = buf;
1385         end = buf + buflen;
1386
1387         os_get_reltime(&now);
1388         uptime = (now.sec - data->start_time.sec) * 100 +
1389                 ((now.usec - data->start_time.usec) / 10000) % 100;
1390         ret = os_snprintf(pos, end - pos,
1391                           "RADIUS-AUTH-SERVER-MIB\n"
1392                           "radiusAuthServIdent=hostapd\n"
1393                           "radiusAuthServUpTime=%d\n"
1394                           "radiusAuthServResetTime=0\n"
1395                           "radiusAuthServConfigReset=4\n",
1396                           uptime);
1397         if (ret < 0 || ret >= end - pos) {
1398                 *pos = '\0';
1399                 return pos - buf;
1400         }
1401         pos += ret;
1402
1403         ret = os_snprintf(pos, end - pos,
1404                           "radiusAuthServTotalAccessRequests=%u\n"
1405                           "radiusAuthServTotalInvalidRequests=%u\n"
1406                           "radiusAuthServTotalDupAccessRequests=%u\n"
1407                           "radiusAuthServTotalAccessAccepts=%u\n"
1408                           "radiusAuthServTotalAccessRejects=%u\n"
1409                           "radiusAuthServTotalAccessChallenges=%u\n"
1410                           "radiusAuthServTotalMalformedAccessRequests=%u\n"
1411                           "radiusAuthServTotalBadAuthenticators=%u\n"
1412                           "radiusAuthServTotalPacketsDropped=%u\n"
1413                           "radiusAuthServTotalUnknownTypes=%u\n",
1414                           data->counters.access_requests,
1415                           data->counters.invalid_requests,
1416                           data->counters.dup_access_requests,
1417                           data->counters.access_accepts,
1418                           data->counters.access_rejects,
1419                           data->counters.access_challenges,
1420                           data->counters.malformed_access_requests,
1421                           data->counters.bad_authenticators,
1422                           data->counters.packets_dropped,
1423                           data->counters.unknown_types);
1424         if (ret < 0 || ret >= end - pos) {
1425                 *pos = '\0';
1426                 return pos - buf;
1427         }
1428         pos += ret;
1429
1430         for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
1431                 char abuf[50], mbuf[50];
1432 #ifdef CONFIG_IPV6
1433                 if (data->ipv6) {
1434                         if (inet_ntop(AF_INET6, &cli->addr6, abuf,
1435                                       sizeof(abuf)) == NULL)
1436                                 abuf[0] = '\0';
1437                         if (inet_ntop(AF_INET6, &cli->mask6, abuf,
1438                                       sizeof(mbuf)) == NULL)
1439                                 mbuf[0] = '\0';
1440                 }
1441 #endif /* CONFIG_IPV6 */
1442                 if (!data->ipv6) {
1443                         os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
1444                         os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
1445                 }
1446
1447                 ret = os_snprintf(pos, end - pos,
1448                                   "radiusAuthClientIndex=%u\n"
1449                                   "radiusAuthClientAddress=%s/%s\n"
1450                                   "radiusAuthServAccessRequests=%u\n"
1451                                   "radiusAuthServDupAccessRequests=%u\n"
1452                                   "radiusAuthServAccessAccepts=%u\n"
1453                                   "radiusAuthServAccessRejects=%u\n"
1454                                   "radiusAuthServAccessChallenges=%u\n"
1455                                   "radiusAuthServMalformedAccessRequests=%u\n"
1456                                   "radiusAuthServBadAuthenticators=%u\n"
1457                                   "radiusAuthServPacketsDropped=%u\n"
1458                                   "radiusAuthServUnknownTypes=%u\n",
1459                                   idx,
1460                                   abuf, mbuf,
1461                                   cli->counters.access_requests,
1462                                   cli->counters.dup_access_requests,
1463                                   cli->counters.access_accepts,
1464                                   cli->counters.access_rejects,
1465                                   cli->counters.access_challenges,
1466                                   cli->counters.malformed_access_requests,
1467                                   cli->counters.bad_authenticators,
1468                                   cli->counters.packets_dropped,
1469                                   cli->counters.unknown_types);
1470                 if (ret < 0 || ret >= end - pos) {
1471                         *pos = '\0';
1472                         return pos - buf;
1473                 }
1474                 pos += ret;
1475         }
1476
1477         return pos - buf;
1478 }
1479
1480
1481 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
1482                                       size_t identity_len, int phase2,
1483                                       struct eap_user *user)
1484 {
1485         struct radius_session *sess = ctx;
1486         struct radius_server_data *data = sess->server;
1487
1488         return data->get_eap_user(data->conf_ctx, identity, identity_len,
1489                                   phase2, user);
1490 }
1491
1492
1493 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
1494 {
1495         struct radius_session *sess = ctx;
1496         struct radius_server_data *data = sess->server;
1497         *len = data->eap_req_id_text_len;
1498         return data->eap_req_id_text;
1499 }
1500
1501
1502 static struct eapol_callbacks radius_server_eapol_cb =
1503 {
1504         .get_eap_user = radius_server_get_eap_user,
1505         .get_eap_req_id_text = radius_server_get_eap_req_id_text,
1506 };
1507
1508
1509 /**
1510  * radius_server_eap_pending_cb - Pending EAP data notification
1511  * @data: RADIUS server context from radius_server_init()
1512  * @ctx: Pending EAP context pointer
1513  *
1514  * This function is used to notify EAP server module that a pending operation
1515  * has been completed and processing of the EAP session can proceed.
1516  */
1517 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
1518 {
1519         struct radius_client *cli;
1520         struct radius_session *s, *sess = NULL;
1521         struct radius_msg *msg;
1522
1523         if (data == NULL)
1524                 return;
1525
1526         for (cli = data->clients; cli; cli = cli->next) {
1527                 for (s = cli->sessions; s; s = s->next) {
1528                         if (s->eap == ctx && s->last_msg) {
1529                                 sess = s;
1530                                 break;
1531                         }
1532                         if (sess)
1533                                 break;
1534                 }
1535                 if (sess)
1536                         break;
1537         }
1538
1539         if (sess == NULL) {
1540                 RADIUS_DEBUG("No session matched callback ctx");
1541                 return;
1542         }
1543
1544         msg = sess->last_msg;
1545         sess->last_msg = NULL;
1546         eap_sm_pending_cb(sess->eap);
1547         if (radius_server_request(data, msg,
1548                                   (struct sockaddr *) &sess->last_from,
1549                                   sess->last_fromlen, cli,
1550                                   sess->last_from_addr,
1551                                   sess->last_from_port, sess) == -2)
1552                 return; /* msg was stored with the session */
1553
1554         radius_msg_free(msg);
1555 }