radius_client.c 39 KB

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