ucspi-tcp6 1.13.02
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 if (dns_txt(&text,&tmp) < 0) {
112 if (flagfailclosed) {
113 if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem();
114 decision = 4;
115 }
116 return;
117 }
118 if (text.len) {
119 if (flagrblbounce)
120 decision = 5;
121 else
122 decision = 4;
123 }
124}
125
126void antirbl(char *base)
127{
128 if (decision) return;
129 int flagip;
130
131 if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
132 if (!stralloc_cats(&tmp,base)) nomem();
133
134 if (flagip6)
135 flagip = dns_ip6(&text,&tmp);
136 else
137 flagip = dns_ip4(&text,&tmp);
138
139 if (flagip < 0) {
141 if (!flagfailclosed)
142 decision = 1;
143 return;
144 }
145 if (text.len)
146 decision = 1;
147}
148
149static char strnum[FMT_ULONG];
150static stralloc message = {0};;
151static stralloc info = {0};
152
153char inspace[64];
154buffer in = BUFFER_INIT(buffer_unixread,0,inspace,sizeof(inspace));
155char outspace[1];
156buffer out = BUFFER_INIT(buffer_unixwrite,1,outspace,sizeof(outspace));
157
158void waitdelay(unsigned long delay)
159{
160 unsigned long u;
161 char *x;
162
163 if (!delay) {
164 x = env_get("GREETDELAY");
165 if (x) {
166 scan_ulong(x,&u);
167 delay = u;
168 }
169 }
170
171 if (delay) {
172 if (!stralloc_copys(&info,"greetdelay: ")) nomem();
173
174 buffer_puts(buffer_2,"rblsmtpd: ");
175 buffer_puts(buffer_2,ip_env);
176 buffer_puts(buffer_2," pid ");
177 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
178 buffer_puts(buffer_2,": ");
179 buffer_put(buffer_2,info.s,info.len);
180 buffer_put(buffer_2,strnum,fmt_ulong(strnum,delay));
181 buffer_puts(buffer_2,"\n");
182 buffer_flush(buffer_2);
183
184 if (!stralloc_cats(&info,"\r\n")) nomem();
185
186 sleep(delay);
187 }
188}
189
190void rblinfo(void)
191{
192 int i;
193
194 if (!stralloc_copys(&message,"[RBL info] ")) nomem();
195
196 if (text.len > 200) text.len = 200;
197 if (!stralloc_cat(&message,&text)) nomem();
198
199 for (i = 0; i < message.len; ++i)
200 if ((message.s[i] < 32) || (message.s[i] > 126))
201 message.s[i] = '?';
202
203 buffer_puts(buffer_2,"rblsmtpd: ");
204 buffer_puts(buffer_2,ip_env);
205 buffer_puts(buffer_2," pid ");
206 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
207 buffer_puts(buffer_2,": ");
208 buffer_put(buffer_2,message.s,message.len);
209 buffer_puts(buffer_2,"\n");
210 buffer_flush(buffer_2);
211
212 if (!stralloc_copy(&info,&message)) nomem();
213 if (!stralloc_0(&info)) nomem();
214 if (!pathexec_env("RBLSMTPD",info.s)) nomem();
215}
216
217void reject() { buffer_putflush(&out,message.s,message.len); }
218void accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
219void greet() { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); }
220void quit() { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); }
221void drop() { _exit(0); }
222
224 { "quit", quit, 0 }
225, { "helo", accept, 0 }
226, { "ehlo", accept, 0 }
227, { "mail", accept, 0 }
228, { "rset", accept, 0 }
229, { "noop", accept, 0 }
230, { 0, reject, 0 }
231} ;
232
233void rblsmtpd(void)
234{
235 int i;
236
237 if (flagmustnotbounce || (decision == 2) || (decision == 4)) {
238 if (!stralloc_copys(&message,"451 ")) nomem();
239 } else
240 if (!stralloc_copys(&message,"553 ")) nomem();
241
242 if (text.len > 200) text.len = 200;
243 if (!stralloc_cat(&message,&text)) nomem();
244 for (i = 0; i < message.len; ++i)
245 if ((message.s[i] < 32) || (message.s[i] > 126))
246 message.s[i] = '?';
247
248 buffer_puts(buffer_2,"rblsmtpd: ");
249 buffer_puts(buffer_2,ip_env);
250 buffer_puts(buffer_2," pid ");
251 buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid()));
252 buffer_puts(buffer_2,": ");
253 buffer_put(buffer_2,message.s,message.len);
254 buffer_puts(buffer_2,"\n");
255 buffer_flush(buffer_2);
256
257 if (!stralloc_cats(&message,"\r\n")) nomem();
258
259 if (!timeout)
260 reject();
261 else {
262 sig_catch(sig_alarm,drop);
263 alarm(timeout);
264 greet();
266 }
267 _exit(0);
268}
269
270int main(int argc,char * const *argv,char * const *envp)
271{
272 char *x;
273 int opt;
274 unsigned long greetdelay = 0;
275
276 ip_init();
277
278 x = env_get("RBLSMTPD");
279 if (x) {
280 if (!*x)
281 decision = 1;
282 else if (*x == '-') {
283 if (!stralloc_copys(&text,x + 1)) nomem();
284 decision = 3;
285 }
286 else {
287 if (!stralloc_copys(&text,x)) nomem();
288 decision = 2;
289 }
290 }
291
292 while ((opt = getoptb(argc,(char **)argv,"bBcCit:r:a:w:W")) != opteof)
293 switch(opt) {
294 case 'b': flagrblbounce = 1; break;
295 case 'B': flagrblbounce = 0; break;
296 case 'c': flagfailclosed = 1; break;
297 case 'C': flagfailclosed = 0; break;
298 case 'i': flagrblinfo = 1; break;
299 case 't': scan_ulong(optarg,&timeout); break;
300 case 'r': rbl(optarg); break;
301 case 'a': antirbl(optarg); break;
302 case 'W': if (!decision) { waitdelay(greetdelay); } break;
303 case 'w': if (!decision) { scan_ulong(optarg,&greetdelay); waitdelay(greetdelay); } break;
304 default: usage();
305 }
306
307 argv += optind;
308 if (!*argv) usage();
309
310 if (flagrblinfo && decision >= 4)
311 rblinfo();
312 else if (decision >= 2)
313 rblsmtpd();
314
315 pathexec(argv);
316 logmsg(WHO,111,FATAL,B("unable to run: ",*argv));
317
318 return 0;
319}
char remoteip[16]
Definition: tcpserver.c:56
buffer out
Definition: rblsmtpd.c:156
void quit()
Definition: rblsmtpd.c:220
void drop()
Definition: rblsmtpd.c:221
unsigned long timeout
Definition: rblsmtpd.c:94
void waitdelay(unsigned long delay)
Definition: rblsmtpd.c:158
int flagrblinfo
Definition: rblsmtpd.c:98
void reject()
Definition: rblsmtpd.c:217
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:155
void rblinfo(void)
Definition: rblsmtpd.c:190
int flagfailclosed
Definition: rblsmtpd.c:96
void accept()
Definition: rblsmtpd.c:218
char * ip_env
Definition: rblsmtpd.c:35
struct commands smtpcommands[]
Definition: rblsmtpd.c:223
void greet()
Definition: rblsmtpd.c:219
int decision
Definition: rblsmtpd.c:100
buffer in
Definition: rblsmtpd.c:154
void antirbl(char *base)
Definition: rblsmtpd.c:126
#define WHO
Definition: rblsmtpd.c:18
void rblsmtpd(void)
Definition: rblsmtpd.c:233
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:105
char inspace[64]
Definition: rblsmtpd.c:153
int main()
Definition: addcr.c:4