diff misc/wlist.c @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/wlist.c	Tue Mar 10 13:49:58 2009 +0100
@@ -0,0 +1,405 @@
+/* Distributed Checksum Clearinghouse
+ *
+ * whitelist lister
+ *
+ * Copyright (c) 2008 by Rhyolite Software, LLC
+ *
+ * This agreement is not applicable to any entity which sells anti-spam
+ * solutions to others or provides an anti-spam solution as part of a
+ * security solution sold to other entities, or to a private network
+ * which employs the DCC or uses data provided by operation of the DCC
+ * but does not provide corresponding data to other users.
+ *
+ * Permission to use, copy, modify, and distribute this software without
+ * changes for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear in all
+ * copies and any distributed versions or copies are either unchanged
+ * or not called anything similar to "DCC" or "Distributed Checksum
+ * Clearinghouse".
+ *
+ * Parties not eligible to receive a license under this agreement can
+ * obtain a commercial license to use DCC by contacting Rhyolite Software
+ * at sales@rhyolite.com.
+ *
+ * A commercial license would be for Distributed Checksum and Reputation
+ * Clearinghouse software.  That software includes additional features.  This
+ * free license for Distributed ChecksumClearinghouse Software does not in any
+ * way grant permision to use Distributed Checksum and Reputation Clearinghouse
+ * software
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Rhyolite Software DCC 1.3.103-1.67 $Revision$
+ */
+
+#include "dcc_defs.h"
+#include "dcc_ck.h"
+#include <arpa/inet.h>
+
+static DCC_EMSG dcc_emsg;
+static const char *homedir;
+
+static u_char quiet;
+
+static const char *ts2buf(time_t);
+
+
+static void NRATTRIB
+usage(void)
+{
+	dcc_logbad(EX_USAGE, "usage: [-VPQ] [-h homedir] [-t env_to] file");
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+	const char *to = 0;
+	u_char print_version = 0;
+	u_char first;
+	DCC_WHITE_INX inx, inx2;
+	const char *nm;
+	DCC_SUM sum;
+	struct stat ht_sb, ascii_sb, inc_sb;
+	char tgts_buf[20];
+	int col;
+	u_char heading;
+	DCC_TGTS tgts;
+	DCC_WHITE_LISTING listing;
+	DCC_CK_TYPES type;
+	int i;
+
+	dcc_syslog_init(0, argv[0], 0);
+	dcc_clnt_debug = 99;
+
+	dup2(1, 2);			/* put error messages in context */
+
+	dcc_wf_init(&cmn_wf, DCC_WF_WLIST | DCC_WF_EITHER);
+
+	while ((i = getopt(argc, argv, "VPQqh:t:")) != EOF) {
+		switch (i) {
+		case 'V':
+			fprintf(stderr, DCC_VERSION"\n");
+			print_version = 1;
+			break;
+
+		case 'P':		/* parse or rebuild hash table */
+			cmn_wf.wf_flags &= ~DCC_WF_WLIST_RO;
+			cmn_wf.wf_flags |= DCC_WF_WLIST_RW;
+			break;
+
+		case 'Q':		/* query; don't rebuild hash table */
+			cmn_wf.wf_flags &= ~DCC_WF_WLIST_RW;
+			cmn_wf.wf_flags |= DCC_WF_WLIST_RO;
+			break;
+
+		case 'q':
+			quiet = 1;
+			break;
+
+		case 'h':
+			homedir = optarg;
+			break;
+
+		case 't':
+			to = optarg;
+			break;
+
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc == 0) {
+		if (print_version)
+			exit(EX_OK);
+		usage();
+	}
+
+	dcc_cdhome(0, homedir, 1);
+
+	first = 1;
+	while ((nm = *argv++) != 0) {
+		if (first) {
+			first = 0;
+		} else {
+			printf("\n\n--------------------------------\n");
+		}
+		if (cmn_wf.wf_flags & DCC_WF_WLIST_RO)
+			cmn_wf.wf_flags |= DCC_WF_RO;
+		else
+			cmn_wf.wf_flags &= ~DCC_WF_RO;
+		if (!dcc_new_white_nm(dcc_emsg, &cmn_wf, nm)) {
+			dcc_error_msg("%s", dcc_emsg);
+			exit(EX_DATAERR);
+		}
+		printf("%s\n", cmn_wf.ascii_nm);
+
+		switch (dcc_rdy_white(dcc_emsg, &cmn_wf, &cmn_tmp_wf)) {
+		case DCC_WHITE_OK:
+			break;
+		case DCC_WHITE_NOFILE:
+			dcc_error_msg("does %s exist?", nm);
+			exit(EX_DATAERR);
+		case DCC_WHITE_CONTINUE:
+			dcc_error_msg("%s", dcc_emsg);
+			break;
+		case DCC_WHITE_SILENT:
+		case DCC_WHITE_COMPLAIN:
+			dcc_error_msg("%s", dcc_emsg);
+			exit(EX_DATAERR);
+			break;
+		}
+		printf("%s\n", cmn_wf.wtbl->magic);
+
+		if (to) {
+			dcc_str2ck(sum, 0, 0, to);
+			printf("%s\n%8s %s\t",
+			       to,
+			       dcc_type2str_err(DCC_CK_ENV_TO, 0, 0, 0),
+			       dcc_ck2str_err(DCC_CK_ENV_TO, sum, 0));
+			if (DCC_WHITE_OK != dcc_white_sum(dcc_emsg, &cmn_wf,
+							DCC_CK_ENV_TO, sum,
+							&tgts, &listing)) {
+				dcc_error_msg("%s", dcc_emsg);
+			}
+			if (listing == DCC_WHITE_UNLISTED) {
+				printf("unlisted\n");
+			} else {
+				printf("%s\n",
+				       dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
+						    tgts, 0));
+			}
+			continue;
+		}
+
+		printf("  %s whitelist  %d entries\n",
+		       (cmn_wf.wtbl_flags & DCC_WHITE_FG_PER_USER)
+		       ? "per-user" : "global",
+		       cmn_wf.wtbl->hdr.entries);
+
+		if (0 > fstat(cmn_wf.ht_fd, &ht_sb)) {
+			dcc_error_msg("stat(%s): %s",
+				      cmn_wf.ht_nm, ERROR_STR());
+			exit(EX_DATAERR);
+		}
+
+		if (0 > stat(cmn_wf.ascii_nm, &ascii_sb)) {
+			dcc_error_msg("stat(%s): %s",
+				      cmn_wf.ascii_nm, ERROR_STR());
+		} else if (ht_sb.st_mtime < ascii_sb.st_mtime) {
+			printf("    %s is older than %s\n",
+			       cmn_wf.ht_nm, cmn_wf.ascii_nm);
+		}
+
+		if (cmn_wf.wtbl->hdr.ascii_mtime == 0) {
+			printf("    %s broken\n", cmn_wf.ht_nm);
+		} else if (cmn_wf.wtbl->hdr.ascii_mtime != ascii_sb.st_mtime) {
+			printf("    %s has timestamp %s\n"
+			       "\tfor %s which has mtime %s\n",
+			       cmn_wf.ht_nm,
+			       ts2buf(cmn_wf.wtbl->hdr.ascii_mtime),
+			       cmn_wf.ascii_nm,
+			       ts2buf(ascii_sb.st_mtime));
+		}
+
+		if (cmn_wf.wtbl->hdr.broken != 0)
+			printf("    %s broken until %s\n",
+			       cmn_wf.ht_nm,
+			       ts2buf(cmn_wf.wtbl->hdr.broken));
+		if (cmn_wf.wtbl->hdr.reparse != 0)
+			printf("    re-parse %s for errors after %s\n",
+			       cmn_wf.ascii_nm,
+			       ts2buf(cmn_wf.wtbl->hdr.reparse));
+
+		if (cmn_wf.wtbl->hdr.flags & DCC_WHITE_FG_HOSTNAMES) {
+			printf("    resolve hostnames after %s\n",
+			       ts2buf(ht_sb.st_mtime + DCC_WHITECLNT_RESOLVE));
+		} else if (!(cmn_wf.wtbl->hdr.flags & DCC_WHITE_FG_PER_USER)) {
+			printf("    contains no hostnames\n");
+		}
+
+		for (i = 0; i < DIM(cmn_wf.wtbl->hdr.white_incs); ++i) {
+			if (cmn_wf.wtbl->hdr.white_incs[i].nm[0] == '\0')
+				break;
+			if (!i)
+				printf("    includes\n");
+			printf("      %s\n",
+			       fnm2abs_err(0,
+					   cmn_wf.wtbl->hdr.white_incs[i].nm));
+			if (0 > stat(cmn_wf.wtbl->hdr.white_incs[i].nm,
+				     &inc_sb)) {
+				dcc_error_msg("stat(%s): %s",
+					      cmn_wf.ascii_nm, ERROR_STR());
+			} else if (ht_sb.st_mtime < inc_sb.st_mtime) {
+				printf("    %s is older than %s"
+				       " and needs rebuilding\n",
+				       cmn_wf.ht_nm,
+				       path2fnm(cmn_wf.wtbl->hdr.white_incs[i
+							].nm));
+			}
+		}
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DCC_ON)
+			printf("    option DCC-on\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DCC_OFF)
+			printf("    option DCC-off\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_REP_ON)
+			printf("    option dcc-rep-on\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_REP_OFF)
+			printf("    option dcc-rep-off\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_ON)
+			printf("    option greylist-on\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_OFF)
+			printf("    option greylist-off\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_ALL)
+			printf("    option log-all\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_NORMAL)
+			printf("    option log-normal\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_D)
+			printf("    option log-subdirectory-day\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_H)
+			printf("    option log-subdirectory-hour\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_M)
+			printf("    option log-subdirectory-minute\n");
+
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_LOG_ON)
+			printf("    option greylist-log-on\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_LOG_OFF)
+			printf("    option greylist-log-off\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_MTA_FIRST)
+			printf("    option MTA-first\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_MTA_LAST)
+			printf("    option MTA-last\n");
+
+		for (i = 0; i < MAX_DNSBL_GROUPS; ++i) {
+			if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DNSBL_ON(i))
+				printf("    option DNSBL%d-on\n", i+1);
+			if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DNSBL_OFF(i))
+				printf("    option DNSBL%d-off\n", i+1);
+		}
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DISCARD_OK)
+			printf("    option forced-discard-ok\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_NO_DISCARD)
+			printf("    option no-forced-discard\n");
+
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_TRAP_ACC)
+			printf("    option spam-trap-accept\n");
+		if (cmn_wf.wtbl_flags & DCC_WHITE_FG_TRAP_REJ)
+			printf("    option spam-trap_rej\n");
+
+		for (type = DCC_CK_TYPE_FIRST;
+		     type <= DCC_CK_TYPE_LAST;
+		     ++type) {
+			tgts = cmn_wf.wtbl->hdr.tholds_rej[type];
+			if (tgts == DCC_THOLD_UNSET)
+				continue;
+			printf("    option threshold %s,%s\n",
+			       dcc_type2str_err(type, 0, 0, 0),
+			       dcc_thold2str(tgts_buf, sizeof(tgts_buf),
+					     type, tgts));
+		}
+
+		printf("\n    file checksum %s\n",
+		       dcc_ck2str_err(0, cmn_wf.wtbl->hdr.ck_sum, 0));
+
+		if (quiet)
+			continue;
+
+		heading = 0;
+		for (i = 0; i < cmn_wf.wtbl->hdr.cidr.len; ++i) {
+			struct in_addr addr4;
+			char cidr_buf[INET6_ADDRSTRLEN];
+
+			DCC_WHITE_CIDR_ENTRY *e=&cmn_wf.wtbl->hdr.cidr.e[i];
+			if (!heading) {
+				heading = 1;
+				fputs("\n CIDR blocks\n", stdout);
+			}
+			printf("%6s    %s/%d\n",
+			       dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
+					    e->tgts,0),
+			       dcc_ipv6tostr2(cidr_buf, sizeof(cidr_buf),
+					      &e->addr),
+			       dcc_ipv6toipv4(&addr4, &e->addr)
+			       ? e->bits-96 : e->bits);
+		}
+		if (heading)
+			putchar('\n');
+
+		/* first the hash table */
+		fputs("\n hash table\n", stdout);
+		col = 0;
+		for (inx = 0; inx < DIM(cmn_wf.wtbl->bins); ++inx) {
+			if (!cmn_wf.wtbl->bins[inx]
+			    && col == 0
+			    && inx != 0) {
+				inx2 = inx;
+				while (inx2 < DIM(cmn_wf.wtbl->bins)
+				       && !cmn_wf.wtbl->bins[inx2])
+					++inx2;
+				i = inx2 - inx;
+				i -= i % 4;
+				if (i != 0) {
+					printf(" ...\n");
+					inx += i;
+				}
+			}
+			printf("%4d:", inx);
+			if (cmn_wf.wtbl->bins[inx]) {
+				printf("%-4d", cmn_wf.wtbl->bins[inx]);
+			} else {
+				printf("    ");
+			}
+			col = (col + 1) % 4;
+			putchar(col == 0 ? '\n' : '\t');
+		}
+
+		/* then the entries */
+		printf("\n\n%4s->%-4s  %12s  %6s\n",
+		       "slot", "next", "type", "count");
+		for (inx = 0; inx < cmn_wf.wtbl_entries; ++inx) {
+			DCC_WHITE_ENTRY *e = &cmn_wf.wtbl->tbl[inx];
+			if (e->type == DCC_CK_INVALID)
+				continue;
+			printf("%4d->%-4d  %12s  %6s  %s\n",
+			       inx, e->fwd,
+			       dcc_type2str_err(e->type, 0, 0, 0),
+			       dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
+					    e->tgts, 0),
+			       dcc_ck2str_err(e->type, e->sum, 0));
+		}
+	}
+	exit(EX_OK);
+}
+
+
+
+static const char *
+ts2buf(time_t ts)
+{
+	static struct {
+		char buf[26];
+	} times[4];
+	static int nbuf;
+
+	nbuf = (nbuf+1) % DIM(times);
+	return dcc_time2str(times[nbuf].buf, sizeof(times[nbuf].buf),
+			    "%b %d %X %Z",
+			    ts);
+}