comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:c7f6b056b673
1 /* Distributed Checksum Clearinghouse
2 *
3 * whitelist lister
4 *
5 * Copyright (c) 2008 by Rhyolite Software, LLC
6 *
7 * This agreement is not applicable to any entity which sells anti-spam
8 * solutions to others or provides an anti-spam solution as part of a
9 * security solution sold to other entities, or to a private network
10 * which employs the DCC or uses data provided by operation of the DCC
11 * but does not provide corresponding data to other users.
12 *
13 * Permission to use, copy, modify, and distribute this software without
14 * changes for any purpose with or without fee is hereby granted, provided
15 * that the above copyright notice and this permission notice appear in all
16 * copies and any distributed versions or copies are either unchanged
17 * or not called anything similar to "DCC" or "Distributed Checksum
18 * Clearinghouse".
19 *
20 * Parties not eligible to receive a license under this agreement can
21 * obtain a commercial license to use DCC by contacting Rhyolite Software
22 * at sales@rhyolite.com.
23 *
24 * A commercial license would be for Distributed Checksum and Reputation
25 * Clearinghouse software. That software includes additional features. This
26 * free license for Distributed ChecksumClearinghouse Software does not in any
27 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
28 * software
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
31 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
33 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
34 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
35 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
36 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37 * SOFTWARE.
38 *
39 * Rhyolite Software DCC 1.3.103-1.67 $Revision$
40 */
41
42 #include "dcc_defs.h"
43 #include "dcc_ck.h"
44 #include <arpa/inet.h>
45
46 static DCC_EMSG dcc_emsg;
47 static const char *homedir;
48
49 static u_char quiet;
50
51 static const char *ts2buf(time_t);
52
53
54 static void NRATTRIB
55 usage(void)
56 {
57 dcc_logbad(EX_USAGE, "usage: [-VPQ] [-h homedir] [-t env_to] file");
58 }
59
60
61
62 int
63 main(int argc, char **argv)
64 {
65 const char *to = 0;
66 u_char print_version = 0;
67 u_char first;
68 DCC_WHITE_INX inx, inx2;
69 const char *nm;
70 DCC_SUM sum;
71 struct stat ht_sb, ascii_sb, inc_sb;
72 char tgts_buf[20];
73 int col;
74 u_char heading;
75 DCC_TGTS tgts;
76 DCC_WHITE_LISTING listing;
77 DCC_CK_TYPES type;
78 int i;
79
80 dcc_syslog_init(0, argv[0], 0);
81 dcc_clnt_debug = 99;
82
83 dup2(1, 2); /* put error messages in context */
84
85 dcc_wf_init(&cmn_wf, DCC_WF_WLIST | DCC_WF_EITHER);
86
87 while ((i = getopt(argc, argv, "VPQqh:t:")) != EOF) {
88 switch (i) {
89 case 'V':
90 fprintf(stderr, DCC_VERSION"\n");
91 print_version = 1;
92 break;
93
94 case 'P': /* parse or rebuild hash table */
95 cmn_wf.wf_flags &= ~DCC_WF_WLIST_RO;
96 cmn_wf.wf_flags |= DCC_WF_WLIST_RW;
97 break;
98
99 case 'Q': /* query; don't rebuild hash table */
100 cmn_wf.wf_flags &= ~DCC_WF_WLIST_RW;
101 cmn_wf.wf_flags |= DCC_WF_WLIST_RO;
102 break;
103
104 case 'q':
105 quiet = 1;
106 break;
107
108 case 'h':
109 homedir = optarg;
110 break;
111
112 case 't':
113 to = optarg;
114 break;
115
116 default:
117 usage();
118 }
119 }
120 argc -= optind;
121 argv += optind;
122 if (argc == 0) {
123 if (print_version)
124 exit(EX_OK);
125 usage();
126 }
127
128 dcc_cdhome(0, homedir, 1);
129
130 first = 1;
131 while ((nm = *argv++) != 0) {
132 if (first) {
133 first = 0;
134 } else {
135 printf("\n\n--------------------------------\n");
136 }
137 if (cmn_wf.wf_flags & DCC_WF_WLIST_RO)
138 cmn_wf.wf_flags |= DCC_WF_RO;
139 else
140 cmn_wf.wf_flags &= ~DCC_WF_RO;
141 if (!dcc_new_white_nm(dcc_emsg, &cmn_wf, nm)) {
142 dcc_error_msg("%s", dcc_emsg);
143 exit(EX_DATAERR);
144 }
145 printf("%s\n", cmn_wf.ascii_nm);
146
147 switch (dcc_rdy_white(dcc_emsg, &cmn_wf, &cmn_tmp_wf)) {
148 case DCC_WHITE_OK:
149 break;
150 case DCC_WHITE_NOFILE:
151 dcc_error_msg("does %s exist?", nm);
152 exit(EX_DATAERR);
153 case DCC_WHITE_CONTINUE:
154 dcc_error_msg("%s", dcc_emsg);
155 break;
156 case DCC_WHITE_SILENT:
157 case DCC_WHITE_COMPLAIN:
158 dcc_error_msg("%s", dcc_emsg);
159 exit(EX_DATAERR);
160 break;
161 }
162 printf("%s\n", cmn_wf.wtbl->magic);
163
164 if (to) {
165 dcc_str2ck(sum, 0, 0, to);
166 printf("%s\n%8s %s\t",
167 to,
168 dcc_type2str_err(DCC_CK_ENV_TO, 0, 0, 0),
169 dcc_ck2str_err(DCC_CK_ENV_TO, sum, 0));
170 if (DCC_WHITE_OK != dcc_white_sum(dcc_emsg, &cmn_wf,
171 DCC_CK_ENV_TO, sum,
172 &tgts, &listing)) {
173 dcc_error_msg("%s", dcc_emsg);
174 }
175 if (listing == DCC_WHITE_UNLISTED) {
176 printf("unlisted\n");
177 } else {
178 printf("%s\n",
179 dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
180 tgts, 0));
181 }
182 continue;
183 }
184
185 printf(" %s whitelist %d entries\n",
186 (cmn_wf.wtbl_flags & DCC_WHITE_FG_PER_USER)
187 ? "per-user" : "global",
188 cmn_wf.wtbl->hdr.entries);
189
190 if (0 > fstat(cmn_wf.ht_fd, &ht_sb)) {
191 dcc_error_msg("stat(%s): %s",
192 cmn_wf.ht_nm, ERROR_STR());
193 exit(EX_DATAERR);
194 }
195
196 if (0 > stat(cmn_wf.ascii_nm, &ascii_sb)) {
197 dcc_error_msg("stat(%s): %s",
198 cmn_wf.ascii_nm, ERROR_STR());
199 } else if (ht_sb.st_mtime < ascii_sb.st_mtime) {
200 printf(" %s is older than %s\n",
201 cmn_wf.ht_nm, cmn_wf.ascii_nm);
202 }
203
204 if (cmn_wf.wtbl->hdr.ascii_mtime == 0) {
205 printf(" %s broken\n", cmn_wf.ht_nm);
206 } else if (cmn_wf.wtbl->hdr.ascii_mtime != ascii_sb.st_mtime) {
207 printf(" %s has timestamp %s\n"
208 "\tfor %s which has mtime %s\n",
209 cmn_wf.ht_nm,
210 ts2buf(cmn_wf.wtbl->hdr.ascii_mtime),
211 cmn_wf.ascii_nm,
212 ts2buf(ascii_sb.st_mtime));
213 }
214
215 if (cmn_wf.wtbl->hdr.broken != 0)
216 printf(" %s broken until %s\n",
217 cmn_wf.ht_nm,
218 ts2buf(cmn_wf.wtbl->hdr.broken));
219 if (cmn_wf.wtbl->hdr.reparse != 0)
220 printf(" re-parse %s for errors after %s\n",
221 cmn_wf.ascii_nm,
222 ts2buf(cmn_wf.wtbl->hdr.reparse));
223
224 if (cmn_wf.wtbl->hdr.flags & DCC_WHITE_FG_HOSTNAMES) {
225 printf(" resolve hostnames after %s\n",
226 ts2buf(ht_sb.st_mtime + DCC_WHITECLNT_RESOLVE));
227 } else if (!(cmn_wf.wtbl->hdr.flags & DCC_WHITE_FG_PER_USER)) {
228 printf(" contains no hostnames\n");
229 }
230
231 for (i = 0; i < DIM(cmn_wf.wtbl->hdr.white_incs); ++i) {
232 if (cmn_wf.wtbl->hdr.white_incs[i].nm[0] == '\0')
233 break;
234 if (!i)
235 printf(" includes\n");
236 printf(" %s\n",
237 fnm2abs_err(0,
238 cmn_wf.wtbl->hdr.white_incs[i].nm));
239 if (0 > stat(cmn_wf.wtbl->hdr.white_incs[i].nm,
240 &inc_sb)) {
241 dcc_error_msg("stat(%s): %s",
242 cmn_wf.ascii_nm, ERROR_STR());
243 } else if (ht_sb.st_mtime < inc_sb.st_mtime) {
244 printf(" %s is older than %s"
245 " and needs rebuilding\n",
246 cmn_wf.ht_nm,
247 path2fnm(cmn_wf.wtbl->hdr.white_incs[i
248 ].nm));
249 }
250 }
251 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DCC_ON)
252 printf(" option DCC-on\n");
253 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DCC_OFF)
254 printf(" option DCC-off\n");
255
256 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_REP_ON)
257 printf(" option dcc-rep-on\n");
258 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_REP_OFF)
259 printf(" option dcc-rep-off\n");
260
261 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_ON)
262 printf(" option greylist-on\n");
263 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_OFF)
264 printf(" option greylist-off\n");
265
266 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_ALL)
267 printf(" option log-all\n");
268 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_NORMAL)
269 printf(" option log-normal\n");
270
271 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_D)
272 printf(" option log-subdirectory-day\n");
273 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_H)
274 printf(" option log-subdirectory-hour\n");
275 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_LOG_M)
276 printf(" option log-subdirectory-minute\n");
277
278
279 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_LOG_ON)
280 printf(" option greylist-log-on\n");
281 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_GREY_LOG_OFF)
282 printf(" option greylist-log-off\n");
283
284 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_MTA_FIRST)
285 printf(" option MTA-first\n");
286 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_MTA_LAST)
287 printf(" option MTA-last\n");
288
289 for (i = 0; i < MAX_DNSBL_GROUPS; ++i) {
290 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DNSBL_ON(i))
291 printf(" option DNSBL%d-on\n", i+1);
292 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DNSBL_OFF(i))
293 printf(" option DNSBL%d-off\n", i+1);
294 }
295
296 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_DISCARD_OK)
297 printf(" option forced-discard-ok\n");
298 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_NO_DISCARD)
299 printf(" option no-forced-discard\n");
300
301 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_TRAP_ACC)
302 printf(" option spam-trap-accept\n");
303 if (cmn_wf.wtbl_flags & DCC_WHITE_FG_TRAP_REJ)
304 printf(" option spam-trap_rej\n");
305
306 for (type = DCC_CK_TYPE_FIRST;
307 type <= DCC_CK_TYPE_LAST;
308 ++type) {
309 tgts = cmn_wf.wtbl->hdr.tholds_rej[type];
310 if (tgts == DCC_THOLD_UNSET)
311 continue;
312 printf(" option threshold %s,%s\n",
313 dcc_type2str_err(type, 0, 0, 0),
314 dcc_thold2str(tgts_buf, sizeof(tgts_buf),
315 type, tgts));
316 }
317
318 printf("\n file checksum %s\n",
319 dcc_ck2str_err(0, cmn_wf.wtbl->hdr.ck_sum, 0));
320
321 if (quiet)
322 continue;
323
324 heading = 0;
325 for (i = 0; i < cmn_wf.wtbl->hdr.cidr.len; ++i) {
326 struct in_addr addr4;
327 char cidr_buf[INET6_ADDRSTRLEN];
328
329 DCC_WHITE_CIDR_ENTRY *e=&cmn_wf.wtbl->hdr.cidr.e[i];
330 if (!heading) {
331 heading = 1;
332 fputs("\n CIDR blocks\n", stdout);
333 }
334 printf("%6s %s/%d\n",
335 dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
336 e->tgts,0),
337 dcc_ipv6tostr2(cidr_buf, sizeof(cidr_buf),
338 &e->addr),
339 dcc_ipv6toipv4(&addr4, &e->addr)
340 ? e->bits-96 : e->bits);
341 }
342 if (heading)
343 putchar('\n');
344
345 /* first the hash table */
346 fputs("\n hash table\n", stdout);
347 col = 0;
348 for (inx = 0; inx < DIM(cmn_wf.wtbl->bins); ++inx) {
349 if (!cmn_wf.wtbl->bins[inx]
350 && col == 0
351 && inx != 0) {
352 inx2 = inx;
353 while (inx2 < DIM(cmn_wf.wtbl->bins)
354 && !cmn_wf.wtbl->bins[inx2])
355 ++inx2;
356 i = inx2 - inx;
357 i -= i % 4;
358 if (i != 0) {
359 printf(" ...\n");
360 inx += i;
361 }
362 }
363 printf("%4d:", inx);
364 if (cmn_wf.wtbl->bins[inx]) {
365 printf("%-4d", cmn_wf.wtbl->bins[inx]);
366 } else {
367 printf(" ");
368 }
369 col = (col + 1) % 4;
370 putchar(col == 0 ? '\n' : '\t');
371 }
372
373 /* then the entries */
374 printf("\n\n%4s->%-4s %12s %6s\n",
375 "slot", "next", "type", "count");
376 for (inx = 0; inx < cmn_wf.wtbl_entries; ++inx) {
377 DCC_WHITE_ENTRY *e = &cmn_wf.wtbl->tbl[inx];
378 if (e->type == DCC_CK_INVALID)
379 continue;
380 printf("%4d->%-4d %12s %6s %s\n",
381 inx, e->fwd,
382 dcc_type2str_err(e->type, 0, 0, 0),
383 dcc_tgts2str(tgts_buf, sizeof(tgts_buf),
384 e->tgts, 0),
385 dcc_ck2str_err(e->type, e->sum, 0));
386 }
387 }
388 exit(EX_OK);
389 }
390
391
392
393 static const char *
394 ts2buf(time_t ts)
395 {
396 static struct {
397 char buf[26];
398 } times[4];
399 static int nbuf;
400
401 nbuf = (nbuf+1) % DIM(times);
402 return dcc_time2str(times[nbuf].buf, sizeof(times[nbuf].buf),
403 "%b %d %X %Z",
404 ts);
405 }