ucspi-tcp6 1.13.04
ucspi-tcp6
Loading...
Searching...
No Matches
rblsmtpd.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "byte.h"
3#include "str.h"
4#include "scan.h"
5#include "fmt.h"
6#include "env.h"
7#include "exit.h"
8#include "sig.h"
9#include "buffer.h"
10#include "getoptb.h"
11#include "logmsg.h"
12#include "stralloc.h"
13#include "commands.h"
14#include "pathexec.h"
15#include "dnsresolv.h"
16#include "ip.h"
17
18#define WHO "rblsmtpd"
19
20void nomem(void)
21{
22 logmsg(WHO,111,FATAL,"out of memory");
23}
24void usage(void)
25{
26 logmsg(WHO,100,USAGE,"rblsmtpd \
27[ -B ] [ -b ] \
28[ -C ] [ -c ] \
29[ -i ] [ -t timeout ] \
30[ -r base ] [ -a base ] \
31[-W] [-w delay] smtpd [ arg ... ]");
32}
33
35char *ip_env = 0;;
36static stralloc ip_reverse;
38
39void ip_init(void)
40{
41 unsigned int i;
42 unsigned int j;
43 char hexval;
44 char remoteip[16];
45
46 flagip6 = 0;
47 byte_zero(remoteip,16);
48
49 tcp_proto = env_get("PROTO");
50 if (!tcp_proto) tcp_proto = "";
51 if (!str_diff(tcp_proto,"TCP6")) {
52 ip_env = env_get("TCP6REMOTEIP");
53 if (!ip_env) ip_env = "::";
54 if (byte_equal(ip_env,7,V4MAPPREFIX))
55 ip_env = ip_env + 7;
56 else
57 flagip6 = 1;
58 } else {
59 ip_env = env_get("TCPREMOTEIP");
60 if (!ip_env) ip_env = "0.0.0.0";
61 else if (byte_equal(ip_env,7,V4MAPPREFIX))
62 ip_env = ip_env + 7;
63 }
64
65 if (!stralloc_copys(&ip_reverse,"")) nomem();
66
67 if (flagip6) {
68 if ((ip6_scan(ip_env,remoteip)) == 0) return;
69
70 for (j = 15; j >= 0; j--) {
71 hexval = tohex(remoteip[j] & 15);
72 if (!stralloc_catb(&ip_reverse,&hexval,1)) nomem();
73 if (!stralloc_cats(&ip_reverse,".")) nomem();
74
75 hexval = tohex(remoteip[j] >> 4 & 15);
76 if (!stralloc_catb(&ip_reverse,&hexval,1)) nomem();
77 if (!stralloc_cats(&ip_reverse,".")) nomem();
78 if (!j) break;
79 }
80 }
81 else {
82 i = str_len(ip_env);
83 while (i) {
84 for (j = i; j > 0; --j)
85 if (ip_env[j - 1] == '.') break;
86 if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) nomem();
87 if (!stralloc_cats(&ip_reverse,".")) nomem();
88 if (!j) break;
89 i = j - 1;
90 }
91 }
92}
93
94unsigned long timeout = 60;
99
100int decision = 0; /* 0 undecided, 1 accept, 2 direct refuse, 3 direct bounce, 4 rbl refuse, 5 rbl bounce */
101static stralloc cn; /* defined if lookup return CNAME */
102static stralloc text; /* defined if decision is > 2 */
103
104static stralloc tmp;
105
106void rbl(char *base)
107{
108 if (decision) return;
109 if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
110 if (!stralloc_cats(&tmp,base)) nomem();
111
112 if (dns_txt(&text,&tmp) < 0) {
114 if (flagfailclosed) {
115 if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem();
116 decision = 4;
117 }
118 return;
119 }
120 if (text.len) {
121 if (flagrblbounce)
122 decision = 5;
123 else
124 decision = 4;
125 }
126}
127
128void antirbl(char *base)
129{
130 if (decision) return;
131 int flagip;
132
133 if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
134 if (!stralloc_cats(&tmp,base)) nomem();
135
136 if (flagip6)
137 flagip = dns_ip6(&text,&tmp);
138 else
139 flagip = dns_ip4(&text,&tmp);
140
141 if (flagip < 0) {
143 if (!flagfailclosed)
144 decision = 1;
145 return;
146 }
147 if (text.len)
148 decision = 1;
149}
150
151static char strnum[FMT_ULONG];
152static stralloc message = {0};;
153static stralloc info = {0};
154
155char inspace[64];
156buffer in = BUFFER_INIT(buffer_unixread,0,inspace,sizeof(inspace));
157char outspace[1];
158buffer out = BUFFER_INIT(buffer_unixwrite,1,outspace,sizeof(outspace));
159
160void waitdelay(unsigned long delay)
161{
162 unsigned long u;
163 char *x;
164
165 if (!delay) {
166 x = env_get("GREETDELAY");
167 if (x) {
168 scan_ulong(x,&u);
169 delay = u;
170 }
171 }
172
173 if (delay) {
174 if (!stralloc_copys(&info,"greetdelay: ")) nomem();
175
176 buffer_puts(buffer_2,"rblsmtpd: ");
177 buffer_puts(buffer_2,ip_env);
178 buffer_puts(buffer_2," pid ");
179 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
180 buffer_puts(buffer_2,": ");
181 buffer_put(buffer_2,info.s,info.len);
182 buffer_put(buffer_2,strnum,fmt_ulong(strnum,delay));
183 buffer_puts(buffer_2,"\n");
184 buffer_flush(buffer_2);
185
186 if (!stralloc_cats(&info,"\r\n")) nomem();
187
188 sleep(delay);
189 }
190}
191
192void rblinfo(void)
193{
194 int i;
195
196 if (!stralloc_copys(&message,"[RBL info] ")) nomem();
197
198 if (text.len > 200) text.len = 200;
199 if (!stralloc_cat(&message,&text)) nomem();
200
201 for (i = 0; i < message.len; ++i)
202 if ((message.s[i] < 32) || (message.s[i] > 126))
203 message.s[i] = '?';
204
205 buffer_puts(buffer_2,"rblsmtpd: ");
206 buffer_puts(buffer_2,ip_env);
207 buffer_puts(buffer_2," pid ");
208 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
209 buffer_puts(buffer_2,": ");
210 buffer_put(buffer_2,message.s,message.len);
211 buffer_puts(buffer_2,"\n");
212 buffer_flush(buffer_2);
213
214 if (!stralloc_copy(&info,&message)) nomem();
215 if (!stralloc_0(&info)) nomem();
216 if (!pathexec_env("RBLSMTPD",info.s)) nomem();
217}
218
219void reject() { buffer_putflush(&out,message.s,message.len); }
220void accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
221void greet() { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); }
222void quit() { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); }
223void drop() { _exit(0); }
224
226 { "quit", quit, 0 }
227, { "helo", accept, 0 }
228, { "ehlo", accept, 0 }
229, { "mail", accept, 0 }
230, { "rset", accept, 0 }
231, { "noop", accept, 0 }
232, { 0, reject, 0 }
233} ;
234
235void rblsmtpd(void)
236{
237 int i;
238
239 if (flagmustnotbounce || (decision == 2) || (decision == 4)) {
240 if (!stralloc_copys(&message,"451 ")) nomem();
241 } else
242 if (!stralloc_copys(&message,"553 ")) nomem();
243
244 if (text.len > 200) text.len = 200;
245 if (!stralloc_cat(&message,&text)) nomem();
246 for (i = 0; i < message.len; ++i)
247 if ((message.s[i] < 32) || (message.s[i] > 126))
248 message.s[i] = '?';
249
250 buffer_puts(buffer_2,"rblsmtpd: ");
251 buffer_puts(buffer_2,ip_env);
252 buffer_puts(buffer_2," pid ");
253 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
254 buffer_puts(buffer_2,": ");
255 buffer_put(buffer_2,message.s,message.len);
256 buffer_puts(buffer_2,"\n");
257 buffer_flush(buffer_2);
258
259 if (!stralloc_cats(&message,"\r\n")) nomem();
260
261 if (!timeout)
262 reject();
263 else {
264 sig_catch(sig_alarm,drop);
265 alarm(timeout);
266 greet();
268 }
269 _exit(0);
270}
271
272int main(int argc,char * const *argv,char * const *envp)
273{
274 char *x;
275 int opt;
276 unsigned long greetdelay = 0;
277
278 ip_init();
279
280 x = env_get("RBLSMTPD");
281 if (x) {
282 if (!*x)
283 decision = 1;
284 else if (*x == '-') {
285 if (!stralloc_copys(&text,x + 1)) nomem();
286 decision = 3;
287 }
288 else {
289 if (!stralloc_copys(&text,x)) nomem();
290 decision = 2;
291 }
292 }
293
294 while ((opt = getoptb(argc,argv,"bBcCit:r:a:w:W")) != opteof)
295 switch(opt) {
296 case 'b': flagrblbounce = 1; break;
297 case 'B': flagrblbounce = 0; break;
298 case 'c': flagfailclosed = 1; break;
299 case 'C': flagfailclosed = 0; break;
300 case 'i': flagrblinfo = 1; break;
301 case 't': scan_ulong(optarg,&timeout); break;
302 case 'r': rbl(optarg); break;
303 case 'a': antirbl(optarg); break;
304 case 'W': if (!decision) { waitdelay(greetdelay); } break;
305 case 'w': if (!decision) { scan_ulong(optarg,&greetdelay); waitdelay(greetdelay); } break;
306 default: usage();
307 }
308
309 argv += optind;
310 if (!*argv) usage();
311
312 if (flagrblinfo && decision >= 4)
313 rblinfo();
314 else if (decision >= 2)
315 rblsmtpd();
316
317 pathexec(argv);
318 logmsg(WHO,111,FATAL,B("unable to run: ",*argv));
319
320 return 0;
321}
int commands(buffer *ss, struct commands *c)
Definition commands.c:9
buffer out
Definition rblsmtpd.c:158
void quit()
Definition rblsmtpd.c:222
void drop()
Definition rblsmtpd.c:223
unsigned long timeout
Definition rblsmtpd.c:94
void waitdelay(unsigned long delay)
Definition rblsmtpd.c:160
int flagrblinfo
Definition rblsmtpd.c:98
void reject()
Definition rblsmtpd.c:219
void nomem(void)
Definition rblsmtpd.c:20
char * tcp_proto
Definition rblsmtpd.c:34
void ip_init(void)
Definition rblsmtpd.c:39
char outspace[1]
Definition rblsmtpd.c:157
void rblinfo(void)
Definition rblsmtpd.c:192
int flagfailclosed
Definition rblsmtpd.c:96
void accept()
Definition rblsmtpd.c:220
char * ip_env
Definition rblsmtpd.c:35
struct commands smtpcommands[]
Definition rblsmtpd.c:225
void greet()
Definition rblsmtpd.c:221
int decision
Definition rblsmtpd.c:100
buffer in
Definition rblsmtpd.c:156
void antirbl(char *base)
Definition rblsmtpd.c:128
void rblsmtpd(void)
Definition rblsmtpd.c:235
void usage(void)
Definition rblsmtpd.c:24
int flagip6
Definition rblsmtpd.c:37
int flagmustnotbounce
Definition rblsmtpd.c:97
int flagrblbounce
Definition rblsmtpd.c:95
void rbl(char *base)
Definition rblsmtpd.c:106
char inspace[64]
Definition rblsmtpd.c:155
char remoteip[16]
Definition tcpserver.c:56
int main()
Definition addcr.c:4
#define WHO
Definition argv0.c:4