radius_server.c 30 KB

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