config.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. /*
  2. * $Id: config.c,v 1.23 2010/04/28 14:26:15 aland Exp $
  3. *
  4. * Copyright (C) 1995,1996,1997 Lars Fenneberg
  5. *
  6. * Copyright 1992 Livingston Enterprises, Inc.
  7. *
  8. * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
  9. * and Merit Network, Inc. All Rights Reserved
  10. *
  11. * See the file COPYRIGHT for the respective terms and conditions.
  12. * If the file is missing contact me at lf@elemental.net
  13. * and I'll send you a copy.
  14. *
  15. */
  16. #include <radius_config.h>
  17. #include <includes.h>
  18. #include <freeradius-client.h>
  19. #include <fr_options.h>
  20. #include "util.h"
  21. extern OPTION rcOptions;
  22. /** Find an option in the option list
  23. *
  24. * @param rh a handle to parsed configuration.
  25. * @param optname the name of the option.
  26. * @param type the option type.
  27. * @return pointer to option on success, NULL otherwise.
  28. */
  29. static OPTION *find_option(rc_handle const *rh, char const *optname, unsigned int type)
  30. {
  31. int i;
  32. /* there're so few options that a binary search seems not necessary */
  33. for (i = 0; i < NUM_OPTIONS; i++) {
  34. if (!strcmp(rh->config_options[i].name, optname) &&
  35. (rh->config_options[i].type & type))
  36. {
  37. return &rh->config_options[i];
  38. }
  39. }
  40. return NULL;
  41. }
  42. /** Set a specific option doing type conversions
  43. *
  44. * @param filename the name of the config file (for logging purposes).
  45. * @param line the line number in the file.
  46. * @param p Value.
  47. * @return 0 on success, -1 on failure.
  48. */
  49. static int set_option_str(char const *filename, int line, OPTION *option, char const *p)
  50. {
  51. if (p) {
  52. option->val = (void *) strdup(p);
  53. if (option->val == NULL) {
  54. rc_log(LOG_CRIT, "read_config: out of memory");
  55. return -1;
  56. }
  57. } else {
  58. option->val = NULL;
  59. }
  60. return 0;
  61. }
  62. static int set_option_int(char const *filename, int line, OPTION *option, char const *p)
  63. {
  64. int *iptr;
  65. if (p == NULL) {
  66. rc_log(LOG_ERR, "%s: line %d: bogus option value", filename, line);
  67. return -1;
  68. }
  69. if ((iptr = malloc(sizeof(*iptr))) == NULL) {
  70. rc_log(LOG_CRIT, "read_config: out of memory");
  71. return -1;
  72. }
  73. *iptr = atoi(p);
  74. option->val = (void *) iptr;
  75. return 0;
  76. }
  77. static int set_option_srv(char const *filename, int line, OPTION *option, char const *p)
  78. {
  79. #if 0
  80. SERVER *serv;
  81. char *p_pointer;
  82. char *p_dupe;
  83. char *p_save;
  84. char *q;
  85. char *s;
  86. struct servent *svp;
  87. p_dupe = strdup(p);
  88. if (p_dupe == NULL) {
  89. rc_log(LOG_ERR, "%s: line %d: Invalid option or memory failure", filename, line);
  90. return -1;
  91. }
  92. serv = (SERVER *) option->val;
  93. if (serv == NULL) {
  94. DEBUG(LOG_ERR, "option->val / server is NULL, allocating memory");
  95. serv = malloc(sizeof(*serv));
  96. if (serv == NULL) {
  97. rc_log(LOG_CRIT, "read_config: out of memory");
  98. free(p_dupe);
  99. return -1;
  100. }
  101. memset(serv, 0, sizeof(*serv));
  102. serv->max = 0;
  103. }
  104. p_pointer = strtok_r(p_dupe, ", \t", &p_save);
  105. /* check to see for '[IPv6]:port' syntax */
  106. if ((q = strchr(p_pointer,'[')) != NULL) {
  107. *q = '\0';
  108. q++;
  109. p_pointer = q;
  110. q = strchr(p_pointer, ']');
  111. if (q == NULL) {
  112. free(p_dupe);
  113. rc_log(LOG_CRIT, "read_config: IPv6 parse error");
  114. return -1;
  115. }
  116. *q = '\0';
  117. q++;
  118. if (q[0] == ':') {
  119. q++;
  120. }
  121. /* Check to see if we have '[IPv6]:port:secret' syntax */
  122. if((s=strchr(q, ':')) != NULL) {
  123. *s = '\0';
  124. s++;
  125. serv->secret[serv->max] = strdup(s);
  126. if (serv->secret[serv->max] == NULL) {
  127. rc_log(LOG_CRIT, "read_config: out of memory");
  128. if (option->val == NULL) {
  129. free(p_dupe);
  130. free(serv);
  131. }
  132. return -1;
  133. }
  134. }
  135. } else /* Check to see if we have 'servername:port' syntax */
  136. if ((q = strchr(p_pointer,':')) != NULL) {
  137. *q = '\0';
  138. q++;
  139. /* Check to see if we have 'servername:port:secret' syntax */
  140. if((s = strchr(q,':')) != NULL) {
  141. *s = '\0';
  142. s++;
  143. serv->secret[serv->max] = strdup(s);
  144. if (serv->secret[serv->max] == NULL) {
  145. rc_log(LOG_CRIT, "read_config: out of memory");
  146. if (option->val == NULL) {
  147. free(p_dupe);
  148. free(serv);
  149. }
  150. return -1;
  151. }
  152. }
  153. }
  154. if(q && strlen(q) > 0) {
  155. serv->port[serv->max] = atoi(q);
  156. } else {
  157. if (!strcmp(option->name,"authserver"))
  158. if ((svp = getservbyname ("radius", "udp")) == NULL)
  159. serv->port[serv->max] = PW_AUTH_UDP_PORT;
  160. else
  161. serv->port[serv->max] = ntohs ((unsigned int) svp->s_port);
  162. else if (!strcmp(option->name, "acctserver"))
  163. if ((svp = getservbyname ("radacct", "udp")) == NULL)
  164. serv->port[serv->max] = PW_ACCT_UDP_PORT;
  165. else
  166. serv->port[serv->max] = ntohs ((unsigned int) svp->s_port);
  167. else {
  168. rc_log(LOG_ERR, "%s: line %d: no default port for %s", filename, line, option->name);
  169. if (option->val == NULL) {
  170. free(p_dupe);
  171. free(serv);
  172. }
  173. return -1;
  174. }
  175. }
  176. serv->name[serv->max] = strdup(p_pointer);
  177. if (serv->name[serv->max] == NULL) {
  178. rc_log(LOG_CRIT, "read_config: out of memory");
  179. if (option->val == NULL) {
  180. free(p_dupe);
  181. free(serv);
  182. }
  183. return -1;
  184. }
  185. free(p_dupe);
  186. serv->deadtime_ends[serv->max] = -1;
  187. serv->max++;
  188. if (option->val == NULL)
  189. option->val = (void *)serv;
  190. #endif
  191. return 0;
  192. }
  193. static int set_option_auo(char const *filename, int line, OPTION *option, char const *p)
  194. {
  195. int *iptr;
  196. char *p_dupe = NULL;
  197. char *p_pointer = NULL;
  198. char *p_save = NULL;
  199. p_dupe = strdup(p);
  200. if (p_dupe == NULL) {
  201. rc_log(LOG_WARNING, "%s: line %d: bogus option value", filename, line);
  202. return -1;
  203. }
  204. if ((iptr = malloc(sizeof(iptr))) == NULL) {
  205. rc_log(LOG_CRIT, "read_config: out of memory");
  206. free(p_dupe);
  207. return -1;
  208. }
  209. *iptr = 0;
  210. p_pointer = strtok_r(p_dupe, ", \t", &p_save);
  211. if (!strncmp(p_pointer, "local", 5))
  212. *iptr = AUTH_LOCAL_FST;
  213. else if (!strncmp(p_pointer, "radius", 6))
  214. *iptr = AUTH_RADIUS_FST;
  215. else {
  216. rc_log(LOG_ERR,"%s: auth_order: unknown keyword: %s", filename, p);
  217. free(iptr);
  218. free(p_dupe);
  219. return -1;
  220. }
  221. p_pointer = strtok_r(NULL, ", \t", &p_save);
  222. if (p_pointer && (*p_pointer != '\0')) {
  223. if ((*iptr & AUTH_RADIUS_FST) && !strcmp(p_pointer, "local"))
  224. *iptr = (*iptr) | AUTH_LOCAL_SND;
  225. else if ((*iptr & AUTH_LOCAL_FST) && !strcmp(p_pointer, "radius"))
  226. *iptr = (*iptr) | AUTH_RADIUS_SND;
  227. else {
  228. rc_log(LOG_ERR,"%s: auth_order: unknown or unexpected keyword: %s", filename, p);
  229. free(iptr);
  230. free(p_dupe);
  231. return -1;
  232. }
  233. }
  234. option->val = (void *) iptr;
  235. free(p_dupe);
  236. return 0;
  237. }
  238. /** Allow a config option to be added to rc_handle from inside a program
  239. *
  240. * @param rh a handle to parsed configuration.
  241. * @param option_name the name of the option.
  242. * @param option_val the value to be added.
  243. * @param source typically should be %__FILE__ or %__func__ for logging purposes.
  244. * @param line %__LINE__ for logging purposes.
  245. * @return 0 on success, -1 on failure.
  246. */
  247. int rc_add_config(rc_handle *rh, char const *option_name, char const *option_val, char const *source, int line)
  248. {
  249. OPTION *option;
  250. if ((option = find_option(rh, option_name, OT_ANY)) == NULL)
  251. {
  252. rc_log(LOG_ERR, "ERROR: unrecognized option: %s", option_name);
  253. return -1;
  254. }
  255. if (option->status != ST_UNDEF)
  256. {
  257. rc_log(LOG_ERR, "ERROR: duplicate option: %s", option_name);
  258. return -1;
  259. }
  260. switch (option->type) {
  261. case OT_STR:
  262. if (set_option_str(source, line, option, option_val) < 0) {
  263. return -1;
  264. }
  265. break;
  266. case OT_INT:
  267. if (set_option_int(source, line, option, option_val) < 0) {
  268. return -1;
  269. }
  270. break;
  271. case OT_SRV:
  272. if (set_option_srv(source, line, option, option_val) < 0) {
  273. return -1;
  274. }
  275. break;
  276. case OT_AUO:
  277. if (set_option_auo(source, line, option, option_val) < 0) {
  278. return -1;
  279. }
  280. break;
  281. default:
  282. rc_log(LOG_CRIT, "rc_add_config: impossible case branch!");
  283. abort();
  284. }
  285. if (strcmp(option->name, "bindaddr") == 0) {
  286. memset(&rh->own_bind_addr, 0, sizeof(rh->own_bind_addr));
  287. rh->own_bind_addr_set = 0;
  288. rc_own_bind_addr(rh, &rh->own_bind_addr);
  289. rh->own_bind_addr_set = 1;
  290. }
  291. return 0;
  292. }
  293. /** Initialise a configuration structure
  294. *
  295. * Initialize the configuration structure from an external program. For use when not
  296. * running a standalone client that reads from a config file.
  297. *
  298. * @param rh a handle to parsed configuration.
  299. * @return rc_handle on success, NULL on failure.
  300. */
  301. rc_handle *rc_config_init(rc_handle *rh)
  302. {
  303. int i;
  304. SERVER *authservers;
  305. SERVER *acctservers;
  306. OPTION *acct;
  307. OPTION *auth;
  308. rh->config_options = malloc(sizeof(config_options_default));
  309. if (rh->config_options == NULL)
  310. {
  311. rc_log(LOG_CRIT, "rc_config_init: out of memory");
  312. rc_destroy(rh);
  313. return NULL;
  314. }
  315. memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  316. acct = find_option(rh, "acctserver", OT_ANY);
  317. auth = find_option(rh, "authserver", OT_ANY);
  318. authservers = malloc(sizeof(SERVER));
  319. acctservers = malloc(sizeof(SERVER));
  320. if(authservers == NULL || acctservers == NULL)
  321. {
  322. rc_log(LOG_CRIT, "rc_config_init: error initializing server structs");
  323. rc_destroy(rh);
  324. if(authservers) free(authservers);
  325. if(acctservers) free(acctservers);
  326. return NULL;
  327. }
  328. authservers->max = 0;
  329. acctservers->max = 0;
  330. for(i=0; i < SERVER_MAX; i++)
  331. {
  332. authservers->name[i] = NULL;
  333. authservers->secret[i] = NULL;
  334. acctservers->name[i] = NULL;
  335. acctservers->secret[i] = NULL;
  336. }
  337. acct->val = acctservers;
  338. auth->val = authservers;
  339. return rh;
  340. }
  341. /** Read the global config file
  342. *
  343. * @param filename a name of a file.
  344. * @return new rc_handle on success, NULL when failure.
  345. */
  346. void rc_read_config(rc_handle* rh)
  347. {
  348. // TODO запускаем random generator
  349. rh->config_options = &rcOptions;
  350. //memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  351. }
  352. #if 0
  353. rc_handle *rc_read_config(char const *filename)
  354. {
  355. FILE *configfd;
  356. char buffer[512], *p;
  357. OPTION *option;
  358. int line;
  359. size_t pos;
  360. rc_handle *rh;
  361. srandom((unsigned int)(time(NULL)+getpid()));
  362. rh = rc_new();
  363. if (rh == NULL)
  364. return NULL;
  365. rh->config_options = malloc(sizeof(config_options_default));
  366. if (rh->config_options == NULL) {
  367. rc_log(LOG_CRIT, "rc_read_config: out of memory");
  368. rc_destroy(rh);
  369. return NULL;
  370. }
  371. memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  372. if ((configfd = fopen(filename,"r")) == NULL)
  373. {
  374. rc_log(LOG_ERR,"rc_read_config: can't open %s: %s", filename, strerror(errno));
  375. rc_destroy(rh);
  376. return NULL;
  377. }
  378. line = 0;
  379. while ((fgets(buffer, sizeof(buffer), configfd) != NULL))
  380. {
  381. line++;
  382. p = buffer;
  383. if ((*p == '\n') || (*p == '#') || (*p == '\0'))
  384. continue;
  385. p[strlen(p)-1] = '\0';
  386. if ((pos = strcspn(p, "\t ")) == 0) {
  387. rc_log(LOG_ERR, "%s: line %d: bogus format: %s", filename, line, p);
  388. fclose(configfd);
  389. rc_destroy(rh);
  390. return NULL;
  391. }
  392. p[pos] = '\0';
  393. if ((option = find_option(rh, p, OT_ANY)) == NULL) {
  394. rc_log(LOG_ERR, "%s: line %d: unrecognized keyword: %s", filename, line, p);
  395. fclose(configfd);
  396. rc_destroy(rh);
  397. return NULL;
  398. }
  399. if (option->status != ST_UNDEF) {
  400. rc_log(LOG_ERR, "%s: line %d: duplicate option line: %s", filename, line, p);
  401. fclose(configfd);
  402. rc_destroy(rh);
  403. return NULL;
  404. }
  405. p += pos+1;
  406. while (isspace(*p))
  407. p++;
  408. pos = strlen(p) - 1;
  409. while(pos != 0 && isspace(p[pos]))
  410. pos--;
  411. p[pos + 1] = '\0';
  412. switch (option->type) {
  413. case OT_STR:
  414. if (set_option_str(filename, line, option, p) < 0) {
  415. fclose(configfd);
  416. rc_destroy(rh);
  417. return NULL;
  418. }
  419. break;
  420. case OT_INT:
  421. if (set_option_int(filename, line, option, p) < 0) {
  422. fclose(configfd);
  423. rc_destroy(rh);
  424. return NULL;
  425. }
  426. break;
  427. case OT_SRV:
  428. if (set_option_srv(filename, line, option, p) < 0) {
  429. fclose(configfd);
  430. rc_destroy(rh);
  431. return NULL;
  432. }
  433. break;
  434. case OT_AUO:
  435. if (set_option_auo(filename, line, option, p) < 0) {
  436. fclose(configfd);
  437. rc_destroy(rh);
  438. return NULL;
  439. }
  440. break;
  441. default:
  442. rc_log(LOG_CRIT, "rc_read_config: impossible case branch!");
  443. abort();
  444. }
  445. }
  446. fclose(configfd);
  447. if (test_config(rh, filename) == -1) {
  448. rc_destroy(rh);
  449. return NULL;
  450. }
  451. return rh;
  452. }
  453. #endif
  454. /** Get the value of a config option
  455. *
  456. * @param rh a handle to parsed configuration.
  457. * @param optname the name of an option.
  458. * @return config option value.
  459. */
  460. char *rc_conf_str(rc_handle const *rh, char const *optname)
  461. {
  462. OPTION *option;
  463. option = find_option(rh, optname, OT_STR);
  464. if (option != NULL) {
  465. return (char *)option->val;
  466. } else {
  467. rc_log(LOG_CRIT, "rc_conf_str: unkown config option requested: %s", optname);
  468. return NULL;
  469. }
  470. }
  471. /** Get the value of a config option
  472. *
  473. * @param rh a handle to parsed configuration.
  474. * @param optname the name of an option.
  475. * @return config option value.
  476. */
  477. int rc_conf_int(rc_handle const *rh, char const *optname)
  478. {
  479. OPTION *option;
  480. option = find_option(rh, optname, OT_INT|OT_AUO);
  481. if (option != NULL) {
  482. if (option->val) {
  483. return *((int *)option->val);
  484. } else {
  485. rc_log(LOG_ERR, "rc_conf_int: config option %s was not set", optname);
  486. return 0;
  487. }
  488. } else {
  489. rc_log(LOG_CRIT, "rc_conf_int: unkown config option requested: %s", optname);
  490. return 0;
  491. }
  492. }
  493. /** Get the value of a config option
  494. *
  495. * @param rh a handle to parsed configuration.
  496. * @param optname the name of an option.
  497. * @return config option value.
  498. */
  499. SERVER *rc_conf_srv(rc_handle const *rh, char const *optname)
  500. {
  501. OPTION *option;
  502. option = find_option(rh, optname, OT_SRV);
  503. if (option != NULL) {
  504. return (SERVER *)option->val;
  505. } else {
  506. rc_log(LOG_CRIT, "rc_conf_srv: unkown config option requested: %s", optname);
  507. return NULL;
  508. }
  509. }
  510. /** Tests the configuration the user supplied
  511. *
  512. * @param rh a handle to parsed configuration.
  513. * @param filename a name of a configuration file.
  514. * @return 0 on success, -1 when failure.
  515. */
  516. int test_config(rc_handle const *rh, char const *filename)
  517. {
  518. SERVER *srv;
  519. srv = rc_conf_srv(rh, "authserver");
  520. if (!srv || !srv->max)
  521. {
  522. rc_log(LOG_ERR,"%s: no authserver specified", filename);
  523. return -1;
  524. }
  525. srv = rc_conf_srv(rh, "acctserver");
  526. if (!srv || !srv->max)
  527. {
  528. rc_log(LOG_ERR,"%s: no acctserver specified", filename);
  529. return -1;
  530. }
  531. if (!rc_conf_str(rh, "servers"))
  532. {
  533. rc_log(LOG_ERR,"%s: no servers file specified", filename);
  534. return -1;
  535. }
  536. if (!rc_conf_str(rh, "dictionary"))
  537. {
  538. rc_log(LOG_ERR,"%s: no dictionary specified", filename);
  539. return -1;
  540. }
  541. if (rc_conf_int(rh, "radius_timeout") <= 0)
  542. {
  543. rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename);
  544. return -1;
  545. }
  546. if (rc_conf_int(rh, "radius_retries") <= 0)
  547. {
  548. rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename);
  549. return -1;
  550. }
  551. if (rc_conf_int(rh, "radius_deadtime") < 0)
  552. {
  553. rc_log(LOG_ERR,"%s: radius_deadtime is illegal", filename);
  554. return -1;
  555. }
  556. if (rc_conf_int(rh, "login_tries") <= 0)
  557. {
  558. rc_log(LOG_ERR,"%s: login_tries <= 0 is illegal", filename);
  559. return -1;
  560. }
  561. if (rc_conf_int(rh, "login_timeout") <= 0)
  562. {
  563. rc_log(LOG_ERR,"%s: login_timeout <= 0 is illegal", filename);
  564. return -1;
  565. }
  566. if (rc_conf_str(rh, "mapfile") == NULL)
  567. {
  568. rc_log(LOG_ERR,"%s: mapfile not specified", filename);
  569. return -1;
  570. }
  571. if (rc_conf_str(rh, "nologin") == NULL)
  572. {
  573. rc_log(LOG_ERR,"%s: nologin not specified", filename);
  574. return -1;
  575. }
  576. return 0;
  577. }
  578. /** See if info matches hostname
  579. *
  580. * @param info a struct addrinfo
  581. * @param hostname the name of the host.
  582. * @return 0 on success, -1 when failure.
  583. */
  584. static int find_match (const struct addrinfo* addr, const struct addrinfo *hostname)
  585. {
  586. #if 0
  587. const struct addrinfo *ptr, *ptr2;
  588. unsigned len1, len2;
  589. ptr = addr;
  590. while(ptr) {
  591. ptr2 = hostname;
  592. while(ptr2) {
  593. len1 = SA_GET_INLEN(ptr->ai_addr);
  594. len2 = SA_GET_INLEN(ptr2->ai_addr);
  595. if (len1 > 0 &&
  596. len1 == len2 &&
  597. memcmp(SA_GET_INADDR(ptr->ai_addr), SA_GET_INADDR(ptr2->ai_addr), len1) == 0) {
  598. return 0;
  599. }
  600. ptr2 = ptr2->ai_next;
  601. }
  602. ptr = ptr->ai_next;
  603. }
  604. #endif
  605. return -1;
  606. }
  607. /** Checks if provided address is local address
  608. *
  609. * @param addr an %AF_INET or %AF_INET6 address
  610. * @return 0 if local, 1 if not local, -1 on failure.
  611. */
  612. static int rc_ipaddr_local(const struct sockaddr *addr)
  613. {
  614. #if 0
  615. int temp_sock, res, serrno;
  616. struct sockaddr tmpaddr;
  617. memcpy(&tmpaddr, addr, SA_LEN(addr));
  618. temp_sock = socket(addr->sa_family, SOCK_DGRAM, 0);
  619. if (temp_sock == -1)
  620. return -1;
  621. if (addr->sa_family == AF_INET) {
  622. ((struct sockaddr_in*)&tmpaddr)->sin_port = 0;
  623. } else {
  624. ((struct sockaddr_in6*)&tmpaddr)->sin6_port = 0;
  625. }
  626. res = bind(temp_sock, &tmpaddr, SA_LEN(&tmpaddr));
  627. serrno = errno;
  628. close(temp_sock);
  629. if (res == 0)
  630. return 0;
  631. if (serrno == EADDRNOTAVAIL)
  632. return 1;
  633. #endif
  634. return -1;
  635. }
  636. /** Checks if provided name refers to ourselves
  637. *
  638. * @param info an addrinfo of the host to check
  639. * @return 0 if yes, 1 if no and -1 on failure.
  640. */
  641. static int rc_is_myname(const struct addrinfo *info)
  642. {
  643. #if 0
  644. const struct addrinfo *p;
  645. int res;
  646. p = info;
  647. while(p != NULL) {
  648. res = rc_ipaddr_local(p->ai_addr);
  649. if (res == 0 || res == -1) {
  650. return res;
  651. }
  652. p = p->ai_next;
  653. }
  654. #endif
  655. return 1;
  656. }
  657. /** Locate a server in the rh config or if not found, check for a servers file
  658. *
  659. * @param rh a handle to parsed configuration.
  660. * @param server_name the name of the server.
  661. * @param info: will hold a pointer to addrinfo
  662. * @param secret will hold the server's secret (of %MAX_SECRET_LENGTH).
  663. * @param flags %AUTH or %ACCT
  664. * @return 0 on success, -1 on failure.
  665. */
  666. //int rc_find_server_addr(rc_handle const *, char const *, struct addrinfo **, char *, unsigned flags);
  667. int rc_find_server_addr(rc_handle const *rh, char const *server_name,
  668. struct addrinfo** info, char *secret, unsigned flags)
  669. {
  670. int i;
  671. int result = 0;
  672. FILE *clientfd;
  673. char *h;
  674. char *s;
  675. char buffer[128];
  676. char hostnm[AUTH_ID_LEN + 1];
  677. char *buffer_save;
  678. char *hostnm_save;
  679. SERVER *authservers;
  680. SERVER *acctservers;
  681. struct addrinfo *tmpinfo = NULL;
  682. /* Lookup the IP address of the radius server */
  683. if ((*info = rc_getaddrinfo (server_name, flags==AUTH?PW_AI_AUTH:PW_AI_ACCT)) == NULL)
  684. return -1;
  685. if (flags == AUTH) {
  686. /* Check to see if the server secret is defined in the rh config */
  687. if( (authservers = rc_conf_srv(rh, "authserver")) != NULL )
  688. {
  689. for( i = 0; i < authservers->max; i++ )
  690. {
  691. if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) &&
  692. (authservers->secret[i] != NULL) )
  693. {
  694. memset (secret, '\0', MAX_SECRET_LENGTH);
  695. strlcpy (secret, authservers->secret[i], MAX_SECRET_LENGTH);
  696. return 0;
  697. }
  698. }
  699. }
  700. } else if (flags == ACCT) {
  701. if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL )
  702. {
  703. for( i = 0; i < acctservers->max; i++ )
  704. {
  705. if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) &&
  706. (acctservers->secret[i] != NULL) )
  707. {
  708. memset (secret, '\0', MAX_SECRET_LENGTH);
  709. strlcpy (secret, acctservers->secret[i], MAX_SECRET_LENGTH);
  710. return 0;
  711. }
  712. }
  713. }
  714. }
  715. /* We didn't find it in the rh_config or the servername is too long so look for a
  716. * servers file to define the secret(s)
  717. */
  718. if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL)
  719. {
  720. rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers"));
  721. goto fail;
  722. }
  723. while (fgets (buffer, sizeof (buffer), clientfd) != NULL)
  724. {
  725. if (*buffer == '#')
  726. continue;
  727. if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */
  728. continue;
  729. strlcpy (hostnm, h, AUTH_ID_LEN);
  730. if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */
  731. continue;
  732. strlcpy (secret, s, MAX_SECRET_LENGTH);
  733. if (!strchr (hostnm, '/')) /* If single name form */
  734. {
  735. tmpinfo = rc_getaddrinfo(hostnm, 0);
  736. if (tmpinfo)
  737. {
  738. result = find_match (*info, tmpinfo);
  739. if (result == 0)
  740. {
  741. result++;
  742. break;
  743. }
  744. //freeaddrinfo(tmpinfo);
  745. tmpinfo = NULL;
  746. }
  747. }
  748. else /* <name1>/<name2> "paired" form */
  749. {
  750. strtok_r(hostnm, "/", &hostnm_save);
  751. tmpinfo = rc_getaddrinfo(hostnm, 0);
  752. if (tmpinfo)
  753. {
  754. if (rc_is_myname(tmpinfo) == 0)
  755. { /* If we're the 1st name, target is 2nd */
  756. if (find_match (*info, tmpinfo) == 0)
  757. {
  758. result++;
  759. break;
  760. }
  761. }
  762. else /* If we were 2nd name, target is 1st name */
  763. {
  764. if (find_match (*info, tmpinfo) == 0)
  765. {
  766. result++;
  767. break;
  768. }
  769. }
  770. //freeaddrinfo(tmpinfo);
  771. tmpinfo = NULL;
  772. }
  773. }
  774. }
  775. fclose (clientfd);
  776. if (result == 0)
  777. {
  778. memset (buffer, '\0', sizeof (buffer));
  779. memset (secret, '\0', MAX_SECRET_LENGTH);
  780. rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s",
  781. server_name, rc_conf_str(rh, "servers"));
  782. goto fail;
  783. }
  784. result = 0;
  785. goto cleanup;
  786. fail:
  787. //freeaddrinfo(*info);
  788. result = -1;
  789. cleanup:
  790. //if (tmpinfo)
  791. //freeaddrinfo(tmpinfo);
  792. return result;
  793. }
  794. /**
  795. * rc_config_free:
  796. * @param rh a handle to parsed configuration
  797. *
  798. * Free allocated config values
  799. *
  800. */
  801. void
  802. rc_config_free(rc_handle *rh)
  803. {
  804. int i, j;
  805. SERVER *serv;
  806. if (rh->config_options == NULL)
  807. return;
  808. for (i = 0; i < NUM_OPTIONS; i++) {
  809. if (rh->config_options[i].val == NULL)
  810. continue;
  811. if (rh->config_options[i].type == OT_SRV) {
  812. serv = (SERVER *)rh->config_options[i].val;
  813. for (j = 0; j < serv->max; j++){
  814. free(serv->name[j]);
  815. if(serv->secret[j]) free(serv->secret[j]);
  816. }
  817. free(serv);
  818. } else {
  819. free(rh->config_options[i].val);
  820. }
  821. }
  822. free(rh->config_options);
  823. rh->config_options = NULL;
  824. }