config.c 22 KB

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