acl.c 21 KB

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