00001
00016 #include "includes.h"
00017 #include <net/if.h>
00018
00019 #include "common.h"
00020 #include "radius.h"
00021 #include "eloop.h"
00022 #include "defs.h"
00023 #include "eap_server/eap.h"
00024 #include "radius_server.h"
00025
00026 #define RADIUS_SESSION_TIMEOUT 60
00027 #define RADIUS_MAX_SESSION 100
00028 #define RADIUS_MAX_MSG_LEN 3000
00029
00030 static struct eapol_callbacks radius_server_eapol_cb;
00031
00032 struct radius_client;
00033 struct radius_server_data;
00034
00035 struct radius_server_counters {
00036 u32 access_requests;
00037 u32 invalid_requests;
00038 u32 dup_access_requests;
00039 u32 access_accepts;
00040 u32 access_rejects;
00041 u32 access_challenges;
00042 u32 malformed_access_requests;
00043 u32 bad_authenticators;
00044 u32 packets_dropped;
00045 u32 unknown_types;
00046 };
00047
00048 struct radius_session {
00049 struct radius_session *next;
00050 struct radius_client *client;
00051 struct radius_server_data *server;
00052 unsigned int sess_id;
00053 struct eap_sm *eap;
00054 struct eap_eapol_interface *eap_if;
00055
00056 struct radius_msg *last_msg;
00057 char *last_from_addr;
00058 int last_from_port;
00059 struct sockaddr_storage last_from;
00060 socklen_t last_fromlen;
00061 u8 last_identifier;
00062 struct radius_msg *last_reply;
00063 u8 last_authenticator[16];
00064 };
00065
00066 struct radius_client {
00067 struct radius_client *next;
00068 struct in_addr addr;
00069 struct in_addr mask;
00070 #ifdef CONFIG_IPV6
00071 struct in6_addr addr6;
00072 struct in6_addr mask6;
00073 #endif
00074 char *shared_secret;
00075 int shared_secret_len;
00076 struct radius_session *sessions;
00077 struct radius_server_counters counters;
00078 };
00079
00080 struct radius_server_data {
00081 int auth_sock;
00082 struct radius_client *clients;
00083 unsigned int next_sess_id;
00084 void *conf_ctx;
00085 int num_sess;
00086 void *eap_sim_db_priv;
00087 void *ssl_ctx;
00088 u8 *pac_opaque_encr_key;
00089 u8 *eap_fast_a_id;
00090 size_t eap_fast_a_id_len;
00091 char *eap_fast_a_id_info;
00092 int eap_fast_prov;
00093 int pac_key_lifetime;
00094 int pac_key_refresh_time;
00095 int eap_sim_aka_result_ind;
00096 int tnc;
00097 struct wps_context *wps;
00098 int ipv6;
00099 struct os_time start_time;
00100 struct radius_server_counters counters;
00101 int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
00102 int phase2, struct eap_user *user);
00103 char *eap_req_id_text;
00104 size_t eap_req_id_text_len;
00105 };
00106
00107
00108 extern int wpa_debug_level;
00109
00110 #define RADIUS_DEBUG(args...) \
00111 wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
00112 #define RADIUS_ERROR(args...) \
00113 wpa_printf(MSG_ERROR, "RADIUS SRV: " args)
00114 #define RADIUS_DUMP(args...) \
00115 wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)
00116 #define RADIUS_DUMP_ASCII(args...) \
00117 wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)
00118
00119
00120 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
00121
00122
00123
00124 static struct radius_client *
00125 radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
00126 int ipv6)
00127 {
00128 struct radius_client *client = data->clients;
00129
00130 while (client) {
00131 #ifdef CONFIG_IPV6
00132 if (ipv6) {
00133 struct in6_addr *addr6;
00134 int i;
00135
00136 addr6 = (struct in6_addr *) addr;
00137 for (i = 0; i < 16; i++) {
00138 if ((addr6->s6_addr[i] &
00139 client->mask6.s6_addr[i]) !=
00140 (client->addr6.s6_addr[i] &
00141 client->mask6.s6_addr[i])) {
00142 i = 17;
00143 break;
00144 }
00145 }
00146 if (i == 16) {
00147 break;
00148 }
00149 }
00150 #endif
00151 if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==
00152 (addr->s_addr & client->mask.s_addr)) {
00153 break;
00154 }
00155
00156 client = client->next;
00157 }
00158
00159 return client;
00160 }
00161
00162
00163 static struct radius_session *
00164 radius_server_get_session(struct radius_client *client, unsigned int sess_id)
00165 {
00166 struct radius_session *sess = client->sessions;
00167
00168 while (sess) {
00169 if (sess->sess_id == sess_id) {
00170 break;
00171 }
00172 sess = sess->next;
00173 }
00174
00175 return sess;
00176 }
00177
00178
00179 static void radius_server_session_free(struct radius_server_data *data,
00180 struct radius_session *sess)
00181 {
00182 eloop_cancel_timeout(radius_server_session_timeout, data, sess);
00183 eap_server_sm_deinit(sess->eap);
00184 if (sess->last_msg) {
00185 radius_msg_free(sess->last_msg);
00186 os_free(sess->last_msg);
00187 }
00188 os_free(sess->last_from_addr);
00189 if (sess->last_reply) {
00190 radius_msg_free(sess->last_reply);
00191 os_free(sess->last_reply);
00192 }
00193 os_free(sess);
00194 data->num_sess--;
00195 }
00196
00197
00198 static void radius_server_session_remove_timeout(void *eloop_ctx,
00199 void *timeout_ctx);
00200
00201 static void radius_server_session_remove(struct radius_server_data *data,
00202 struct radius_session *sess)
00203 {
00204 struct radius_client *client = sess->client;
00205 struct radius_session *session, *prev;
00206
00207 eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
00208
00209 prev = NULL;
00210 session = client->sessions;
00211 while (session) {
00212 if (session == sess) {
00213 if (prev == NULL) {
00214 client->sessions = sess->next;
00215 } else {
00216 prev->next = sess->next;
00217 }
00218 radius_server_session_free(data, sess);
00219 break;
00220 }
00221 prev = session;
00222 session = session->next;
00223 }
00224 }
00225
00226
00227 static void radius_server_session_remove_timeout(void *eloop_ctx,
00228 void *timeout_ctx)
00229 {
00230 struct radius_server_data *data = eloop_ctx;
00231 struct radius_session *sess = timeout_ctx;
00232 RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);
00233 radius_server_session_remove(data, sess);
00234 }
00235
00236
00237 static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx)
00238 {
00239 struct radius_server_data *data = eloop_ctx;
00240 struct radius_session *sess = timeout_ctx;
00241
00242 RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);
00243 radius_server_session_remove(data, sess);
00244 }
00245
00246
00247 static struct radius_session *
00248 radius_server_new_session(struct radius_server_data *data,
00249 struct radius_client *client)
00250 {
00251 struct radius_session *sess;
00252
00253 if (data->num_sess >= RADIUS_MAX_SESSION) {
00254 RADIUS_DEBUG("Maximum number of existing session - no room "
00255 "for a new session");
00256 return NULL;
00257 }
00258
00259 sess = os_zalloc(sizeof(*sess));
00260 if (sess == NULL)
00261 return NULL;
00262
00263 sess->server = data;
00264 sess->client = client;
00265 sess->sess_id = data->next_sess_id++;
00266 sess->next = client->sessions;
00267 client->sessions = sess;
00268 eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,
00269 radius_server_session_timeout, data, sess);
00270 data->num_sess++;
00271 return sess;
00272 }
00273
00274
00275 static struct radius_session *
00276 radius_server_get_new_session(struct radius_server_data *data,
00277 struct radius_client *client,
00278 struct radius_msg *msg)
00279 {
00280 u8 *user;
00281 size_t user_len;
00282 int res;
00283 struct radius_session *sess;
00284 struct eap_config eap_conf;
00285
00286 RADIUS_DEBUG("Creating a new session");
00287
00288 user = os_malloc(256);
00289 if (user == NULL) {
00290 return NULL;
00291 }
00292 res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
00293 if (res < 0 || res > 256) {
00294 RADIUS_DEBUG("Could not get User-Name");
00295 os_free(user);
00296 return NULL;
00297 }
00298 user_len = res;
00299 RADIUS_DUMP_ASCII("User-Name", user, user_len);
00300
00301 res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
00302 os_free(user);
00303
00304 if (res == 0) {
00305 RADIUS_DEBUG("Matching user entry found");
00306 sess = radius_server_new_session(data, client);
00307 if (sess == NULL) {
00308 RADIUS_DEBUG("Failed to create a new session");
00309 return NULL;
00310 }
00311 } else {
00312 RADIUS_DEBUG("User-Name not found from user database");
00313 return NULL;
00314 }
00315
00316 os_memset(&eap_conf, 0, sizeof(eap_conf));
00317 eap_conf.ssl_ctx = data->ssl_ctx;
00318 eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
00319 eap_conf.backend_auth = TRUE;
00320 eap_conf.eap_server = 1;
00321 eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
00322 eap_conf.eap_fast_a_id = data->eap_fast_a_id;
00323 eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
00324 eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
00325 eap_conf.eap_fast_prov = data->eap_fast_prov;
00326 eap_conf.pac_key_lifetime = data->pac_key_lifetime;
00327 eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
00328 eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
00329 eap_conf.tnc = data->tnc;
00330 eap_conf.wps = data->wps;
00331 sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
00332 &eap_conf);
00333 if (sess->eap == NULL) {
00334 RADIUS_DEBUG("Failed to initialize EAP state machine for the "
00335 "new session");
00336 radius_server_session_free(data, sess);
00337 return NULL;
00338 }
00339 sess->eap_if = eap_get_interface(sess->eap);
00340 sess->eap_if->eapRestart = TRUE;
00341 sess->eap_if->portEnabled = TRUE;
00342
00343 RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);
00344
00345 return sess;
00346 }
00347
00348
00349 static struct radius_msg *
00350 radius_server_encapsulate_eap(struct radius_server_data *data,
00351 struct radius_client *client,
00352 struct radius_session *sess,
00353 struct radius_msg *request)
00354 {
00355 struct radius_msg *msg;
00356 int code;
00357 unsigned int sess_id;
00358
00359 if (sess->eap_if->eapFail) {
00360 sess->eap_if->eapFail = FALSE;
00361 code = RADIUS_CODE_ACCESS_REJECT;
00362 } else if (sess->eap_if->eapSuccess) {
00363 sess->eap_if->eapSuccess = FALSE;
00364 code = RADIUS_CODE_ACCESS_ACCEPT;
00365 } else {
00366 sess->eap_if->eapReq = FALSE;
00367 code = RADIUS_CODE_ACCESS_CHALLENGE;
00368 }
00369
00370 msg = radius_msg_new(code, request->hdr->identifier);
00371 if (msg == NULL) {
00372 RADIUS_DEBUG("Failed to allocate reply message");
00373 return NULL;
00374 }
00375
00376 sess_id = htonl(sess->sess_id);
00377 if (code == RADIUS_CODE_ACCESS_CHALLENGE &&
00378 !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,
00379 (u8 *) &sess_id, sizeof(sess_id))) {
00380 RADIUS_DEBUG("Failed to add State attribute");
00381 }
00382
00383 if (sess->eap_if->eapReqData &&
00384 !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),
00385 wpabuf_len(sess->eap_if->eapReqData))) {
00386 RADIUS_DEBUG("Failed to add EAP-Message attribute");
00387 }
00388
00389 if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {
00390 int len;
00391 if (sess->eap_if->eapKeyDataLen > 64) {
00392 len = 32;
00393 } else {
00394 len = sess->eap_if->eapKeyDataLen / 2;
00395 }
00396 if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
00397 (u8 *) client->shared_secret,
00398 client->shared_secret_len,
00399 sess->eap_if->eapKeyData + len,
00400 len, sess->eap_if->eapKeyData,
00401 len)) {
00402 RADIUS_DEBUG("Failed to add MPPE key attributes");
00403 }
00404 }
00405
00406 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
00407 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
00408 radius_msg_free(msg);
00409 os_free(msg);
00410 return NULL;
00411 }
00412
00413 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
00414 client->shared_secret_len,
00415 request->hdr->authenticator) < 0) {
00416 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
00417 }
00418
00419 return msg;
00420 }
00421
00422
00423 static int radius_server_reject(struct radius_server_data *data,
00424 struct radius_client *client,
00425 struct radius_msg *request,
00426 struct sockaddr *from, socklen_t fromlen,
00427 const char *from_addr, int from_port)
00428 {
00429 struct radius_msg *msg;
00430 int ret = 0;
00431 struct eap_hdr eapfail;
00432
00433 RADIUS_DEBUG("Reject invalid request from %s:%d",
00434 from_addr, from_port);
00435
00436 msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
00437 request->hdr->identifier);
00438 if (msg == NULL) {
00439 return -1;
00440 }
00441
00442 os_memset(&eapfail, 0, sizeof(eapfail));
00443 eapfail.code = EAP_CODE_FAILURE;
00444 eapfail.identifier = 0;
00445 eapfail.length = host_to_be16(sizeof(eapfail));
00446
00447 if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) {
00448 RADIUS_DEBUG("Failed to add EAP-Message attribute");
00449 }
00450
00451 if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
00452 RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
00453 radius_msg_free(msg);
00454 os_free(msg);
00455 return -1;
00456 }
00457
00458 if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
00459 client->shared_secret_len,
00460 request->hdr->authenticator) < 0) {
00461 RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
00462 }
00463
00464 if (wpa_debug_level <= MSG_MSGDUMP) {
00465 radius_msg_dump(msg);
00466 }
00467
00468 data->counters.access_rejects++;
00469 client->counters.access_rejects++;
00470 if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
00471 (struct sockaddr *) from, sizeof(*from)) < 0) {
00472 perror("sendto[RADIUS SRV]");
00473 ret = -1;
00474 }
00475
00476 radius_msg_free(msg);
00477 os_free(msg);
00478
00479 return ret;
00480 }
00481
00482
00483 static int radius_server_request(struct radius_server_data *data,
00484 struct radius_msg *msg,
00485 struct sockaddr *from, socklen_t fromlen,
00486 struct radius_client *client,
00487 const char *from_addr, int from_port,
00488 struct radius_session *force_sess)
00489 {
00490 u8 *eap = NULL;
00491 size_t eap_len;
00492 int res, state_included = 0;
00493 u8 statebuf[4];
00494 unsigned int state;
00495 struct radius_session *sess;
00496 struct radius_msg *reply;
00497 int is_complete = 0;
00498
00499 if (force_sess)
00500 sess = force_sess;
00501 else {
00502 res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf,
00503 sizeof(statebuf));
00504 state_included = res >= 0;
00505 if (res == sizeof(statebuf)) {
00506 state = WPA_GET_BE32(statebuf);
00507 sess = radius_server_get_session(client, state);
00508 } else {
00509 sess = NULL;
00510 }
00511 }
00512
00513 if (sess) {
00514 RADIUS_DEBUG("Request for session 0x%x", sess->sess_id);
00515 } else if (state_included) {
00516 RADIUS_DEBUG("State attribute included but no session found");
00517 radius_server_reject(data, client, msg, from, fromlen,
00518 from_addr, from_port);
00519 return -1;
00520 } else {
00521 sess = radius_server_get_new_session(data, client, msg);
00522 if (sess == NULL) {
00523 RADIUS_DEBUG("Could not create a new session");
00524 radius_server_reject(data, client, msg, from, fromlen,
00525 from_addr, from_port);
00526 return -1;
00527 }
00528 }
00529
00530 if (sess->last_from_port == from_port &&
00531 sess->last_identifier == msg->hdr->identifier &&
00532 os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
00533 0) {
00534 RADIUS_DEBUG("Duplicate message from %s", from_addr);
00535 data->counters.dup_access_requests++;
00536 client->counters.dup_access_requests++;
00537
00538 if (sess->last_reply) {
00539 res = sendto(data->auth_sock, sess->last_reply->buf,
00540 sess->last_reply->buf_used, 0,
00541 (struct sockaddr *) from, fromlen);
00542 if (res < 0) {
00543 perror("sendto[RADIUS SRV]");
00544 }
00545 return 0;
00546 }
00547
00548 RADIUS_DEBUG("No previous reply available for duplicate "
00549 "message");
00550 return -1;
00551 }
00552
00553 eap = radius_msg_get_eap(msg, &eap_len);
00554 if (eap == NULL) {
00555 RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
00556 from_addr);
00557 data->counters.packets_dropped++;
00558 client->counters.packets_dropped++;
00559 return -1;
00560 }
00561
00562 RADIUS_DUMP("Received EAP data", eap, eap_len);
00563
00564
00565
00566
00567
00568
00569
00570
00571 wpabuf_free(sess->eap_if->eapRespData);
00572 sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len);
00573 if (sess->eap_if->eapRespData == NULL)
00574 os_free(eap);
00575 eap = NULL;
00576 sess->eap_if->eapResp = TRUE;
00577 eap_server_sm_step(sess->eap);
00578
00579 if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess ||
00580 sess->eap_if->eapFail) && sess->eap_if->eapReqData) {
00581 RADIUS_DUMP("EAP data from the state machine",
00582 wpabuf_head(sess->eap_if->eapReqData),
00583 wpabuf_len(sess->eap_if->eapReqData));
00584 } else if (sess->eap_if->eapFail) {
00585 RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
00586 "set");
00587 } else if (eap_sm_method_pending(sess->eap)) {
00588 if (sess->last_msg) {
00589 radius_msg_free(sess->last_msg);
00590 os_free(sess->last_msg);
00591 }
00592 sess->last_msg = msg;
00593 sess->last_from_port = from_port;
00594 os_free(sess->last_from_addr);
00595 sess->last_from_addr = os_strdup(from_addr);
00596 sess->last_fromlen = fromlen;
00597 os_memcpy(&sess->last_from, from, fromlen);
00598 return -2;
00599 } else {
00600 RADIUS_DEBUG("No EAP data from the state machine - ignore this"
00601 " Access-Request silently (assuming it was a "
00602 "duplicate)");
00603 data->counters.packets_dropped++;
00604 client->counters.packets_dropped++;
00605 return -1;
00606 }
00607
00608 if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
00609 is_complete = 1;
00610
00611 reply = radius_server_encapsulate_eap(data, client, sess, msg);
00612
00613 if (reply) {
00614 RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
00615 if (wpa_debug_level <= MSG_MSGDUMP) {
00616 radius_msg_dump(reply);
00617 }
00618
00619 switch (reply->hdr->code) {
00620 case RADIUS_CODE_ACCESS_ACCEPT:
00621 data->counters.access_accepts++;
00622 client->counters.access_accepts++;
00623 break;
00624 case RADIUS_CODE_ACCESS_REJECT:
00625 data->counters.access_rejects++;
00626 client->counters.access_rejects++;
00627 break;
00628 case RADIUS_CODE_ACCESS_CHALLENGE:
00629 data->counters.access_challenges++;
00630 client->counters.access_challenges++;
00631 break;
00632 }
00633 res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
00634 (struct sockaddr *) from, fromlen);
00635 if (res < 0) {
00636 perror("sendto[RADIUS SRV]");
00637 }
00638 if (sess->last_reply) {
00639 radius_msg_free(sess->last_reply);
00640 os_free(sess->last_reply);
00641 }
00642 sess->last_reply = reply;
00643 sess->last_from_port = from_port;
00644 sess->last_identifier = msg->hdr->identifier;
00645 os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
00646 16);
00647 } else {
00648 data->counters.packets_dropped++;
00649 client->counters.packets_dropped++;
00650 }
00651
00652 if (is_complete) {
00653 RADIUS_DEBUG("Removing completed session 0x%x after timeout",
00654 sess->sess_id);
00655 eloop_cancel_timeout(radius_server_session_remove_timeout,
00656 data, sess);
00657 eloop_register_timeout(10, 0,
00658 radius_server_session_remove_timeout,
00659 data, sess);
00660 }
00661
00662 return 0;
00663 }
00664
00665
00666 static void radius_server_receive_auth(int sock, void *eloop_ctx,
00667 void *sock_ctx)
00668 {
00669 struct radius_server_data *data = eloop_ctx;
00670 u8 *buf = NULL;
00671 union {
00672 struct sockaddr_storage ss;
00673 struct sockaddr_in sin;
00674 #ifdef CONFIG_IPV6
00675 struct sockaddr_in6 sin6;
00676 #endif
00677 } from;
00678 socklen_t fromlen;
00679 int len;
00680 struct radius_client *client = NULL;
00681 struct radius_msg *msg = NULL;
00682 char abuf[50];
00683 int from_port = 0;
00684
00685 buf = os_malloc(RADIUS_MAX_MSG_LEN);
00686 if (buf == NULL) {
00687 goto fail;
00688 }
00689
00690 fromlen = sizeof(from);
00691 len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0,
00692 (struct sockaddr *) &from.ss, &fromlen);
00693 if (len < 0) {
00694 perror("recvfrom[radius_server]");
00695 goto fail;
00696 }
00697
00698 #ifdef CONFIG_IPV6
00699 if (data->ipv6) {
00700 if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf,
00701 sizeof(abuf)) == NULL)
00702 abuf[0] = '\0';
00703 from_port = ntohs(from.sin6.sin6_port);
00704 RADIUS_DEBUG("Received %d bytes from %s:%d",
00705 len, abuf, from_port);
00706
00707 client = radius_server_get_client(data,
00708 (struct in_addr *)
00709 &from.sin6.sin6_addr, 1);
00710 }
00711 #endif
00712
00713 if (!data->ipv6) {
00714 os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
00715 from_port = ntohs(from.sin.sin_port);
00716 RADIUS_DEBUG("Received %d bytes from %s:%d",
00717 len, abuf, from_port);
00718
00719 client = radius_server_get_client(data, &from.sin.sin_addr, 0);
00720 }
00721
00722 RADIUS_DUMP("Received data", buf, len);
00723
00724 if (client == NULL) {
00725 RADIUS_DEBUG("Unknown client %s - packet ignored", abuf);
00726 data->counters.invalid_requests++;
00727 goto fail;
00728 }
00729
00730 msg = radius_msg_parse(buf, len);
00731 if (msg == NULL) {
00732 RADIUS_DEBUG("Parsing incoming RADIUS frame failed");
00733 data->counters.malformed_access_requests++;
00734 client->counters.malformed_access_requests++;
00735 goto fail;
00736 }
00737
00738 os_free(buf);
00739 buf = NULL;
00740
00741 if (wpa_debug_level <= MSG_MSGDUMP) {
00742 radius_msg_dump(msg);
00743 }
00744
00745 if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
00746 RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
00747 data->counters.unknown_types++;
00748 client->counters.unknown_types++;
00749 goto fail;
00750 }
00751
00752 data->counters.access_requests++;
00753 client->counters.access_requests++;
00754
00755 if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret,
00756 client->shared_secret_len, NULL)) {
00757 RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf);
00758 data->counters.bad_authenticators++;
00759 client->counters.bad_authenticators++;
00760 goto fail;
00761 }
00762
00763 if (radius_server_request(data, msg, (struct sockaddr *) &from,
00764 fromlen, client, abuf, from_port, NULL) ==
00765 -2)
00766 return;
00767
00768 fail:
00769 if (msg) {
00770 radius_msg_free(msg);
00771 os_free(msg);
00772 }
00773 os_free(buf);
00774 }
00775
00776
00777 static int radius_server_disable_pmtu_discovery(int s)
00778 {
00779 int r = -1;
00780 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
00781
00782 int action = IP_PMTUDISC_DONT;
00783 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
00784 sizeof(action));
00785 if (r == -1)
00786 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: "
00787 "%s", strerror(errno));
00788 #endif
00789 return r;
00790 }
00791
00792
00793 static int radius_server_open_socket(int port)
00794 {
00795 int s;
00796 struct sockaddr_in addr;
00797
00798 s = socket(PF_INET, SOCK_DGRAM, 0);
00799 if (s < 0) {
00800 perror("socket");
00801 return -1;
00802 }
00803
00804 radius_server_disable_pmtu_discovery(s);
00805
00806 os_memset(&addr, 0, sizeof(addr));
00807 addr.sin_family = AF_INET;
00808 addr.sin_port = htons(port);
00809 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00810 perror("bind");
00811 close(s);
00812 return -1;
00813 }
00814
00815 return s;
00816 }
00817
00818
00819 #ifdef CONFIG_IPV6
00820 static int radius_server_open_socket6(int port)
00821 {
00822 int s;
00823 struct sockaddr_in6 addr;
00824
00825 s = socket(PF_INET6, SOCK_DGRAM, 0);
00826 if (s < 0) {
00827 perror("socket[IPv6]");
00828 return -1;
00829 }
00830
00831 os_memset(&addr, 0, sizeof(addr));
00832 addr.sin6_family = AF_INET6;
00833 os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
00834 addr.sin6_port = htons(port);
00835 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00836 perror("bind");
00837 close(s);
00838 return -1;
00839 }
00840
00841 return s;
00842 }
00843 #endif
00844
00845
00846 static void radius_server_free_sessions(struct radius_server_data *data,
00847 struct radius_session *sessions)
00848 {
00849 struct radius_session *session, *prev;
00850
00851 session = sessions;
00852 while (session) {
00853 prev = session;
00854 session = session->next;
00855 radius_server_session_free(data, prev);
00856 }
00857 }
00858
00859
00860 static void radius_server_free_clients(struct radius_server_data *data,
00861 struct radius_client *clients)
00862 {
00863 struct radius_client *client, *prev;
00864
00865 client = clients;
00866 while (client) {
00867 prev = client;
00868 client = client->next;
00869
00870 radius_server_free_sessions(data, prev->sessions);
00871 os_free(prev->shared_secret);
00872 os_free(prev);
00873 }
00874 }
00875
00876
00877 static struct radius_client *
00878 radius_server_read_clients(const char *client_file, int ipv6)
00879 {
00880 FILE *f;
00881 const int buf_size = 1024;
00882 char *buf, *pos;
00883 struct radius_client *clients, *tail, *entry;
00884 int line = 0, mask, failed = 0, i;
00885 struct in_addr addr;
00886 #ifdef CONFIG_IPV6
00887 struct in6_addr addr6;
00888 #endif
00889 unsigned int val;
00890
00891 f = fopen(client_file, "r");
00892 if (f == NULL) {
00893 RADIUS_ERROR("Could not open client file '%s'", client_file);
00894 return NULL;
00895 }
00896
00897 buf = os_malloc(buf_size);
00898 if (buf == NULL) {
00899 fclose(f);
00900 return NULL;
00901 }
00902
00903 clients = tail = NULL;
00904 while (fgets(buf, buf_size, f)) {
00905
00906
00907
00908
00909
00910 line++;
00911 buf[buf_size - 1] = '\0';
00912 pos = buf;
00913 while (*pos != '\0' && *pos != '\n')
00914 pos++;
00915 if (*pos == '\n')
00916 *pos = '\0';
00917 if (*buf == '\0' || *buf == '#')
00918 continue;
00919
00920 pos = buf;
00921 while ((*pos >= '0' && *pos <= '9') || *pos == '.' ||
00922 (*pos >= 'a' && *pos <= 'f') || *pos == ':' ||
00923 (*pos >= 'A' && *pos <= 'F')) {
00924 pos++;
00925 }
00926
00927 if (*pos == '\0') {
00928 failed = 1;
00929 break;
00930 }
00931
00932 if (*pos == '/') {
00933 char *end;
00934 *pos++ = '\0';
00935 mask = strtol(pos, &end, 10);
00936 if ((pos == end) ||
00937 (mask < 0 || mask > (ipv6 ? 128 : 32))) {
00938 failed = 1;
00939 break;
00940 }
00941 pos = end;
00942 } else {
00943 mask = ipv6 ? 128 : 32;
00944 *pos++ = '\0';
00945 }
00946
00947 if (!ipv6 && inet_aton(buf, &addr) == 0) {
00948 failed = 1;
00949 break;
00950 }
00951 #ifdef CONFIG_IPV6
00952 if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) {
00953 if (inet_pton(AF_INET, buf, &addr) <= 0) {
00954 failed = 1;
00955 break;
00956 }
00957
00958 if (mask <= 32)
00959 mask += (128 - 32);
00960 os_memset(addr6.s6_addr, 0, 10);
00961 addr6.s6_addr[10] = 0xff;
00962 addr6.s6_addr[11] = 0xff;
00963 os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr,
00964 4);
00965 }
00966 #endif
00967
00968 while (*pos == ' ' || *pos == '\t') {
00969 pos++;
00970 }
00971
00972 if (*pos == '\0') {
00973 failed = 1;
00974 break;
00975 }
00976
00977 entry = os_zalloc(sizeof(*entry));
00978 if (entry == NULL) {
00979 failed = 1;
00980 break;
00981 }
00982 entry->shared_secret = os_strdup(pos);
00983 if (entry->shared_secret == NULL) {
00984 failed = 1;
00985 os_free(entry);
00986 break;
00987 }
00988 entry->shared_secret_len = os_strlen(entry->shared_secret);
00989 entry->addr.s_addr = addr.s_addr;
00990 if (!ipv6) {
00991 val = 0;
00992 for (i = 0; i < mask; i++)
00993 val |= 1 << (31 - i);
00994 entry->mask.s_addr = htonl(val);
00995 }
00996 #ifdef CONFIG_IPV6
00997 if (ipv6) {
00998 int offset = mask / 8;
00999
01000 os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16);
01001 os_memset(entry->mask6.s6_addr, 0xff, offset);
01002 val = 0;
01003 for (i = 0; i < (mask % 8); i++)
01004 val |= 1 << (7 - i);
01005 if (offset < 16)
01006 entry->mask6.s6_addr[offset] = val;
01007 }
01008 #endif
01009
01010 if (tail == NULL) {
01011 clients = tail = entry;
01012 } else {
01013 tail->next = entry;
01014 tail = entry;
01015 }
01016 }
01017
01018 if (failed) {
01019 RADIUS_ERROR("Invalid line %d in '%s'", line, client_file);
01020 radius_server_free_clients(NULL, clients);
01021 clients = NULL;
01022 }
01023
01024 os_free(buf);
01025 fclose(f);
01026
01027 return clients;
01028 }
01029
01030
01031 struct radius_server_data *
01032 radius_server_init(struct radius_server_conf *conf)
01033 {
01034 struct radius_server_data *data;
01035
01036 #ifndef CONFIG_IPV6
01037 if (conf->ipv6) {
01038 fprintf(stderr, "RADIUS server compiled without IPv6 "
01039 "support.\n");
01040 return NULL;
01041 }
01042 #endif
01043
01044 data = os_zalloc(sizeof(*data));
01045 if (data == NULL)
01046 return NULL;
01047
01048 os_get_time(&data->start_time);
01049 data->conf_ctx = conf->conf_ctx;
01050 data->eap_sim_db_priv = conf->eap_sim_db_priv;
01051 data->ssl_ctx = conf->ssl_ctx;
01052 data->ipv6 = conf->ipv6;
01053 if (conf->pac_opaque_encr_key) {
01054 data->pac_opaque_encr_key = os_malloc(16);
01055 os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
01056 16);
01057 }
01058 if (conf->eap_fast_a_id) {
01059 data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
01060 if (data->eap_fast_a_id) {
01061 os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
01062 conf->eap_fast_a_id_len);
01063 data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
01064 }
01065 }
01066 if (conf->eap_fast_a_id_info)
01067 data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
01068 data->eap_fast_prov = conf->eap_fast_prov;
01069 data->pac_key_lifetime = conf->pac_key_lifetime;
01070 data->pac_key_refresh_time = conf->pac_key_refresh_time;
01071 data->get_eap_user = conf->get_eap_user;
01072 data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
01073 data->tnc = conf->tnc;
01074 data->wps = conf->wps;
01075 if (conf->eap_req_id_text) {
01076 data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
01077 if (data->eap_req_id_text) {
01078 os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
01079 conf->eap_req_id_text_len);
01080 data->eap_req_id_text_len = conf->eap_req_id_text_len;
01081 }
01082 }
01083
01084 data->clients = radius_server_read_clients(conf->client_file,
01085 conf->ipv6);
01086 if (data->clients == NULL) {
01087 printf("No RADIUS clients configured.\n");
01088 radius_server_deinit(data);
01089 return NULL;
01090 }
01091
01092 #ifdef CONFIG_IPV6
01093 if (conf->ipv6)
01094 data->auth_sock = radius_server_open_socket6(conf->auth_port);
01095 else
01096 #endif
01097 data->auth_sock = radius_server_open_socket(conf->auth_port);
01098 if (data->auth_sock < 0) {
01099 printf("Failed to open UDP socket for RADIUS authentication "
01100 "server\n");
01101 radius_server_deinit(data);
01102 return NULL;
01103 }
01104 if (eloop_register_read_sock(data->auth_sock,
01105 radius_server_receive_auth,
01106 data, NULL)) {
01107 radius_server_deinit(data);
01108 return NULL;
01109 }
01110
01111 return data;
01112 }
01113
01114
01115 void radius_server_deinit(struct radius_server_data *data)
01116 {
01117 if (data == NULL)
01118 return;
01119
01120 if (data->auth_sock >= 0) {
01121 eloop_unregister_read_sock(data->auth_sock);
01122 close(data->auth_sock);
01123 }
01124
01125 radius_server_free_clients(data, data->clients);
01126
01127 os_free(data->pac_opaque_encr_key);
01128 os_free(data->eap_fast_a_id);
01129 os_free(data->eap_fast_a_id_info);
01130 os_free(data->eap_req_id_text);
01131 os_free(data);
01132 }
01133
01134
01135 int radius_server_get_mib(struct radius_server_data *data, char *buf,
01136 size_t buflen)
01137 {
01138 int ret, uptime;
01139 unsigned int idx;
01140 char *end, *pos;
01141 struct os_time now;
01142 struct radius_client *cli;
01143
01144
01145
01146 if (data == NULL || buflen == 0)
01147 return 0;
01148
01149 pos = buf;
01150 end = buf + buflen;
01151
01152 os_get_time(&now);
01153 uptime = (now.sec - data->start_time.sec) * 100 +
01154 ((now.usec - data->start_time.usec) / 10000) % 100;
01155 ret = os_snprintf(pos, end - pos,
01156 "RADIUS-AUTH-SERVER-MIB\n"
01157 "radiusAuthServIdent=hostapd\n"
01158 "radiusAuthServUpTime=%d\n"
01159 "radiusAuthServResetTime=0\n"
01160 "radiusAuthServConfigReset=4\n",
01161 uptime);
01162 if (ret < 0 || ret >= end - pos) {
01163 *pos = '\0';
01164 return pos - buf;
01165 }
01166 pos += ret;
01167
01168 ret = os_snprintf(pos, end - pos,
01169 "radiusAuthServTotalAccessRequests=%u\n"
01170 "radiusAuthServTotalInvalidRequests=%u\n"
01171 "radiusAuthServTotalDupAccessRequests=%u\n"
01172 "radiusAuthServTotalAccessAccepts=%u\n"
01173 "radiusAuthServTotalAccessRejects=%u\n"
01174 "radiusAuthServTotalAccessChallenges=%u\n"
01175 "radiusAuthServTotalMalformedAccessRequests=%u\n"
01176 "radiusAuthServTotalBadAuthenticators=%u\n"
01177 "radiusAuthServTotalPacketsDropped=%u\n"
01178 "radiusAuthServTotalUnknownTypes=%u\n",
01179 data->counters.access_requests,
01180 data->counters.invalid_requests,
01181 data->counters.dup_access_requests,
01182 data->counters.access_accepts,
01183 data->counters.access_rejects,
01184 data->counters.access_challenges,
01185 data->counters.malformed_access_requests,
01186 data->counters.bad_authenticators,
01187 data->counters.packets_dropped,
01188 data->counters.unknown_types);
01189 if (ret < 0 || ret >= end - pos) {
01190 *pos = '\0';
01191 return pos - buf;
01192 }
01193 pos += ret;
01194
01195 for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) {
01196 char abuf[50], mbuf[50];
01197 #ifdef CONFIG_IPV6
01198 if (data->ipv6) {
01199 if (inet_ntop(AF_INET6, &cli->addr6, abuf,
01200 sizeof(abuf)) == NULL)
01201 abuf[0] = '\0';
01202 if (inet_ntop(AF_INET6, &cli->mask6, abuf,
01203 sizeof(mbuf)) == NULL)
01204 mbuf[0] = '\0';
01205 }
01206 #endif
01207 if (!data->ipv6) {
01208 os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf));
01209 os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf));
01210 }
01211
01212 ret = os_snprintf(pos, end - pos,
01213 "radiusAuthClientIndex=%u\n"
01214 "radiusAuthClientAddress=%s/%s\n"
01215 "radiusAuthServAccessRequests=%u\n"
01216 "radiusAuthServDupAccessRequests=%u\n"
01217 "radiusAuthServAccessAccepts=%u\n"
01218 "radiusAuthServAccessRejects=%u\n"
01219 "radiusAuthServAccessChallenges=%u\n"
01220 "radiusAuthServMalformedAccessRequests=%u\n"
01221 "radiusAuthServBadAuthenticators=%u\n"
01222 "radiusAuthServPacketsDropped=%u\n"
01223 "radiusAuthServUnknownTypes=%u\n",
01224 idx,
01225 abuf, mbuf,
01226 cli->counters.access_requests,
01227 cli->counters.dup_access_requests,
01228 cli->counters.access_accepts,
01229 cli->counters.access_rejects,
01230 cli->counters.access_challenges,
01231 cli->counters.malformed_access_requests,
01232 cli->counters.bad_authenticators,
01233 cli->counters.packets_dropped,
01234 cli->counters.unknown_types);
01235 if (ret < 0 || ret >= end - pos) {
01236 *pos = '\0';
01237 return pos - buf;
01238 }
01239 pos += ret;
01240 }
01241
01242 return pos - buf;
01243 }
01244
01245
01246 static int radius_server_get_eap_user(void *ctx, const u8 *identity,
01247 size_t identity_len, int phase2,
01248 struct eap_user *user)
01249 {
01250 struct radius_session *sess = ctx;
01251 struct radius_server_data *data = sess->server;
01252
01253 return data->get_eap_user(data->conf_ctx, identity, identity_len,
01254 phase2, user);
01255 }
01256
01257
01258 static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
01259 {
01260 struct radius_session *sess = ctx;
01261 struct radius_server_data *data = sess->server;
01262 *len = data->eap_req_id_text_len;
01263 return data->eap_req_id_text;
01264 }
01265
01266
01267 static struct eapol_callbacks radius_server_eapol_cb =
01268 {
01269 .get_eap_user = radius_server_get_eap_user,
01270 .get_eap_req_id_text = radius_server_get_eap_req_id_text,
01271 };
01272
01273
01274 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
01275 {
01276 struct radius_client *cli;
01277 struct radius_session *s, *sess = NULL;
01278 struct radius_msg *msg;
01279
01280 if (data == NULL)
01281 return;
01282
01283 for (cli = data->clients; cli; cli = cli->next) {
01284 for (s = cli->sessions; s; s = s->next) {
01285 if (s->eap == ctx && s->last_msg) {
01286 sess = s;
01287 break;
01288 }
01289 if (sess)
01290 break;
01291 }
01292 if (sess)
01293 break;
01294 }
01295
01296 if (sess == NULL) {
01297 RADIUS_DEBUG("No session matched callback ctx");
01298 return;
01299 }
01300
01301 msg = sess->last_msg;
01302 sess->last_msg = NULL;
01303 eap_sm_pending_cb(sess->eap);
01304 if (radius_server_request(data, msg,
01305 (struct sockaddr *) &sess->last_from,
01306 sess->last_fromlen, cli,
01307 sess->last_from_addr,
01308 sess->last_from_port, sess) == -2)
01309 return;
01310
01311 radius_msg_free(msg);
01312 os_free(msg);
01313 }
01314