ucspi-tcp6 1.13.07
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 text; /* defined if decision is > 2 */
102
103static stralloc tmp;
104
105void rbl(char *base)
106{
107 if (decision) return;
108 if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
109 if (!stralloc_cats(&tmp,base)) nomem();
110
111 if (dns_txt(&text,&tmp) < 0) {
113 if (flagfailclosed) {
114 if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem();
115 decision = 4;
116 }
117 return;
118 }
119 if (text.len) {
120 if (flagrblbounce)
121 decision = 5;
122 else
123 decision = 4;
124 }
125}
126
127void antirbl(char *base)
128{
129 if (decision) return;
130 int flagip;
131
132 if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
133 if (!stralloc_cats(&tmp,base)) nomem();
134
135 if (flagip6)
136 flagip = dns_ip6(&text,&tmp);
137 else
138 flagip = dns_ip4(&text,&tmp);
139
140 if (flagip < 0) {
142 if (!flagfailclosed)
143 decision = 1;
144 return;
145 }
146 if (text.len)
147 decision = 1;
148}
149
150static char strnum[FMT_ULONG];
151static stralloc message = {0};;
152static stralloc info = {0};
153
154char inspace[64];
155buffer in = BUFFER_INIT(buffer_unixread,0,inspace,sizeof(inspace));
156char outspace[1];
157buffer out = BUFFER_INIT(buffer_unixwrite,1,outspace,sizeof(outspace));
158
159void waitdelay(unsigned long delay)
160{
161 unsigned long u;
162 char *x;
163
164 if (!delay) {
165 x = env_get("GREETDELAY");
166 if (x) {
167 scan_ulong(x,&u);
168 delay = u;
169 }
170 }
171
172 if (delay) {
173 if (!stralloc_copys(&info,"Greetdelay: ")) nomem();
174
175 buffer_puts(buffer_2,"rblsmtpd: ");
176 buffer_puts(buffer_2,ip_env);
177 buffer_puts(buffer_2," pid ");
178 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
179 buffer_puts(buffer_2,": ");
180 buffer_put(buffer_2,info.s,info.len);
181 buffer_put(buffer_2,strnum,fmt_ulong(strnum,delay));
182 buffer_puts(buffer_2,"\n");
183 buffer_flush(buffer_2);
184
185 sleep(delay);
186 }
187}
188
189void rblinfo(void)
190{
191 int i;
192
193 if (!stralloc_copys(&message,"[RBL info] ")) nomem();
194
195 if (text.len > 200) text.len = 200;
196 if (!stralloc_cat(&message,&text)) nomem();
197
198 for (i = 0; i < message.len; ++i)
199 if ((message.s[i] < 32) || (message.s[i] > 126))
200 message.s[i] = '?';
201
202 buffer_puts(buffer_2,"rblsmtpd: ");
203 buffer_puts(buffer_2,ip_env);
204 buffer_puts(buffer_2," pid ");
205 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
206 buffer_puts(buffer_2," ");
207 buffer_put(buffer_2,message.s,message.len);
208 buffer_puts(buffer_2,"\n");
209 buffer_flush(buffer_2);
210
211 if (!stralloc_copy(&info,&message)) nomem();
212 if (!stralloc_0(&info)) nomem();
213 if (!pathexec_env("RBLSMTPD",info.s)) nomem();
214}
215
216// Needs to be same signature like in qmail-smtpd
217
218void reject(char *d) { buffer_putflush(&out,message.s,message.len); }
219void accept(char *d) { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
220void greet(char *d) { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); }
221void quit(char *d) { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); }
222void drop(char *d) { _exit(0); }
223
225 { "quit", quit, 0 }
226, { "helo", accept, 0 }
227, { "ehlo", accept, 0 }
228, { "mail", accept, 0 }
229, { "rset", accept, 0 }
230, { "noop", accept, 0 }
231, { 0, reject, 0 }
232} ;
233
234void rblsmtpd(void)
235{
236 int i;
237 char *dummy = 0;
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(dummy);
263 else {
264 sig_catch(sig_alarm,(void *)drop);
265 alarm(timeout);
266 greet(dummy);
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,(char **)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:157
void greet(char *d)
Definition rblsmtpd.c:220
unsigned long timeout
Definition rblsmtpd.c:94
void waitdelay(unsigned long delay)
Definition rblsmtpd.c:159
int flagrblinfo
Definition rblsmtpd.c:98
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:156
void rblinfo(void)
Definition rblsmtpd.c:189
void accept(char *d)
Definition rblsmtpd.c:219
int flagfailclosed
Definition rblsmtpd.c:96
char * ip_env
Definition rblsmtpd.c:35
struct commands smtpcommands[]
Definition rblsmtpd.c:224
void reject(char *d)
Definition rblsmtpd.c:218
int decision
Definition rblsmtpd.c:100
void quit(char *d)
Definition rblsmtpd.c:221
buffer in
Definition rblsmtpd.c:155
void antirbl(char *base)
Definition rblsmtpd.c:127
void rblsmtpd(void)
Definition rblsmtpd.c:234
void usage(void)
Definition rblsmtpd.c:24
int flagip6
Definition rblsmtpd.c:37
void drop(char *d)
Definition rblsmtpd.c:222
int flagmustnotbounce
Definition rblsmtpd.c:97
int flagrblbounce
Definition rblsmtpd.c:95
void rbl(char *base)
Definition rblsmtpd.c:105
char inspace[64]
Definition rblsmtpd.c:154
char remoteip[16]
Definition tcpserver.c:56
#define WHO
Definition argv0.c:4
int main()
Definition addcr.c:4