acl.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /****************************************************************************
  2. *
  3. * acl.c - a small library for nrpe.c. It adds IPv4 subnets support to ACL in nrpe.
  4. *
  5. * License: GPLv2
  6. * Copyright (c) 2011 Kaspersky Lab ZAO
  7. *
  8. * Description:
  9. *
  10. * acl.c creates two linked lists. One is for IPv4 hosts and networks, another
  11. * is for domain names. All connecting hosts (if allowed_hosts is defined)
  12. * are checked in these two lists.
  13. *
  14. * Note:
  15. * Only ANCII names are supported in ACL.
  16. *
  17. * License Notice:
  18. *
  19. * This program is free software; you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation; either version 2 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program; if not, write to the Free Software
  31. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  32. *
  33. ****************************************************************************/
  34. #ifdef HAVE_CONFIG_H
  35. # include "config.h"
  36. #endif
  37. #include "common.h"
  38. #include "utils.h"
  39. #include "acl.h"
  40. #include <sys/types.h>
  41. #include <sys/socket.h>
  42. #include <netinet/in.h>
  43. #include <arpa/inet.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <ctype.h>
  48. #include <netdb.h>
  49. #include <stdarg.h>
  50. /* Pointers to head ACL structs */
  51. static struct ip_acl *ip_acl_head, *ip_acl_prev;
  52. static struct dns_acl *dns_acl_head, *dns_acl_prev;
  53. extern int debug;
  54. /* This function checks if a char argument from valid char range.
  55. * Valid range is: ASCII only, a number or a letter, a space, a dot, a slash, a dash, a comma.
  56. *
  57. * Returns:
  58. * 0 - char isn't from valid group
  59. * 1 - char is a number
  60. * 2 - char is a letter
  61. * 3 - char is a space(' ')
  62. * 4 - char is a dot('.')
  63. * 5 - char is a slash('/')
  64. * 6 - char is a dash('-')
  65. * 7 - char is a comma(',')
  66. */
  67. int isvalidchar(int c) {
  68. if (!isascii(c))
  69. return 0;
  70. if (isdigit(c))
  71. return 1;
  72. if (isalpha(c))
  73. return 2;
  74. if (isspace(c))
  75. return 3;
  76. switch (c) {
  77. case '.':
  78. return 4;
  79. case '/':
  80. return 5;
  81. case '-':
  82. return 6;
  83. case ',':
  84. return 7;
  85. default:
  86. return 0;
  87. }
  88. }
  89. /*
  90. * Add IPv4 host or network to IP ACL. IPv4 format is X.X.X.X[/X].
  91. * Host will be added to ACL only if it has passed IPv4 format check.
  92. *
  93. * Returns:
  94. * 1 - on success
  95. * 0 - on failure
  96. *
  97. * States for IPv4 format check:
  98. * 0 - numbers(-> 1), dot(-> -1), slash(-> -1), other(-> -1)
  99. * 1 - numbers(-> 1), dot(-> 2), slash(-> -1), other(-> -1)
  100. * 2 - numbers(-> 3), dot(-> -1), slash(-> -1), other(-> -1)
  101. * 3 - numbers(-> 3), dot(-> 4), slash(-> -1), other(-> -1)
  102. * 4 - numbers(-> 5), dot(-> -1), slash(-> -1), other(-> -1)
  103. * 5 - numbers(-> 5), dot(-> 6), slash(-> -1), other(-> -1)
  104. * 6 - numbers(-> 7), dot(-> -1), slash(-> -1), other(-> -1)
  105. * 7 - numbers(-> 7), dor(-> -1), slash(-> 8), other(-> -1)
  106. * 8 - numbers(-> 9), dor(-> -1), slash(-> -1), other(-> -1)
  107. * 9 - numbers(-> 9), dot(-> -1), slash(-> -1), other(-> -1)
  108. *
  109. * Good states are 7(IPv4 host) and 9(IPv4 network)
  110. */
  111. int add_ipv4_to_acl(char *ipv4) {
  112. int state = 0;
  113. int octet = 0;
  114. int index = 0; /* position in data array */
  115. int data[5]; /* array to store ip octets and mask */
  116. int len = strlen(ipv4);
  117. int i, c;
  118. unsigned long ip, mask;
  119. struct ip_acl *ip_acl_curr;
  120. if(debug == TRUE)
  121. logit(LOG_INFO, "add_ipv4_to_acl: checking ip-address >%s<", ipv4);
  122. /* Check for min and max IPv4 valid length */
  123. if (len < 7 || len > 18) {
  124. logit(LOG_INFO, "add_ipv4_to_acl: Error, ip-address >%s< incorrect length", ipv4);
  125. return 0;
  126. }
  127. /* default mask for ipv4 */
  128. data[4] = 32;
  129. /* Basic IPv4 format check */
  130. for (i = 0; i < len; i++) {
  131. /* Return 0 on error state */
  132. if (state == -1) {
  133. if(debug == TRUE)
  134. logit(LOG_INFO, "add_ipv4_to_acl: Error, ip-address >%s< incorrect "
  135. "format, continue with next check ...", ipv4);
  136. return 0;
  137. }
  138. c = ipv4[i];
  139. switch (c) {
  140. case '0': case '1': case '2': case '3': case '4':
  141. case '5': case '6': case '7': case '8': case '9':
  142. octet = octet * 10 + CHAR_TO_NUMBER(c);
  143. switch (state) {
  144. case 0: case 2: case 4: case 6: case 8:
  145. state++;
  146. break;
  147. }
  148. break;
  149. case '.':
  150. switch (state) {
  151. case 1: case 3: case 5:
  152. data[index++] = octet;
  153. octet = 0;
  154. state++;
  155. break;
  156. default:
  157. state = -1;
  158. }
  159. break;
  160. case '/':
  161. switch (state) {
  162. case 7:
  163. data[index++] = octet;
  164. octet = 0;
  165. state++;
  166. break;
  167. default:
  168. state = -1;
  169. }
  170. break;
  171. default:
  172. state = -1;
  173. }
  174. }
  175. /* Exit state handling */
  176. switch (state) {
  177. case 7: case 9:
  178. data[index] = octet;
  179. break;
  180. default:
  181. /* Bad states */
  182. logit(LOG_INFO, "add_ipv4_to_acl: Error, ip-address >%s< bad state", ipv4);
  183. return 0;
  184. }
  185. /*
  186. * Final IPv4 format check.
  187. */
  188. for (i=0; i < 4; i++) {
  189. if (data[i] < 0 || data[i] > 255) {
  190. logit(LOG_ERR,"Invalid IPv4 address/network format(%s) in allowed_hosts option\n",ipv4);
  191. return 0;
  192. }
  193. }
  194. if (data[4] < 0 || data[4] > 32) {
  195. logit(LOG_ERR,"Invalid IPv4 network mask format(%s) in allowed_hosts option\n",ipv4);
  196. return 0;
  197. }
  198. /* Convert ip and mask to unsigned long */
  199. ip = htonl((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]);
  200. mask = htonl(~0u << (32 - data[4]));
  201. /* Wrong network address */
  202. if ( (ip & mask) != ip) {
  203. logit(LOG_ERR,"IP address and mask do not match in %s\n",ipv4);
  204. return 0;
  205. }
  206. /* Add addr to ip_acl list */
  207. if ( (ip_acl_curr = malloc(sizeof(*ip_acl_curr))) == NULL) {
  208. logit(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
  209. return 0;
  210. }
  211. /* Save result in ACL ip list */
  212. ip_acl_curr->family = AF_INET;
  213. ip_acl_curr->addr.s_addr = ip;
  214. ip_acl_curr->mask.s_addr = mask;
  215. ip_acl_curr->next = NULL;
  216. if (ip_acl_head == NULL) {
  217. ip_acl_head = ip_acl_curr;
  218. } else {
  219. ip_acl_prev->next = ip_acl_curr;
  220. }
  221. ip_acl_prev = ip_acl_curr;
  222. if(debug == TRUE)
  223. logit(LOG_INFO, "add_ipv4_to_acl: ip-address >%s< correct, adding.", ipv4);
  224. return 1;
  225. }
  226. /*
  227. * Add IPv6 host or network to IP ACL. Host will be added to ACL only if
  228. * it has passed IPv6 format check.
  229. *
  230. */
  231. int add_ipv6_to_acl(char *ipv6) {
  232. char *ipv6tmp;
  233. char *addr_part, *mask_part;
  234. struct in6_addr addr;
  235. struct in6_addr mask;
  236. int maskval;
  237. int byte, bit;
  238. int nbytes = sizeof(mask.s6_addr) / sizeof(mask.s6_addr[0]);
  239. int x;
  240. struct ip_acl *ip_acl_curr;
  241. /* Save temporary copy of ipv6 so we can use the original in error
  242. messages if needed */
  243. ipv6tmp = strdup(ipv6);
  244. if(NULL == ipv6tmp) {
  245. logit(LOG_ERR, "Memory allocation failed for copy of address: %s\n",
  246. ipv6);
  247. return 0;
  248. }
  249. addr_part = ipv6tmp;
  250. mask_part = strchr(ipv6tmp, '/');
  251. if (mask_part) {
  252. *mask_part = '\0';
  253. ++mask_part;
  254. }
  255. /* Parse the address itself */
  256. if(inet_pton(AF_INET6, addr_part, &addr) <= 0) {
  257. free(ipv6tmp);
  258. return 0;
  259. }
  260. /* Check whether there is a netmask */
  261. if (mask_part && *mask_part) {
  262. /* If so, build a netmask */
  263. /* Get the number of bits in the mask */
  264. maskval = atoi(mask_part);
  265. if(maskval < 0 || maskval > 128) {
  266. free(ipv6tmp);
  267. return 0;
  268. }
  269. /* Initialize to zero */
  270. for(x = 0; x < nbytes; x++) {
  271. mask.s6_addr[x] = 0;
  272. }
  273. /* Set mask based on mask bits */
  274. byte = 0;
  275. bit = 7;
  276. while(maskval > 0) {
  277. mask.s6_addr[byte] |= 1 << bit;
  278. bit -= 1;
  279. if(bit < 0) {
  280. bit = 7;
  281. byte++;
  282. }
  283. maskval--;
  284. }
  285. }
  286. else {
  287. /* Otherwise, this is a single address */
  288. for(x = 0; x < nbytes; x++) {
  289. mask.s6_addr[x] = 0xFF;
  290. }
  291. }
  292. /* Add address to ip_acl list */
  293. ip_acl_curr = malloc(sizeof(*ip_acl_curr));
  294. if(NULL == ip_acl_curr) {
  295. logit(LOG_ERR, "Memory allocation failed for ACL: %s\n", ipv6);
  296. return 0;
  297. }
  298. /* Save result in ACL ip list */
  299. ip_acl_curr->family = AF_INET6;
  300. for(x = 0; x < nbytes; x++) {
  301. ip_acl_curr->addr6.s6_addr[x] =
  302. addr.s6_addr[x] & mask.s6_addr[x];
  303. ip_acl_curr->mask6.s6_addr[x] = mask.s6_addr[x];
  304. }
  305. ip_acl_curr->next = NULL;
  306. if(NULL == ip_acl_head) {
  307. ip_acl_head = ip_acl_curr;
  308. }
  309. else {
  310. ip_acl_prev->next = ip_acl_curr;
  311. }
  312. ip_acl_prev = ip_acl_curr;
  313. free(ipv6tmp);
  314. return 1;
  315. }
  316. /*
  317. * Add domain to DNS ACL list
  318. * Domain will be added only if it has passed domain name check.
  319. *
  320. * In this case domain valid format is:
  321. * 1) Domain names must use only alphanumeric characters and dashes (-).
  322. * 2) Domain names mustn't begin or end with dashes (-).
  323. * 3) Domain names mustn't have more than 63 characters.
  324. *
  325. * Return:
  326. * 1 - for success
  327. * 0 - for failure
  328. *
  329. * 0 - alpha(-> 1), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
  330. * 1 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
  331. * 2 - alpha(-> 3), number(-> 1), dot(-> -1), dash(-> -1), all other(-> -1)
  332. * 3 - alpha(-> 4), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
  333. * 4 - alpha(-> 5), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
  334. * 5 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
  335. * 6 - alpha(-> 1), number(-> 1), dot(-> 2), dash(-> 6), all other(-> -1)
  336. * For real FQDN only 4 and 5 states are good for exit.
  337. * I don't check if top domain exists (com, ru and etc.)
  338. * But in real life NRPE could work in LAN,
  339. * with local domain zones like .local or with names like 'mars' added to /etc/hosts.
  340. * So 1 is good state too. And maybe this check is not necessary at all...
  341. */
  342. int add_domain_to_acl(char *domain) {
  343. int state = 0;
  344. int len = strlen(domain);
  345. int i, c;
  346. struct dns_acl *dns_acl_curr;
  347. if (len > 63) {
  348. logit(LOG_INFO,
  349. "ADD_DOMAIN_TO_ACL: Error, did not add >%s< to acl list, too long!",
  350. domain);
  351. return 0;
  352. }
  353. for (i = 0; i < len; i++) {
  354. c = domain[i];
  355. switch (isvalidchar(c)) {
  356. case 1:
  357. state = 1;
  358. break;
  359. case 2:
  360. switch (state) {
  361. case 0: case 1: case 5: case 6:
  362. state = 1;
  363. break;
  364. case 2: case 3: case 4:
  365. state++;
  366. break;
  367. }
  368. break;
  369. case 4:
  370. switch (state) {
  371. case 0: case 2:
  372. state = -1;
  373. break;
  374. default:
  375. state = 2;
  376. }
  377. break;
  378. case 6:
  379. switch (state) {
  380. case 0: case 2:
  381. state = -1;
  382. break;
  383. default:
  384. state = 6;
  385. }
  386. break;
  387. default:
  388. logit(LOG_INFO,
  389. "ADD_DOMAIN_TO_ACL: Error, did not add >%s< to acl list, "
  390. "invalid chars!", domain);
  391. /* Not valid chars */
  392. return 0;
  393. }
  394. }
  395. /* Check exit code */
  396. switch (state) {
  397. case 1: case 4: case 5:
  398. /* Add name to domain ACL list */
  399. if ( (dns_acl_curr = malloc(sizeof(*dns_acl_curr))) == NULL) {
  400. logit(LOG_ERR,"Can't allocate memory for ACL, malloc error\n");
  401. return 0;
  402. }
  403. strncpy(dns_acl_curr->domain, domain, sizeof(dns_acl_curr->domain));
  404. dns_acl_curr->domain[sizeof(dns_acl_curr->domain) - 1] = '\0';
  405. dns_acl_curr->next = NULL;
  406. if (dns_acl_head == NULL)
  407. dns_acl_head = dns_acl_curr;
  408. else
  409. dns_acl_prev->next = dns_acl_curr;
  410. dns_acl_prev = dns_acl_curr;
  411. if(debug == TRUE)
  412. logit(LOG_INFO, "ADD_DOMAIN_TO_ACL: added >%s< to acl list!", domain);
  413. return 1;
  414. default:
  415. logit(LOG_INFO,
  416. "ADD_DOMAIN_TO_ACL: ERROR, did not add >%s< to acl list, "
  417. "check allowed_host in config file!", domain);
  418. return 0;
  419. }
  420. }
  421. /* Checks connection host in ACL
  422. *
  423. * Returns:
  424. * 1 - on success
  425. * 0 - on failure
  426. */
  427. int is_an_allowed_host(int family, void *host)
  428. {
  429. struct ip_acl *ip_acl_curr;
  430. int nbytes;
  431. int x;
  432. struct dns_acl *dns_acl_curr = dns_acl_head;
  433. struct sockaddr_in *addr;
  434. struct sockaddr_in6 addr6;
  435. struct addrinfo *res, *ai;
  436. struct in_addr tmp;
  437. for (ip_acl_curr = ip_acl_head; ip_acl_curr != NULL; ip_acl_curr = ip_acl_curr->next) {
  438. if (ip_acl_curr->family != family)
  439. continue;
  440. switch (ip_acl_curr->family) {
  441. case AF_INET:
  442. if (debug == TRUE) {
  443. char host_addr[INET_ADDRSTRLEN];
  444. char acl_addr[INET_ADDRSTRLEN];
  445. logit(LOG_INFO, "is_an_allowed_host (AF_INET): is host >%s< an allowed host >%s<\n",
  446. inet_ntop(AF_INET, host, host_addr, INET_ADDRSTRLEN),
  447. inet_ntop(AF_INET, &ip_acl_curr->addr, acl_addr, INET_ADDRSTRLEN));
  448. }
  449. if ((((struct in_addr *)host)->s_addr &
  450. ip_acl_curr->mask.s_addr) ==
  451. ip_acl_curr->addr.s_addr) {
  452. if (debug == TRUE)
  453. logit(LOG_INFO, "is_an_allowed_host (AF_INET): host is in allowed host list!");
  454. return 1;
  455. }
  456. break;
  457. case AF_INET6:
  458. nbytes = sizeof(ip_acl_curr->mask6.s6_addr) /
  459. sizeof(ip_acl_curr->mask6.s6_addr[0]);
  460. for (x = 0; x < nbytes; x++) {
  461. if ((((struct in6_addr *)host)->s6_addr[x] &
  462. ip_acl_curr->mask6.s6_addr[x]) !=
  463. ip_acl_curr->addr6.s6_addr[x]) {
  464. break;
  465. }
  466. }
  467. if (x == nbytes) {
  468. /* All bytes in host's address pass the netmask mask */
  469. return 1;
  470. }
  471. break;
  472. }
  473. }
  474. while(dns_acl_curr != NULL) {
  475. if (!getaddrinfo(dns_acl_curr->domain, NULL, NULL, &res)) {
  476. for (ai = res; ai; ai = ai->ai_next) {
  477. if (ai->ai_family == family) {
  478. switch (ai->ai_family) {
  479. case AF_INET:
  480. if (debug == TRUE) {
  481. tmp.s_addr = ((struct in_addr *) host)->s_addr;
  482. logit(LOG_INFO, "is_an_allowed_host (AF_INET): test match host >%s< "
  483. "for allowed host >%s<\n",
  484. inet_ntoa(tmp), dns_acl_curr->domain);
  485. }
  486. addr = (struct sockaddr_in *) (ai->ai_addr);
  487. if (addr->sin_addr.s_addr == ((struct in_addr *) host)->s_addr) {
  488. if (debug == TRUE)
  489. logit(LOG_INFO, "is_an_allowed_host (AF_INET): "
  490. "host is in allowed host list!");
  491. return 1;
  492. }
  493. break;
  494. case AF_INET6:
  495. if (debug == TRUE) {
  496. char formattedStr[INET6_ADDRSTRLEN];
  497. inet_ntop(ai->ai_family, (void *) &(((struct sockaddr_in6 *) (ai->ai_addr))->sin6_addr),
  498. formattedStr, INET6_ADDRSTRLEN);
  499. logit(LOG_INFO, "is_an_allowed_host (AF_INET6): test match host against >%s< "
  500. "for allowed host >%s<\n",
  501. formattedStr, dns_acl_curr->domain);
  502. }
  503. memcpy((char *) &addr6, ai->ai_addr, sizeof(addr6));
  504. if (!memcmp(&addr6.sin6_addr, host, sizeof(addr6.sin6_addr))) {
  505. if (debug == TRUE)
  506. logit(LOG_INFO, "is_an_allowed_host (AF_INET6): "
  507. "host is in allowed host list!");
  508. return 1;
  509. }
  510. break;
  511. }
  512. }
  513. }
  514. }
  515. dns_acl_curr = dns_acl_curr->next;
  516. }
  517. return 0;
  518. }
  519. /* The trim() function takes a source string and copies it to the destination string,
  520. * stripped of leading and training whitespace. The destination string must be
  521. * allocated at least as large as the source string.
  522. */
  523. void trim( char *src, char *dest) {
  524. char *sptr, *dptr;
  525. for( sptr = src; isspace( *sptr) && *sptr; sptr++); /* Jump past leading spaces */
  526. for( dptr = dest; !isspace( *sptr) && *sptr; ) {
  527. *dptr = *sptr;
  528. sptr++;
  529. dptr++;
  530. }
  531. *dptr = '\0';
  532. return;
  533. }
  534. /*
  535. * Free all existing ACLs
  536. */
  537. static void clear_allowed_hosts(void) {
  538. int count;
  539. count = 0;
  540. while (ip_acl_head) {
  541. struct ip_acl *next = ip_acl_head->next;
  542. free(ip_acl_head);
  543. ip_acl_head = next;
  544. count++;
  545. }
  546. ip_acl_prev = NULL;
  547. if (debug == TRUE)
  548. logit(LOG_INFO, "clear_allowed_hosts: Cleared %i IP ACLs\n", count);
  549. count = 0;
  550. while (dns_acl_head) {
  551. struct dns_acl *next = dns_acl_head->next;
  552. free(dns_acl_head);
  553. dns_acl_head = next;
  554. count++;
  555. }
  556. dns_acl_prev = NULL;
  557. if (debug == TRUE)
  558. logit(LOG_INFO, "clear_allowed_hosts: Cleared %i DNS ACLs\n", count);
  559. }
  560. /* This function splits allowed_hosts to substrings with comma(,) as a delimiter.
  561. * It doesn't check validness of ACL record (add_ipv4_to_acl() and add_domain_to_acl() do),
  562. * just trims spaces from ACL records.
  563. * After this it sends ACL records to add_ipv4_to_acl() or add_domain_to_acl().
  564. */
  565. void parse_allowed_hosts(char *allowed_hosts) {
  566. char *hosts = strdup( allowed_hosts); /* Copy since strtok* modifies original */
  567. char *saveptr;
  568. char *tok;
  569. const char *delim = ",";
  570. char *trimmed_tok;
  571. int add_to_acl = 0;
  572. clear_allowed_hosts();
  573. if (debug == TRUE)
  574. logit(LOG_INFO,
  575. "parse_allowed_hosts: parsing the allowed host string >%s< to add to ACL list\n",
  576. allowed_hosts);
  577. #ifdef HAVE_STRTOK_R
  578. tok = strtok_r(hosts, delim, &saveptr);
  579. #else
  580. if (debug == TRUE)
  581. logit(LOG_INFO,"parse_allowed_hosts: using strtok, this might lead to "
  582. "problems in the allowed_hosts string determination!\n");
  583. tok = strtok(hosts, delim);
  584. #endif
  585. while( tok) {
  586. trimmed_tok = malloc(sizeof(char) * (strlen(tok) + 1));
  587. trim(tok, trimmed_tok);
  588. if (debug == TRUE)
  589. logit(LOG_DEBUG, "parse_allowed_hosts: ADDING this record (%s) to ACL list!\n", trimmed_tok);
  590. if (strlen(trimmed_tok) > 0) {
  591. /* lets check the type of the address before we try and add it to the acl */
  592. if (strchr(trimmed_tok, ':') != NULL) {
  593. /* its an ipv6 address */
  594. add_to_acl = add_ipv6_to_acl(trimmed_tok);
  595. } else {
  596. /* its either a fqdn or an ipv4 address
  597. unfortunately, i don't want to re-invent the wheel here
  598. the logic exists inside of add_ipv4_to_acl() to detect
  599. whether or not it is a ip or not */
  600. add_to_acl = add_ipv4_to_acl(trimmed_tok);
  601. }
  602. /* but we only try to add it to a domain if the other tests have failed */
  603. if (!add_to_acl && !add_domain_to_acl(trimmed_tok)) {
  604. logit(LOG_ERR,"Can't add to ACL this record (%s). Check allowed_hosts option!\n",trimmed_tok);
  605. } else if (debug == TRUE)
  606. logit(LOG_DEBUG,"parse_allowed_hosts: Record added to ACL list!\n");
  607. }
  608. free( trimmed_tok);
  609. #ifdef HAVE_STRTOK_R
  610. tok = strtok_r(NULL, delim, &saveptr);
  611. #else
  612. tok = strtok(NULL, delim);
  613. #endif
  614. }
  615. free( hosts);
  616. }
  617. /*
  618. * Converts mask in unsigned long format to two digit prefix
  619. */
  620. unsigned int prefix_from_mask(int family, const void* mask) {
  621. int prefix = 0;
  622. int bytes = 4;
  623. int i;
  624. const unsigned char *ptr = mask;
  625. if (family == AF_INET6)
  626. bytes = 16;
  627. for (i = 0; i < bytes; i++) {
  628. int j;
  629. for (j = 0; j < 8; j++) {
  630. unsigned char bit = 1 << j;
  631. if (ptr[i] & bit)
  632. prefix++;
  633. }
  634. }
  635. return (prefix);
  636. }
  637. /*
  638. * It shows all hosts in ACL lists
  639. */
  640. void show_acl_lists(void)
  641. {
  642. struct ip_acl *ip_acl_curr = ip_acl_head;
  643. struct dns_acl *dns_acl_curr = dns_acl_head;
  644. logit(LOG_INFO, "Showing ACL lists for both IP and DOMAIN acl's:\n" );
  645. while (ip_acl_curr != NULL) {
  646. if (ip_acl_curr->family == AF_INET) {
  647. logit(LOG_INFO, " IP ACL: %s/%u %u\n", inet_ntoa(ip_acl_curr->addr),
  648. prefix_from_mask(AF_INET, &ip_acl_curr->mask), ip_acl_curr->addr.s_addr);
  649. } else if (ip_acl_curr->family == AF_INET6) {
  650. char formattedStr[INET6_ADDRSTRLEN];
  651. logit(LOG_INFO, " IP ACL: %s/%u\n",
  652. inet_ntop(AF_INET6, &ip_acl_curr->addr6, formattedStr, INET6_ADDRSTRLEN),
  653. prefix_from_mask(AF_INET6, &ip_acl_curr->mask6));
  654. }
  655. ip_acl_curr = ip_acl_curr->next;
  656. }
  657. while (dns_acl_curr != NULL) {
  658. logit(LOG_INFO, " DNS ACL: %s\n", dns_acl_curr->domain);
  659. dns_acl_curr = dns_acl_curr->next;
  660. }
  661. }