Blob


1 #include <sys/socket.h>
3 #include <err.h>
4 #include <errno.h>
5 #include <netdb.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
11 #include "smtp_proc.h"
13 static char **blacklists = NULL;
14 static size_t nblacklists = 0;
15 int retries = 0;
16 int reject_onfailure = 0;
18 void usage(void);
19 enum filter_decision dnsbl_connect(char *, int, time_t, char *, char *,
20 uint64_t, uint64_t, struct smtp_filter_connect *);
22 int
23 main(int argc, char *argv[])
24 {
25 int ch;
26 size_t i;
27 char *line = NULL;
28 size_t linesize = 0;
29 ssize_t linelen;
30 char *msgid, *token, *ip;
31 const char *errstr;
32 int lookup;
34 if (pledge("stdio dns", NULL) == -1)
35 err(1, "pledge");
37 while ((ch = getopt(argc, argv, "b:f:r:")) != -1) {
38 switch (ch) {
39 case 'b':
40 blacklists = reallocarray(blacklists, nblacklists + 1,
41 sizeof(*blacklists));
42 if (blacklists == NULL)
43 err(1, NULL);
44 if ((blacklists[nblacklists] = strdup(optarg)) == NULL)
45 err(1, NULL);
46 nblacklists++;
47 break;
48 case 'f':
49 reject_onfailure = 1;
50 case 'r':
51 if ((retries = strtonum(optarg, 0, 10, &errstr)) == 0 &&
52 errstr != NULL)
53 errx(1, "retries %s", errstr);
54 break;
55 default:
56 usage();
57 }
58 }
60 if (nblacklists == 0)
61 errx(1, "No blacklist specified");
63 smtp_register_filter_connect(dnsbl_connect);
64 smtp_run();
66 return 0;
67 }
69 enum filter_decision
70 dnsbl_connect(char *type, int version, time_t tm, char *direction, char *phase,
71 uint64_t reqid, uint64_t token, struct smtp_filter_connect *params)
72 {
73 char query[255];
74 char reply[1500];
75 struct hostent *hent;
76 u_char *addr;
77 int i, try;
79 addr = (u_char *)&(params->addr);
80 for (i = 0; i < nblacklists; i++) {
81 if (params->af == AF_INET) {
82 if (snprintf(query, sizeof(query), "%u.%u.%u.%u.%s",
83 addr[3], addr[2], addr[1], addr[0],
84 blacklists[i]) >= sizeof(query))
85 errx(1, "Can't create query, domain too long");
86 } else if (params->af == AF_INET6) {
87 if (snprintf(query, sizeof(query), "%hhx.%hhx.%hhx.%hhx"
88 ".%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx"
89 ".%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx"
90 ".%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%hhx.%s",
91 (u_char) (addr[15] & 0xf), (u_char) (addr[15] >> 4),
92 (u_char) (addr[14] & 0xf), (u_char) (addr[14] >> 4),
93 (u_char) (addr[13] & 0xf), (u_char) (addr[13] >> 4),
94 (u_char) (addr[12] & 0xf), (u_char) (addr[12] >> 4),
95 (u_char) (addr[11] & 0xf), (u_char) (addr[11] >> 4),
96 (u_char) (addr[10] & 0xf), (u_char) (addr[10] >> 4),
97 (u_char) (addr[9] & 0xf), (u_char) (addr[9] >> 4),
98 (u_char) (addr[8] & 0xf), (u_char) (addr[8] >> 4),
99 (u_char) (addr[7] & 0xf), (u_char) (addr[8] >> 4),
100 (u_char) (addr[6] & 0xf), (u_char) (addr[7] >> 4),
101 (u_char) (addr[5] & 0xf), (u_char) (addr[5] >> 4),
102 (u_char) (addr[4] & 0xf), (u_char) (addr[4] >> 4),
103 (u_char) (addr[3] & 0xf), (u_char) (addr[3] >> 4),
104 (u_char) (addr[2] & 0xf), (u_char) (addr[2] >> 4),
105 (u_char) (addr[1] & 0xf), (u_char) (addr[1] >> 4),
106 (u_char) (addr[0] & 0xf), (u_char) (addr[0] >> 4),
107 blacklists[i]) >= sizeof(query))
108 errx(1, "Can't create query, domain too long");
109 } else
110 errx(1, "Invalid address family received");
112 for (try = -1; try < retries; try++) {
113 if ((hent = gethostbyname(query)) == NULL) {
114 if (h_errno == HOST_NOT_FOUND)
115 break;
116 if (h_errno != TRY_AGAIN) {
117 if (!reject_onfailure)
118 break;
119 else
120 smtp_filter_disconnect(reqid,
121 token,
122 "Blacklist check failed");
123 return FILTER_DISCONNECT;
125 } else {
126 smtp_filter_disconnect(reqid, token,
127 "Listed at %s", blacklists[i]);
128 return FILTER_DISCONNECT;
132 return FILTER_PROCEED;
135 void
136 usage(void)
138 fprintf(stderr, "usage: %s [-b blacklist]\n",
139 getprogname());
140 exit(1);