s/qmail 4.2.29a
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-qmtpd.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "stralloc.h"
3#include "buffer.h"
4#include "qmail.h"
5#include "now.h"
6#include "str.h"
7#include "fmt.h"
8#include "env.h"
9#include "sig.h"
10#include "case.h"
11#include "exit.h"
12#include "scan.h"
13#include "rcpthosts.h"
14#include "auto_qmail.h"
15#include "control.h"
16#include "received.h"
17#include "ip.h"
18#include "byte.h"
19
20#define PORT_QMTP "209"
21#define PORT_QMTPS "6209"
22
26void badproto() { _exit(100); }
27void resources() { _exit(111); }
28
29ssize_t safewrite(int fd,char *buf,int len)
30{
31 int r;
32 r = write(fd,buf,len);
33 if (r <= 0) _exit(0);
34 return r;
35}
36
37char outbuf[256];
38buffer bo = BUFFER_INIT(safewrite,1,outbuf,sizeof(outbuf));
39
40ssize_t saferead(int fd,char *buf,int len)
41{
42 int r;
43 buffer_flush(&bo);
44 r = read(fd,buf,len);
45 if (r <= 0) _exit(0);
46 return r;
47}
48
49char inbuf[512];
50buffer bi = BUFFER_INIT(saferead,0,inbuf,sizeof(inbuf));
51
52unsigned long getlen()
53{
54 unsigned long len = 0;
55 char ch;
56 for (;;) {
57 buffer_get(&bi,&ch,1);
58 if (ch == ':') return len;
59 if (ch < '0' || ch > '9') resources();
60 if (len > 200000000) resources();
61 len = 10 * len + (ch - '0');
62 }
63}
64
66{
67 char ch;
68 buffer_get(&bi,&ch,1);
69 if (ch != ',') badproto();
70}
71
72unsigned int databytes = 0;
73unsigned int bytestooverflow = 0;
74struct qmail qq;
75
76char buf[1000];
77char buf2[100];
78
83char *local;
84
85stralloc failure = {0};
86stralloc protocol = {0};
87stralloc tlsinfo = {0};
88
91
94char *cipher;
99char *dnemail;
100
101int seentls = 0;
102
104{
105 tlsversion = env_get("SSL_PROTOCOL");
106 if (!tlsversion) return 0;
107 seentls = 1;
108
109 cipher = env_get("SSL_CIPHER");
110 if (!cipher) cipher = "unknown";
111 cipherperm = env_get("SSL_CIPHER_ALGKEYSIZE");
112 if (!cipherperm) cipherperm = "unknown";
113 cipherused = env_get("SSL_CIPHER_USEKEYSIZE");
114 if (!cipherused) cipherused = "unknown";
115 clientdn = env_get("SSL_CLIENT_S_DN");
116 if (clientdn) seentls = 2;
117 else
118 clientdn = "none";
119
121 if (!stralloc_cats(&tlsinfo,": ")) resources();
122 if (!stralloc_cats(&tlsinfo,cipher)) resources();
123 if (!stralloc_cats(&tlsinfo," [")) resources();
124 if (!stralloc_cats(&tlsinfo,cipherused)) resources();
125 if (!stralloc_cats(&tlsinfo,"/")) resources();
126 if (!stralloc_cats(&tlsinfo,cipherperm)) resources();
127 if (!stralloc_cats(&tlsinfo,"] \n")) resources();
128 if (!stralloc_cats(&tlsinfo," DN=")) resources();
129 if (!stralloc_cats(&tlsinfo,clientdn)) resources();
130 if (!stralloc_0(&tlsinfo)) resources();
131
132 if (!stralloc_append(&protocol,"S")) resources();
133
134 if (seentls == 2) {
135 clientcn = env_get("SSL_CLIENT_S_DN_CN");
137 dnemail = env_get("SSL_CLIENT_S_DN_Email");
138 if (!dnemail) dnemail = "unknown";
139 if (!stralloc_append(&protocol,"A")) resources();
140 relayclient = "";
141 }
142 return 1;
143}
144
145int main()
146{
147 char ch;
148 int i;
149 unsigned long biglen;
150 unsigned long len;
151 int flagdos;
152 int flagsenderok;
153 int flagbother;
154 unsigned long qp;
155 char *result;
156 char *x;
157 unsigned long u;
158
159 sig_pipeignore();
160 sig_alarmcatch(resources);
161 alarm(3600);
162
163 if (chdir(auto_qmail) == -1) resources();
164
165 if (control_init() == -1) resources();
166 if (rcpthosts_init() == -1) resources();
167
168 if (control_readint(&databytes,"control/databytes") == -1) resources();
169 x = env_get("DATABYTES");
170 if (x) { scan_ulong(x,&u); databytes = u; }
171 if (!(databytes + 1)) --databytes;
172
173 relayclient = env_get("RELAYCLIENT");
174 remotehost = env_get("TCP6REMOTEHOST");
175 if (!remotehost) remotehost = env_get("TCPREMOTEHOST");
176 if (!remotehost) remotehost = "unknown";
177 remoteinfo = env_get("TCP6REMOTEINFO");
178 if (!remoteinfo) remoteinfo = env_get("TCPREMOTEINFO");
179 remoteip = env_get("TCP6REMOTEIP");
180 if (!remoteip) remoteip = env_get("TCPREMOTEIP");
181 if (remoteip && byte_equal(remoteip,7,V4MAPPREFIX)) remoteip = remoteip + 7;
182 if (!remoteip) remoteip = "unknown";
183 local = env_get("TCP6LOCALHOST");
184 if (!local) local = env_get("TCPLOCALHOST");
185 if (!local) local = env_get("TCP6LOCALIP");
186 if (!local) local = env_get("TCPLOCALIP");
187 if (!local) local = "unknown";
188 localport = env_get("TCP6LOCALPORT");
189 if (!localport) localport = env_get("TCPLOCALPORT");
190 if (!localport) localport = "0";
191
192 if (!stralloc_copys(&protocol,"QMTP")) resources();
193 if (!case_diffs(localport,PORT_QMTPS))
194 if (!modssl_info()) resources();
195
196 if (relayclient)
197 relayclientlen = str_len(relayclient);
198
199 for (;;) {
200 if (!stralloc_copys(&failure,"")) resources();
201 flagsenderok = 1;
202
203 len = getlen();
204 if (len == 0) badproto();
205
207 if (qmail_open(&qq) == -1) resources();
208 qp = qmail_qp(&qq);
209
210 buffer_get(&bi,&ch,1);
211 --len;
212 if (ch == 10) flagdos = 0;
213 else if (ch == 13) flagdos = 1;
214 else badproto();
215
216 /* no fakehelo, no spfinfo */
217
218 received(&qq,protocol.s,local,remoteip,remotehost,remoteinfo,(char *) 0,tlsinfo.s,(char *) 0);
219
220 /* XXX: check for loops? only if len is big? */
221
222 if (flagdos)
223 while (len > 0) {
224 buffer_get(&bi,&ch,1);
225 --len;
226 while ((ch == 13) && len) {
227 buffer_get(&bi,&ch,1);
228 --len;
229 if (ch == 10) break;
231 qmail_put(&qq,"\015",1);
232 }
234 qmail_put(&qq,&ch,1);
235 }
236 else {
237 if (databytes)
238 if (len > databytes) {
239 bytestooverflow = 0;
240 qmail_fail(&qq);
241 }
242 while (len > 0) { /* XXX: could speed this up, obviously */
243 buffer_get(&bi,&ch,1);
244 --len;
245 qmail_put(&qq,&ch,1);
246 }
247 }
248 getcomma();
249
250 len = getlen();
251
252 if (len >= 1000) {
253 buf[0] = 0;
254 flagsenderok = 0;
255 for (i = 0; i < len; ++i)
256 buffer_get(&bi,&ch,1);
257 }
258 else {
259 for (i = 0; i < len; ++i) {
260 buffer_get(&bi,buf + i,1);
261 if (!buf[i]) flagsenderok = 0;
262 }
263 buf[len] = 0;
264 }
265 getcomma();
266
267 flagbother = 0;
268 qmail_from(&qq,buf);
269 if (!flagsenderok) qmail_fail(&qq);
270
271 biglen = getlen();
272 while (biglen > 0) {
273 if (!stralloc_append(&failure,"")) resources();
274
275 len = 0;
276 for (;;) {
277 if (!biglen) badproto();
278 buffer_get(&bi,&ch,1);
279 --biglen;
280 if (ch == ':') break;
281 if (ch < '0' || ch > '9') resources();
282 if (len > 200000000) resources();
283 len = 10 * len + (ch - '0');
284 }
285 if (len >= biglen) badproto();
286 if (len + relayclientlen >= 1000) {
287 failure.s[failure.len - 1] = 'L';
288 for (i = 0; i < len; ++i)
289 buffer_get(&bi,&ch,1);
290 }
291 else {
292 for (i = 0; i < len; ++i) {
293 buffer_get(&bi,buf + i,1);
294 if (!buf[i]) failure.s[failure.len - 1] = 'N';
295 }
296 buf[len] = 0;
297
298 if (relayclientlen)
299 str_copy(buf + len,relayclient);
300 if (!relayclient)
301 switch (rcpthosts(buf,len)) {
302 case -1: resources();
303 case 0: failure.s[failure.len - 1] = 'D';
304 }
305
306 if (!failure.s[failure.len - 1]) {
307 qmail_to(&qq,buf);
308 flagbother = 1;
309 }
310 }
311 getcomma();
312 biglen -= (len + 1);
313 }
314 getcomma();
315
316 if (!flagbother) qmail_fail(&qq);
317 result = qmail_close(&qq);
318 if (!flagsenderok) result = "D Unacceptable sender (#5.1.7)";
319 if (databytes) if (!bytestooverflow) result = "D Sorry, that message size exceeds my databytes limit (#5.3.4)";
320
321 if (*result)
322 len = str_len(result);
323 else {
324 /* success! */
325 len = 0;
326 len += fmt_str(buf2 + len,"K Ok ");
327 len += fmt_ulong(buf2 + len,(unsigned long) now());
328 len += fmt_str(buf2 + len," qp ");
329 len += fmt_ulong(buf2 + len,qp);
330 buf2[len] = 0;
331 result = buf2;
332 }
333
334 len = fmt_ulong(buf,len);
335 buf[len++] = ':';
336 len += fmt_str(buf + len,result);
337 buf[len++] = ',';
338
339 for (i = 0; i < failure.len; ++i)
340 switch (failure.s[i]) {
341 case 0:
342 buffer_put(&bo,buf,len);
343 break;
344 case 'D':
345 buffer_puts(&bo,"66:D Sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),");
346 break;
347 default:
348 buffer_puts(&bo,"46:D Sorry, I can't handle that recipient (#5.1.3),");
349 break;
350 }
351
352 /* bo will be flushed when we read from the network again */
353 }
354}
char auto_qmail[]
int control_readint(int *i, char *fn)
Definition: control.c:71
int control_init(void)
Definition: control.c:32
int stralloc_copys(stralloc *, char const *)
void _exit()
char qp[FMT_ULONG]
Definition: fastforward.c:53
datetime_sec now()
Definition: now.c:5
int fd
int seentls
Definition: qmail-qmtpd.c:101
stralloc tlsinfo
Definition: qmail-qmtpd.c:87
char * dnemail
Definition: qmail-qmtpd.c:99
ssize_t saferead(int fd, char *buf, int len)
Definition: qmail-qmtpd.c:40
int modssl_info()
Definition: qmail-qmtpd.c:103
char * cipherused
Definition: qmail-qmtpd.c:96
char buf2[100]
Definition: qmail-qmtpd.c:77
char * local
Definition: qmail-qmtpd.c:83
#define PORT_QMTPS
Definition: qmail-qmtpd.c:21
stralloc failure
Definition: qmail-qmtpd.c:85
char * clientdn
Definition: qmail-qmtpd.c:97
char * cipher
Definition: qmail-qmtpd.c:94
char * clientcn
Definition: qmail-qmtpd.c:98
void badproto()
Definition: qmail-qmtpd.c:26
unsigned int bytestooverflow
Definition: qmail-qmtpd.c:73
void getcomma()
Definition: qmail-qmtpd.c:65
stralloc protocol
Definition: qmail-qmtpd.c:86
char * relayclient
Definition: qmail-qmtpd.c:89
char * cipherperm
Definition: qmail-qmtpd.c:95
char * remoteip
Definition: qmail-qmtpd.c:81
char * tlsversion
Definition: qmail-qmtpd.c:93
char * ucspitls
Definition: qmail-qmtpd.c:92
char inbuf[512]
Definition: qmail-qmtpd.c:49
char * localport
Definition: qmail-qmtpd.c:82
int relayclientlen
Definition: qmail-qmtpd.c:90
buffer bi
Definition: qmail-qmtpd.c:50
char outbuf[256]
Definition: qmail-qmtpd.c:37
char buf[1000]
Definition: qmail-qmtpd.c:76
void resources()
Definition: qmail-qmtpd.c:27
char * remotehost
Definition: qmail-qmtpd.c:79
buffer bo
Definition: qmail-qmtpd.c:38
int main()
Definition: qmail-qmtpd.c:145
char * remoteinfo
Definition: qmail-qmtpd.c:80
unsigned int databytes
Definition: qmail-qmtpd.c:72
unsigned long getlen()
Definition: qmail-qmtpd.c:52
struct qmail qq
Definition: qmail-qmtpd.c:74
char * received
Definition: qmail-queue.c:67
void qmail_to(struct qmail *, char *)
Definition: qmail.c:83
void qmail_from(struct qmail *, char *)
Definition: qmail.c:73
void qmail_put(struct qmail *, char *, int)
Definition: qmail.c:63
char * qmail_close(struct qmail *)
Definition: qmail.c:90
unsigned long qmail_qp(struct qmail *)
Definition: qmail.c:53
int qmail_open(struct qmail *)
Definition: qmail.c:21
void qmail_fail(struct qmail *)
Definition: qmail.c:58
int rcpthosts_init()
Definition: rcpthosts.c:22
int rcpthosts()
ssize_t safewrite()
Definition: qmail.h:6
void write()