radius_client.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552
  1. /*
  2. * RADIUS client
  3. * Copyright (c) 2002-2009, 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. #include "includes.h"
  9. #include "common.h"
  10. #include "radius.h"
  11. #include "radius_client.h"
  12. #include "eloop.h"
  13. /* Defaults for RADIUS retransmit values (exponential backoff) */
  14. /**
  15. * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds
  16. */
  17. #define RADIUS_CLIENT_FIRST_WAIT 3
  18. /**
  19. * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds
  20. */
  21. #define RADIUS_CLIENT_MAX_WAIT 120
  22. /**
  23. * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries
  24. *
  25. * Maximum number of retransmit attempts before the entry is removed from
  26. * retransmit list.
  27. */
  28. #define RADIUS_CLIENT_MAX_RETRIES 10
  29. /**
  30. * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages
  31. *
  32. * Maximum number of entries in retransmit list (oldest entries will be
  33. * removed, if this limit is exceeded).
  34. */
  35. #define RADIUS_CLIENT_MAX_ENTRIES 30
  36. /**
  37. * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point
  38. *
  39. * The number of failed retry attempts after which the RADIUS server will be
  40. * changed (if one of more backup servers are configured).
  41. */
  42. #define RADIUS_CLIENT_NUM_FAILOVER 4
  43. /**
  44. * struct radius_rx_handler - RADIUS client RX handler
  45. *
  46. * This data structure is used internally inside the RADIUS client module to
  47. * store registered RX handlers. These handlers are registered by calls to
  48. * radius_client_register() and unregistered when the RADIUS client is
  49. * deinitialized with a call to radius_client_deinit().
  50. */
  51. struct radius_rx_handler {
  52. /**
  53. * handler - Received RADIUS message handler
  54. */
  55. RadiusRxResult (*handler)(struct radius_msg *msg,
  56. struct radius_msg *req,
  57. const u8 *shared_secret,
  58. size_t shared_secret_len,
  59. void *data);
  60. /**
  61. * data - Context data for the handler
  62. */
  63. void *data;
  64. };
  65. /**
  66. * struct radius_msg_list - RADIUS client message retransmit list
  67. *
  68. * This data structure is used internally inside the RADIUS client module to
  69. * store pending RADIUS requests that may still need to be retransmitted.
  70. */
  71. struct radius_msg_list {
  72. /**
  73. * addr - STA/client address
  74. *
  75. * This is used to find RADIUS messages for the same STA.
  76. */
  77. u8 addr[ETH_ALEN];
  78. /**
  79. * msg - RADIUS message
  80. */
  81. struct radius_msg *msg;
  82. /**
  83. * msg_type - Message type
  84. */
  85. RadiusType msg_type;
  86. /**
  87. * first_try - Time of the first transmission attempt
  88. */
  89. os_time_t first_try;
  90. /**
  91. * next_try - Time for the next transmission attempt
  92. */
  93. os_time_t next_try;
  94. /**
  95. * attempts - Number of transmission attempts
  96. */
  97. int attempts;
  98. /**
  99. * next_wait - Next retransmission wait time in seconds
  100. */
  101. int next_wait;
  102. /**
  103. * last_attempt - Time of the last transmission attempt
  104. */
  105. struct os_reltime last_attempt;
  106. /**
  107. * shared_secret - Shared secret with the target RADIUS server
  108. */
  109. const u8 *shared_secret;
  110. /**
  111. * shared_secret_len - shared_secret length in octets
  112. */
  113. size_t shared_secret_len;
  114. /* TODO: server config with failover to backup server(s) */
  115. /**
  116. * next - Next message in the list
  117. */
  118. struct radius_msg_list *next;
  119. };
  120. /**
  121. * struct radius_client_data - Internal RADIUS client data
  122. *
  123. * This data structure is used internally inside the RADIUS client module.
  124. * External users allocate this by calling radius_client_init() and free it by
  125. * calling radius_client_deinit(). The pointer to this opaque data is used in
  126. * calls to other functions as an identifier for the RADIUS client instance.
  127. */
  128. struct radius_client_data {
  129. /**
  130. * ctx - Context pointer for hostapd_logger() callbacks
  131. */
  132. void *ctx;
  133. /**
  134. * conf - RADIUS client configuration (list of RADIUS servers to use)
  135. */
  136. struct hostapd_radius_servers *conf;
  137. /**
  138. * auth_serv_sock - IPv4 socket for RADIUS authentication messages
  139. */
  140. int auth_serv_sock;
  141. /**
  142. * acct_serv_sock - IPv4 socket for RADIUS accounting messages
  143. */
  144. int acct_serv_sock;
  145. /**
  146. * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages
  147. */
  148. int auth_serv_sock6;
  149. /**
  150. * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages
  151. */
  152. int acct_serv_sock6;
  153. /**
  154. * auth_sock - Currently used socket for RADIUS authentication server
  155. */
  156. int auth_sock;
  157. /**
  158. * acct_sock - Currently used socket for RADIUS accounting server
  159. */
  160. int acct_sock;
  161. /**
  162. * auth_handlers - Authentication message handlers
  163. */
  164. struct radius_rx_handler *auth_handlers;
  165. /**
  166. * num_auth_handlers - Number of handlers in auth_handlers
  167. */
  168. size_t num_auth_handlers;
  169. /**
  170. * acct_handlers - Accounting message handlers
  171. */
  172. struct radius_rx_handler *acct_handlers;
  173. /**
  174. * num_acct_handlers - Number of handlers in acct_handlers
  175. */
  176. size_t num_acct_handlers;
  177. /**
  178. * msgs - Pending outgoing RADIUS messages
  179. */
  180. struct radius_msg_list *msgs;
  181. /**
  182. * num_msgs - Number of pending messages in the msgs list
  183. */
  184. size_t num_msgs;
  185. /**
  186. * next_radius_identifier - Next RADIUS message identifier to use
  187. */
  188. u8 next_radius_identifier;
  189. };
  190. static int
  191. radius_change_server(struct radius_client_data *radius,
  192. struct hostapd_radius_server *nserv,
  193. struct hostapd_radius_server *oserv,
  194. int sock, int sock6, int auth);
  195. static int radius_client_init_acct(struct radius_client_data *radius);
  196. static int radius_client_init_auth(struct radius_client_data *radius);
  197. static void radius_client_msg_free(struct radius_msg_list *req)
  198. {
  199. radius_msg_free(req->msg);
  200. os_free(req);
  201. }
  202. /**
  203. * radius_client_register - Register a RADIUS client RX handler
  204. * @radius: RADIUS client context from radius_client_init()
  205. * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
  206. * @handler: Handler for received RADIUS messages
  207. * @data: Context pointer for handler callbacks
  208. * Returns: 0 on success, -1 on failure
  209. *
  210. * This function is used to register a handler for processing received RADIUS
  211. * authentication and accounting messages. The handler() callback function will
  212. * be called whenever a RADIUS message is received from the active server.
  213. *
  214. * There can be multiple registered RADIUS message handlers. The handlers will
  215. * be called in order until one of them indicates that it has processed or
  216. * queued the message.
  217. */
  218. int radius_client_register(struct radius_client_data *radius,
  219. RadiusType msg_type,
  220. RadiusRxResult (*handler)(struct radius_msg *msg,
  221. struct radius_msg *req,
  222. const u8 *shared_secret,
  223. size_t shared_secret_len,
  224. void *data),
  225. void *data)
  226. {
  227. struct radius_rx_handler **handlers, *newh;
  228. size_t *num;
  229. if (msg_type == RADIUS_ACCT) {
  230. handlers = &radius->acct_handlers;
  231. num = &radius->num_acct_handlers;
  232. } else {
  233. handlers = &radius->auth_handlers;
  234. num = &radius->num_auth_handlers;
  235. }
  236. newh = os_realloc_array(*handlers, *num + 1,
  237. sizeof(struct radius_rx_handler));
  238. if (newh == NULL)
  239. return -1;
  240. newh[*num].handler = handler;
  241. newh[*num].data = data;
  242. (*num)++;
  243. *handlers = newh;
  244. return 0;
  245. }
  246. /*
  247. * Returns >0 if message queue was flushed (i.e., the message that triggered
  248. * the error is not available anymore)
  249. */
  250. static int radius_client_handle_send_error(struct radius_client_data *radius,
  251. int s, RadiusType msg_type)
  252. {
  253. #ifndef CONFIG_NATIVE_WINDOWS
  254. int _errno = errno;
  255. wpa_printf(MSG_INFO, "send[RADIUS]: %s", strerror(errno));
  256. if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
  257. _errno == EBADF || _errno == ENETUNREACH) {
  258. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  259. HOSTAPD_LEVEL_INFO,
  260. "Send failed - maybe interface status changed -"
  261. " try to connect again");
  262. if (msg_type == RADIUS_ACCT ||
  263. msg_type == RADIUS_ACCT_INTERIM) {
  264. radius_client_init_acct(radius);
  265. return 0;
  266. } else {
  267. radius_client_init_auth(radius);
  268. return 1;
  269. }
  270. }
  271. #endif /* CONFIG_NATIVE_WINDOWS */
  272. return 0;
  273. }
  274. static int radius_client_retransmit(struct radius_client_data *radius,
  275. struct radius_msg_list *entry,
  276. os_time_t now)
  277. {
  278. struct hostapd_radius_servers *conf = radius->conf;
  279. int s;
  280. struct wpabuf *buf;
  281. if (entry->msg_type == RADIUS_ACCT ||
  282. entry->msg_type == RADIUS_ACCT_INTERIM) {
  283. s = radius->acct_sock;
  284. if (entry->attempts == 0)
  285. conf->acct_server->requests++;
  286. else {
  287. conf->acct_server->timeouts++;
  288. conf->acct_server->retransmissions++;
  289. }
  290. } else {
  291. s = radius->auth_sock;
  292. if (entry->attempts == 0)
  293. conf->auth_server->requests++;
  294. else {
  295. conf->auth_server->timeouts++;
  296. conf->auth_server->retransmissions++;
  297. }
  298. }
  299. /* retransmit; remove entry if too many attempts */
  300. entry->attempts++;
  301. hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
  302. HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
  303. radius_msg_get_hdr(entry->msg)->identifier);
  304. os_get_reltime(&entry->last_attempt);
  305. buf = radius_msg_get_buf(entry->msg);
  306. if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
  307. if (radius_client_handle_send_error(radius, s, entry->msg_type)
  308. > 0)
  309. return 0;
  310. }
  311. entry->next_try = now + entry->next_wait;
  312. entry->next_wait *= 2;
  313. if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
  314. entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
  315. if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
  316. wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
  317. return 1;
  318. }
  319. return 0;
  320. }
  321. static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
  322. {
  323. struct radius_client_data *radius = eloop_ctx;
  324. struct hostapd_radius_servers *conf = radius->conf;
  325. struct os_reltime now;
  326. os_time_t first;
  327. struct radius_msg_list *entry, *prev, *tmp;
  328. int auth_failover = 0, acct_failover = 0;
  329. char abuf[50];
  330. size_t prev_num_msgs;
  331. entry = radius->msgs;
  332. if (!entry)
  333. return;
  334. os_get_reltime(&now);
  335. first = 0;
  336. prev = NULL;
  337. while (entry) {
  338. prev_num_msgs = radius->num_msgs;
  339. if (now.sec >= entry->next_try &&
  340. radius_client_retransmit(radius, entry, now.sec)) {
  341. if (prev)
  342. prev->next = entry->next;
  343. else
  344. radius->msgs = entry->next;
  345. tmp = entry;
  346. entry = entry->next;
  347. radius_client_msg_free(tmp);
  348. radius->num_msgs--;
  349. continue;
  350. }
  351. if (prev_num_msgs != radius->num_msgs) {
  352. wpa_printf(MSG_DEBUG,
  353. "RADIUS: Message removed from queue - restart from beginning");
  354. entry = radius->msgs;
  355. prev = NULL;
  356. continue;
  357. }
  358. if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) {
  359. if (entry->msg_type == RADIUS_ACCT ||
  360. entry->msg_type == RADIUS_ACCT_INTERIM)
  361. acct_failover++;
  362. else
  363. auth_failover++;
  364. }
  365. if (first == 0 || entry->next_try < first)
  366. first = entry->next_try;
  367. prev = entry;
  368. entry = entry->next;
  369. }
  370. if (radius->msgs) {
  371. if (first < now.sec)
  372. first = now.sec;
  373. eloop_register_timeout(first - now.sec, 0,
  374. radius_client_timer, radius, NULL);
  375. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  376. HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
  377. "retransmit in %ld seconds",
  378. (long int) (first - now.sec));
  379. }
  380. if (auth_failover && conf->num_auth_servers > 1) {
  381. struct hostapd_radius_server *next, *old;
  382. old = conf->auth_server;
  383. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  384. HOSTAPD_LEVEL_NOTICE,
  385. "No response from Authentication server "
  386. "%s:%d - failover",
  387. hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
  388. old->port);
  389. for (entry = radius->msgs; entry; entry = entry->next) {
  390. if (entry->msg_type == RADIUS_AUTH)
  391. old->timeouts++;
  392. }
  393. next = old + 1;
  394. if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
  395. next = conf->auth_servers;
  396. conf->auth_server = next;
  397. radius_change_server(radius, next, old,
  398. radius->auth_serv_sock,
  399. radius->auth_serv_sock6, 1);
  400. }
  401. if (acct_failover && conf->num_acct_servers > 1) {
  402. struct hostapd_radius_server *next, *old;
  403. old = conf->acct_server;
  404. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  405. HOSTAPD_LEVEL_NOTICE,
  406. "No response from Accounting server "
  407. "%s:%d - failover",
  408. hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
  409. old->port);
  410. for (entry = radius->msgs; entry; entry = entry->next) {
  411. if (entry->msg_type == RADIUS_ACCT ||
  412. entry->msg_type == RADIUS_ACCT_INTERIM)
  413. old->timeouts++;
  414. }
  415. next = old + 1;
  416. if (next > &conf->acct_servers[conf->num_acct_servers - 1])
  417. next = conf->acct_servers;
  418. conf->acct_server = next;
  419. radius_change_server(radius, next, old,
  420. radius->acct_serv_sock,
  421. radius->acct_serv_sock6, 0);
  422. }
  423. }
  424. static void radius_client_update_timeout(struct radius_client_data *radius)
  425. {
  426. struct os_reltime now;
  427. os_time_t first;
  428. struct radius_msg_list *entry;
  429. eloop_cancel_timeout(radius_client_timer, radius, NULL);
  430. if (radius->msgs == NULL) {
  431. return;
  432. }
  433. first = 0;
  434. for (entry = radius->msgs; entry; entry = entry->next) {
  435. if (first == 0 || entry->next_try < first)
  436. first = entry->next_try;
  437. }
  438. os_get_reltime(&now);
  439. if (first < now.sec)
  440. first = now.sec;
  441. eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
  442. NULL);
  443. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  444. HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
  445. " %ld seconds", (long int) (first - now.sec));
  446. }
  447. static void radius_client_list_add(struct radius_client_data *radius,
  448. struct radius_msg *msg,
  449. RadiusType msg_type,
  450. const u8 *shared_secret,
  451. size_t shared_secret_len, const u8 *addr)
  452. {
  453. struct radius_msg_list *entry, *prev;
  454. if (eloop_terminated()) {
  455. /* No point in adding entries to retransmit queue since event
  456. * loop has already been terminated. */
  457. radius_msg_free(msg);
  458. return;
  459. }
  460. entry = os_zalloc(sizeof(*entry));
  461. if (entry == NULL) {
  462. wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list");
  463. radius_msg_free(msg);
  464. return;
  465. }
  466. if (addr)
  467. os_memcpy(entry->addr, addr, ETH_ALEN);
  468. entry->msg = msg;
  469. entry->msg_type = msg_type;
  470. entry->shared_secret = shared_secret;
  471. entry->shared_secret_len = shared_secret_len;
  472. os_get_reltime(&entry->last_attempt);
  473. entry->first_try = entry->last_attempt.sec;
  474. entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
  475. entry->attempts = 1;
  476. entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
  477. entry->next = radius->msgs;
  478. radius->msgs = entry;
  479. radius_client_update_timeout(radius);
  480. if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
  481. wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits");
  482. prev = NULL;
  483. while (entry->next) {
  484. prev = entry;
  485. entry = entry->next;
  486. }
  487. if (prev) {
  488. prev->next = NULL;
  489. radius_client_msg_free(entry);
  490. }
  491. } else
  492. radius->num_msgs++;
  493. }
  494. static void radius_client_list_del(struct radius_client_data *radius,
  495. RadiusType msg_type, const u8 *addr)
  496. {
  497. struct radius_msg_list *entry, *prev, *tmp;
  498. if (addr == NULL)
  499. return;
  500. entry = radius->msgs;
  501. prev = NULL;
  502. while (entry) {
  503. if (entry->msg_type == msg_type &&
  504. os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
  505. if (prev)
  506. prev->next = entry->next;
  507. else
  508. radius->msgs = entry->next;
  509. tmp = entry;
  510. entry = entry->next;
  511. hostapd_logger(radius->ctx, addr,
  512. HOSTAPD_MODULE_RADIUS,
  513. HOSTAPD_LEVEL_DEBUG,
  514. "Removing matching RADIUS message");
  515. radius_client_msg_free(tmp);
  516. radius->num_msgs--;
  517. continue;
  518. }
  519. prev = entry;
  520. entry = entry->next;
  521. }
  522. }
  523. /**
  524. * radius_client_send - Send a RADIUS request
  525. * @radius: RADIUS client context from radius_client_init()
  526. * @msg: RADIUS message to be sent
  527. * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
  528. * @addr: MAC address of the device related to this message or %NULL
  529. * Returns: 0 on success, -1 on failure
  530. *
  531. * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
  532. * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
  533. * between accounting and interim accounting messages is that the interim
  534. * message will override any pending interim accounting updates while a new
  535. * accounting message does not remove any pending messages.
  536. *
  537. * The message is added on the retransmission queue and will be retransmitted
  538. * automatically until a response is received or maximum number of retries
  539. * (RADIUS_CLIENT_MAX_RETRIES) is reached.
  540. *
  541. * The related device MAC address can be used to identify pending messages that
  542. * can be removed with radius_client_flush_auth() or with interim accounting
  543. * updates.
  544. */
  545. int radius_client_send(struct radius_client_data *radius,
  546. struct radius_msg *msg, RadiusType msg_type,
  547. const u8 *addr)
  548. {
  549. struct hostapd_radius_servers *conf = radius->conf;
  550. const u8 *shared_secret;
  551. size_t shared_secret_len;
  552. char *name;
  553. int s, res;
  554. struct wpabuf *buf;
  555. if (msg_type == RADIUS_ACCT_INTERIM) {
  556. /* Remove any pending interim acct update for the same STA. */
  557. radius_client_list_del(radius, msg_type, addr);
  558. }
  559. if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
  560. if (conf->acct_server == NULL || radius->acct_sock < 0) {
  561. hostapd_logger(radius->ctx, NULL,
  562. HOSTAPD_MODULE_RADIUS,
  563. HOSTAPD_LEVEL_INFO,
  564. "No accounting server configured");
  565. return -1;
  566. }
  567. shared_secret = conf->acct_server->shared_secret;
  568. shared_secret_len = conf->acct_server->shared_secret_len;
  569. radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
  570. name = "accounting";
  571. s = radius->acct_sock;
  572. conf->acct_server->requests++;
  573. } else {
  574. if (conf->auth_server == NULL || radius->auth_sock < 0) {
  575. hostapd_logger(radius->ctx, NULL,
  576. HOSTAPD_MODULE_RADIUS,
  577. HOSTAPD_LEVEL_INFO,
  578. "No authentication server configured");
  579. return -1;
  580. }
  581. shared_secret = conf->auth_server->shared_secret;
  582. shared_secret_len = conf->auth_server->shared_secret_len;
  583. radius_msg_finish(msg, shared_secret, shared_secret_len);
  584. name = "authentication";
  585. s = radius->auth_sock;
  586. conf->auth_server->requests++;
  587. }
  588. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  589. HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
  590. "server", name);
  591. if (conf->msg_dumps)
  592. radius_msg_dump(msg);
  593. buf = radius_msg_get_buf(msg);
  594. res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
  595. if (res < 0)
  596. radius_client_handle_send_error(radius, s, msg_type);
  597. radius_client_list_add(radius, msg, msg_type, shared_secret,
  598. shared_secret_len, addr);
  599. return 0;
  600. }
  601. static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
  602. {
  603. struct radius_client_data *radius = eloop_ctx;
  604. struct hostapd_radius_servers *conf = radius->conf;
  605. RadiusType msg_type = (RadiusType) sock_ctx;
  606. int len, roundtrip;
  607. unsigned char buf[3000];
  608. struct radius_msg *msg;
  609. struct radius_hdr *hdr;
  610. struct radius_rx_handler *handlers;
  611. size_t num_handlers, i;
  612. struct radius_msg_list *req, *prev_req;
  613. struct os_reltime now;
  614. struct hostapd_radius_server *rconf;
  615. int invalid_authenticator = 0;
  616. if (msg_type == RADIUS_ACCT) {
  617. handlers = radius->acct_handlers;
  618. num_handlers = radius->num_acct_handlers;
  619. rconf = conf->acct_server;
  620. } else {
  621. handlers = radius->auth_handlers;
  622. num_handlers = radius->num_auth_handlers;
  623. rconf = conf->auth_server;
  624. }
  625. len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
  626. if (len < 0) {
  627. wpa_printf(MSG_INFO, "recv[RADIUS]: %s", strerror(errno));
  628. return;
  629. }
  630. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  631. HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
  632. "server", len);
  633. if (len == sizeof(buf)) {
  634. wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it");
  635. return;
  636. }
  637. msg = radius_msg_parse(buf, len);
  638. if (msg == NULL) {
  639. wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed");
  640. rconf->malformed_responses++;
  641. return;
  642. }
  643. hdr = radius_msg_get_hdr(msg);
  644. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  645. HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
  646. if (conf->msg_dumps)
  647. radius_msg_dump(msg);
  648. switch (hdr->code) {
  649. case RADIUS_CODE_ACCESS_ACCEPT:
  650. rconf->access_accepts++;
  651. break;
  652. case RADIUS_CODE_ACCESS_REJECT:
  653. rconf->access_rejects++;
  654. break;
  655. case RADIUS_CODE_ACCESS_CHALLENGE:
  656. rconf->access_challenges++;
  657. break;
  658. case RADIUS_CODE_ACCOUNTING_RESPONSE:
  659. rconf->responses++;
  660. break;
  661. }
  662. prev_req = NULL;
  663. req = radius->msgs;
  664. while (req) {
  665. /* TODO: also match by src addr:port of the packet when using
  666. * alternative RADIUS servers (?) */
  667. if ((req->msg_type == msg_type ||
  668. (req->msg_type == RADIUS_ACCT_INTERIM &&
  669. msg_type == RADIUS_ACCT)) &&
  670. radius_msg_get_hdr(req->msg)->identifier ==
  671. hdr->identifier)
  672. break;
  673. prev_req = req;
  674. req = req->next;
  675. }
  676. if (req == NULL) {
  677. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  678. HOSTAPD_LEVEL_DEBUG,
  679. "No matching RADIUS request found (type=%d "
  680. "id=%d) - dropping packet",
  681. msg_type, hdr->identifier);
  682. goto fail;
  683. }
  684. os_get_reltime(&now);
  685. roundtrip = (now.sec - req->last_attempt.sec) * 100 +
  686. (now.usec - req->last_attempt.usec) / 10000;
  687. hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
  688. HOSTAPD_LEVEL_DEBUG,
  689. "Received RADIUS packet matched with a pending "
  690. "request, round trip time %d.%02d sec",
  691. roundtrip / 100, roundtrip % 100);
  692. rconf->round_trip_time = roundtrip;
  693. /* Remove ACKed RADIUS packet from retransmit list */
  694. if (prev_req)
  695. prev_req->next = req->next;
  696. else
  697. radius->msgs = req->next;
  698. radius->num_msgs--;
  699. for (i = 0; i < num_handlers; i++) {
  700. RadiusRxResult res;
  701. res = handlers[i].handler(msg, req->msg, req->shared_secret,
  702. req->shared_secret_len,
  703. handlers[i].data);
  704. switch (res) {
  705. case RADIUS_RX_PROCESSED:
  706. radius_msg_free(msg);
  707. /* continue */
  708. case RADIUS_RX_QUEUED:
  709. radius_client_msg_free(req);
  710. return;
  711. case RADIUS_RX_INVALID_AUTHENTICATOR:
  712. invalid_authenticator++;
  713. /* continue */
  714. case RADIUS_RX_UNKNOWN:
  715. /* continue with next handler */
  716. break;
  717. }
  718. }
  719. if (invalid_authenticator)
  720. rconf->bad_authenticators++;
  721. else
  722. rconf->unknown_types++;
  723. hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
  724. HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
  725. "(type=%d code=%d id=%d)%s - dropping packet",
  726. msg_type, hdr->code, hdr->identifier,
  727. invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
  728. "");
  729. radius_client_msg_free(req);
  730. fail:
  731. radius_msg_free(msg);
  732. }
  733. /**
  734. * radius_client_get_id - Get an identifier for a new RADIUS message
  735. * @radius: RADIUS client context from radius_client_init()
  736. * Returns: Allocated identifier
  737. *
  738. * This function is used to fetch a unique (among pending requests) identifier
  739. * for a new RADIUS message.
  740. */
  741. u8 radius_client_get_id(struct radius_client_data *radius)
  742. {
  743. struct radius_msg_list *entry, *prev, *_remove;
  744. u8 id = radius->next_radius_identifier++;
  745. /* remove entries with matching id from retransmit list to avoid
  746. * using new reply from the RADIUS server with an old request */
  747. entry = radius->msgs;
  748. prev = NULL;
  749. while (entry) {
  750. if (radius_msg_get_hdr(entry->msg)->identifier == id) {
  751. hostapd_logger(radius->ctx, entry->addr,
  752. HOSTAPD_MODULE_RADIUS,
  753. HOSTAPD_LEVEL_DEBUG,
  754. "Removing pending RADIUS message, "
  755. "since its id (%d) is reused", id);
  756. if (prev)
  757. prev->next = entry->next;
  758. else
  759. radius->msgs = entry->next;
  760. _remove = entry;
  761. } else {
  762. _remove = NULL;
  763. prev = entry;
  764. }
  765. entry = entry->next;
  766. if (_remove)
  767. radius_client_msg_free(_remove);
  768. }
  769. return id;
  770. }
  771. /**
  772. * radius_client_flush - Flush all pending RADIUS client messages
  773. * @radius: RADIUS client context from radius_client_init()
  774. * @only_auth: Whether only authentication messages are removed
  775. */
  776. void radius_client_flush(struct radius_client_data *radius, int only_auth)
  777. {
  778. struct radius_msg_list *entry, *prev, *tmp;
  779. if (!radius)
  780. return;
  781. prev = NULL;
  782. entry = radius->msgs;
  783. while (entry) {
  784. if (!only_auth || entry->msg_type == RADIUS_AUTH) {
  785. if (prev)
  786. prev->next = entry->next;
  787. else
  788. radius->msgs = entry->next;
  789. tmp = entry;
  790. entry = entry->next;
  791. radius_client_msg_free(tmp);
  792. radius->num_msgs--;
  793. } else {
  794. prev = entry;
  795. entry = entry->next;
  796. }
  797. }
  798. if (radius->msgs == NULL)
  799. eloop_cancel_timeout(radius_client_timer, radius, NULL);
  800. }
  801. static void radius_client_update_acct_msgs(struct radius_client_data *radius,
  802. const u8 *shared_secret,
  803. size_t shared_secret_len)
  804. {
  805. struct radius_msg_list *entry;
  806. if (!radius)
  807. return;
  808. for (entry = radius->msgs; entry; entry = entry->next) {
  809. if (entry->msg_type == RADIUS_ACCT) {
  810. entry->shared_secret = shared_secret;
  811. entry->shared_secret_len = shared_secret_len;
  812. radius_msg_finish_acct(entry->msg, shared_secret,
  813. shared_secret_len);
  814. }
  815. }
  816. }
  817. static int
  818. radius_change_server(struct radius_client_data *radius,
  819. struct hostapd_radius_server *nserv,
  820. struct hostapd_radius_server *oserv,
  821. int sock, int sock6, int auth)
  822. {
  823. struct sockaddr_in serv, claddr;
  824. #ifdef CONFIG_IPV6
  825. struct sockaddr_in6 serv6, claddr6;
  826. #endif /* CONFIG_IPV6 */
  827. struct sockaddr *addr, *cl_addr;
  828. socklen_t addrlen, claddrlen;
  829. char abuf[50];
  830. int sel_sock;
  831. struct radius_msg_list *entry;
  832. struct hostapd_radius_servers *conf = radius->conf;
  833. hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
  834. HOSTAPD_LEVEL_INFO,
  835. "%s server %s:%d",
  836. auth ? "Authentication" : "Accounting",
  837. hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
  838. nserv->port);
  839. if (oserv && oserv != nserv &&
  840. (nserv->shared_secret_len != oserv->shared_secret_len ||
  841. os_memcmp(nserv->shared_secret, oserv->shared_secret,
  842. nserv->shared_secret_len) != 0)) {
  843. /* Pending RADIUS packets used different shared secret, so
  844. * they need to be modified. Update accounting message
  845. * authenticators here. Authentication messages are removed
  846. * since they would require more changes and the new RADIUS
  847. * server may not be prepared to receive them anyway due to
  848. * missing state information. Client will likely retry
  849. * authentication, so this should not be an issue. */
  850. if (auth)
  851. radius_client_flush(radius, 1);
  852. else {
  853. radius_client_update_acct_msgs(
  854. radius, nserv->shared_secret,
  855. nserv->shared_secret_len);
  856. }
  857. }
  858. /* Reset retry counters for the new server */
  859. for (entry = radius->msgs; oserv && oserv != nserv && entry;
  860. entry = entry->next) {
  861. if ((auth && entry->msg_type != RADIUS_AUTH) ||
  862. (!auth && entry->msg_type != RADIUS_ACCT))
  863. continue;
  864. entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
  865. entry->attempts = 0;
  866. entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
  867. }
  868. if (radius->msgs) {
  869. eloop_cancel_timeout(radius_client_timer, radius, NULL);
  870. eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
  871. radius_client_timer, radius, NULL);
  872. }
  873. switch (nserv->addr.af) {
  874. case AF_INET:
  875. os_memset(&serv, 0, sizeof(serv));
  876. serv.sin_family = AF_INET;
  877. serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
  878. serv.sin_port = htons(nserv->port);
  879. addr = (struct sockaddr *) &serv;
  880. addrlen = sizeof(serv);
  881. sel_sock = sock;
  882. break;
  883. #ifdef CONFIG_IPV6
  884. case AF_INET6:
  885. os_memset(&serv6, 0, sizeof(serv6));
  886. serv6.sin6_family = AF_INET6;
  887. os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
  888. sizeof(struct in6_addr));
  889. serv6.sin6_port = htons(nserv->port);
  890. addr = (struct sockaddr *) &serv6;
  891. addrlen = sizeof(serv6);
  892. sel_sock = sock6;
  893. break;
  894. #endif /* CONFIG_IPV6 */
  895. default:
  896. return -1;
  897. }
  898. if (conf->force_client_addr) {
  899. switch (conf->client_addr.af) {
  900. case AF_INET:
  901. os_memset(&claddr, 0, sizeof(claddr));
  902. claddr.sin_family = AF_INET;
  903. claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr;
  904. claddr.sin_port = htons(0);
  905. cl_addr = (struct sockaddr *) &claddr;
  906. claddrlen = sizeof(claddr);
  907. break;
  908. #ifdef CONFIG_IPV6
  909. case AF_INET6:
  910. os_memset(&claddr6, 0, sizeof(claddr6));
  911. claddr6.sin6_family = AF_INET6;
  912. os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6,
  913. sizeof(struct in6_addr));
  914. claddr6.sin6_port = htons(0);
  915. cl_addr = (struct sockaddr *) &claddr6;
  916. claddrlen = sizeof(claddr6);
  917. break;
  918. #endif /* CONFIG_IPV6 */
  919. default:
  920. return -1;
  921. }
  922. if (bind(sel_sock, cl_addr, claddrlen) < 0) {
  923. wpa_printf(MSG_INFO, "bind[radius]: %s",
  924. strerror(errno));
  925. return -1;
  926. }
  927. }
  928. if (connect(sel_sock, addr, addrlen) < 0) {
  929. wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
  930. return -1;
  931. }
  932. #ifndef CONFIG_NATIVE_WINDOWS
  933. switch (nserv->addr.af) {
  934. case AF_INET:
  935. claddrlen = sizeof(claddr);
  936. getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen);
  937. wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
  938. inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port));
  939. break;
  940. #ifdef CONFIG_IPV6
  941. case AF_INET6: {
  942. claddrlen = sizeof(claddr6);
  943. getsockname(sel_sock, (struct sockaddr *) &claddr6,
  944. &claddrlen);
  945. wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
  946. inet_ntop(AF_INET6, &claddr6.sin6_addr,
  947. abuf, sizeof(abuf)),
  948. ntohs(claddr6.sin6_port));
  949. break;
  950. }
  951. #endif /* CONFIG_IPV6 */
  952. }
  953. #endif /* CONFIG_NATIVE_WINDOWS */
  954. if (auth)
  955. radius->auth_sock = sel_sock;
  956. else
  957. radius->acct_sock = sel_sock;
  958. return 0;
  959. }
  960. static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
  961. {
  962. struct radius_client_data *radius = eloop_ctx;
  963. struct hostapd_radius_servers *conf = radius->conf;
  964. struct hostapd_radius_server *oserv;
  965. if (radius->auth_sock >= 0 && conf->auth_servers &&
  966. conf->auth_server != conf->auth_servers) {
  967. oserv = conf->auth_server;
  968. conf->auth_server = conf->auth_servers;
  969. radius_change_server(radius, conf->auth_server, oserv,
  970. radius->auth_serv_sock,
  971. radius->auth_serv_sock6, 1);
  972. }
  973. if (radius->acct_sock >= 0 && conf->acct_servers &&
  974. conf->acct_server != conf->acct_servers) {
  975. oserv = conf->acct_server;
  976. conf->acct_server = conf->acct_servers;
  977. radius_change_server(radius, conf->acct_server, oserv,
  978. radius->acct_serv_sock,
  979. radius->acct_serv_sock6, 0);
  980. }
  981. if (conf->retry_primary_interval)
  982. eloop_register_timeout(conf->retry_primary_interval, 0,
  983. radius_retry_primary_timer, radius,
  984. NULL);
  985. }
  986. static int radius_client_disable_pmtu_discovery(int s)
  987. {
  988. int r = -1;
  989. #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
  990. /* Turn off Path MTU discovery on IPv4/UDP sockets. */
  991. int action = IP_PMTUDISC_DONT;
  992. r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
  993. sizeof(action));
  994. if (r == -1)
  995. wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
  996. strerror(errno));
  997. #endif
  998. return r;
  999. }
  1000. static void radius_close_auth_sockets(struct radius_client_data *radius)
  1001. {
  1002. radius->auth_sock = -1;
  1003. if (radius->auth_serv_sock >= 0) {
  1004. eloop_unregister_read_sock(radius->auth_serv_sock);
  1005. close(radius->auth_serv_sock);
  1006. radius->auth_serv_sock = -1;
  1007. }
  1008. #ifdef CONFIG_IPV6
  1009. if (radius->auth_serv_sock6 >= 0) {
  1010. eloop_unregister_read_sock(radius->auth_serv_sock6);
  1011. close(radius->auth_serv_sock6);
  1012. radius->auth_serv_sock6 = -1;
  1013. }
  1014. #endif /* CONFIG_IPV6 */
  1015. }
  1016. static void radius_close_acct_sockets(struct radius_client_data *radius)
  1017. {
  1018. radius->acct_sock = -1;
  1019. if (radius->acct_serv_sock >= 0) {
  1020. eloop_unregister_read_sock(radius->acct_serv_sock);
  1021. close(radius->acct_serv_sock);
  1022. radius->acct_serv_sock = -1;
  1023. }
  1024. #ifdef CONFIG_IPV6
  1025. if (radius->acct_serv_sock6 >= 0) {
  1026. eloop_unregister_read_sock(radius->acct_serv_sock6);
  1027. close(radius->acct_serv_sock6);
  1028. radius->acct_serv_sock6 = -1;
  1029. }
  1030. #endif /* CONFIG_IPV6 */
  1031. }
  1032. static int radius_client_init_auth(struct radius_client_data *radius)
  1033. {
  1034. struct hostapd_radius_servers *conf = radius->conf;
  1035. int ok = 0;
  1036. radius_close_auth_sockets(radius);
  1037. radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
  1038. if (radius->auth_serv_sock < 0)
  1039. wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s",
  1040. strerror(errno));
  1041. else {
  1042. radius_client_disable_pmtu_discovery(radius->auth_serv_sock);
  1043. ok++;
  1044. }
  1045. #ifdef CONFIG_IPV6
  1046. radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
  1047. if (radius->auth_serv_sock6 < 0)
  1048. wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s",
  1049. strerror(errno));
  1050. else
  1051. ok++;
  1052. #endif /* CONFIG_IPV6 */
  1053. if (ok == 0)
  1054. return -1;
  1055. radius_change_server(radius, conf->auth_server, NULL,
  1056. radius->auth_serv_sock, radius->auth_serv_sock6,
  1057. 1);
  1058. if (radius->auth_serv_sock >= 0 &&
  1059. eloop_register_read_sock(radius->auth_serv_sock,
  1060. radius_client_receive, radius,
  1061. (void *) RADIUS_AUTH)) {
  1062. wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server");
  1063. radius_close_auth_sockets(radius);
  1064. return -1;
  1065. }
  1066. #ifdef CONFIG_IPV6
  1067. if (radius->auth_serv_sock6 >= 0 &&
  1068. eloop_register_read_sock(radius->auth_serv_sock6,
  1069. radius_client_receive, radius,
  1070. (void *) RADIUS_AUTH)) {
  1071. wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server");
  1072. radius_close_auth_sockets(radius);
  1073. return -1;
  1074. }
  1075. #endif /* CONFIG_IPV6 */
  1076. return 0;
  1077. }
  1078. static int radius_client_init_acct(struct radius_client_data *radius)
  1079. {
  1080. struct hostapd_radius_servers *conf = radius->conf;
  1081. int ok = 0;
  1082. radius_close_acct_sockets(radius);
  1083. radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
  1084. if (radius->acct_serv_sock < 0)
  1085. wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s",
  1086. strerror(errno));
  1087. else {
  1088. radius_client_disable_pmtu_discovery(radius->acct_serv_sock);
  1089. ok++;
  1090. }
  1091. #ifdef CONFIG_IPV6
  1092. radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
  1093. if (radius->acct_serv_sock6 < 0)
  1094. wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s",
  1095. strerror(errno));
  1096. else
  1097. ok++;
  1098. #endif /* CONFIG_IPV6 */
  1099. if (ok == 0)
  1100. return -1;
  1101. radius_change_server(radius, conf->acct_server, NULL,
  1102. radius->acct_serv_sock, radius->acct_serv_sock6,
  1103. 0);
  1104. if (radius->acct_serv_sock >= 0 &&
  1105. eloop_register_read_sock(radius->acct_serv_sock,
  1106. radius_client_receive, radius,
  1107. (void *) RADIUS_ACCT)) {
  1108. wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server");
  1109. radius_close_acct_sockets(radius);
  1110. return -1;
  1111. }
  1112. #ifdef CONFIG_IPV6
  1113. if (radius->acct_serv_sock6 >= 0 &&
  1114. eloop_register_read_sock(radius->acct_serv_sock6,
  1115. radius_client_receive, radius,
  1116. (void *) RADIUS_ACCT)) {
  1117. wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server");
  1118. radius_close_acct_sockets(radius);
  1119. return -1;
  1120. }
  1121. #endif /* CONFIG_IPV6 */
  1122. return 0;
  1123. }
  1124. /**
  1125. * radius_client_init - Initialize RADIUS client
  1126. * @ctx: Callback context to be used in hostapd_logger() calls
  1127. * @conf: RADIUS client configuration (RADIUS servers)
  1128. * Returns: Pointer to private RADIUS client context or %NULL on failure
  1129. *
  1130. * The caller is responsible for keeping the configuration data available for
  1131. * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
  1132. * called for the returned context pointer.
  1133. */
  1134. struct radius_client_data *
  1135. radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
  1136. {
  1137. struct radius_client_data *radius;
  1138. radius = os_zalloc(sizeof(struct radius_client_data));
  1139. if (radius == NULL)
  1140. return NULL;
  1141. radius->ctx = ctx;
  1142. radius->conf = conf;
  1143. radius->auth_serv_sock = radius->acct_serv_sock =
  1144. radius->auth_serv_sock6 = radius->acct_serv_sock6 =
  1145. radius->auth_sock = radius->acct_sock = -1;
  1146. if (conf->auth_server && radius_client_init_auth(radius)) {
  1147. radius_client_deinit(radius);
  1148. return NULL;
  1149. }
  1150. if (conf->acct_server && radius_client_init_acct(radius)) {
  1151. radius_client_deinit(radius);
  1152. return NULL;
  1153. }
  1154. if (conf->retry_primary_interval)
  1155. eloop_register_timeout(conf->retry_primary_interval, 0,
  1156. radius_retry_primary_timer, radius,
  1157. NULL);
  1158. return radius;
  1159. }
  1160. /**
  1161. * radius_client_deinit - Deinitialize RADIUS client
  1162. * @radius: RADIUS client context from radius_client_init()
  1163. */
  1164. void radius_client_deinit(struct radius_client_data *radius)
  1165. {
  1166. if (!radius)
  1167. return;
  1168. radius_close_auth_sockets(radius);
  1169. radius_close_acct_sockets(radius);
  1170. eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
  1171. radius_client_flush(radius, 0);
  1172. os_free(radius->auth_handlers);
  1173. os_free(radius->acct_handlers);
  1174. os_free(radius);
  1175. }
  1176. /**
  1177. * radius_client_flush_auth - Flush pending RADIUS messages for an address
  1178. * @radius: RADIUS client context from radius_client_init()
  1179. * @addr: MAC address of the related device
  1180. *
  1181. * This function can be used to remove pending RADIUS authentication messages
  1182. * that are related to a specific device. The addr parameter is matched with
  1183. * the one used in radius_client_send() call that was used to transmit the
  1184. * authentication request.
  1185. */
  1186. void radius_client_flush_auth(struct radius_client_data *radius,
  1187. const u8 *addr)
  1188. {
  1189. struct radius_msg_list *entry, *prev, *tmp;
  1190. prev = NULL;
  1191. entry = radius->msgs;
  1192. while (entry) {
  1193. if (entry->msg_type == RADIUS_AUTH &&
  1194. os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
  1195. hostapd_logger(radius->ctx, addr,
  1196. HOSTAPD_MODULE_RADIUS,
  1197. HOSTAPD_LEVEL_DEBUG,
  1198. "Removing pending RADIUS authentication"
  1199. " message for removed client");
  1200. if (prev)
  1201. prev->next = entry->next;
  1202. else
  1203. radius->msgs = entry->next;
  1204. tmp = entry;
  1205. entry = entry->next;
  1206. radius_client_msg_free(tmp);
  1207. radius->num_msgs--;
  1208. continue;
  1209. }
  1210. prev = entry;
  1211. entry = entry->next;
  1212. }
  1213. }
  1214. static int radius_client_dump_auth_server(char *buf, size_t buflen,
  1215. struct hostapd_radius_server *serv,
  1216. struct radius_client_data *cli)
  1217. {
  1218. int pending = 0;
  1219. struct radius_msg_list *msg;
  1220. char abuf[50];
  1221. if (cli) {
  1222. for (msg = cli->msgs; msg; msg = msg->next) {
  1223. if (msg->msg_type == RADIUS_AUTH)
  1224. pending++;
  1225. }
  1226. }
  1227. return os_snprintf(buf, buflen,
  1228. "radiusAuthServerIndex=%d\n"
  1229. "radiusAuthServerAddress=%s\n"
  1230. "radiusAuthClientServerPortNumber=%d\n"
  1231. "radiusAuthClientRoundTripTime=%d\n"
  1232. "radiusAuthClientAccessRequests=%u\n"
  1233. "radiusAuthClientAccessRetransmissions=%u\n"
  1234. "radiusAuthClientAccessAccepts=%u\n"
  1235. "radiusAuthClientAccessRejects=%u\n"
  1236. "radiusAuthClientAccessChallenges=%u\n"
  1237. "radiusAuthClientMalformedAccessResponses=%u\n"
  1238. "radiusAuthClientBadAuthenticators=%u\n"
  1239. "radiusAuthClientPendingRequests=%u\n"
  1240. "radiusAuthClientTimeouts=%u\n"
  1241. "radiusAuthClientUnknownTypes=%u\n"
  1242. "radiusAuthClientPacketsDropped=%u\n",
  1243. serv->index,
  1244. hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
  1245. serv->port,
  1246. serv->round_trip_time,
  1247. serv->requests,
  1248. serv->retransmissions,
  1249. serv->access_accepts,
  1250. serv->access_rejects,
  1251. serv->access_challenges,
  1252. serv->malformed_responses,
  1253. serv->bad_authenticators,
  1254. pending,
  1255. serv->timeouts,
  1256. serv->unknown_types,
  1257. serv->packets_dropped);
  1258. }
  1259. static int radius_client_dump_acct_server(char *buf, size_t buflen,
  1260. struct hostapd_radius_server *serv,
  1261. struct radius_client_data *cli)
  1262. {
  1263. int pending = 0;
  1264. struct radius_msg_list *msg;
  1265. char abuf[50];
  1266. if (cli) {
  1267. for (msg = cli->msgs; msg; msg = msg->next) {
  1268. if (msg->msg_type == RADIUS_ACCT ||
  1269. msg->msg_type == RADIUS_ACCT_INTERIM)
  1270. pending++;
  1271. }
  1272. }
  1273. return os_snprintf(buf, buflen,
  1274. "radiusAccServerIndex=%d\n"
  1275. "radiusAccServerAddress=%s\n"
  1276. "radiusAccClientServerPortNumber=%d\n"
  1277. "radiusAccClientRoundTripTime=%d\n"
  1278. "radiusAccClientRequests=%u\n"
  1279. "radiusAccClientRetransmissions=%u\n"
  1280. "radiusAccClientResponses=%u\n"
  1281. "radiusAccClientMalformedResponses=%u\n"
  1282. "radiusAccClientBadAuthenticators=%u\n"
  1283. "radiusAccClientPendingRequests=%u\n"
  1284. "radiusAccClientTimeouts=%u\n"
  1285. "radiusAccClientUnknownTypes=%u\n"
  1286. "radiusAccClientPacketsDropped=%u\n",
  1287. serv->index,
  1288. hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
  1289. serv->port,
  1290. serv->round_trip_time,
  1291. serv->requests,
  1292. serv->retransmissions,
  1293. serv->responses,
  1294. serv->malformed_responses,
  1295. serv->bad_authenticators,
  1296. pending,
  1297. serv->timeouts,
  1298. serv->unknown_types,
  1299. serv->packets_dropped);
  1300. }
  1301. /**
  1302. * radius_client_get_mib - Get RADIUS client MIB information
  1303. * @radius: RADIUS client context from radius_client_init()
  1304. * @buf: Buffer for returning MIB data in text format
  1305. * @buflen: Maximum buf length in octets
  1306. * Returns: Number of octets written into the buffer
  1307. */
  1308. int radius_client_get_mib(struct radius_client_data *radius, char *buf,
  1309. size_t buflen)
  1310. {
  1311. struct hostapd_radius_servers *conf = radius->conf;
  1312. int i;
  1313. struct hostapd_radius_server *serv;
  1314. int count = 0;
  1315. if (conf->auth_servers) {
  1316. for (i = 0; i < conf->num_auth_servers; i++) {
  1317. serv = &conf->auth_servers[i];
  1318. count += radius_client_dump_auth_server(
  1319. buf + count, buflen - count, serv,
  1320. serv == conf->auth_server ?
  1321. radius : NULL);
  1322. }
  1323. }
  1324. if (conf->acct_servers) {
  1325. for (i = 0; i < conf->num_acct_servers; i++) {
  1326. serv = &conf->acct_servers[i];
  1327. count += radius_client_dump_acct_server(
  1328. buf + count, buflen - count, serv,
  1329. serv == conf->acct_server ?
  1330. radius : NULL);
  1331. }
  1332. }
  1333. return count;
  1334. }
  1335. void radius_client_reconfig(struct radius_client_data *radius,
  1336. struct hostapd_radius_servers *conf)
  1337. {
  1338. if (radius)
  1339. radius->conf = conf;
  1340. }