Commit | Line | Data |
---|---|---|
2117e02e MW |
1 | #include "stralloc.h" |
2 | #include "substdio.h" | |
2117e02e MW |
3 | #include "qmail.h" |
4 | #include "now.h" | |
5 | #include "str.h" | |
6 | #include "fmt.h" | |
7 | #include "env.h" | |
8 | #include "sig.h" | |
212b6f5d | 9 | #include "rcpthosts.h" |
2117e02e | 10 | #include "auto_qmail.h" |
2117e02e MW |
11 | #include "readwrite.h" |
12 | #include "control.h" | |
2117e02e MW |
13 | #include "received.h" |
14 | ||
2117e02e MW |
15 | void badproto() { _exit(100); } |
16 | void resources() { _exit(111); } | |
2117e02e | 17 | |
212b6f5d | 18 | int safewrite(fd,buf,len) int fd; char *buf; int len; |
2117e02e | 19 | { |
212b6f5d MW |
20 | int r; |
21 | r = write(fd,buf,len); | |
22 | if (r <= 0) _exit(0); | |
23 | return r; | |
24 | } | |
25 | ||
26 | char ssoutbuf[256]; | |
27 | substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); | |
2117e02e | 28 | |
212b6f5d MW |
29 | int saferead(fd,buf,len) int fd; char *buf; int len; |
30 | { | |
31 | int r; | |
32 | substdio_flush(&ssout); | |
33 | r = read(fd,buf,len); | |
34 | if (r <= 0) _exit(0); | |
35 | return r; | |
36 | } | |
37 | ||
38 | char ssinbuf[512]; | |
39 | substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); | |
40 | ||
41 | unsigned long getlen() | |
42 | { | |
43 | unsigned long len = 0; | |
44 | char ch; | |
45 | for (;;) { | |
46 | substdio_get(&ssin,&ch,1); | |
47 | if (ch == ':') return len; | |
48 | if (len > 200000000) resources(); | |
49 | len = 10 * len + (ch - '0'); | |
2117e02e MW |
50 | } |
51 | } | |
52 | ||
53 | void getcomma() | |
54 | { | |
212b6f5d MW |
55 | char ch; |
56 | substdio_get(&ssin,&ch,1); | |
57 | if (ch != ',') badproto(); | |
2117e02e MW |
58 | } |
59 | ||
212b6f5d MW |
60 | unsigned int databytes = 0; |
61 | unsigned int bytestooverflow = 0; | |
62 | struct qmail qq; | |
63 | ||
2117e02e MW |
64 | char buf[1000]; |
65 | char buf2[100]; | |
66 | ||
67 | char *remotehost; | |
68 | char *remoteinfo; | |
69 | char *remoteip; | |
70 | char *local; | |
71 | ||
72 | stralloc failure = {0}; | |
73 | ||
2117e02e MW |
74 | char *relayclient; |
75 | int relayclientlen; | |
76 | ||
2117e02e MW |
77 | main() |
78 | { | |
212b6f5d MW |
79 | char ch; |
80 | int i; | |
81 | unsigned long biglen; | |
82 | unsigned long len; | |
83 | int flagdos; | |
84 | int flagsenderok; | |
85 | int flagbother; | |
86 | unsigned long qp; | |
87 | char *result; | |
88 | char *x; | |
89 | unsigned long u; | |
90 | ||
91 | sig_pipeignore(); | |
92 | sig_alarmcatch(resources); | |
93 | alarm(3600); | |
94 | ||
95 | if (chdir(auto_qmail) == -1) resources(); | |
96 | ||
97 | if (control_init() == -1) resources(); | |
98 | if (rcpthosts_init() == -1) resources(); | |
99 | relayclient = env_get("RELAYCLIENT"); | |
100 | relayclientlen = relayclient ? str_len(relayclient) : 0; | |
101 | ||
102 | if (control_readint(&databytes,"control/databytes") == -1) resources(); | |
103 | x = env_get("DATABYTES"); | |
104 | if (x) { scan_ulong(x,&u); databytes = u; } | |
105 | if (!(databytes + 1)) --databytes; | |
106 | ||
107 | remotehost = env_get("TCPREMOTEHOST"); | |
108 | if (!remotehost) remotehost = "unknown"; | |
109 | remoteinfo = env_get("TCPREMOTEINFO"); | |
110 | remoteip = env_get("TCPREMOTEIP"); | |
111 | if (!remoteip) remoteip = "unknown"; | |
112 | local = env_get("TCPLOCALHOST"); | |
113 | if (!local) local = env_get("TCPLOCALIP"); | |
114 | if (!local) local = "unknown"; | |
115 | ||
116 | for (;;) { | |
117 | if (!stralloc_copys(&failure,"")) resources(); | |
118 | flagsenderok = 1; | |
119 | ||
120 | len = getlen(); | |
121 | if (len == 0) badproto(); | |
122 | ||
123 | if (databytes) bytestooverflow = databytes + 1; | |
124 | if (qmail_open(&qq) == -1) resources(); | |
125 | qp = qmail_qp(&qq); | |
126 | ||
127 | substdio_get(&ssin,&ch,1); | |
128 | --len; | |
129 | if (ch == 10) flagdos = 0; | |
130 | else if (ch == 13) flagdos = 1; | |
131 | else badproto(); | |
132 | ||
133 | received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0); | |
134 | ||
135 | /* XXX: check for loops? only if len is big? */ | |
136 | ||
137 | if (flagdos) | |
138 | while (len > 0) { | |
139 | substdio_get(&ssin,&ch,1); | |
140 | --len; | |
141 | while ((ch == 13) && len) { | |
142 | substdio_get(&ssin,&ch,1); | |
143 | --len; | |
144 | if (ch == 10) break; | |
145 | if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); | |
146 | qmail_put(&qq,"\015",1); | |
2117e02e | 147 | } |
212b6f5d MW |
148 | if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); |
149 | qmail_put(&qq,&ch,1); | |
2117e02e | 150 | } |
212b6f5d MW |
151 | else { |
152 | if (databytes) | |
153 | if (len > databytes) { | |
154 | bytestooverflow = 0; | |
155 | qmail_fail(&qq); | |
156 | } | |
157 | while (len > 0) { /* XXX: could speed this up, obviously */ | |
158 | substdio_get(&ssin,&ch,1); | |
159 | --len; | |
160 | qmail_put(&qq,&ch,1); | |
2117e02e | 161 | } |
2117e02e | 162 | } |
212b6f5d MW |
163 | getcomma(); |
164 | ||
165 | len = getlen(); | |
166 | ||
167 | if (len >= 1000) { | |
168 | buf[0] = 0; | |
169 | flagsenderok = 0; | |
170 | for (i = 0;i < len;++i) | |
171 | substdio_get(&ssin,&ch,1); | |
172 | } | |
173 | else { | |
174 | for (i = 0;i < len;++i) { | |
175 | substdio_get(&ssin,buf + i,1); | |
176 | if (!buf[i]) flagsenderok = 0; | |
2117e02e | 177 | } |
212b6f5d | 178 | buf[len] = 0; |
2117e02e | 179 | } |
212b6f5d MW |
180 | getcomma(); |
181 | ||
182 | flagbother = 0; | |
183 | qmail_from(&qq,buf); | |
184 | if (!flagsenderok) qmail_fail(&qq); | |
185 | ||
186 | biglen = getlen(); | |
187 | while (biglen > 0) { | |
188 | if (!stralloc_append(&failure,"")) resources(); | |
189 | ||
190 | len = 0; | |
191 | for (;;) { | |
192 | if (!biglen) badproto(); | |
193 | substdio_get(&ssin,&ch,1); | |
194 | --biglen; | |
195 | if (ch == ':') break; | |
196 | if (len > 200000000) resources(); | |
197 | len = 10 * len + (ch - '0'); | |
2117e02e | 198 | } |
212b6f5d MW |
199 | if (len >= biglen) badproto(); |
200 | if (len + relayclientlen >= 1000) { | |
201 | failure.s[failure.len - 1] = 'L'; | |
202 | for (i = 0;i < len;++i) | |
203 | substdio_get(&ssin,&ch,1); | |
2117e02e | 204 | } |
212b6f5d MW |
205 | else { |
206 | for (i = 0;i < len;++i) { | |
207 | substdio_get(&ssin,buf + i,1); | |
208 | if (!buf[i]) failure.s[failure.len - 1] = 'N'; | |
209 | } | |
210 | buf[len] = 0; | |
211 | ||
212 | if (relayclient) | |
213 | str_copy(buf + len,relayclient); | |
214 | else | |
215 | switch(rcpthosts(buf,len)) { | |
216 | case -1: resources(); | |
217 | case 0: failure.s[failure.len - 1] = 'D'; | |
218 | } | |
219 | ||
220 | if (!failure.s[failure.len - 1]) { | |
221 | qmail_to(&qq,buf); | |
222 | flagbother = 1; | |
2117e02e | 223 | } |
2117e02e | 224 | } |
212b6f5d MW |
225 | getcomma(); |
226 | biglen -= (len + 1); | |
2117e02e | 227 | } |
212b6f5d MW |
228 | getcomma(); |
229 | ||
230 | if (!flagbother) qmail_fail(&qq); | |
231 | result = qmail_close(&qq); | |
232 | if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)"; | |
233 | if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)"; | |
234 | ||
235 | if (*result) | |
236 | len = str_len(result); | |
237 | else { | |
238 | /* success! */ | |
239 | len = 0; | |
240 | len += fmt_str(buf2 + len,"Kok "); | |
241 | len += fmt_ulong(buf2 + len,(unsigned long) now()); | |
242 | len += fmt_str(buf2 + len," qp "); | |
243 | len += fmt_ulong(buf2 + len,qp); | |
244 | buf2[len] = 0; | |
245 | result = buf2; | |
2117e02e | 246 | } |
212b6f5d MW |
247 | |
248 | len = fmt_ulong(buf,len); | |
249 | buf[len++] = ':'; | |
250 | len += fmt_str(buf + len,result); | |
251 | buf[len++] = ','; | |
252 | ||
253 | for (i = 0;i < failure.len;++i) | |
254 | switch(failure.s[i]) { | |
255 | case 0: | |
256 | substdio_put(&ssout,buf,len); | |
257 | break; | |
258 | case 'D': | |
259 | substdio_puts(&ssout,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),"); | |
260 | break; | |
261 | default: | |
262 | substdio_puts(&ssout,"46:Dsorry, I can't handle that recipient (#5.1.3),"); | |
263 | break; | |
2117e02e | 264 | } |
212b6f5d MW |
265 | |
266 | /* ssout will be flushed when we read from the network again */ | |
2117e02e MW |
267 | } |
268 | } |