config.c 22 KB

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