home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / acld-1.11.tar.gz / acld-1.11.tar / acld-1.11 / whitelist.c < prev    next >
C/C++ Source or Header  |  2011-09-27  |  8KB  |  346 lines

  1. /*
  2.  * Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static const char rcsid[] =
  24.     "@(#) $Id: whitelist.c 784 2011-09-28 02:05:06Z leres $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #include <sys/time.h>
  29.  
  30. #include <ctype.h>
  31. #include <errno.h>
  32. #include <signal.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <sysexits.h>
  37. #include <syslog.h>
  38. #include <time.h>
  39. #include <unistd.h>
  40.  
  41. #include "acld.h"
  42. #include "cf.h"
  43. #include "child.h"
  44. #include "util.h"
  45. #include "whitelist.h"
  46.  
  47. /* Forwards */
  48. static void whiteliststradd(struct cf *, const char *);
  49.  
  50. /* Returns addr if address or network is whitelisted else NULL */
  51. struct addr *
  52. whitelist(struct cf *cf, struct addr *addr)
  53. {
  54.     int i, w;
  55.     struct addr *a;
  56.  
  57.     if (cf->c_whitelist == NULL)
  58.         return (NULL);
  59.  
  60.     /* Return on any overlap */
  61.     w = maskwidth(addr);
  62.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a) {
  63.         if (a->family != addr->family)
  64.             continue;
  65.         if (w >= maskwidth(a)) {
  66.             /* Test addr is more specific than whitelist addr */
  67.             if (insubnet(a, addr))
  68.                 return (a);
  69.         } else {
  70.             /* Test addr is less specific than whitelist addr */
  71.             if (insubnet(addr, a))
  72.                 return (a);
  73.         }
  74.     }
  75.  
  76.     return (NULL);
  77. }
  78.  
  79. /* Does not check to see if the addr is already on the list */
  80. void
  81. whitelistadd(struct cf *cf, struct addr *addr)
  82. {
  83.     struct addr *a;
  84.  
  85.     DYNARRAY(cf->c_whitelist, cf->c_whitelistlen,
  86.         &cf->c_whitelistsize, sizeof(*cf->c_whitelist), 1024, 1024,
  87.         "whitelistadd");
  88.     a = cf->c_whitelist + cf->c_whitelistlen;
  89.     *a = *addr;
  90.     ++cf->c_whitelistlen;
  91. }
  92.  
  93. int
  94. whitelistdump(struct cf *cf, struct iobuf *ip)
  95. {
  96.     int i, cnt;
  97.     struct addr *a;
  98.  
  99.     cnt = 0;
  100.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a) {
  101.         ioappendfmt(ip, "%s", addr2str(a));
  102.         ++cnt;
  103.     }
  104.     return (cnt);
  105. }
  106.  
  107. void
  108. whitelistread(struct cf *cf)
  109. {
  110.     int n;
  111.     char *cp, *cp2;
  112.     const char *errstr;
  113.     FILE *f;
  114.     char buf[1024];
  115.  
  116.     if (cf->c_whitelistfn == NULL)
  117.         return;
  118.  
  119.     f = fopen(cf->c_whitelistfn, "r");
  120.     if (f == NULL) {
  121.         if (errno != ENOENT) {
  122.             lg(LOG_ERR, "whitelistread: fopen %s: %s",
  123.                 cf->c_whitelistfn, strerror(errno));
  124.             exit(1);
  125.         }
  126.         lg(LOG_INFO,
  127.             "whitelistread: %s missing; creating empty whitelist file",
  128.             cf->c_whitelistfn);
  129.         errstr = whitelistupdate(cf);
  130.         if (errstr != NULL) {
  131.             lg(LOG_ERR, "whitelistread: whitelistupdate: %s",
  132.                 errstr);
  133.             exit(1);
  134.         }
  135.         return;
  136.     }
  137.  
  138.     n = 0;
  139.     while (fgets(buf, sizeof(buf), f) != NULL) {
  140.         ++n;
  141.  
  142.         /* Eat comments */
  143.         cp = strchr(buf, '#');
  144.         if (cp)
  145.             *cp = '\0';
  146.  
  147.         /* Eat trailing whitesapce */
  148.         cp = buf + strlen(buf) - 1;
  149.         while (cp >= buf && isspace((int)*cp))
  150.             *cp-- = '\0';
  151.         cp = buf;
  152.  
  153.         /* Skip blank lines */
  154.         if (*cp == '\n' || *cp == '\0')
  155.             continue;
  156.  
  157.         /* Get address/network */
  158.         cp2 = cp;
  159.         while (!isspace((int)*cp) && *cp != '\0')
  160.             ++cp;
  161.         *cp++ = '\0';
  162.  
  163.         whiteliststradd(cf, cp2);
  164.     }
  165.     (void)fclose(f);
  166. }
  167.  
  168. int
  169. whitelistrem(struct cf *cf, struct addr *addr)
  170. {
  171.     int i, j;
  172.     struct addr *a;
  173.  
  174.     if (cf->c_whitelist == NULL)
  175.         return (0);
  176.  
  177.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a)
  178.         if (ADDREQ(a, addr)) {
  179.             j = cf->c_whitelistlen - (i + 1);
  180.             if (j > 0)
  181.                 memmove(cf->c_whitelist + i,
  182.                     cf->c_whitelist + i + 1,
  183.                     j * sizeof(cf->c_whitelist[0]));
  184.             --cf->c_whitelistlen;
  185.             ADDRZERO(&cf->c_whitelist[cf->c_whitelistlen]);
  186.             return (1);
  187.         }
  188.  
  189.     a = cf->c_whitelist + cf->c_whitelistlen;
  190.     *a = *addr;
  191.     ++cf->c_whitelistlen;
  192.  
  193.     return (0);
  194. }
  195.  
  196. /* Look for the exact address in the whitelist */
  197. struct addr *
  198. whitelistsearch(struct cf *cf, struct addr *addr)
  199. {
  200.     int i;
  201.     struct addr *a;
  202.  
  203.     if (cf->c_whitelist == NULL)
  204.         return (NULL);
  205.  
  206.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a)
  207.         if (ADDREQ(a, addr))
  208.             return (a);
  209.  
  210.     return (NULL);
  211. }
  212.  
  213. static void
  214. whiteliststradd(struct cf *cf, const char *str)
  215. {
  216.     const char *p;
  217.     struct addr *a;
  218.     struct addr addr;
  219.  
  220.     /* Eat leading dot; done if there was only one */
  221.     if (*str == '.') {
  222.         ++str;
  223.         if (*str == '\n'|| *str == '\0') {
  224.             lg(LOG_ERR, "whiteliststradd: junk \"%.80s\"", str);
  225.             return;
  226.         }
  227.     }
  228.  
  229.     /* Eat comments */
  230.     if (*str == '#')
  231.         return;
  232.  
  233.     a = &addr;
  234.     memset(a, 0, sizeof(*a));
  235.  
  236.     p = extractaddr(str, NULL, a);
  237.     if (p != NULL) {
  238.         lg(LOG_ERR, "whiteliststradd: extractaddr dst %.80s: %s",
  239.             str, p);
  240.         exit(EX_SOFTWARE);
  241.     }
  242.  
  243.     if (whitelistsearch(cf, a)) {
  244.         lg(LOG_ERR, "whiteliststradd: duplicate %.80s", str);
  245.         return;
  246.     }
  247.     whitelistadd(cf, a);
  248. }
  249.  
  250. const char *
  251. whitelistupdate(struct cf *cf)
  252. {
  253.     int i;
  254.     FILE *f;
  255.     time_t now;
  256.     struct addr *a;
  257.     struct tm *tm;
  258.     char date[64];
  259.     char zone[32];
  260.     char temp[256];
  261.     static char errstr[256];
  262. #ifdef HAVE_ALTZONE
  263.     int z;
  264. #endif
  265.     if (cf->c_whitelistfn == NULL)
  266.         return ("whitelistupdate: whitelist file not configured");
  267.  
  268.     (void)snprintf(temp, sizeof(temp), "%.*s-",
  269.         (int)sizeof(temp) - 2, cf->c_whitelistfn);
  270.     f = fopen(temp, "w");
  271.     if (f == NULL) {
  272.         (void)snprintf(errstr, sizeof(errstr),
  273.             "whitelistwrite: fopen %s: %s", temp, strerror(errno));
  274.         lg(LOG_ERR, "%s", errstr);
  275.         return (errstr);
  276.     }
  277.     fprintf(f, "# WARNING: dynamically updated; do not edit\n");
  278.     now = time(NULL);
  279.     tm = localtime(&now);
  280.     (void)strftime(date, sizeof(date), "%d-%b-%Y %T", tm);
  281. #ifndef HAVE_ALTZONE
  282.     (void)strftime(zone, sizeof(zone), "%z", tm);
  283. #else
  284.     z = altzone / -36;
  285.     if (z < 0) {
  286.         z = -z;
  287.         zone[0] = '-';
  288.     } else
  289.         zone[0] = '+';
  290.     (void)sprintf(zone + 1, "%04d", z);
  291. #endif
  292.     fprintf(f, "# Last update: %s %s\n", date, zone);
  293.  
  294.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a)
  295.         fprintf(f, "%s\n", addr2str(a));
  296.  
  297.     if (fclose(f) != 0) {
  298.         (void)snprintf(errstr, sizeof(errstr),
  299.             "whitelistwrite: fclose %s: %s", temp, strerror(errno));
  300.         lg(LOG_ERR, "%s", errstr);
  301.         return (errstr);
  302.     }
  303.     if (rename(temp, cf->c_whitelistfn) < 0) {
  304.         (void)snprintf(errstr, sizeof(errstr),
  305.             "whitelistwrite: rename %s -> %s: %s",
  306.             temp, cf->c_whitelistfn, strerror(errno));
  307.         lg(LOG_ERR, "%s", errstr);
  308.         return (errstr);
  309.     }
  310.     return (NULL);
  311. }
  312.  
  313. /* Returns number of matching whitelist entries reported */
  314. int
  315. whitelistquery(struct cf *cf, struct addr *addr, struct iobuf *ip)
  316. {
  317.     int i, cnt, w;
  318.     struct addr *a;
  319.  
  320.     if (cf->c_whitelist == NULL)
  321.         return (0);
  322.  
  323.     /* Report on any overlap */
  324.     w = maskwidth(addr);
  325.     cnt = 0;
  326.     for (i = 0, a = cf->c_whitelist; i < cf->c_whitelistlen; ++i, ++a) {
  327.         if (a->family != addr->family)
  328.             continue;
  329.         if (w >= maskwidth(a)) {
  330.             /* Test addr is more specific than whitelist addr */
  331.             if (insubnet(a, addr)) {
  332.                 ioappendfmt(ip, "%s", addr2str(a));
  333.                 ++cnt;
  334.             }
  335.         } else {
  336.             /* Test addr is less specific than whitelist addr */
  337.             if (insubnet(addr, a)) {
  338.                 ioappendfmt(ip, "%s", addr2str(a));
  339.                 ++cnt;
  340.             }
  341.         }
  342.     }
  343.  
  344.     return (cnt);
  345. }
  346.