config.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  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. OPTION *option;
  254. if ((option = find_option(rh, option_name, OT_ANY)) == NULL)
  255. {
  256. rc_log(LOG_ERR, "ERROR: unrecognized option: %s", option_name);
  257. return -1;
  258. }
  259. if (option->status != ST_UNDEF)
  260. {
  261. rc_log(LOG_ERR, "ERROR: duplicate option: %s", option_name);
  262. return -1;
  263. }
  264. switch (option->type) {
  265. case OT_STR:
  266. if (set_option_str(source, line, option, option_val) < 0) {
  267. return -1;
  268. }
  269. break;
  270. case OT_INT:
  271. if (set_option_int(source, line, option, option_val) < 0) {
  272. return -1;
  273. }
  274. break;
  275. case OT_SRV:
  276. if (set_option_srv(source, line, option, option_val) < 0) {
  277. return -1;
  278. }
  279. break;
  280. case OT_AUO:
  281. if (set_option_auo(source, line, option, option_val) < 0) {
  282. return -1;
  283. }
  284. break;
  285. default:
  286. rc_log(LOG_CRIT, "rc_add_config: impossible case branch!");
  287. abort();
  288. }
  289. if (strcmp(option->name, "bindaddr") == 0) {
  290. memset(&rh->own_bind_addr, 0, sizeof(rh->own_bind_addr));
  291. rh->own_bind_addr_set = 0;
  292. rc_own_bind_addr(rh, &rh->own_bind_addr);
  293. rh->own_bind_addr_set = 1;
  294. }
  295. return 0;
  296. }
  297. /** Initialise a configuration structure
  298. *
  299. * Initialize the configuration structure from an external program. For use when not
  300. * running a standalone client that reads from a config file.
  301. *
  302. * @param rh a handle to parsed configuration.
  303. * @return rc_handle on success, NULL on failure.
  304. */
  305. rc_handle *rc_config_init(rc_handle *rh)
  306. {
  307. int i;
  308. SERVER *authservers;
  309. SERVER *acctservers;
  310. OPTION *acct;
  311. OPTION *auth;
  312. rh->config_options = malloc(sizeof(config_options_default));
  313. if (rh->config_options == NULL)
  314. {
  315. rc_log(LOG_CRIT, "rc_config_init: out of memory");
  316. rc_destroy(rh);
  317. return NULL;
  318. }
  319. memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  320. acct = find_option(rh, "acctserver", OT_ANY);
  321. auth = find_option(rh, "authserver", OT_ANY);
  322. authservers = malloc(sizeof(SERVER));
  323. acctservers = malloc(sizeof(SERVER));
  324. if(authservers == NULL || acctservers == NULL)
  325. {
  326. rc_log(LOG_CRIT, "rc_config_init: error initializing server structs");
  327. rc_destroy(rh);
  328. if(authservers) free(authservers);
  329. if(acctservers) free(acctservers);
  330. return NULL;
  331. }
  332. authservers->max = 0;
  333. acctservers->max = 0;
  334. for(i=0; i < SERVER_MAX; i++)
  335. {
  336. authservers->name[i] = NULL;
  337. authservers->secret[i] = NULL;
  338. acctservers->name[i] = NULL;
  339. acctservers->secret[i] = NULL;
  340. }
  341. acct->val = acctservers;
  342. auth->val = authservers;
  343. return rh;
  344. }
  345. /** Read the global config file
  346. *
  347. * @param filename a name of a file.
  348. * @return new rc_handle on success, NULL when failure.
  349. */
  350. void rc_read_config(rc_handle* rh)
  351. {
  352. rh->config_options = &rcOptions;
  353. //memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  354. }
  355. #if 0
  356. rc_handle *rc_read_config(char const *filename)
  357. {
  358. FILE *configfd;
  359. char buffer[512], *p;
  360. OPTION *option;
  361. int line;
  362. size_t pos;
  363. rc_handle *rh;
  364. srandom((unsigned int)(time(NULL)+getpid()));
  365. rh = rc_new();
  366. if (rh == NULL)
  367. return NULL;
  368. rh->config_options = malloc(sizeof(config_options_default));
  369. if (rh->config_options == NULL) {
  370. rc_log(LOG_CRIT, "rc_read_config: out of memory");
  371. rc_destroy(rh);
  372. return NULL;
  373. }
  374. memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
  375. if ((configfd = fopen(filename,"r")) == NULL)
  376. {
  377. rc_log(LOG_ERR,"rc_read_config: can't open %s: %s", filename, strerror(errno));
  378. rc_destroy(rh);
  379. return NULL;
  380. }
  381. line = 0;
  382. while ((fgets(buffer, sizeof(buffer), configfd) != NULL))
  383. {
  384. line++;
  385. p = buffer;
  386. if ((*p == '\n') || (*p == '#') || (*p == '\0'))
  387. continue;
  388. p[strlen(p)-1] = '\0';
  389. if ((pos = strcspn(p, "\t ")) == 0) {
  390. rc_log(LOG_ERR, "%s: line %d: bogus format: %s", filename, line, p);
  391. fclose(configfd);
  392. rc_destroy(rh);
  393. return NULL;
  394. }
  395. p[pos] = '\0';
  396. if ((option = find_option(rh, p, OT_ANY)) == NULL) {
  397. rc_log(LOG_ERR, "%s: line %d: unrecognized keyword: %s", filename, line, p);
  398. fclose(configfd);
  399. rc_destroy(rh);
  400. return NULL;
  401. }
  402. if (option->status != ST_UNDEF) {
  403. rc_log(LOG_ERR, "%s: line %d: duplicate option line: %s", filename, line, p);
  404. fclose(configfd);
  405. rc_destroy(rh);
  406. return NULL;
  407. }
  408. p += pos+1;
  409. while (isspace(*p))
  410. p++;
  411. pos = strlen(p) - 1;
  412. while(pos != 0 && isspace(p[pos]))
  413. pos--;
  414. p[pos + 1] = '\0';
  415. switch (option->type) {
  416. case OT_STR:
  417. if (set_option_str(filename, line, option, p) < 0) {
  418. fclose(configfd);
  419. rc_destroy(rh);
  420. return NULL;
  421. }
  422. break;
  423. case OT_INT:
  424. if (set_option_int(filename, line, option, p) < 0) {
  425. fclose(configfd);
  426. rc_destroy(rh);
  427. return NULL;
  428. }
  429. break;
  430. case OT_SRV:
  431. if (set_option_srv(filename, line, option, p) < 0) {
  432. fclose(configfd);
  433. rc_destroy(rh);
  434. return NULL;
  435. }
  436. break;
  437. case OT_AUO:
  438. if (set_option_auo(filename, line, option, p) < 0) {
  439. fclose(configfd);
  440. rc_destroy(rh);
  441. return NULL;
  442. }
  443. break;
  444. default:
  445. rc_log(LOG_CRIT, "rc_read_config: impossible case branch!");
  446. abort();
  447. }
  448. }
  449. fclose(configfd);
  450. if (test_config(rh, filename) == -1) {
  451. rc_destroy(rh);
  452. return NULL;
  453. }
  454. return rh;
  455. }
  456. #endif
  457. /** Get the value of a config option
  458. *
  459. * @param rh a handle to parsed configuration.
  460. * @param optname the name of an option.
  461. * @return config option value.
  462. */
  463. char *rc_conf_str(rc_handle const *rh, char const *optname)
  464. {
  465. OPTION *option;
  466. option = find_option(rh, optname, OT_STR);
  467. if (option != NULL) {
  468. return (char *)option->val;
  469. } else {
  470. rc_log(LOG_CRIT, "rc_conf_str: unkown config option requested: %s", optname);
  471. return NULL;
  472. }
  473. }
  474. /** Get the value of a config option
  475. *
  476. * @param rh a handle to parsed configuration.
  477. * @param optname the name of an option.
  478. * @return config option value.
  479. */
  480. int rc_conf_int(rc_handle const *rh, char const *optname)
  481. {
  482. OPTION *option;
  483. option = find_option(rh, optname, OT_INT|OT_AUO);
  484. if (option != NULL) {
  485. if (option->val) {
  486. return *((int *)option->val);
  487. } else {
  488. rc_log(LOG_ERR, "rc_conf_int: config option %s was not set", optname);
  489. return 0;
  490. }
  491. } else {
  492. rc_log(LOG_CRIT, "rc_conf_int: unkown config option requested: %s", optname);
  493. return 0;
  494. }
  495. }
  496. /** Get the value of a config option
  497. *
  498. * @param rh a handle to parsed configuration.
  499. * @param optname the name of an option.
  500. * @return config option value.
  501. */
  502. SERVER *rc_conf_srv(rc_handle const *rh, char const *optname)
  503. {
  504. OPTION *option;
  505. option = find_option(rh, optname, OT_SRV);
  506. if (option != NULL) {
  507. return (SERVER *)option->val;
  508. } else {
  509. rc_log(LOG_CRIT, "rc_conf_srv: unkown config option requested: %s", optname);
  510. return NULL;
  511. }
  512. }
  513. /** Tests the configuration the user supplied
  514. *
  515. * @param rh a handle to parsed configuration.
  516. * @param filename a name of a configuration file.
  517. * @return 0 on success, -1 when failure.
  518. */
  519. int test_config(rc_handle const *rh, char const *filename)
  520. {
  521. SERVER *srv;
  522. srv = rc_conf_srv(rh, "authserver");
  523. if (!srv || !srv->max)
  524. {
  525. rc_log(LOG_ERR,"%s: no authserver specified", filename);
  526. return -1;
  527. }
  528. srv = rc_conf_srv(rh, "acctserver");
  529. if (!srv || !srv->max)
  530. {
  531. rc_log(LOG_ERR,"%s: no acctserver specified", filename);
  532. return -1;
  533. }
  534. if (!rc_conf_str(rh, "servers"))
  535. {
  536. rc_log(LOG_ERR,"%s: no servers file specified", filename);
  537. return -1;
  538. }
  539. if (!rc_conf_str(rh, "dictionary"))
  540. {
  541. rc_log(LOG_ERR,"%s: no dictionary specified", filename);
  542. return -1;
  543. }
  544. if (rc_conf_int(rh, "radius_timeout") <= 0)
  545. {
  546. rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename);
  547. return -1;
  548. }
  549. if (rc_conf_int(rh, "radius_retries") <= 0)
  550. {
  551. rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename);
  552. return -1;
  553. }
  554. if (rc_conf_int(rh, "radius_deadtime") < 0)
  555. {
  556. rc_log(LOG_ERR,"%s: radius_deadtime is illegal", filename);
  557. return -1;
  558. }
  559. if (rc_conf_int(rh, "login_tries") <= 0)
  560. {
  561. rc_log(LOG_ERR,"%s: login_tries <= 0 is illegal", filename);
  562. return -1;
  563. }
  564. if (rc_conf_int(rh, "login_timeout") <= 0)
  565. {
  566. rc_log(LOG_ERR,"%s: login_timeout <= 0 is illegal", filename);
  567. return -1;
  568. }
  569. if (rc_conf_str(rh, "mapfile") == NULL)
  570. {
  571. rc_log(LOG_ERR,"%s: mapfile not specified", filename);
  572. return -1;
  573. }
  574. if (rc_conf_str(rh, "nologin") == NULL)
  575. {
  576. rc_log(LOG_ERR,"%s: nologin not specified", filename);
  577. return -1;
  578. }
  579. return 0;
  580. }
  581. /** See if info matches hostname
  582. *
  583. * @param info a struct addrinfo
  584. * @param hostname the name of the host.
  585. * @return 0 on success, -1 when failure.
  586. */
  587. static int find_match (const struct addrinfo* addr, const struct addrinfo *hostname)
  588. {
  589. #if 0
  590. const struct addrinfo *ptr, *ptr2;
  591. unsigned len1, len2;
  592. ptr = addr;
  593. while(ptr) {
  594. ptr2 = hostname;
  595. while(ptr2) {
  596. len1 = SA_GET_INLEN(ptr->ai_addr);
  597. len2 = SA_GET_INLEN(ptr2->ai_addr);
  598. if (len1 > 0 &&
  599. len1 == len2 &&
  600. memcmp(SA_GET_INADDR(ptr->ai_addr), SA_GET_INADDR(ptr2->ai_addr), len1) == 0) {
  601. return 0;
  602. }
  603. ptr2 = ptr2->ai_next;
  604. }
  605. ptr = ptr->ai_next;
  606. }
  607. #endif
  608. return -1;
  609. }
  610. /** Checks if provided address is local address
  611. *
  612. * @param addr an %AF_INET or %AF_INET6 address
  613. * @return 0 if local, 1 if not local, -1 on failure.
  614. */
  615. static int rc_ipaddr_local(const struct sockaddr *addr)
  616. {
  617. #if 0
  618. int temp_sock, res, serrno;
  619. struct sockaddr tmpaddr;
  620. memcpy(&tmpaddr, addr, SA_LEN(addr));
  621. temp_sock = socket(addr->sa_family, SOCK_DGRAM, 0);
  622. if (temp_sock == -1)
  623. return -1;
  624. if (addr->sa_family == AF_INET) {
  625. ((struct sockaddr_in*)&tmpaddr)->sin_port = 0;
  626. } else {
  627. ((struct sockaddr_in6*)&tmpaddr)->sin6_port = 0;
  628. }
  629. res = bind(temp_sock, &tmpaddr, SA_LEN(&tmpaddr));
  630. serrno = errno;
  631. close(temp_sock);
  632. if (res == 0)
  633. return 0;
  634. if (serrno == EADDRNOTAVAIL)
  635. return 1;
  636. #endif
  637. return -1;
  638. }
  639. /** Checks if provided name refers to ourselves
  640. *
  641. * @param info an addrinfo of the host to check
  642. * @return 0 if yes, 1 if no and -1 on failure.
  643. */
  644. static int rc_is_myname(const struct addrinfo *info)
  645. {
  646. #if 0
  647. const struct addrinfo *p;
  648. int res;
  649. p = info;
  650. while(p != NULL) {
  651. res = rc_ipaddr_local(p->ai_addr);
  652. if (res == 0 || res == -1) {
  653. return res;
  654. }
  655. p = p->ai_next;
  656. }
  657. #endif
  658. return 1;
  659. }
  660. /** Locate a server in the rh config or if not found, check for a servers file
  661. *
  662. * @param rh a handle to parsed configuration.
  663. * @param server_name the name of the server.
  664. * @param info: will hold a pointer to addrinfo
  665. * @param secret will hold the server's secret (of %MAX_SECRET_LENGTH).
  666. * @param flags %AUTH or %ACCT
  667. * @return 0 on success, -1 on failure.
  668. */
  669. //int rc_find_server_addr(rc_handle const *, char const *, struct addrinfo **, char *, unsigned flags);
  670. int rc_find_server_addr(rc_handle const *rh, char const *server_name,
  671. struct addrinfo** info, char *secret, unsigned flags)
  672. {
  673. #if 0
  674. int i;
  675. int result = 0;
  676. FILE *clientfd;
  677. char *h;
  678. char *s;
  679. char buffer[128];
  680. char hostnm[AUTH_ID_LEN + 1];
  681. char *buffer_save;
  682. char *hostnm_save;
  683. SERVER *authservers;
  684. SERVER *acctservers;
  685. struct addrinfo *tmpinfo = NULL;
  686. /* Lookup the IP address of the radius server */
  687. if ((*info = rc_getaddrinfo (server_name, flags==AUTH?PW_AI_AUTH:PW_AI_ACCT)) == NULL)
  688. return -1;
  689. if (flags == AUTH) {
  690. /* Check to see if the server secret is defined in the rh config */
  691. if( (authservers = rc_conf_srv(rh, "authserver")) != NULL )
  692. {
  693. for( i = 0; i < authservers->max; i++ )
  694. {
  695. if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) &&
  696. (authservers->secret[i] != NULL) )
  697. {
  698. memset (secret, '\0', MAX_SECRET_LENGTH);
  699. strlcpy (secret, authservers->secret[i], MAX_SECRET_LENGTH);
  700. return 0;
  701. }
  702. }
  703. }
  704. } else if (flags == ACCT) {
  705. if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL )
  706. {
  707. for( i = 0; i < acctservers->max; i++ )
  708. {
  709. if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) &&
  710. (acctservers->secret[i] != NULL) )
  711. {
  712. memset (secret, '\0', MAX_SECRET_LENGTH);
  713. strlcpy (secret, acctservers->secret[i], MAX_SECRET_LENGTH);
  714. return 0;
  715. }
  716. }
  717. }
  718. }
  719. /* We didn't find it in the rh_config or the servername is too long so look for a
  720. * servers file to define the secret(s)
  721. */
  722. if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL)
  723. {
  724. rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers"));
  725. goto fail;
  726. }
  727. while (fgets (buffer, sizeof (buffer), clientfd) != NULL)
  728. {
  729. if (*buffer == '#')
  730. continue;
  731. if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */
  732. continue;
  733. strlcpy (hostnm, h, AUTH_ID_LEN);
  734. if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */
  735. continue;
  736. strlcpy (secret, s, MAX_SECRET_LENGTH);
  737. if (!strchr (hostnm, '/')) /* If single name form */
  738. {
  739. tmpinfo = rc_getaddrinfo(hostnm, 0);
  740. if (tmpinfo)
  741. {
  742. result = find_match (*info, tmpinfo);
  743. if (result == 0)
  744. {
  745. result++;
  746. break;
  747. }
  748. //freeaddrinfo(tmpinfo);
  749. tmpinfo = NULL;
  750. }
  751. }
  752. else /* <name1>/<name2> "paired" form */
  753. {
  754. strtok_r(hostnm, "/", &hostnm_save);
  755. tmpinfo = rc_getaddrinfo(hostnm, 0);
  756. if (tmpinfo)
  757. {
  758. if (rc_is_myname(tmpinfo) == 0)
  759. { /* If we're the 1st name, target is 2nd */
  760. if (find_match (*info, tmpinfo) == 0)
  761. {
  762. result++;
  763. break;
  764. }
  765. }
  766. else /* If we were 2nd name, target is 1st name */
  767. {
  768. if (find_match (*info, tmpinfo) == 0)
  769. {
  770. result++;
  771. break;
  772. }
  773. }
  774. //freeaddrinfo(tmpinfo);
  775. tmpinfo = NULL;
  776. }
  777. }
  778. }
  779. fclose (clientfd);
  780. if (result == 0)
  781. {
  782. memset (buffer, '\0', sizeof (buffer));
  783. memset (secret, '\0', MAX_SECRET_LENGTH);
  784. rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s",
  785. server_name, rc_conf_str(rh, "servers"));
  786. goto fail;
  787. }
  788. result = 0;
  789. goto cleanup;
  790. fail:
  791. //freeaddrinfo(*info);
  792. result = -1;
  793. cleanup:
  794. //if (tmpinfo)
  795. //freeaddrinfo(tmpinfo);
  796. return result;
  797. #endif
  798. }
  799. /**
  800. * rc_config_free:
  801. * @param rh a handle to parsed configuration
  802. *
  803. * Free allocated config values
  804. *
  805. */
  806. void
  807. rc_config_free(rc_handle *rh)
  808. {
  809. int i, j;
  810. SERVER *serv;
  811. if (rh->config_options == NULL)
  812. return;
  813. for (i = 0; i < NUM_OPTIONS; i++) {
  814. if (rh->config_options[i].val == NULL)
  815. continue;
  816. if (rh->config_options[i].type == OT_SRV) {
  817. serv = (SERVER *)rh->config_options[i].val;
  818. for (j = 0; j < serv->max; j++){
  819. free(serv->name[j]);
  820. if(serv->secret[j]) free(serv->secret[j]);
  821. }
  822. free(serv);
  823. } else {
  824. free(rh->config_options[i].val);
  825. }
  826. }
  827. free(rh->config_options);
  828. rh->config_options = NULL;
  829. }