]>
Commit | Line | Data |
---|---|---|
4022a9ec AM |
1 | commit aa7751be078fe9a20efa2cf2a8856fadb98f4178 |
2 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
3 | Date: Sun Jun 28 15:14:02 2015 +0100 | |
4 | ||
5 | Compiler quietening | |
6 | ||
7 | diff --git a/src/src/dns.c b/src/src/dns.c | |
8 | index 64958d9..a239bec 100644 | |
9 | --- a/src/src/dns.c | |
10 | +++ b/src/src/dns.c | |
11 | @@ -40,7 +40,6 @@ fakens_search(const uschar *domain, int type, uschar *answerptr, int size) | |
12 | { | |
13 | int len = Ustrlen(domain); | |
14 | int asize = size; /* Locally modified */ | |
15 | -uschar *endname; | |
16 | uschar name[256]; | |
17 | uschar utilname[256]; | |
18 | uschar *aptr = answerptr; /* Locally modified */ | |
19 | @@ -51,7 +50,6 @@ struct stat statbuf; | |
20 | if (domain[len - 1] == '.') len--; | |
21 | Ustrncpy(name, domain, len); | |
22 | name[len] = 0; | |
23 | -endname = name + len; | |
24 | ||
25 | /* Look for the fakens utility, and if it exists, call it. */ | |
26 | ||
27 | @@ -86,7 +84,7 @@ if (stat(CS utilname, &statbuf) >= 0) | |
28 | asize -= rc; /* may need to be passed on to res_search(). */ | |
29 | } | |
30 | ||
31 | - /* If we ran out of output buffer before exhasting the return, | |
32 | + /* If we ran out of output buffer before exhausting the return, | |
33 | carry on reading and counting it. */ | |
34 | ||
35 | if (asize == 0) | |
36 | diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c | |
37 | index cf0a5d6..711ee86 100644 | |
38 | --- a/src/src/smtp_in.c | |
39 | +++ b/src/src/smtp_in.c | |
40 | @@ -3293,7 +3293,7 @@ while (done <= 0) | |
41 | pid_t pid; | |
42 | int start, end, sender_domain, recipient_domain; | |
43 | int ptr, size, rc; | |
44 | - int c, i; | |
45 | + int c; | |
46 | auth_instance *au; | |
47 | uschar *orcpt = NULL; | |
48 | int flags; | |
49 | diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c | |
50 | index e1dcd77..d8377fd 100644 | |
51 | --- a/src/src/tls-openssl.c | |
52 | +++ b/src/src/tls-openssl.c | |
53 | @@ -708,7 +708,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef | |
54 | ||
55 | if (!(ecdh = EC_KEY_new_by_curve_name(nid))) | |
56 | { | |
57 | - tls_error("Unable to create ec curve", host, NULL); | |
58 | + tls_error(US"Unable to create ec curve", host, NULL); | |
59 | return FALSE; | |
60 | } | |
61 | ||
62 | diff --git a/src/src/utf8.c b/src/src/utf8.c | |
63 | index a0ec003..8a7cf38 100644 | |
64 | --- a/src/src/utf8.c | |
65 | +++ b/src/src/utf8.c | |
66 | @@ -127,7 +127,7 @@ if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUC | |
67 | return NULL; | |
68 | } | |
69 | ||
70 | -s = stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len); | |
71 | +s = US stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len); | |
72 | res = string_copyn(s, p_len); | |
73 | free(s); | |
74 | return res; | |
75 | ||
76 | commit 5b881b5a8e0d7bc540f4b63cc9559d2cb1775965 | |
77 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
78 | Date: Thu Jul 30 09:43:51 2015 +0200 | |
79 | ||
80 | Docs: Add a note about the maximum spam bar length | |
81 | ||
82 | diff --git a/src/src/spam.h b/src/src/spam.h | |
83 | index 05ab655..2fe7380 100644 | |
84 | --- a/src/src/spam.h | |
85 | +++ b/src/src/spam.h | |
86 | @@ -12,7 +12,8 @@ | |
87 | /* timeout for reading and writing spamd */ | |
88 | #define SPAMD_TIMEOUT 120 | |
89 | ||
90 | -/* maximum length of the spam bar */ | |
91 | +/* maximum length of the spam bar, please update the | |
92 | + * spec, the max length is mentioned there */ | |
93 | #define MAX_SPAM_BAR_CHARS 50 | |
94 | ||
95 | /* SHUT_WR seems to be undefined on Unixware ? */ | |
96 | ||
97 | commit 98716abe2b636d275e866f3ad6374cb70bf6e504 | |
98 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
99 | Date: Sun Aug 2 13:44:31 2015 +0100 | |
100 | ||
101 | Testsuite: Add testcase for OCSP-nonaware client, to supporting server. Bug 1664 | |
102 | ||
103 | The logfile here is for (I hope) the passing case, though the fixed GnuTLS library | |
104 | is not yet available. Also due to the bug, client-gnutls is not usable for the | |
105 | test; client-openssl must be used - meaning that a GnuTLS-only system cannot run | |
106 | the testcase: | |
107 | ||
108 | OCSP-GnuTLS/5650 OCSP stapling, server | |
109 | ** Command 15 ("client-ssl", starting at line 98) | |
110 | ** Return code 127 (expected 0) | |
111 | ||
112 | diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c | |
113 | index 61ed0e8..e2ac17c 100644 | |
114 | --- a/src/src/tls-gnu.c | |
115 | +++ b/src/src/tls-gnu.c | |
116 | @@ -842,7 +842,7 @@ if ( !host /* server */ | |
117 | gnutls_certificate_set_ocsp_status_request_function(state->x509_cred, | |
118 | server_ocsp_stapling_cb, state->exp_tls_ocsp_file); | |
119 | ||
120 | - DEBUG(D_tls) debug_printf("Set OCSP response file %s\n", &state->exp_tls_ocsp_file); | |
121 | + DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file); | |
122 | } | |
123 | #endif | |
124 | ||
125 | ||
126 | commit 9196d5bf543d75a81ae0825a352920d27241c325 | |
127 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
128 | Date: Sun Aug 2 13:53:15 2015 +0100 | |
129 | ||
130 | GnuTLS: avoid using OCSP on buggy library versions. Bug 1664 | |
131 | ||
132 | diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c | |
133 | index e2ac17c..8aabc5c 100644 | |
134 | --- a/src/src/tls-gnu.c | |
135 | +++ b/src/src/tls-gnu.c | |
136 | @@ -176,6 +176,8 @@ static const char * const exim_default_gnutls_priority = "NORMAL"; | |
137 | ||
138 | static BOOL exim_gnutls_base_init_done = FALSE; | |
139 | ||
140 | +static BOOL gnutls_buggy_ocsp = FALSE; | |
141 | + | |
142 | ||
143 | /* ------------------------------------------------------------------------ */ | |
144 | /* macros */ | |
145 | @@ -831,18 +833,25 @@ if ( !host /* server */ | |
146 | && tls_ocsp_file | |
147 | ) | |
148 | { | |
149 | - if (!expand_check(tls_ocsp_file, US"tls_ocsp_file", | |
150 | - &state->exp_tls_ocsp_file)) | |
151 | - return DEFER; | |
152 | + if (gnutls_buggy_ocsp) | |
153 | + { | |
154 | + DEBUG(D_tls) debug_printf("GnuTLS library is buggy for OCSP; avoiding\n"); | |
155 | + } | |
156 | + else | |
157 | + { | |
158 | + if (!expand_check(tls_ocsp_file, US"tls_ocsp_file", | |
159 | + &state->exp_tls_ocsp_file)) | |
160 | + return DEFER; | |
161 | ||
162 | - /* Use the full callback method for stapling just to get observability. | |
163 | - More efficient would be to read the file once only, if it never changed | |
164 | - (due to SNI). Would need restart on file update, or watch datestamp. */ | |
165 | + /* Use the full callback method for stapling just to get observability. | |
166 | + More efficient would be to read the file once only, if it never changed | |
167 | + (due to SNI). Would need restart on file update, or watch datestamp. */ | |
168 | ||
169 | - gnutls_certificate_set_ocsp_status_request_function(state->x509_cred, | |
170 | - server_ocsp_stapling_cb, state->exp_tls_ocsp_file); | |
171 | + gnutls_certificate_set_ocsp_status_request_function(state->x509_cred, | |
172 | + server_ocsp_stapling_cb, state->exp_tls_ocsp_file); | |
173 | ||
174 | - DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file); | |
175 | + DEBUG(D_tls) debug_printf("OCSP response file = %s\n", state->exp_tls_ocsp_file); | |
176 | + } | |
177 | } | |
178 | #endif | |
179 | ||
180 | @@ -1011,6 +1020,35 @@ return OK; | |
181 | * Initialize for GnuTLS * | |
182 | *************************************************/ | |
183 | ||
184 | + | |
185 | +static BOOL | |
186 | +tls_is_buggy_ocsp(void) | |
187 | +{ | |
188 | +const uschar * s; | |
189 | +uschar maj, mid, mic; | |
190 | + | |
191 | +s = CUS gnutls_check_version(NULL); | |
192 | +maj = atoi(CCS s); | |
193 | +if (maj == 3) | |
194 | + { | |
195 | + while (*s && *s != '.') s++; | |
196 | + mid = atoi(CCS ++s); | |
197 | + if (mid <= 2) | |
198 | + return TRUE; | |
199 | + else if (mid >= 5) | |
200 | + return FALSE; | |
201 | + else | |
202 | + { | |
203 | + while (*s && *s != '.') s++; | |
204 | + mic = atoi(CCS ++s); | |
205 | + return mic <= (mid == 3 ? 16 : 3); | |
206 | + } | |
207 | + } | |
208 | +return FALSE; | |
209 | +} | |
210 | + | |
211 | + | |
212 | + | |
213 | /* Called from both server and client code. In the case of a server, errors | |
214 | before actual TLS negotiation return DEFER. | |
215 | ||
216 | @@ -1074,6 +1112,9 @@ if (!exim_gnutls_base_init_done) | |
217 | } | |
218 | #endif | |
219 | ||
220 | + if ((gnutls_buggy_ocsp = tls_is_buggy_ocsp())) | |
221 | + log_write(0, LOG_MAIN, "OCSP unusable with this GnuTLS library version"); | |
222 | + | |
223 | exim_gnutls_base_init_done = TRUE; | |
224 | } | |
225 | ||
226 | ||
227 | commit 63f0dbe0ca0aba7be3bc8807f45c8703a1cfafe1 | |
228 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
229 | Date: Thu Aug 6 21:38:33 2015 +0100 | |
230 | ||
231 | OpenSSL: fix complile on pre-EC-capable library versions | |
232 | ||
233 | diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c | |
234 | index d8377fd..b1dccb8 100644 | |
235 | --- a/src/src/tls-openssl.c | |
236 | +++ b/src/src/tls-openssl.c | |
237 | @@ -659,15 +659,15 @@ Returns: TRUE if OK (nothing to set up, or setup worked) | |
238 | static BOOL | |
239 | init_ecdh(SSL_CTX * sctx, host_item * host) | |
240 | { | |
241 | +#ifdef OPENSSL_NO_ECDH | |
242 | +return TRUE; | |
243 | +#else | |
244 | + | |
245 | EC_KEY * ecdh; | |
246 | uschar * exp_curve; | |
247 | int nid; | |
248 | BOOL rv; | |
249 | ||
250 | -#ifdef OPENSSL_NO_ECDH | |
251 | -return TRUE; | |
252 | -#else | |
253 | - | |
254 | if (host) /* No ECDH setup for clients, only for servers */ | |
255 | return TRUE; | |
256 | ||
257 | ||
258 | commit 755762fd4c420cabbcba4a9c79947e926fa82219 | |
259 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
260 | Date: Sun Aug 9 23:29:44 2015 +0200 | |
261 | ||
262 | Compiler quietening | |
263 | ||
264 | diff --git a/src/src/malware.c b/src/src/malware.c | |
265 | index 141c6ea..96af1e8 100644 | |
266 | --- a/src/src/malware.c | |
267 | +++ b/src/src/malware.c | |
268 | @@ -886,7 +886,7 @@ if (!malware_ok) | |
269 | string_sprintf("unable to read result (%s)", strerror(errno)), | |
270 | sock); | |
271 | ||
272 | - for (p[bread] = '\0'; q = Ustrchr(p, '\n'); p = q+1) | |
273 | + for (p[bread] = '\0'; (q = Ustrchr(p, '\n')); p = q+1) | |
274 | { | |
275 | *q = '\0'; | |
276 | ||
277 | @@ -1880,6 +1880,9 @@ if (!malware_ok) | |
278 | ||
279 | /* here for any unexpected response from the scanner */ | |
280 | goto endloop; | |
281 | + | |
282 | + case AVA_DONE: log_write(0, LOG_PANIC, "%s:%d:%s: should not happen", | |
283 | + __FILE__, __LINE__, __FUNCTION__); | |
284 | } | |
285 | } | |
286 | } | |
287 | diff --git a/src/src/spam.c b/src/src/spam.c | |
288 | index ca8d207..457aa3a 100644 | |
289 | --- a/src/src/spam.c | |
290 | +++ b/src/src/spam.c | |
291 | @@ -297,7 +297,7 @@ start = time(NULL); | |
292 | sd = (spamd_address_container *)store_get(sizeof(spamd_address_container)); | |
293 | ||
294 | for (sublist = address, args = 0, spamd_param_init(sd); | |
295 | - s = string_nextinlist(&sublist, &sublist_sep, NULL, 0); | |
296 | + (s = string_nextinlist(&sublist, &sublist_sep, NULL, 0)); | |
297 | args++ | |
298 | ) | |
299 | { | |
300 | diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c | |
301 | index 72808a7..19db040 100644 | |
302 | --- a/src/src/tlscert-openssl.c | |
303 | +++ b/src/src/tlscert-openssl.c | |
304 | @@ -127,7 +127,7 @@ else | |
305 | { | |
306 | struct tm tm; | |
307 | struct tm * tm_p = &tm; | |
308 | - BOOL mod_tz; | |
309 | + BOOL mod_tz = TRUE; | |
310 | uschar * tz = to_tz(US"GMT0"); /* need to call strptime with baseline TZ */ | |
311 | ||
312 | /* Parse OpenSSL ASN1_TIME_print output. A shame there seems to | |
313 | @@ -164,7 +164,7 @@ else | |
314 | } | |
315 | } | |
316 | ||
317 | - if (mod_tz); | |
318 | + if (mod_tz) | |
319 | restore_tz(tz); | |
320 | } | |
321 | BIO_free(bp); | |
322 | ||
323 | commit 4bd6107db73131e1b48f1902833fd7c637c08bda | |
324 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
325 | Date: Mon Aug 10 00:39:36 2015 +0200 | |
326 | ||
327 | Really re-select() when interrupted. | |
328 | ||
329 | diff --git a/src/src/ip.c b/src/src/ip.c | |
330 | index ead7299..cb54f16 100644 | |
331 | --- a/src/src/ip.c | |
332 | +++ b/src/src/ip.c | |
333 | @@ -499,7 +499,7 @@ do | |
334 | ||
335 | /* If the socket is ready, break out of the loop. */ | |
336 | } | |
337 | -while (!FD_ISSET(fd, &select_inset)); | |
338 | +while (rc < 0 || !FD_ISSET(fd, &select_inset)); | |
339 | return TRUE; | |
340 | } | |
341 | ||
342 | ||
343 | commit 505d976aa23de4294751162dee6466e335c96fbf | |
344 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
345 | Date: Tue Aug 11 09:13:11 2015 +0200 | |
346 | ||
347 | Build: Make test_{os,parse,dbfn,string} work | |
348 | ||
349 | diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base | |
350 | index 1d5a5f6..95110e6 100644 | |
351 | --- a/src/OS/Makefile-Base | |
352 | +++ b/src/OS/Makefile-Base | |
353 | @@ -743,11 +743,11 @@ sa-os.o: $(HDRS) os.c | |
354 | # These are the test targets themselves | |
355 | ||
356 | test_dbfn: config.h dbfn.c dummies.o sa-globals.o sa-os.o store.o \ | |
357 | - string.o tod.o version.o | |
358 | + string.o tod.o version.o utf8.o | |
359 | $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE dbfn.c | |
360 | $(LNCC) -o test_dbfn $(LFLAGS) dbfn.o \ | |
361 | dummies.o sa-globals.o sa-os.o store.o string.o \ | |
362 | - tod.o version.o $(LIBS) $(DBMLIB) | |
363 | + tod.o version.o utf8.o $(LIBS) $(DBMLIB) $(LDFLAGS) | |
364 | rm -f dbfn.o | |
365 | ||
366 | test_host: config.h child.c host.c dns.c dummies.c sa-globals.o os.o \ | |
367 | @@ -761,23 +761,24 @@ test_host: config.h child.c host.c dns.c dummies.c sa-globals.o os.o \ | |
368 | tod.o tree.o $(LIBS) $(LIBRESOLV) | |
369 | rm -f child.o dummies.o host.o dns.o | |
370 | ||
371 | -test_os: os.h os.c dummies.o sa-globals.o store.o string.o tod.o | |
372 | +test_os: os.h os.c dummies.o sa-globals.o store.o string.o tod.o utf8.o | |
373 | $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE os.c | |
374 | $(LNCC) -o test_os $(LFLAGS) os.o dummies.o \ | |
375 | - sa-globals.o store.o string.o tod.o $(LIBS) | |
376 | + sa-globals.o store.o string.o tod.o utf8.o $(LIBS) $(LDFLAGS) | |
377 | rm -f os.o | |
378 | ||
379 | test_parse: config.h parse.c dummies.o sa-globals.o \ | |
380 | - store.o string.o tod.o version.o | |
381 | + store.o string.o tod.o version.o utf8.o | |
382 | $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE parse.c | |
383 | $(LNCC) -o test_parse $(LFLAGS) parse.o \ | |
384 | - dummies.o sa-globals.o store.o string.o tod.o version.o | |
385 | + dummies.o sa-globals.o store.o string.o tod.o version.o \ | |
386 | + utf8.o $(LDFLAGS) | |
387 | rm -f parse.o | |
388 | ||
389 | -test_string: config.h string.c dummies.o sa-globals.o store.o tod.o | |
390 | +test_string: config.h string.c dummies.o sa-globals.o store.o tod.o utf8.o | |
391 | $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE string.c | |
392 | $(LNCC) -o test_string $(LFLAGS) -DSTAND_ALONE string.o \ | |
393 | - dummies.o sa-globals.o store.o tod.o $(LIBS) | |
394 | + dummies.o sa-globals.o store.o tod.o utf8.o $(LIBS) $(LDFLAGS) | |
395 | rm -f string.o | |
396 | ||
397 | # End | |
398 | diff --git a/src/src/host.c b/src/src/host.c | |
399 | index 94126d4..31c2bbf 100644 | |
400 | --- a/src/src/host.c | |
401 | +++ b/src/src/host.c | |
402 | @@ -3212,7 +3212,7 @@ while (Ufgets(buffer, 256, stdin) != NULL) | |
403 | else | |
404 | { | |
405 | int flags = whichrrs; | |
406 | - dnssec d; | |
407 | + dnssec_domains d; | |
408 | ||
409 | h.name = buffer; | |
410 | h.next = NULL; | |
411 | ||
412 | commit 2ef7ed082481b2dccd3c2e0eae849b24bf0b172a | |
413 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
414 | Date: Tue Aug 11 17:36:29 2015 +0200 | |
415 | ||
416 | Fix ESMTP MAIL command option processing | |
417 | ||
418 | If the address containes spaces, the option processing | |
419 | was confused. | |
420 | ||
421 | diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c | |
422 | index 711ee86..effc636 100644 | |
423 | --- a/src/src/smtp_in.c | |
424 | +++ b/src/src/smtp_in.c | |
425 | @@ -9,6 +9,7 @@ | |
426 | ||
427 | ||
428 | #include "exim.h" | |
429 | +#include <assert.h> | |
430 | ||
431 | ||
432 | /* Initialize for TCP wrappers if so configured. It appears that the macro | |
433 | @@ -232,6 +233,7 @@ static uschar *protocols[] = { | |
434 | ||
435 | /* Sanity check and validate optional args to MAIL FROM: envelope */ | |
436 | enum { | |
437 | + ENV_MAIL_OPT_NULL, | |
438 | ENV_MAIL_OPT_SIZE, ENV_MAIL_OPT_BODY, ENV_MAIL_OPT_AUTH, | |
439 | #ifndef DISABLE_PRDR | |
440 | ENV_MAIL_OPT_PRDR, | |
441 | @@ -240,7 +242,6 @@ enum { | |
442 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
443 | ENV_MAIL_OPT_UTF8, | |
444 | #endif | |
445 | - ENV_MAIL_OPT_NULL | |
446 | }; | |
447 | typedef struct { | |
448 | uschar * name; /* option requested during MAIL cmd */ | |
449 | @@ -260,7 +261,8 @@ static env_mail_type_t env_mail_type_list[] = { | |
450 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
451 | { US"SMTPUTF8",ENV_MAIL_OPT_UTF8, FALSE }, /* rfc6531 */ | |
452 | #endif | |
453 | - { US"NULL", ENV_MAIL_OPT_NULL, FALSE } | |
454 | + /* keep this the last entry */ | |
455 | + { US"NULL", ENV_MAIL_OPT_NULL, FALSE }, | |
456 | }; | |
457 | ||
458 | /* When reading SMTP from a remote host, we have to use our own versions of the | |
459 | @@ -3887,7 +3889,7 @@ while (done <= 0) | |
460 | if (!extract_option(&name, &value)) break; | |
461 | ||
462 | for (mail_args = env_mail_type_list; | |
463 | - (char *)mail_args < (char *)env_mail_type_list + sizeof(env_mail_type_list); | |
464 | + mail_args->value != ENV_MAIL_OPT_NULL; | |
465 | mail_args++ | |
466 | ) | |
467 | if (strcmpic(name, mail_args->name) == 0) | |
468 | @@ -4066,15 +4068,17 @@ while (done <= 0) | |
469 | } | |
470 | break; | |
471 | #endif | |
472 | - /* Unknown option. Stick back the terminator characters and break | |
473 | + /* No valid option. Stick back the terminator characters and break | |
474 | the loop. Do the name-terminator second as extract_option sets | |
475 | - value==name when it found no equal-sign. | |
476 | - An error for a malformed address will occur. */ | |
477 | - default: | |
478 | + value==name when it found no equal-sign. | |
479 | + An error for a malformed address will occur. */ | |
480 | + case ENV_MAIL_OPT_NULL: | |
481 | value[-1] = '='; | |
482 | name[-1] = ' '; | |
483 | arg_error = TRUE; | |
484 | break; | |
485 | + | |
486 | + default: assert(0); | |
487 | } | |
488 | /* Break out of for loop if switch() had bad argument or | |
489 | when start of the email address is reached */ | |
490 | ||
491 | commit 4fb7df6d044a39151e72346ac0d67ac09686f704 | |
492 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
493 | Date: Tue Aug 11 22:54:53 2015 +0100 | |
494 | ||
495 | GnuTLS: avoid whining about OCSP when not requested by config | |
496 | ||
497 | diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c | |
498 | index 8aabc5c..fe18094 100644 | |
499 | --- a/src/src/tls-gnu.c | |
500 | +++ b/src/src/tls-gnu.c | |
501 | @@ -176,7 +176,9 @@ static const char * const exim_default_gnutls_priority = "NORMAL"; | |
502 | ||
503 | static BOOL exim_gnutls_base_init_done = FALSE; | |
504 | ||
505 | +#ifndef DISABLE_OCSP | |
506 | static BOOL gnutls_buggy_ocsp = FALSE; | |
507 | +#endif | |
508 | ||
509 | ||
510 | /* ------------------------------------------------------------------------ */ | |
511 | @@ -1021,6 +1023,8 @@ return OK; | |
512 | *************************************************/ | |
513 | ||
514 | ||
515 | +#ifndef DISABLE_OCSP | |
516 | + | |
517 | static BOOL | |
518 | tls_is_buggy_ocsp(void) | |
519 | { | |
520 | @@ -1047,6 +1051,7 @@ if (maj == 3) | |
521 | return FALSE; | |
522 | } | |
523 | ||
524 | +#endif | |
525 | ||
526 | ||
527 | /* Called from both server and client code. In the case of a server, errors | |
528 | @@ -1112,8 +1117,10 @@ if (!exim_gnutls_base_init_done) | |
529 | } | |
530 | #endif | |
531 | ||
532 | - if ((gnutls_buggy_ocsp = tls_is_buggy_ocsp())) | |
533 | +#ifndef DISABLE_OCSP | |
534 | + if (tls_ocsp_file && (gnutls_buggy_ocsp = tls_is_buggy_ocsp())) | |
535 | log_write(0, LOG_MAIN, "OCSP unusable with this GnuTLS library version"); | |
536 | +#endif | |
537 | ||
538 | exim_gnutls_base_init_done = TRUE; | |
539 | } | |
540 | ||
541 | commit c528cec4dbfdb6e367a6ac0ed72e2e768a9c4392 | |
542 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
543 | Date: Wed Aug 12 23:45:44 2015 +0200 | |
544 | ||
545 | Adjust the timeout after interrupted select() | |
546 | ||
547 | diff --git a/src/src/ip.c b/src/src/ip.c | |
548 | index cb54f16..7991a58 100644 | |
549 | --- a/src/src/ip.c | |
550 | +++ b/src/src/ip.c | |
551 | @@ -451,8 +451,8 @@ BOOL | |
552 | fd_ready(int fd, int timeout) | |
553 | { | |
554 | fd_set select_inset; | |
555 | -struct timeval tv; | |
556 | time_t start_recv = time(NULL); | |
557 | +int time_left = timeout; | |
558 | int rc; | |
559 | ||
560 | if (timeout <= 0) | |
561 | @@ -464,10 +464,9 @@ if (timeout <= 0) | |
562 | ||
563 | do | |
564 | { | |
565 | + struct timeval tv = { time_left, 0 }; | |
566 | FD_ZERO (&select_inset); | |
567 | FD_SET (fd, &select_inset); | |
568 | - tv.tv_sec = timeout; | |
569 | - tv.tv_usec = 0; | |
570 | ||
571 | /*DEBUG(D_transport) debug_printf("waiting for data on fd\n");*/ | |
572 | rc = select(fd + 1, (SELECT_ARG2_TYPE *)&select_inset, NULL, NULL, &tv); | |
573 | @@ -479,25 +478,24 @@ do | |
574 | Aug 2004: Somebody set up a cron job that ran exiwhat every 2 minutes, making | |
575 | the interrupt not at all rare. Since the timeout is typically more than 2 | |
576 | minutes, the effect was to block the timeout completely. To prevent this | |
577 | - happening again, we do an explicit time test. */ | |
578 | + happening again, we do an explicit time test and adjust the timeout | |
579 | + accordingly */ | |
580 | ||
581 | if (rc < 0 && errno == EINTR) | |
582 | { | |
583 | DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n"); | |
584 | - if (time(NULL) - start_recv < timeout) continue; | |
585 | - DEBUG(D_transport) debug_printf("total wait time exceeds timeout\n"); | |
586 | + /* Watch out, 'continue' jumps to the condition, not to the loops top */ | |
587 | + if (time_left = timeout - (time(NULL) - start_recv)) continue; | |
588 | } | |
589 | ||
590 | - /* Handle a timeout, and treat any other select error as a timeout, including | |
591 | - an EINTR when we have been in this loop for longer than timeout. */ | |
592 | - | |
593 | if (rc <= 0) | |
594 | { | |
595 | errno = ETIMEDOUT; | |
596 | return FALSE; | |
597 | } | |
598 | ||
599 | - /* If the socket is ready, break out of the loop. */ | |
600 | + /* Checking the FD_ISSET is not enough, if we're interrupted, the | |
601 | + select_inset may still contain the 'input'. */ | |
602 | } | |
603 | while (rc < 0 || !FD_ISSET(fd, &select_inset)); | |
604 | return TRUE; | |
605 | ||
606 | commit 85ff3cf9f3ab78c4dfa9f9ff34d27e6fe8f73c39 | |
607 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
608 | Date: Thu Aug 13 00:20:12 2015 +0200 | |
609 | ||
610 | Fix timeout adjustment in c528cec4 | |
611 | ||
612 | diff --git a/src/src/ip.c b/src/src/ip.c | |
613 | index 7991a58..2d71705 100644 | |
614 | --- a/src/src/ip.c | |
615 | +++ b/src/src/ip.c | |
616 | @@ -455,7 +455,7 @@ time_t start_recv = time(NULL); | |
617 | int time_left = timeout; | |
618 | int rc; | |
619 | ||
620 | -if (timeout <= 0) | |
621 | +if (time_left <= 0) | |
622 | { | |
623 | errno = ETIMEDOUT; | |
624 | return FALSE; | |
625 | @@ -484,8 +484,10 @@ do | |
626 | if (rc < 0 && errno == EINTR) | |
627 | { | |
628 | DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n"); | |
629 | + | |
630 | /* Watch out, 'continue' jumps to the condition, not to the loops top */ | |
631 | - if (time_left = timeout - (time(NULL) - start_recv)) continue; | |
632 | + time_left = timeout - (time(NULL) - start_recv); | |
633 | + if (time_left > 0) continue; | |
634 | } | |
635 | ||
636 | if (rc <= 0) | |
637 | ||
638 | commit 6c6d6e483411af2c087ff258f4041d38eb65e775 | |
639 | Author: Tony Finch <dot@dotat.at> | |
640 | Date: Thu Aug 13 15:16:48 2015 +0100 | |
641 | ||
642 | Overhaul the debug_selector and log_selector machinery to support variable-length bit vectors. No functional change. | |
643 | ||
644 | diff --git a/src/src/acl.c b/src/src/acl.c | |
645 | index 91ee571..f2e0ef2 100644 | |
646 | --- a/src/src/acl.c | |
647 | +++ b/src/src/acl.c | |
648 | @@ -4287,7 +4287,7 @@ while (acl != NULL) | |
649 | case ACL_WARN: | |
650 | if (cond == OK) | |
651 | acl_warn(where, *user_msgptr, *log_msgptr); | |
652 | - else if (cond == DEFER && (log_extra_selector & LX_acl_warn_skipped) != 0) | |
653 | + else if (cond == DEFER && LOGGING(acl_warn_skipped)) | |
654 | log_write(0, LOG_MAIN, "%s Warning: ACL \"warn\" statement skipped: " | |
655 | "condition test deferred%s%s", host_and_ident(TRUE), | |
656 | (*log_msgptr == NULL)? US"" : US": ", | |
657 | diff --git a/src/src/daemon.c b/src/src/daemon.c | |
658 | index 894a96f..2d10387 100644 | |
659 | --- a/src/src/daemon.c | |
660 | +++ b/src/src/daemon.c | |
661 | @@ -145,7 +145,7 @@ int dup_accept_socket = -1; | |
662 | int max_for_this_host = 0; | |
663 | int wfsize = 0; | |
664 | int wfptr = 0; | |
665 | -int use_log_write_selector = log_write_selector; | |
666 | +int save_log_selector = *log_selector; | |
667 | uschar *whofrom = NULL; | |
668 | ||
669 | void *reset_point = store_get(0); | |
670 | @@ -206,11 +206,11 @@ memory is reclaimed. */ | |
671 | ||
672 | whofrom = string_append(whofrom, &wfsize, &wfptr, 3, "[", sender_host_address, "]"); | |
673 | ||
674 | -if ((log_extra_selector & LX_incoming_port) != 0) | |
675 | +if (LOGGING(incoming_port)) | |
676 | whofrom = string_append(whofrom, &wfsize, &wfptr, 2, ":", string_sprintf("%d", | |
677 | sender_host_port)); | |
678 | ||
679 | -if ((log_extra_selector & LX_incoming_interface) != 0) | |
680 | +if (LOGGING(incoming_interface)) | |
681 | whofrom = string_append(whofrom, &wfsize, &wfptr, 4, " I=[", | |
682 | interface_address, "]:", string_sprintf("%d", interface_port)); | |
683 | ||
684 | @@ -338,11 +338,11 @@ the generalized logging code each time when the selector is false. If the | |
685 | selector is set, check whether the host is on the list for logging. If not, | |
686 | arrange to unset the selector in the subprocess. */ | |
687 | ||
688 | -if ((log_write_selector & L_smtp_connection) != 0) | |
689 | +if (LOGGING(smtp_connection)) | |
690 | { | |
691 | uschar *list = hosts_connection_nolog; | |
692 | if (list != NULL && verify_check_host(&list) == OK) | |
693 | - use_log_write_selector &= ~L_smtp_connection; | |
694 | + save_log_selector &= ~L_smtp_connection; | |
695 | else | |
696 | log_write(L_smtp_connection, LOG_MAIN, "SMTP connection from %s " | |
697 | "(TCP/IP connection count = %d)", whofrom, smtp_accept_count + 1); | |
698 | @@ -372,7 +372,7 @@ if (pid == 0) | |
699 | ||
700 | /* May have been modified for the subprocess */ | |
701 | ||
702 | - log_write_selector = use_log_write_selector; | |
703 | + *log_selector = save_log_selector; | |
704 | ||
705 | /* Get the local interface address into permanent store */ | |
706 | ||
707 | diff --git a/src/src/deliver.c b/src/src/deliver.c | |
708 | index 78f8f4b..c796de0 100644 | |
709 | --- a/src/src/deliver.c | |
710 | +++ b/src/src/deliver.c | |
711 | @@ -682,7 +682,7 @@ d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
712 | { | |
713 | s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, | |
714 | US" [", addr->host_used->address, US"]"); | |
715 | - if ((log_extra_selector & LX_outgoing_port) != 0) | |
716 | + if (LOGGING(outgoing_port)) | |
717 | s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", | |
718 | addr->host_used->port)); | |
719 | return s; | |
720 | @@ -692,10 +692,9 @@ d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
721 | static uschar * | |
722 | d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
723 | { | |
724 | - if ((log_extra_selector & LX_tls_cipher) != 0 && addr->cipher != NULL) | |
725 | + if (LOGGING(tls_cipher) && addr->cipher != NULL) | |
726 | s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher); | |
727 | - if ((log_extra_selector & LX_tls_certificate_verified) != 0 && | |
728 | - addr->cipher != NULL) | |
729 | + if (LOGGING(tls_certificate_verified) && addr->cipher != NULL) | |
730 | s = string_append(s, sizep, ptrp, 2, US" CV=", | |
731 | testflag(addr, af_cert_verified) | |
732 | ? | |
733 | @@ -706,7 +705,7 @@ d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
734 | #endif | |
735 | "yes" | |
736 | : "no"); | |
737 | - if ((log_extra_selector & LX_tls_peerdn) != 0 && addr->peerdn != NULL) | |
738 | + if (LOGGING(tls_peerdn) && addr->peerdn != NULL) | |
739 | s = string_append(s, sizep, ptrp, 3, US" DN=\"", | |
740 | string_printing(addr->peerdn), US"\""); | |
741 | return s; | |
742 | @@ -808,7 +807,7 @@ pointer to a single host item in their host list, for use by the transport. */ | |
743 | ||
744 | s = reset_point = store_get(size); | |
745 | ||
746 | -log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE); | |
747 | +log_address = string_log_address(addr, LOGGING(all_parents), TRUE); | |
748 | if (msg) | |
749 | s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address); | |
750 | else | |
751 | @@ -817,11 +816,11 @@ else | |
752 | s = string_append(s, &size, &ptr, 2, US"> ", log_address); | |
753 | } | |
754 | ||
755 | -if (log_extra_selector & LX_incoming_interface && sending_ip_address) | |
756 | +if (LOGGING(incoming_interface) && sending_ip_address) | |
757 | s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]"); | |
758 | /* for the port: string_sprintf("%d", sending_port) */ | |
759 | ||
760 | -if ((log_extra_selector & LX_sender_on_delivery) != 0 || msg) | |
761 | +if (LOGGING(sender_on_delivery) || msg) | |
762 | s = string_append(s, &size, &ptr, 3, US" F=<", | |
763 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
764 | testflag(addr, af_utf8_downcvt) | |
765 | @@ -841,8 +840,7 @@ delivery; indeed, I did for some time, until this statement crashed. The case | |
766 | when it is not set is for a delivery to /dev/null which is optimised by not | |
767 | being run at all. */ | |
768 | ||
769 | -if (used_return_path != NULL && | |
770 | - (log_extra_selector & LX_return_path_on_delivery) != 0) | |
771 | +if (used_return_path != NULL && LOGGING(return_path_on_delivery)) | |
772 | s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">"); | |
773 | ||
774 | if (msg) | |
775 | @@ -854,7 +852,7 @@ if (addr->router != NULL) | |
776 | ||
777 | s = string_append(s, &size, &ptr, 2, US" T=", addr->transport->name); | |
778 | ||
779 | -if ((log_extra_selector & LX_delivery_size) != 0) | |
780 | +if (LOGGING(delivery_size)) | |
781 | s = string_append(s, &size, &ptr, 2, US" S=", | |
782 | string_sprintf("%d", transport_count)); | |
783 | ||
784 | @@ -901,7 +899,7 @@ else | |
785 | if (addr->auth_id) | |
786 | { | |
787 | s = string_append(s, &size, &ptr, 2, US":", addr->auth_id); | |
788 | - if (log_extra_selector & LX_smtp_mailauth && addr->auth_sndr) | |
789 | + if (LOGGING(smtp_mailauth) && addr->auth_sndr) | |
790 | s = string_append(s, &size, &ptr, 2, US":", addr->auth_sndr); | |
791 | } | |
792 | } | |
793 | @@ -914,8 +912,7 @@ else | |
794 | ||
795 | /* confirmation message (SMTP (host_used) and LMTP (driver_name)) */ | |
796 | ||
797 | -if (log_extra_selector & LX_smtp_confirmation && | |
798 | - addr->message && | |
799 | +if (LOGGING(smtp_confirmation) && addr->message && | |
800 | (addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0)) | |
801 | { | |
802 | unsigned i; | |
803 | @@ -935,11 +932,11 @@ if (log_extra_selector & LX_smtp_confirmation && | |
804 | ||
805 | /* Time on queue and actual time taken to deliver */ | |
806 | ||
807 | -if ((log_extra_selector & LX_queue_time) != 0) | |
808 | +if (LOGGING(queue_time)) | |
809 | s = string_append(s, &size, &ptr, 2, US" QT=", | |
810 | readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) ); | |
811 | ||
812 | -if ((log_extra_selector & LX_deliver_time) != 0) | |
813 | +if (LOGGING(deliver_time)) | |
814 | s = string_append(s, &size, &ptr, 2, US" DT=", | |
815 | readconf_printtime(addr->more_errno)); | |
816 | ||
817 | @@ -1230,8 +1227,7 @@ else if (result == DEFER || result == PANIC) | |
818 | /* Create the address string for logging. Must not do this earlier, because | |
819 | an OK result may be changed to FAIL when a pipe returns text. */ | |
820 | ||
821 | - log_address = string_log_address(addr, | |
822 | - (log_write_selector & L_all_parents) != 0, result == OK); | |
823 | + log_address = string_log_address(addr, LOGGING(all_parents), result == OK); | |
824 | ||
825 | s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address)); | |
826 | ||
827 | @@ -1342,18 +1338,16 @@ else | |
828 | /* Create the address string for logging. Must not do this earlier, because | |
829 | an OK result may be changed to FAIL when a pipe returns text. */ | |
830 | ||
831 | - log_address = string_log_address(addr, | |
832 | - (log_write_selector & L_all_parents) != 0, result == OK); | |
833 | + log_address = string_log_address(addr, LOGGING(all_parents), result == OK); | |
834 | ||
835 | s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address)); | |
836 | ||
837 | - if ((log_extra_selector & LX_sender_on_delivery) != 0) | |
838 | + if (LOGGING(sender_on_delivery)) | |
839 | s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">"); | |
840 | ||
841 | /* Return path may not be set if no delivery actually happened */ | |
842 | ||
843 | - if (used_return_path != NULL && | |
844 | - (log_extra_selector & LX_return_path_on_delivery) != 0) | |
845 | + if (used_return_path != NULL && LOGGING(return_path_on_delivery)) | |
846 | s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">"); | |
847 | ||
848 | if (addr->router != NULL) | |
849 | @@ -4449,7 +4443,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) | |
850 | } | |
851 | ||
852 | /* Local interface address/port */ | |
853 | - if (log_extra_selector & LX_incoming_interface && sending_ip_address) | |
854 | + if (LOGGING(incoming_interface) && sending_ip_address) | |
855 | { | |
856 | uschar * ptr = big_buffer; | |
857 | sprintf(CS ptr, "%.128s", sending_ip_address); | |
858 | @@ -7365,7 +7359,7 @@ if (addr_defer == NULL) | |
859 | ||
860 | /* Log the end of this message, with queue time if requested. */ | |
861 | ||
862 | - if ((log_extra_selector & LX_queue_time_overall) != 0) | |
863 | + if (LOGGING(queue_time_overall)) | |
864 | log_write(0, LOG_MAIN, "Completed QT=%s", | |
865 | readconf_printtime( (int) ((long)time(NULL) - (long)received_time)) ); | |
866 | else | |
867 | diff --git a/src/src/exim.c b/src/src/exim.c | |
868 | index f9d57ab..d7cb5d8 100644 | |
869 | --- a/src/src/exim.c | |
870 | +++ b/src/src/exim.c | |
871 | @@ -1639,6 +1639,10 @@ if (log_buffer == NULL) | |
872 | exit(EXIT_FAILURE); | |
873 | } | |
874 | ||
875 | +/* Initialize the default log options. */ | |
876 | + | |
877 | +bits_set(log_selector, log_selector_size, log_default); | |
878 | + | |
879 | /* Set log_stderr to stderr, provided that stderr exists. This gets reset to | |
880 | NULL when the daemon is run and the file is closed. We have to use this | |
881 | indirection, because some systems don't allow writing to the variable "stderr". | |
882 | @@ -2451,8 +2455,8 @@ for (i = 1; i < argc; i++) | |
883 | argrest++; | |
884 | } | |
885 | if (*argrest != 0) | |
886 | - decode_bits(&selector, NULL, D_memory, 0, argrest, debug_options, | |
887 | - debug_options_count, US"debug", 0); | |
888 | + decode_bits(&selector, 1, debug_notall, argrest, | |
889 | + debug_options, debug_options_count, US"debug", 0); | |
890 | debug_selector = selector; | |
891 | } | |
892 | break; | |
893 | @@ -3787,14 +3791,17 @@ else | |
894 | ||
895 | /* Handle the decoding of logging options. */ | |
896 | ||
897 | -decode_bits(&log_write_selector, &log_extra_selector, 0, 0, | |
898 | +decode_bits(log_selector, log_selector_size, log_notall, | |
899 | log_selector_string, log_options, log_options_count, US"log", 0); | |
900 | ||
901 | DEBUG(D_any) | |
902 | { | |
903 | + int i; | |
904 | debug_printf("configuration file is %s\n", config_main_filename); | |
905 | - debug_printf("log selectors = %08x %08x\n", log_write_selector, | |
906 | - log_extra_selector); | |
907 | + debug_printf("log selectors ="); | |
908 | + for (i = 0; i < log_selector_size; i++) | |
909 | + debug_printf(" %08x", log_selector[i]); | |
910 | + debug_printf("\n"); | |
911 | } | |
912 | ||
913 | /* If domain literals are not allowed, check the sender address that was | |
914 | @@ -4001,7 +4008,7 @@ a debugging feature for finding out what arguments certain MUAs actually use. | |
915 | Don't attempt it if logging is disabled, or if listing variables or if | |
916 | verifying/testing addresses or expansions. */ | |
917 | ||
918 | -if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0) | |
919 | +if (((debug_selector & D_any) != 0 || LOGGING(arguments)) | |
920 | && really_exim && !list_options && !checking) | |
921 | { | |
922 | int i; | |
923 | @@ -4036,7 +4043,7 @@ if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0) | |
924 | while (*p) p++; | |
925 | } | |
926 | ||
927 | - if ((log_extra_selector & LX_arguments) != 0) | |
928 | + if (LOGGING(arguments)) | |
929 | log_write(0, LOG_MAIN, "%s", big_buffer); | |
930 | else | |
931 | debug_printf("%s\n", big_buffer); | |
932 | @@ -5021,7 +5028,7 @@ if (host_checking) | |
933 | sender_host_address); | |
934 | ||
935 | if (verify_check_host(&hosts_connection_nolog) == OK) | |
936 | - log_write_selector &= ~L_smtp_connection; | |
937 | + BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection); | |
938 | log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info()); | |
939 | ||
940 | /* NOTE: We do *not* call smtp_log_no_mail() if smtp_start_session() fails, | |
941 | @@ -5195,7 +5202,7 @@ if (smtp_input) | |
942 | smtp_in = stdin; | |
943 | smtp_out = stdout; | |
944 | if (verify_check_host(&hosts_connection_nolog) == OK) | |
945 | - log_write_selector &= ~L_smtp_connection; | |
946 | + BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection); | |
947 | log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info()); | |
948 | if (!smtp_start_session()) | |
949 | { | |
950 | diff --git a/src/src/functions.h b/src/src/functions.h | |
951 | index 0257904..4af0017 100644 | |
952 | --- a/src/src/functions.h | |
953 | +++ b/src/src/functions.h | |
954 | @@ -99,6 +99,9 @@ extern int auth_get_no64_data(uschar **, uschar *); | |
955 | extern uschar *auth_xtextencode(uschar *, int); | |
956 | extern int auth_xtextdecode(uschar *, uschar **); | |
957 | ||
958 | +extern void bits_clear(unsigned int *, size_t, int *); | |
959 | +extern void bits_set(unsigned int *, size_t, int *); | |
960 | + | |
961 | extern void cancel_cutthrough_connection(const char *); | |
962 | extern int check_host(void *, const uschar *, const uschar **, uschar **); | |
963 | extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...); | |
964 | @@ -123,8 +126,8 @@ extern void debug_print_ids(uschar *); | |
965 | extern void debug_print_string(uschar *); | |
966 | extern void debug_print_tree(tree_node *); | |
967 | extern void debug_vprintf(const char *, va_list); | |
968 | -extern void decode_bits(unsigned int *, unsigned int *, | |
969 | - int, int, uschar *, bit_table *, int, uschar *, int); | |
970 | +extern void decode_bits(unsigned int *, size_t, int *, | |
971 | + uschar *, bit_table *, int, uschar *, int); | |
972 | extern address_item *deliver_make_addr(uschar *, BOOL); | |
973 | extern void deliver_init(void); | |
974 | extern void delivery_log(int, address_item *, int, uschar *); | |
975 | diff --git a/src/src/globals.c b/src/src/globals.c | |
976 | index 66baffe..1344b5a 100644 | |
977 | --- a/src/src/globals.c | |
978 | +++ b/src/src/globals.c | |
979 | @@ -536,40 +536,45 @@ uschar *dccifd_options = US"header"; | |
980 | BOOL debug_daemon = FALSE; | |
981 | int debug_fd = -1; | |
982 | FILE *debug_file = NULL; | |
983 | -bit_table debug_options[] = { | |
984 | - { US"acl", D_acl }, | |
985 | - { US"all", D_all }, | |
986 | - { US"auth", D_auth }, | |
987 | - { US"deliver", D_deliver }, | |
988 | - { US"dns", D_dns }, | |
989 | - { US"dnsbl", D_dnsbl }, | |
990 | - { US"exec", D_exec }, | |
991 | - { US"expand", D_expand }, | |
992 | - { US"filter", D_filter }, | |
993 | - { US"hints_lookup", D_hints_lookup }, | |
994 | - { US"host_lookup", D_host_lookup }, | |
995 | - { US"ident", D_ident }, | |
996 | - { US"interface", D_interface }, | |
997 | - { US"lists", D_lists }, | |
998 | - { US"load", D_load }, | |
999 | - { US"local_scan", D_local_scan }, | |
1000 | - { US"lookup", D_lookup }, | |
1001 | - { US"memory", D_memory }, | |
1002 | - { US"pid", D_pid }, | |
1003 | - { US"process_info", D_process_info }, | |
1004 | - { US"queue_run", D_queue_run }, | |
1005 | - { US"receive", D_receive }, | |
1006 | - { US"resolver", D_resolver }, | |
1007 | - { US"retry", D_retry }, | |
1008 | - { US"rewrite", D_rewrite }, | |
1009 | - { US"route", D_route }, | |
1010 | - { US"timestamp", D_timestamp }, | |
1011 | - { US"tls", D_tls }, | |
1012 | - { US"transport", D_transport }, | |
1013 | - { US"uid", D_uid }, | |
1014 | - { US"verify", D_verify } | |
1015 | +int debug_notall[] = { | |
1016 | + Di_memory, | |
1017 | + -1 | |
1018 | }; | |
1019 | -int debug_options_count = sizeof(debug_options)/sizeof(bit_table); | |
1020 | +bit_table debug_options[] = { /* must be in alphabetical order */ | |
1021 | + BIT_TABLE(D, acl), | |
1022 | + BIT_TABLE(D, all), | |
1023 | + BIT_TABLE(D, auth), | |
1024 | + BIT_TABLE(D, deliver), | |
1025 | + BIT_TABLE(D, dns), | |
1026 | + BIT_TABLE(D, dnsbl), | |
1027 | + BIT_TABLE(D, exec), | |
1028 | + BIT_TABLE(D, expand), | |
1029 | + BIT_TABLE(D, filter), | |
1030 | + BIT_TABLE(D, hints_lookup), | |
1031 | + BIT_TABLE(D, host_lookup), | |
1032 | + BIT_TABLE(D, ident), | |
1033 | + BIT_TABLE(D, interface), | |
1034 | + BIT_TABLE(D, lists), | |
1035 | + BIT_TABLE(D, load), | |
1036 | + BIT_TABLE(D, local_scan), | |
1037 | + BIT_TABLE(D, lookup), | |
1038 | + BIT_TABLE(D, memory), | |
1039 | + BIT_TABLE(D, pid), | |
1040 | + BIT_TABLE(D, process_info), | |
1041 | + BIT_TABLE(D, queue_run), | |
1042 | + BIT_TABLE(D, receive), | |
1043 | + BIT_TABLE(D, resolver), | |
1044 | + BIT_TABLE(D, retry), | |
1045 | + BIT_TABLE(D, rewrite), | |
1046 | + BIT_TABLE(D, route), | |
1047 | + BIT_TABLE(D, timestamp), | |
1048 | + BIT_TABLE(D, tls), | |
1049 | + BIT_TABLE(D, transport), | |
1050 | + BIT_TABLE(D, uid), | |
1051 | + BIT_TABLE(D, verify), | |
1052 | +}; | |
1053 | +int debug_options_count = nelem(debug_options); | |
1054 | + | |
1055 | unsigned int debug_selector = 0; | |
1056 | int delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 }; | |
1057 | uschar *delay_warning_condition= | |
1058 | @@ -813,78 +818,91 @@ uid_t local_user_uid = (uid_t)(-1); | |
1059 | tree_node *localpartlist_anchor= NULL; | |
1060 | int localpartlist_count = 0; | |
1061 | uschar *log_buffer = NULL; | |
1062 | -unsigned int log_extra_selector = LX_default; | |
1063 | + | |
1064 | +int log_default[] = { /* for initializing log_selector */ | |
1065 | + Li_acl_warn_skipped, | |
1066 | + Li_connection_reject, | |
1067 | + Li_delay_delivery, | |
1068 | + Li_dnslist_defer, | |
1069 | + Li_etrn, | |
1070 | + Li_host_lookup_failed, | |
1071 | + Li_lost_incoming_connection, | |
1072 | + Li_queue_run, | |
1073 | + Li_rejected_header, | |
1074 | + Li_retry_defer, | |
1075 | + Li_sender_verify_fail, | |
1076 | + Li_size_reject, | |
1077 | + Li_skip_delivery, | |
1078 | + Li_smtp_confirmation, | |
1079 | + Li_tls_certificate_verified, | |
1080 | + Li_tls_cipher, | |
1081 | + -1 | |
1082 | +}; | |
1083 | + | |
1084 | uschar *log_file_path = US LOG_FILE_PATH | |
1085 | "\0<--------------Space to patch log_file_path->"; | |
1086 | ||
1087 | -/* Those log options with L_xxx identifiers have values less than 0x800000 and | |
1088 | -are the ones that get put into log_write_selector. They can be used in calls to | |
1089 | -log_write() to test for the bit. The options with LX_xxx identifiers have | |
1090 | -values greater than 0x80000000 and are put into log_extra_selector (without the | |
1091 | -top bit). They are never used in calls to log_write(), but are tested | |
1092 | -independently. This separation became necessary when the number of log | |
1093 | -selectors was getting close to filling a 32-bit word. */ | |
1094 | - | |
1095 | -/* Note that this list must be in alphabetical order. */ | |
1096 | - | |
1097 | -bit_table log_options[] = { | |
1098 | - { US"8bitmime", LX_8bitmime }, | |
1099 | - { US"acl_warn_skipped", LX_acl_warn_skipped }, | |
1100 | - { US"address_rewrite", L_address_rewrite }, | |
1101 | - { US"all", L_all }, | |
1102 | - { US"all_parents", L_all_parents }, | |
1103 | - { US"arguments", LX_arguments }, | |
1104 | - { US"connection_reject", L_connection_reject }, | |
1105 | - { US"delay_delivery", L_delay_delivery }, | |
1106 | - { US"deliver_time", LX_deliver_time }, | |
1107 | - { US"delivery_size", LX_delivery_size }, | |
1108 | - { US"dnslist_defer", L_dnslist_defer }, | |
1109 | - { US"etrn", L_etrn }, | |
1110 | - { US"host_lookup_failed", L_host_lookup_failed }, | |
1111 | - { US"ident_timeout", LX_ident_timeout }, | |
1112 | - { US"incoming_interface", LX_incoming_interface }, | |
1113 | - { US"incoming_port", LX_incoming_port }, | |
1114 | - { US"lost_incoming_connection", L_lost_incoming_connection }, | |
1115 | - { US"outgoing_port", LX_outgoing_port }, | |
1116 | - { US"pid", LX_pid }, | |
1117 | +int log_notall[] = { | |
1118 | + -1 | |
1119 | +}; | |
1120 | +bit_table log_options[] = { /* must be in alphabetical order */ | |
1121 | + BIT_TABLE(L, 8bitmime), | |
1122 | + BIT_TABLE(L, acl_warn_skipped), | |
1123 | + BIT_TABLE(L, address_rewrite), | |
1124 | + BIT_TABLE(L, all), | |
1125 | + BIT_TABLE(L, all_parents), | |
1126 | + BIT_TABLE(L, arguments), | |
1127 | + BIT_TABLE(L, connection_reject), | |
1128 | + BIT_TABLE(L, delay_delivery), | |
1129 | + BIT_TABLE(L, deliver_time), | |
1130 | + BIT_TABLE(L, delivery_size), | |
1131 | + BIT_TABLE(L, dnslist_defer), | |
1132 | + BIT_TABLE(L, etrn), | |
1133 | + BIT_TABLE(L, host_lookup_failed), | |
1134 | + BIT_TABLE(L, ident_timeout), | |
1135 | + BIT_TABLE(L, incoming_interface), | |
1136 | + BIT_TABLE(L, incoming_port), | |
1137 | + BIT_TABLE(L, lost_incoming_connection), | |
1138 | + BIT_TABLE(L, outgoing_port), | |
1139 | + BIT_TABLE(L, pid), | |
1140 | #ifdef EXPERIMENTAL_PROXY | |
1141 | - { US"proxy", LX_proxy }, | |
1142 | + BIT_TABLE(L, proxy), | |
1143 | #endif | |
1144 | - { US"queue_run", L_queue_run }, | |
1145 | - { US"queue_time", LX_queue_time }, | |
1146 | - { US"queue_time_overall", LX_queue_time_overall }, | |
1147 | - { US"received_recipients", LX_received_recipients }, | |
1148 | - { US"received_sender", LX_received_sender }, | |
1149 | - { US"rejected_header", LX_rejected_header }, | |
1150 | - { US"rejected_headers", LX_rejected_header }, | |
1151 | - { US"retry_defer", L_retry_defer }, | |
1152 | - { US"return_path_on_delivery", LX_return_path_on_delivery }, | |
1153 | - { US"sender_on_delivery", LX_sender_on_delivery }, | |
1154 | - { US"sender_verify_fail", LX_sender_verify_fail }, | |
1155 | - { US"size_reject", L_size_reject }, | |
1156 | - { US"skip_delivery", L_skip_delivery }, | |
1157 | - { US"smtp_confirmation", LX_smtp_confirmation }, | |
1158 | - { US"smtp_connection", L_smtp_connection }, | |
1159 | - { US"smtp_incomplete_transaction", L_smtp_incomplete_transaction }, | |
1160 | - { US"smtp_mailauth", LX_smtp_mailauth }, | |
1161 | - { US"smtp_no_mail", LX_smtp_no_mail }, | |
1162 | - { US"smtp_protocol_error", L_smtp_protocol_error }, | |
1163 | - { US"smtp_syntax_error", L_smtp_syntax_error }, | |
1164 | - { US"subject", LX_subject }, | |
1165 | - { US"tls_certificate_verified", LX_tls_certificate_verified }, | |
1166 | - { US"tls_cipher", LX_tls_cipher }, | |
1167 | - { US"tls_peerdn", LX_tls_peerdn }, | |
1168 | - { US"tls_sni", LX_tls_sni }, | |
1169 | - { US"unknown_in_list", LX_unknown_in_list } | |
1170 | + BIT_TABLE(L, queue_run), | |
1171 | + BIT_TABLE(L, queue_time), | |
1172 | + BIT_TABLE(L, queue_time_overall), | |
1173 | + BIT_TABLE(L, received_recipients), | |
1174 | + BIT_TABLE(L, received_sender), | |
1175 | + BIT_TABLE(L, rejected_header), | |
1176 | + { US"rejected_headers", Li_rejected_header }, | |
1177 | + BIT_TABLE(L, retry_defer), | |
1178 | + BIT_TABLE(L, return_path_on_delivery), | |
1179 | + BIT_TABLE(L, sender_on_delivery), | |
1180 | + BIT_TABLE(L, sender_verify_fail), | |
1181 | + BIT_TABLE(L, size_reject), | |
1182 | + BIT_TABLE(L, skip_delivery), | |
1183 | + BIT_TABLE(L, smtp_confirmation), | |
1184 | + BIT_TABLE(L, smtp_connection), | |
1185 | + BIT_TABLE(L, smtp_incomplete_transaction), | |
1186 | + BIT_TABLE(L, smtp_mailauth), | |
1187 | + BIT_TABLE(L, smtp_no_mail), | |
1188 | + BIT_TABLE(L, smtp_protocol_error), | |
1189 | + BIT_TABLE(L, smtp_syntax_error), | |
1190 | + BIT_TABLE(L, subject), | |
1191 | + BIT_TABLE(L, tls_certificate_verified), | |
1192 | + BIT_TABLE(L, tls_cipher), | |
1193 | + BIT_TABLE(L, tls_peerdn), | |
1194 | + BIT_TABLE(L, tls_sni), | |
1195 | + BIT_TABLE(L, unknown_in_list), | |
1196 | }; | |
1197 | +int log_options_count = nelem(log_options); | |
1198 | ||
1199 | -int log_options_count = sizeof(log_options)/sizeof(bit_table); | |
1200 | int log_reject_target = 0; | |
1201 | +unsigned int log_selector[log_selector_size]; /* initialized in main() */ | |
1202 | uschar *log_selector_string = NULL; | |
1203 | FILE *log_stderr = NULL; | |
1204 | BOOL log_testing_mode = FALSE; | |
1205 | BOOL log_timezone = FALSE; | |
1206 | -unsigned int log_write_selector= L_default; | |
1207 | uschar *login_sender_address = NULL; | |
1208 | uschar *lookup_dnssec_authenticated = NULL; | |
1209 | int lookup_open_max = 25; | |
1210 | diff --git a/src/src/globals.h b/src/src/globals.h | |
1211 | index ab03302..978a4cc 100644 | |
1212 | --- a/src/src/globals.h | |
1213 | +++ b/src/src/globals.h | |
1214 | @@ -319,6 +319,7 @@ extern uschar *dccifd_options; /* options for the dccifd daemon */ | |
1215 | extern BOOL debug_daemon; /* Debug the daemon process only */ | |
1216 | extern int debug_fd; /* The fd for debug_file */ | |
1217 | extern FILE *debug_file; /* Where to write debugging info */ | |
1218 | +extern int debug_notall[]; /* Debug options excluded from +all */ | |
1219 | extern bit_table debug_options[]; /* Table of debug options */ | |
1220 | extern int debug_options_count; /* Size of table */ | |
1221 | extern int delay_warning[]; /* Times between warnings */ | |
1222 | @@ -531,16 +532,17 @@ extern uid_t local_user_uid; /* As it says; may be set in routers */ | |
1223 | extern tree_node *localpartlist_anchor;/* Tree of defined localpart lists */ | |
1224 | extern int localpartlist_count; /* Number defined */ | |
1225 | extern uschar *log_buffer; /* For constructing log entries */ | |
1226 | -extern unsigned int log_extra_selector;/* Bit map of logging options other than used by log_write() */ | |
1227 | +extern int log_default[]; /* Initialization list for log_selector */ | |
1228 | extern uschar *log_file_path; /* If unset, use default */ | |
1229 | +extern int log_notall[]; /* Log options excluded from +all */ | |
1230 | extern bit_table log_options[]; /* Table of options */ | |
1231 | extern int log_options_count; /* Size of table */ | |
1232 | extern int log_reject_target; /* Target log for ACL rejections */ | |
1233 | +extern unsigned int log_selector[]; /* Bit map of logging options */ | |
1234 | extern uschar *log_selector_string; /* As supplied in the config */ | |
1235 | extern FILE *log_stderr; /* Copy of stderr for log use, or NULL */ | |
1236 | extern BOOL log_testing_mode; /* TRUE in various testing modes */ | |
1237 | extern BOOL log_timezone; /* TRUE to include the timezone in log lines */ | |
1238 | -extern unsigned int log_write_selector;/* Bit map of logging options for log_write() */ | |
1239 | extern uschar *login_sender_address; /* The actual sender address */ | |
1240 | extern lookup_info **lookup_list; /* Array of pointers to available lookups */ | |
1241 | extern int lookup_list_count; /* Number of entries in the list */ | |
1242 | diff --git a/src/src/host.c b/src/src/host.c | |
1243 | index 31c2bbf..5c69c7f 100644 | |
1244 | --- a/src/src/host.c | |
1245 | +++ b/src/src/host.c | |
1246 | @@ -544,7 +544,7 @@ use this directly as the first item for Received: because it ain't an RFC 2822 | |
1247 | domain. Sigh. */ | |
1248 | ||
1249 | address = string_sprintf("[%s]:%d", sender_host_address, sender_host_port); | |
1250 | -if ((log_extra_selector & LX_incoming_port) == 0 || sender_host_port <= 0) | |
1251 | +if (!LOGGING(incoming_port) || sender_host_port <= 0) | |
1252 | *(Ustrrchr(address, ':')) = 0; | |
1253 | ||
1254 | /* If there's no EHLO/HELO data, we can't show it. */ | |
1255 | @@ -695,8 +695,7 @@ else | |
1256 | { | |
1257 | uschar *flag = useflag? US"H=" : US""; | |
1258 | uschar *iface = US""; | |
1259 | - if ((log_extra_selector & LX_incoming_interface) != 0 && | |
1260 | - interface_address != NULL) | |
1261 | + if (LOGGING(incoming_interface) && interface_address != NULL) | |
1262 | iface = string_sprintf(" I=[%s]:%d", interface_address, interface_port); | |
1263 | if (sender_ident == NULL) | |
1264 | (void)string_format(big_buffer, big_buffer_size, "%s%s%s", | |
1265 | diff --git a/src/src/log.c b/src/src/log.c | |
1266 | index 11b3edf..b2d1fcf 100644 | |
1267 | --- a/src/src/log.c | |
1268 | +++ b/src/src/log.c | |
1269 | @@ -613,7 +613,7 @@ If a message_id exists, we include it after the timestamp. | |
1270 | ||
1271 | Arguments: | |
1272 | selector write to main log or LOG_INFO only if this value is zero, or if | |
1273 | - its bit is set in log_write_selector | |
1274 | + its bit is set in log_selector[0] | |
1275 | flags each bit indicates some independent action: | |
1276 | LOG_SENDER add raw sender to the message | |
1277 | LOG_RECIPIENTS add raw recipients list to message | |
1278 | @@ -749,15 +749,12 @@ DEBUG(D_any|D_v) | |
1279 | Ustrcpy(ptr, "LOG:"); | |
1280 | ptr += 4; | |
1281 | ||
1282 | - /* Show the options that were passed into the call. These are those whose | |
1283 | - flag values do not have the 0x80000000 bit in them. Note that this | |
1284 | - automatically exclude the "all" setting. */ | |
1285 | + /* Show the selector that was passed into the call. */ | |
1286 | ||
1287 | for (i = 0; i < log_options_count; i++) | |
1288 | { | |
1289 | unsigned int bit = log_options[i].bit; | |
1290 | - if ((bit & 0x80000000) != 0) continue; | |
1291 | - if ((selector & bit) != 0) | |
1292 | + if (bit < BITWORDSIZE && selector == BIT(bit)) | |
1293 | { | |
1294 | *ptr++ = ' '; | |
1295 | Ustrcpy(ptr, log_options[i].name); | |
1296 | @@ -809,7 +806,7 @@ ptr = log_buffer; | |
1297 | sprintf(CS ptr, "%s ", tod_stamp(tod_log)); | |
1298 | while(*ptr) ptr++; | |
1299 | ||
1300 | -if ((log_extra_selector & LX_pid) != 0) | |
1301 | +if (LOGGING(pid)) | |
1302 | { | |
1303 | sprintf(CS ptr, "[%d] ", (int)getpid()); | |
1304 | while (*ptr) ptr++; | |
1305 | @@ -869,7 +866,7 @@ or unless there is no log_stderr (expn called from daemon, for example). */ | |
1306 | if (!really_exim || log_testing_mode) | |
1307 | { | |
1308 | if (debug_selector == 0 && log_stderr != NULL && | |
1309 | - (selector == 0 || (selector & log_write_selector) != 0)) | |
1310 | + (selector == 0 || (selector & log_selector[0]) != 0)) | |
1311 | { | |
1312 | if (host_checking) | |
1313 | fprintf(log_stderr, "LOG: %s", CS(log_buffer + 20)); /* no timestamp */ | |
1314 | @@ -887,7 +884,7 @@ has been renamed. Therefore, do a stat() and see if the inode has changed, and | |
1315 | if so, re-open. */ | |
1316 | ||
1317 | if ((flags & LOG_MAIN) != 0 && | |
1318 | - (selector == 0 || (selector & log_write_selector) != 0)) | |
1319 | + (selector == 0 || (selector & log_selector[0]) != 0)) | |
1320 | { | |
1321 | if ((logging_mode & LOG_MODE_SYSLOG) != 0 && | |
1322 | (syslog_duplication || (flags & (LOG_REJECT|LOG_PANIC)) == 0)) | |
1323 | @@ -956,7 +953,7 @@ if ((flags & LOG_REJECT) != 0) | |
1324 | { | |
1325 | header_line *h; | |
1326 | ||
1327 | - if (header_list != NULL && (log_extra_selector & LX_rejected_header) != 0) | |
1328 | + if (header_list != NULL && LOGGING(rejected_header)) | |
1329 | { | |
1330 | if (recipients_count > 0) | |
1331 | { | |
1332 | @@ -1142,6 +1139,35 @@ syslog_open = FALSE; | |
1333 | ||
1334 | ||
1335 | /************************************************* | |
1336 | +* Multi-bit set or clear * | |
1337 | +*************************************************/ | |
1338 | + | |
1339 | +/* These functions take a list of bit indexes (terminated by -1) and | |
1340 | +clear or set the corresponding bits in the selector. | |
1341 | + | |
1342 | +Arguments: | |
1343 | + selector address of the bit string | |
1344 | + selsize number of words in the bit string | |
1345 | + bits list of bits to set | |
1346 | +*/ | |
1347 | + | |
1348 | +void | |
1349 | +bits_clear(unsigned int *selector, size_t selsize, int *bits) | |
1350 | +{ | |
1351 | +for(; *bits != -1; ++bits) | |
1352 | + BIT_CLEAR(selector, selsize, *bits); | |
1353 | +} | |
1354 | + | |
1355 | +void | |
1356 | +bits_set(unsigned int *selector, size_t selsize, int *bits) | |
1357 | +{ | |
1358 | +for(; *bits != -1; ++bits) | |
1359 | + BIT_SET(selector, selsize, *bits); | |
1360 | +} | |
1361 | + | |
1362 | + | |
1363 | + | |
1364 | +/************************************************* | |
1365 | * Decode bit settings for log/debug * | |
1366 | *************************************************/ | |
1367 | ||
1368 | @@ -1151,13 +1177,9 @@ also recognizes a numeric setting of the form =<number>, but this is not | |
1369 | intended for user use. It's an easy way for Exim to pass the debug settings | |
1370 | when it is re-exec'ed. | |
1371 | ||
1372 | -The log options are held in two unsigned ints (because there became too many | |
1373 | -for one). The top bit in the table means "put in 2nd selector". This does not | |
1374 | -yet apply to debug options, so the "=" facility sets only the first selector. | |
1375 | - | |
1376 | -The "all" selector, which must be equal to 0xffffffff, is recognized specially. | |
1377 | -It sets all the bits in both selectors. However, there is a facility for then | |
1378 | -unsetting certain bits, because we want to turn off "memory" in the debug case. | |
1379 | +The option table is a list of names and bit indexes. The index -1 | |
1380 | +means "set all bits, except for those listed in notall". The notall | |
1381 | +list is terminated by -1. | |
1382 | ||
1383 | The action taken for bad values varies depending upon why we're here. | |
1384 | For log messages, or if the debugging is triggered from config, then we write | |
1385 | @@ -1165,10 +1187,9 @@ to the log on the way out. For debug setting triggered from the command-line, | |
1386 | we treat it as an unknown option: error message to stderr and die. | |
1387 | ||
1388 | Arguments: | |
1389 | - selector1 address of the first bit string | |
1390 | - selector2 address of the second bit string, or NULL | |
1391 | - notall1 bits to exclude from "all" for selector1 | |
1392 | - notall2 bits to exclude from "all" for selector2 | |
1393 | + selector address of the bit string | |
1394 | + selsize number of words in the bit string | |
1395 | + notall list of bits to exclude from "all" | |
1396 | string the configured string | |
1397 | options the table of option names | |
1398 | count size of table | |
1399 | @@ -1179,9 +1200,8 @@ Returns: nothing on success - bomb out on failure | |
1400 | */ | |
1401 | ||
1402 | void | |
1403 | -decode_bits(unsigned int *selector1, unsigned int *selector2, int notall1, | |
1404 | - int notall2, uschar *string, bit_table *options, int count, uschar *which, | |
1405 | - int flags) | |
1406 | +decode_bits(unsigned int *selector, size_t selsize, int *notall, | |
1407 | + uschar *string, bit_table *options, int count, uschar *which, int flags) | |
1408 | { | |
1409 | uschar *errmsg; | |
1410 | if (string == NULL) return; | |
1411 | @@ -1189,7 +1209,8 @@ if (string == NULL) return; | |
1412 | if (*string == '=') | |
1413 | { | |
1414 | char *end; /* Not uschar */ | |
1415 | - *selector1 = strtoul(CS string+1, &end, 0); | |
1416 | + memset(selector, 0, sizeof(*selector)*selsize); | |
1417 | + *selector = strtoul(CS string+1, &end, 0); | |
1418 | if (*end == 0) return; | |
1419 | errmsg = string_sprintf("malformed numeric %s_selector setting: %s", which, | |
1420 | string); | |
1421 | @@ -1232,40 +1253,22 @@ else for(;;) | |
1422 | if (middle->name[len] != 0) c = -1; else | |
1423 | { | |
1424 | unsigned int bit = middle->bit; | |
1425 | - unsigned int *selector; | |
1426 | - | |
1427 | - /* The value with all bits set means "force all bits in both selectors" | |
1428 | - in the case where two are being handled. However, the top bit in the | |
1429 | - second selector is never set. When setting, some bits can be excluded. | |
1430 | - */ | |
1431 | - | |
1432 | - if (bit == 0xffffffff) | |
1433 | - { | |
1434 | - if (adding) | |
1435 | - { | |
1436 | - *selector1 = 0xffffffff ^ notall1; | |
1437 | - if (selector2 != NULL) *selector2 = 0x7fffffff ^ notall2; | |
1438 | - } | |
1439 | - else | |
1440 | - { | |
1441 | - *selector1 = 0; | |
1442 | - if (selector2 != NULL) *selector2 = 0; | |
1443 | - } | |
1444 | - } | |
1445 | - | |
1446 | - /* Otherwise, the 0x80000000 bit means "this value, without the top | |
1447 | - bit, belongs in the second selector". */ | |
1448 | ||
1449 | - else | |
1450 | - { | |
1451 | - if ((bit & 0x80000000) != 0) | |
1452 | - { | |
1453 | - selector = selector2; | |
1454 | - bit &= 0x7fffffff; | |
1455 | - } | |
1456 | - else selector = selector1; | |
1457 | - if (adding) *selector |= bit; else *selector &= ~bit; | |
1458 | - } | |
1459 | + if (bit == -1) | |
1460 | + { | |
1461 | + if (adding) | |
1462 | + { | |
1463 | + memset(selector, -1, sizeof(*selector)*selsize); | |
1464 | + bits_clear(selector, selsize, notall); | |
1465 | + } | |
1466 | + else | |
1467 | + memset(selector, 0, sizeof(*selector)*selsize); | |
1468 | + } | |
1469 | + else if (adding) | |
1470 | + BIT_SET(selector, selsize, bit); | |
1471 | + else | |
1472 | + BIT_CLEAR(selector, selsize, bit); | |
1473 | + | |
1474 | break; /* Out of loop to match selector name */ | |
1475 | } | |
1476 | } | |
1477 | @@ -1335,10 +1338,8 @@ if (tag_name != NULL && (Ustrchr(tag_name, '/') != NULL)) | |
1478 | ||
1479 | debug_selector = D_default; | |
1480 | if (opts) | |
1481 | - { | |
1482 | - decode_bits(&debug_selector, NULL, D_memory, 0, opts, | |
1483 | + decode_bits(&debug_selector, 1, debug_notall, opts, | |
1484 | debug_options, debug_options_count, US"debug", DEBUG_FROM_CONFIG); | |
1485 | - } | |
1486 | ||
1487 | /* When activating from a transport process we may never have logged at all | |
1488 | resulting in certain setup not having been done. Hack this for now so we | |
1489 | diff --git a/src/src/macros.h b/src/src/macros.h | |
1490 | index 61f9ca6..d63025e 100644 | |
1491 | --- a/src/src/macros.h | |
1492 | +++ b/src/src/macros.h | |
1493 | @@ -321,46 +321,84 @@ for having to swallow the rest of an SMTP message is whether the value is | |
1494 | #define END_SIZE 4 /* Reading ended because message too big */ | |
1495 | #define END_WERROR 5 /* Write error while reading the message */ | |
1496 | ||
1497 | -/* Options bits for debugging; D_v and D_local_scan are also in local_scan.h */ | |
1498 | - | |
1499 | -#define D_v 0x00000001 | |
1500 | -#define D_local_scan 0x00000002 | |
1501 | - | |
1502 | -#define D_acl 0x00000004 | |
1503 | -#define D_auth 0x00000008 | |
1504 | -#define D_deliver 0x00000010 | |
1505 | -#define D_dns 0x00000020 | |
1506 | -#define D_dnsbl 0x00000040 | |
1507 | -#define D_exec 0x00000080 | |
1508 | -#define D_expand 0x00000100 | |
1509 | -#define D_filter 0x00000200 | |
1510 | -#define D_hints_lookup 0x00000400 | |
1511 | -#define D_host_lookup 0x00000800 | |
1512 | -#define D_ident 0x00001000 | |
1513 | -#define D_interface 0x00002000 | |
1514 | -#define D_lists 0x00004000 | |
1515 | -#define D_load 0x00008000 | |
1516 | -#define D_lookup 0x00010000 | |
1517 | -#define D_memory 0x00020000 | |
1518 | -#define D_pid 0x00040000 | |
1519 | -#define D_process_info 0x00080000 | |
1520 | -#define D_queue_run 0x00100000 | |
1521 | -#define D_receive 0x00200000 | |
1522 | -#define D_resolver 0x00400000 | |
1523 | -#define D_retry 0x00800000 | |
1524 | -#define D_rewrite 0x01000000 | |
1525 | -#define D_route 0x02000000 | |
1526 | -#define D_timestamp 0x04000000 | |
1527 | -#define D_tls 0x08000000 | |
1528 | -#define D_transport 0x10000000 | |
1529 | -#define D_uid 0x20000000 | |
1530 | -#define D_verify 0x40000000 | |
1531 | - | |
1532 | -/* The D_all value must always have all bits set, as it is recognized specially | |
1533 | -by the function that decodes debug and log selectors. This is to enable it to | |
1534 | -set all the bits in a multi-word selector. Debug doesn't use this yet, but we | |
1535 | -are getting close. In fact, we want to omit "memory" for -d+all, but can't | |
1536 | -handle this here. It is fudged externally. */ | |
1537 | +/* Bit masks for debug and log selectors */ | |
1538 | + | |
1539 | +/* Assume words are 32 bits wide. Tiny waste of space on 64 bit | |
1540 | +platforms, but this ensures bit vectors always work the same way. */ | |
1541 | +#define BITWORDSIZE 32 | |
1542 | + | |
1543 | +/* This macro is for single-word bit vectors: the debug selector, | |
1544 | +and the first word of the log selector. */ | |
1545 | +#define BIT(n) (1 << (n)) | |
1546 | + | |
1547 | +/* And these are for multi-word vectors. */ | |
1548 | +#define BITWORD(n) ( (n) / BITWORDSIZE) | |
1549 | +#define BITMASK(n) (1 << (n) % BITWORDSIZE) | |
1550 | + | |
1551 | +#define BIT_CLEAR(s,z,n) ((s)[BITWORD(n)] &= ~BITMASK(n)) | |
1552 | +#define BIT_SET(s,z,n) ((s)[BITWORD(n)] |= BITMASK(n)) | |
1553 | +#define BIT_TEST(s,z,n) (((s)[BITWORD(n)] & BITMASK(n)) != 0) | |
1554 | + | |
1555 | +/* Used in globals.c for initializing bit_table structures. T will be either | |
1556 | +D or L correspondong to the debug and log selector bits declared below. */ | |
1557 | + | |
1558 | +#define BIT_TABLE(T,name) { US #name, T##i_##name } | |
1559 | + | |
1560 | +/* IOTA allows us to keep an implicit sequential count, like a simple enum, | |
1561 | +but we can have sequentially numbered identifiers which are not declared | |
1562 | +sequentially. We use this for more compact declarations of bit indexes and | |
1563 | +masks, alternating between sequential bit index and corresponding mask. */ | |
1564 | + | |
1565 | +#define IOTA(iota) (__LINE__ - iota) | |
1566 | +#define IOTA_INIT(zero) (__LINE__ - zero + 1) | |
1567 | + | |
1568 | +/* Options bits for debugging. DEBUG_BIT() declares both a bit index and the | |
1569 | +corresponding mask. Di_all is a special value recognized by decode_bits(). | |
1570 | + | |
1571 | +Exim's code assumes in a number of places that the debug_selector is one | |
1572 | +word, and this is exposed in the local_scan ABI. The D_v and D_local_scan bit | |
1573 | +masks are part of the local_scan API so are #defined in local_scan.h */ | |
1574 | + | |
1575 | +#define DEBUG_BIT(name) Di_##name = IOTA(Di_iota), D_##name = BIT(Di_##name) | |
1576 | + | |
1577 | +enum { | |
1578 | + Di_all = -1, | |
1579 | + Di_v = 0, | |
1580 | + Di_local_scan = 1, | |
1581 | + | |
1582 | + Di_iota = IOTA_INIT(2), | |
1583 | + DEBUG_BIT(acl), | |
1584 | + DEBUG_BIT(auth), | |
1585 | + DEBUG_BIT(deliver), | |
1586 | + DEBUG_BIT(dns), | |
1587 | + DEBUG_BIT(dnsbl), | |
1588 | + DEBUG_BIT(exec), | |
1589 | + DEBUG_BIT(expand), | |
1590 | + DEBUG_BIT(filter), | |
1591 | + DEBUG_BIT(hints_lookup), | |
1592 | + DEBUG_BIT(host_lookup), | |
1593 | + DEBUG_BIT(ident), | |
1594 | + DEBUG_BIT(interface), | |
1595 | + DEBUG_BIT(lists), | |
1596 | + DEBUG_BIT(load), | |
1597 | + DEBUG_BIT(lookup), | |
1598 | + DEBUG_BIT(memory), | |
1599 | + DEBUG_BIT(pid), | |
1600 | + DEBUG_BIT(process_info), | |
1601 | + DEBUG_BIT(queue_run), | |
1602 | + DEBUG_BIT(receive), | |
1603 | + DEBUG_BIT(resolver), | |
1604 | + DEBUG_BIT(retry), | |
1605 | + DEBUG_BIT(rewrite), | |
1606 | + DEBUG_BIT(route), | |
1607 | + DEBUG_BIT(timestamp), | |
1608 | + DEBUG_BIT(tls), | |
1609 | + DEBUG_BIT(transport), | |
1610 | + DEBUG_BIT(uid), | |
1611 | + DEBUG_BIT(verify), | |
1612 | +}; | |
1613 | + | |
1614 | +/* Multi-bit debug masks */ | |
1615 | ||
1616 | #define D_all 0xffffffff | |
1617 | ||
1618 | @@ -380,81 +418,67 @@ handle this here. It is fudged externally. */ | |
1619 | D_timestamp | \ | |
1620 | D_resolver)) | |
1621 | ||
1622 | -/* Options bits for logging. Those that will end up in log_write_selector have | |
1623 | -values < 0x80000000. They can be used in calls to log_write(). The others have | |
1624 | -values > 0x80000000 and are put into log_extra_selector (without the top bit). | |
1625 | -These are only ever tested independently. "All" is a magic value that is used | |
1626 | -only in the name table to set all options in both bit maps. */ | |
1627 | - | |
1628 | -/* The L_all value must always have all bits set, as it is recognized specially | |
1629 | -by the function that decodes debug and log selectors. This is to enable it to | |
1630 | -set all the bits in a multi-word selector. */ | |
1631 | - | |
1632 | -#define L_all 0xffffffff | |
1633 | - | |
1634 | -#define L_address_rewrite 0x00000001 | |
1635 | -#define L_all_parents 0x00000002 | |
1636 | -#define L_connection_reject 0x00000004 | |
1637 | -#define L_delay_delivery 0x00000008 | |
1638 | -#define L_dnslist_defer 0x00000010 | |
1639 | -#define L_etrn 0x00000020 | |
1640 | -#define L_host_lookup_failed 0x00000040 | |
1641 | -#define L_lost_incoming_connection 0x00000080 | |
1642 | -#define L_queue_run 0x00000100 | |
1643 | -#define L_retry_defer 0x00000200 | |
1644 | -#define L_size_reject 0x00000400 | |
1645 | -#define L_skip_delivery 0x00000800 | |
1646 | -#define L_smtp_connection 0x00001000 | |
1647 | -#define L_smtp_incomplete_transaction 0x00002000 | |
1648 | -#define L_smtp_protocol_error 0x00004000 | |
1649 | -#define L_smtp_syntax_error 0x00008000 | |
1650 | - | |
1651 | -#define LX_acl_warn_skipped 0x80000001 | |
1652 | -#define LX_arguments 0x80000002 | |
1653 | -#define LX_deliver_time 0x80000004 | |
1654 | -#define LX_delivery_size 0x80000008 | |
1655 | -#define LX_ident_timeout 0x80000010 | |
1656 | -#define LX_incoming_interface 0x80000020 | |
1657 | -#define LX_incoming_port 0x80000040 | |
1658 | -#define LX_outgoing_port 0x80000080 | |
1659 | -#define LX_pid 0x80000100 | |
1660 | -#define LX_queue_time 0x80000200 | |
1661 | -#define LX_queue_time_overall 0x80000400 | |
1662 | -#define LX_received_sender 0x80000800 | |
1663 | -#define LX_received_recipients 0x80001000 | |
1664 | -#define LX_rejected_header 0x80002000 | |
1665 | -#define LX_return_path_on_delivery 0x80004000 | |
1666 | -#define LX_sender_on_delivery 0x80008000 | |
1667 | -#define LX_sender_verify_fail 0x80010000 | |
1668 | -#define LX_smtp_confirmation 0x80020000 | |
1669 | -#define LX_smtp_no_mail 0x80040000 | |
1670 | -#define LX_subject 0x80080000 | |
1671 | -#define LX_tls_certificate_verified 0x80100000 | |
1672 | -#define LX_tls_cipher 0x80200000 | |
1673 | -#define LX_tls_peerdn 0x80400000 | |
1674 | -#define LX_tls_sni 0x80800000 | |
1675 | -#define LX_unknown_in_list 0x81000000 | |
1676 | -#define LX_8bitmime 0x82000000 | |
1677 | -#define LX_smtp_mailauth 0x84000000 | |
1678 | -#define LX_proxy 0x88000000 | |
1679 | - | |
1680 | -#define L_default (L_connection_reject | \ | |
1681 | - L_delay_delivery | \ | |
1682 | - L_dnslist_defer | \ | |
1683 | - L_etrn | \ | |
1684 | - L_host_lookup_failed | \ | |
1685 | - L_lost_incoming_connection | \ | |
1686 | - L_queue_run | \ | |
1687 | - L_retry_defer | \ | |
1688 | - L_size_reject | \ | |
1689 | - L_skip_delivery) | |
1690 | - | |
1691 | -#define LX_default ((LX_acl_warn_skipped | \ | |
1692 | - LX_rejected_header | \ | |
1693 | - LX_sender_verify_fail | \ | |
1694 | - LX_smtp_confirmation | \ | |
1695 | - LX_tls_certificate_verified| \ | |
1696 | - LX_tls_cipher) & 0x7fffffff) | |
1697 | +/* Options bits for logging. Those that have values < BITWORDSIZE can be used | |
1698 | +in calls to log_write(). The others are put into later words in log_selector | |
1699 | +and are only ever tested independently, so they do not need bit mask | |
1700 | +declarations. The Li_all value is recognized specially by decode_bits(). */ | |
1701 | + | |
1702 | +#define LOG_BIT(name) Li_##name = IOTA(Li_iota), L_##name = BIT(Li_##name) | |
1703 | + | |
1704 | +enum { | |
1705 | + Li_all = -1, | |
1706 | + | |
1707 | + Li_iota = IOTA_INIT(0), | |
1708 | + LOG_BIT(address_rewrite), | |
1709 | + LOG_BIT(all_parents), | |
1710 | + LOG_BIT(connection_reject), | |
1711 | + LOG_BIT(delay_delivery), | |
1712 | + LOG_BIT(dnslist_defer), | |
1713 | + LOG_BIT(etrn), | |
1714 | + LOG_BIT(host_lookup_failed), | |
1715 | + LOG_BIT(lost_incoming_connection), | |
1716 | + LOG_BIT(queue_run), | |
1717 | + LOG_BIT(retry_defer), | |
1718 | + LOG_BIT(size_reject), | |
1719 | + LOG_BIT(skip_delivery), | |
1720 | + LOG_BIT(smtp_connection), | |
1721 | + LOG_BIT(smtp_incomplete_transaction), | |
1722 | + LOG_BIT(smtp_protocol_error), | |
1723 | + LOG_BIT(smtp_syntax_error), | |
1724 | + | |
1725 | + Li_acl_warn_skipped = BITWORDSIZE, | |
1726 | + Li_arguments, | |
1727 | + Li_deliver_time, | |
1728 | + Li_delivery_size, | |
1729 | + Li_ident_timeout, | |
1730 | + Li_incoming_interface, | |
1731 | + Li_incoming_port, | |
1732 | + Li_outgoing_port, | |
1733 | + Li_pid, | |
1734 | + Li_queue_time, | |
1735 | + Li_queue_time_overall, | |
1736 | + Li_received_sender, | |
1737 | + Li_received_recipients, | |
1738 | + Li_rejected_header, | |
1739 | + Li_return_path_on_delivery, | |
1740 | + Li_sender_on_delivery, | |
1741 | + Li_sender_verify_fail, | |
1742 | + Li_smtp_confirmation, | |
1743 | + Li_smtp_no_mail, | |
1744 | + Li_subject, | |
1745 | + Li_tls_certificate_verified, | |
1746 | + Li_tls_cipher, | |
1747 | + Li_tls_peerdn, | |
1748 | + Li_tls_sni, | |
1749 | + Li_unknown_in_list, | |
1750 | + Li_8bitmime, | |
1751 | + Li_smtp_mailauth, | |
1752 | + Li_proxy, | |
1753 | + | |
1754 | + log_selector_size = BITWORD(Li_proxy) + 1 | |
1755 | +}; | |
1756 | + | |
1757 | +#define LOGGING(opt) BIT_TEST(log_selector, log_selector_size, Li_##opt) | |
1758 | ||
1759 | /* Private error numbers for delivery failures, set negative so as not | |
1760 | to conflict with system errno values. */ | |
1761 | diff --git a/src/src/match.c b/src/src/match.c | |
1762 | index 9e47110..fa42187 100644 | |
1763 | --- a/src/src/match.c | |
1764 | +++ b/src/src/match.c | |
1765 | @@ -771,7 +771,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) | |
1766 | include_unknown? "yes":"no", error); | |
1767 | if (!include_unknown) | |
1768 | { | |
1769 | - if ((log_extra_selector & LX_unknown_in_list) != 0) | |
1770 | + if (LOGGING(unknown_in_list)) | |
1771 | log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); | |
1772 | return FAIL; | |
1773 | } | |
1774 | @@ -880,7 +880,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) | |
1775 | (void)fclose(f); | |
1776 | if (!include_unknown) | |
1777 | { | |
1778 | - if ((log_extra_selector & LX_unknown_in_list) != 0) | |
1779 | + if (LOGGING(unknown_in_list)) | |
1780 | log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); | |
1781 | return FAIL; | |
1782 | } | |
1783 | diff --git a/src/src/rda.c b/src/src/rda.c | |
1784 | index 7596466..2afd6dc 100644 | |
1785 | --- a/src/src/rda.c | |
1786 | +++ b/src/src/rda.c | |
1787 | @@ -635,7 +635,7 @@ if ((pid = fork()) == 0) | |
1788 | { | |
1789 | DEBUG(D_rewrite) debug_printf("turned off address rewrite logging (not " | |
1790 | "root or exim in this process)\n"); | |
1791 | - log_write_selector &= ~L_address_rewrite; | |
1792 | + BIT_CLEAR(log_selector, log_selector_size, Li_address_rewrite); | |
1793 | } | |
1794 | ||
1795 | /* Now do the business */ | |
1796 | diff --git a/src/src/receive.c b/src/src/receive.c | |
1797 | index 64cf1ae..b430ee2 100644 | |
1798 | --- a/src/src/receive.c | |
1799 | +++ b/src/src/receive.c | |
1800 | @@ -1118,8 +1118,7 @@ add_host_info_for_log(uschar *s, int *sizeptr, int *ptrptr) | |
1801 | if (sender_fullhost != NULL) | |
1802 | { | |
1803 | s = string_append(s, sizeptr, ptrptr, 2, US" H=", sender_fullhost); | |
1804 | - if ((log_extra_selector & LX_incoming_interface) != 0 && | |
1805 | - interface_address != NULL) | |
1806 | + if (LOGGING(incoming_interface) && interface_address != NULL) | |
1807 | { | |
1808 | uschar *ss = string_sprintf(" I=[%s]:%d", interface_address, | |
1809 | interface_port); | |
1810 | @@ -2529,7 +2528,7 @@ if (msgid_header == NULL && | |
1811 | rewriting. Must copy the count, because later ACLs and the local_scan() | |
1812 | function may mess with the real recipients. */ | |
1813 | ||
1814 | -if ((log_extra_selector & LX_received_recipients) != 0) | |
1815 | +if (LOGGING(received_recipients)) | |
1816 | { | |
1817 | raw_recipients = store_get(recipients_count * sizeof(uschar *)); | |
1818 | for (i = 0; i < recipients_count; i++) | |
1819 | @@ -3573,7 +3572,7 @@ else | |
1820 | goto TEMPREJECT; | |
1821 | ||
1822 | case LOCAL_SCAN_REJECT_NOLOGHDR: | |
1823 | - log_extra_selector &= ~LX_rejected_header; | |
1824 | + BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header); | |
1825 | /* Fall through */ | |
1826 | ||
1827 | case LOCAL_SCAN_REJECT: | |
1828 | @@ -3582,7 +3581,7 @@ else | |
1829 | break; | |
1830 | ||
1831 | case LOCAL_SCAN_TEMPREJECT_NOLOGHDR: | |
1832 | - log_extra_selector &= ~LX_rejected_header; | |
1833 | + BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header); | |
1834 | /* Fall through */ | |
1835 | ||
1836 | case LOCAL_SCAN_TEMPREJECT: | |
1837 | @@ -3747,15 +3746,15 @@ if (message_reference != NULL) | |
1838 | s = add_host_info_for_log(s, &size, &sptr); | |
1839 | ||
1840 | #ifdef SUPPORT_TLS | |
1841 | -if (log_extra_selector & LX_tls_cipher && tls_in.cipher) | |
1842 | +if (LOGGING(tls_cipher) && tls_in.cipher) | |
1843 | s = string_append(s, &size, &sptr, 2, US" X=", tls_in.cipher); | |
1844 | -if (log_extra_selector & LX_tls_certificate_verified && tls_in.cipher) | |
1845 | +if (LOGGING(tls_certificate_verified) && tls_in.cipher) | |
1846 | s = string_append(s, &size, &sptr, 2, US" CV=", | |
1847 | tls_in.certificate_verified? "yes":"no"); | |
1848 | -if (log_extra_selector & LX_tls_peerdn && tls_in.peerdn) | |
1849 | +if (LOGGING(tls_peerdn) && tls_in.peerdn) | |
1850 | s = string_append(s, &size, &sptr, 3, US" DN=\"", | |
1851 | string_printing(tls_in.peerdn), US"\""); | |
1852 | -if (log_extra_selector & LX_tls_sni && tls_in.sni) | |
1853 | +if (LOGGING(tls_sni) && tls_in.sni) | |
1854 | s = string_append(s, &size, &sptr, 3, US" SNI=\"", | |
1855 | string_printing(tls_in.sni), US"\""); | |
1856 | #endif | |
1857 | @@ -3766,7 +3765,7 @@ if (sender_host_authenticated) | |
1858 | if (authenticated_id != NULL) | |
1859 | { | |
1860 | s = string_append(s, &size, &sptr, 2, US":", authenticated_id); | |
1861 | - if (log_extra_selector & LX_smtp_mailauth && authenticated_sender != NULL) | |
1862 | + if (LOGGING(smtp_mailauth) && authenticated_sender != NULL) | |
1863 | s = string_append(s, &size, &sptr, 2, US":", authenticated_sender); | |
1864 | } | |
1865 | } | |
1866 | @@ -3777,7 +3776,7 @@ if (prdr_requested) | |
1867 | #endif | |
1868 | ||
1869 | #ifdef EXPERIMENTAL_PROXY | |
1870 | -if (proxy_session && log_extra_selector & LX_proxy) | |
1871 | +if (proxy_session && LOGGING(proxy)) | |
1872 | s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address); | |
1873 | #endif | |
1874 | ||
1875 | @@ -3788,7 +3787,7 @@ s = string_append(s, &size, &sptr, 2, US" S=", big_buffer); | |
1876 | 0 ... no BODY= used | |
1877 | 7 ... 7BIT | |
1878 | 8 ... 8BITMIME */ | |
1879 | -if (log_extra_selector & LX_8bitmime) | |
1880 | +if (LOGGING(8bitmime)) | |
1881 | { | |
1882 | sprintf(CS big_buffer, "%d", body_8bitmime); | |
1883 | s = string_append(s, &size, &sptr, 2, US" M8S=", big_buffer); | |
1884 | @@ -3814,7 +3813,7 @@ if (msgid_header != NULL) | |
1885 | /* If subject logging is turned on, create suitable printing-character | |
1886 | text. By expanding $h_subject: we make use of the MIME decoding. */ | |
1887 | ||
1888 | -if ((log_extra_selector & LX_subject) != 0 && subject_header != NULL) | |
1889 | +if (LOGGING(subject) && subject_header != NULL) | |
1890 | { | |
1891 | int i; | |
1892 | uschar *p = big_buffer; | |
1893 | @@ -4003,8 +4002,8 @@ if(!smtp_reply) | |
1894 | #endif | |
1895 | { | |
1896 | log_write(0, LOG_MAIN | | |
1897 | - (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) | | |
1898 | - (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0), | |
1899 | + (LOGGING(received_recipients)? LOG_RECIPIENTS : 0) | | |
1900 | + (LOGGING(received_sender)? LOG_SENDER : 0), | |
1901 | "%s", s); | |
1902 | ||
1903 | /* Log any control actions taken by an ACL or local_scan(). */ | |
1904 | diff --git a/src/src/rewrite.c b/src/src/rewrite.c | |
1905 | index 296fe8c..ca7fb6a 100644 | |
1906 | --- a/src/src/rewrite.c | |
1907 | +++ b/src/src/rewrite.c | |
1908 | @@ -247,8 +247,7 @@ for (rule = rewrite_rules; | |
1909 | ||
1910 | /* We have a validly rewritten address */ | |
1911 | ||
1912 | - if ((log_write_selector & L_address_rewrite) != 0 || | |
1913 | - (debug_selector & D_rewrite) != 0) | |
1914 | + if (LOGGING(address_rewrite) || (debug_selector & D_rewrite) != 0) | |
1915 | { | |
1916 | int i; | |
1917 | const uschar *where = CUS"?"; | |
1918 | diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c | |
1919 | index effc636..9982451 100644 | |
1920 | --- a/src/src/smtp_in.c | |
1921 | +++ b/src/src/smtp_in.c | |
1922 | @@ -1234,8 +1234,7 @@ if (sender_host_unknown || sender_host_notsocket) | |
1923 | if (is_inetd) | |
1924 | return string_sprintf("SMTP connection from %s (via inetd)", hostname); | |
1925 | ||
1926 | -if ((log_extra_selector & LX_incoming_interface) != 0 && | |
1927 | - interface_address != NULL) | |
1928 | +if (LOGGING(incoming_interface) && interface_address != NULL) | |
1929 | return string_sprintf("SMTP connection from %s I=[%s]:%d", hostname, | |
1930 | interface_address, interface_port); | |
1931 | ||
1932 | @@ -1260,16 +1259,15 @@ s_tlslog(uschar * s, int * sizep, int * ptrp) | |
1933 | int size = sizep ? *sizep : 0; | |
1934 | int ptr = ptrp ? *ptrp : 0; | |
1935 | ||
1936 | - if ((log_extra_selector & LX_tls_cipher) != 0 && tls_in.cipher != NULL) | |
1937 | + if (LOGGING(tls_cipher) && tls_in.cipher != NULL) | |
1938 | s = string_append(s, &size, &ptr, 2, US" X=", tls_in.cipher); | |
1939 | - if ((log_extra_selector & LX_tls_certificate_verified) != 0 && | |
1940 | - tls_in.cipher != NULL) | |
1941 | + if (LOGGING(tls_certificate_verified) && tls_in.cipher != NULL) | |
1942 | s = string_append(s, &size, &ptr, 2, US" CV=", | |
1943 | tls_in.certificate_verified? "yes":"no"); | |
1944 | - if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_in.peerdn != NULL) | |
1945 | + if (LOGGING(tls_peerdn) && tls_in.peerdn != NULL) | |
1946 | s = string_append(s, &size, &ptr, 3, US" DN=\"", | |
1947 | string_printing(tls_in.peerdn), US"\""); | |
1948 | - if ((log_extra_selector & LX_tls_sni) != 0 && tls_in.sni != NULL) | |
1949 | + if (LOGGING(tls_sni) && tls_in.sni != NULL) | |
1950 | s = string_append(s, &size, &ptr, 3, US" SNI=\"", | |
1951 | string_printing(tls_in.sni), US"\""); | |
1952 | ||
1953 | @@ -1301,7 +1299,7 @@ smtp_log_no_mail(void) | |
1954 | int size, ptr, i; | |
1955 | uschar *s, *sep; | |
1956 | ||
1957 | -if (smtp_mailcmd_count > 0 || (log_extra_selector & LX_smtp_no_mail) == 0) | |
1958 | +if (smtp_mailcmd_count > 0 || !LOGGING(smtp_no_mail)) | |
1959 | return; | |
1960 | ||
1961 | s = NULL; | |
1962 | @@ -2510,8 +2508,8 @@ static void | |
1963 | incomplete_transaction_log(uschar *what) | |
1964 | { | |
1965 | if (sender_address == NULL || /* No transaction in progress */ | |
1966 | - (log_write_selector & L_smtp_incomplete_transaction) == 0 /* Not logging */ | |
1967 | - ) return; | |
1968 | + !LOGGING(smtp_incomplete_transaction)) | |
1969 | + return; | |
1970 | ||
1971 | /* Build list of recipients for logging */ | |
1972 | ||
1973 | @@ -2762,7 +2760,7 @@ if (sender_verified_failed != NULL && | |
1974 | ||
1975 | setflag(sender_verified_failed, af_sverify_told); | |
1976 | ||
1977 | - if (rc != FAIL || (log_extra_selector & LX_sender_verify_fail) != 0) | |
1978 | + if (rc != FAIL || LOGGING(sender_verify_fail)) | |
1979 | log_write(0, LOG_MAIN|LOG_REJECT, "%s sender verify %s for <%s>%s", | |
1980 | host_and_ident(TRUE), | |
1981 | ((sender_verified_failed->special_action & 255) == DEFER)? "defer":"fail", | |
1982 | diff --git a/src/src/structs.h b/src/src/structs.h | |
1983 | index 6f143d6..438b521 100644 | |
1984 | --- a/src/src/structs.h | |
1985 | +++ b/src/src/structs.h | |
1986 | @@ -38,7 +38,7 @@ typedef struct macro_item { | |
1987 | ||
1988 | typedef struct bit_table { | |
1989 | uschar *name; | |
1990 | - unsigned int bit; | |
1991 | + int bit; | |
1992 | } bit_table; | |
1993 | ||
1994 | /* Block for holding a uid and gid, possibly unset, and an initgroups flag. */ | |
1995 | diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c | |
1996 | index b1dccb8..73ac807 100644 | |
1997 | --- a/src/src/tls-openssl.c | |
1998 | +++ b/src/src/tls-openssl.c | |
1999 | @@ -1111,8 +1111,7 @@ len = SSL_get_tlsext_status_ocsp_resp(s, &p); | |
2000 | if(!p) | |
2001 | { | |
2002 | /* Expect this when we requested ocsp but got none */ | |
2003 | - if ( cbinfo->u_ocsp.client.verify_required | |
2004 | - && log_extra_selector & LX_tls_cipher) | |
2005 | + if (cbinfo->u_ocsp.client.verify_required && LOGGING(tls_cipher)) | |
2006 | log_write(0, LOG_MAIN, "Received TLS status callback, null content"); | |
2007 | else | |
2008 | DEBUG(D_tls) debug_printf(" null\n"); | |
2009 | @@ -1122,7 +1121,7 @@ if(!p) | |
2010 | if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len))) | |
2011 | { | |
2012 | tls_out.ocsp = OCSP_FAILED; | |
2013 | - if (log_extra_selector & LX_tls_cipher) | |
2014 | + if (LOGGING(tls_cipher)) | |
2015 | log_write(0, LOG_MAIN, "Received TLS cert status response, parse error"); | |
2016 | else | |
2017 | DEBUG(D_tls) debug_printf(" parse error\n"); | |
2018 | @@ -1132,7 +1131,7 @@ if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len))) | |
2019 | if(!(bs = OCSP_response_get1_basic(rsp))) | |
2020 | { | |
2021 | tls_out.ocsp = OCSP_FAILED; | |
2022 | - if (log_extra_selector & LX_tls_cipher) | |
2023 | + if (LOGGING(tls_cipher)) | |
2024 | log_write(0, LOG_MAIN, "Received TLS cert status response, error parsing response"); | |
2025 | else | |
2026 | DEBUG(D_tls) debug_printf(" error parsing response\n"); | |
2027 | @@ -1163,7 +1162,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) | |
2028 | cbinfo->u_ocsp.client.verify_store, 0)) <= 0) | |
2029 | { | |
2030 | tls_out.ocsp = OCSP_FAILED; | |
2031 | - if (log_extra_selector & LX_tls_cipher) | |
2032 | + if (LOGGING(tls_cipher)) | |
2033 | log_write(0, LOG_MAIN, "Received TLS cert status response, itself unverifiable"); | |
2034 | BIO_printf(bp, "OCSP response verify failure\n"); | |
2035 | ERR_print_errors(bp); | |
2036 | diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c | |
2037 | index 0cd89af..1f4d7a6 100644 | |
2038 | --- a/src/src/transports/lmtp.c | |
2039 | +++ b/src/src/transports/lmtp.c | |
2040 | @@ -654,7 +654,7 @@ if (send_data) | |
2041 | if (lmtp_read_response(out, buffer, sizeof(buffer), '2', timeout)) | |
2042 | { | |
2043 | addr->transport_return = OK; | |
2044 | - if ((log_extra_selector & LX_smtp_confirmation) != 0) | |
2045 | + if (LOGGING(smtp_confirmation)) | |
2046 | { | |
2047 | const uschar *s = string_printing(buffer); | |
2048 | /* de-const safe here as string_printing known to have alloc'n'copied */ | |
2049 | diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c | |
2050 | index a952413..609dba3 100644 | |
2051 | --- a/src/src/transports/smtp.c | |
2052 | +++ b/src/src/transports/smtp.c | |
2053 | @@ -638,7 +638,7 @@ if (addr->message) | |
2054 | } | |
2055 | else | |
2056 | { | |
2057 | - if (log_extra_selector & LX_outgoing_port) | |
2058 | + if (LOGGING(outgoing_port)) | |
2059 | message = string_sprintf("%s:%d", message, | |
2060 | host->port == PORT_NONE ? 25 : host->port); | |
2061 | log_write(0, LOG_MAIN, "%s %s", message, strerror(addr->basic_errno)); | |
2062 | @@ -2380,7 +2380,7 @@ if (!ok) ok = TRUE; else | |
2063 | ||
2064 | if ( | |
2065 | #ifndef EXPERIMENTAL_EVENT | |
2066 | - (log_extra_selector & LX_smtp_confirmation) != 0 && | |
2067 | + LOGGING(smtp_confirmation) && | |
2068 | #endif | |
2069 | !lmtp | |
2070 | ) | |
2071 | @@ -2435,7 +2435,7 @@ if (!ok) ok = TRUE; else | |
2072 | continue; | |
2073 | } | |
2074 | completed_address = TRUE; /* NOW we can set this flag */ | |
2075 | - if ((log_extra_selector & LX_smtp_confirmation) != 0) | |
2076 | + if (LOGGING(smtp_confirmation)) | |
2077 | { | |
2078 | const uschar *s = string_printing(buffer); | |
2079 | /* deconst cast ok here as string_printing was checked to have alloc'n'copied */ | |
2080 | diff --git a/src/src/verify.c b/src/src/verify.c | |
2081 | index e00e7b9..7992d58 100644 | |
2082 | --- a/src/src/verify.c | |
2083 | +++ b/src/src/verify.c | |
2084 | @@ -2916,7 +2916,7 @@ if (ip_bind(sock, host_af, interface_address, 0) < 0) | |
2085 | if (ip_connect(sock, host_af, sender_host_address, port, rfc1413_query_timeout) | |
2086 | < 0) | |
2087 | { | |
2088 | - if (errno == ETIMEDOUT && (log_extra_selector & LX_ident_timeout) != 0) | |
2089 | + if (errno == ETIMEDOUT && LOGGING(ident_timeout)) | |
2090 | { | |
2091 | log_write(0, LOG_MAIN, "ident connection to %s timed out", | |
2092 | sender_host_address); | |
2093 | ||
2094 | commit ac881e2749754fbe167b5f38784dd85b088571cf | |
2095 | Author: Tony Finch <dot@dotat.at> | |
2096 | Date: Thu Aug 13 15:16:51 2015 +0100 | |
2097 | ||
2098 | Improve the consistency of logging incoming and outgoing interfaces. | |
2099 | ||
2100 | The I= interface field on outgoing lines is now after the H= remote | |
2101 | host field, same as incoming lines. There is a separate outgoing_interface | |
2102 | log selector which allows you to disable the outgoing I= field. | |
2103 | ||
2104 | (slight massaging by JH) | |
2105 | ||
2106 | diff --git a/src/src/deliver.c b/src/src/deliver.c | |
2107 | index c796de0..0e7cea3 100644 | |
2108 | --- a/src/src/deliver.c | |
2109 | +++ b/src/src/deliver.c | |
2110 | @@ -676,39 +676,78 @@ while (addr->parent != NULL) | |
2111 | ||
2112 | ||
2113 | ||
2114 | +/************************************************* | |
2115 | +* Delivery logging support functions * | |
2116 | +*************************************************/ | |
2117 | + | |
2118 | +/* The LOGGING() checks in d_log_interface() are complicated for backwards | |
2119 | +compatibility. When outgoing interface logging was originally added, it was | |
2120 | +conditional on just incoming_interface (which is off by default). The | |
2121 | +outgoing_interface option is on by default to preserve this behaviour, but | |
2122 | +you can enable incoming_interface and disable outgoing_interface to get I= | |
2123 | +fields on incoming lines only. | |
2124 | + | |
2125 | +Arguments: | |
2126 | + s The log line buffer | |
2127 | + sizep Pointer to the buffer size | |
2128 | + ptrp Pointer to current index into buffer | |
2129 | + addr The address to be logged | |
2130 | + | |
2131 | +Returns: New value for s | |
2132 | +*/ | |
2133 | ||
2134 | static uschar * | |
2135 | -d_hostlog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
2136 | +d_log_interface(uschar *s, int *sizep, int *ptrp) | |
2137 | { | |
2138 | - s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, | |
2139 | - US" [", addr->host_used->address, US"]"); | |
2140 | +if (LOGGING(incoming_interface) && LOGGING(outgoing_interface) | |
2141 | + && sending_ip_address != NULL) | |
2142 | + { | |
2143 | + s = string_append(s, sizep, ptrp, 2, US" I=[", sending_ip_address); | |
2144 | if (LOGGING(outgoing_port)) | |
2145 | - s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", | |
2146 | - addr->host_used->port)); | |
2147 | - return s; | |
2148 | + s = string_append(s, sizep, ptrp, 2, US"]:", | |
2149 | + string_sprintf("%d", sending_port)); | |
2150 | + else | |
2151 | + s = string_cat(s, sizep, ptrp, "]", 1); | |
2152 | + } | |
2153 | +return s; | |
2154 | } | |
2155 | ||
2156 | + | |
2157 | + | |
2158 | +static uschar * | |
2159 | +d_hostlog(uschar *s, int *sizep, int *ptrp, address_item *addr) | |
2160 | +{ | |
2161 | +s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, | |
2162 | + US" [", addr->host_used->address, US"]"); | |
2163 | +if (LOGGING(outgoing_port)) | |
2164 | + s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", | |
2165 | + addr->host_used->port)); | |
2166 | +return d_log_interface(s, sizep, ptrp); | |
2167 | +} | |
2168 | + | |
2169 | + | |
2170 | + | |
2171 | #ifdef SUPPORT_TLS | |
2172 | static uschar * | |
2173 | d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) | |
2174 | { | |
2175 | - if (LOGGING(tls_cipher) && addr->cipher != NULL) | |
2176 | - s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher); | |
2177 | - if (LOGGING(tls_certificate_verified) && addr->cipher != NULL) | |
2178 | - s = string_append(s, sizep, ptrp, 2, US" CV=", | |
2179 | - testflag(addr, af_cert_verified) | |
2180 | - ? | |
2181 | +if (LOGGING(tls_cipher) && addr->cipher != NULL) | |
2182 | + s = string_append(s, sizep, ptrp, 2, US" X=", addr->cipher); | |
2183 | +if (LOGGING(tls_certificate_verified) && addr->cipher != NULL) | |
2184 | + s = string_append(s, sizep, ptrp, 2, US" CV=", | |
2185 | + testflag(addr, af_cert_verified) | |
2186 | + ? | |
2187 | #ifdef EXPERIMENTAL_DANE | |
2188 | - testflag(addr, af_dane_verified) | |
2189 | - ? "dane" | |
2190 | - : | |
2191 | + testflag(addr, af_dane_verified) | |
2192 | + ? "dane" | |
2193 | + : | |
2194 | #endif | |
2195 | - "yes" | |
2196 | - : "no"); | |
2197 | - if (LOGGING(tls_peerdn) && addr->peerdn != NULL) | |
2198 | - s = string_append(s, sizep, ptrp, 3, US" DN=\"", | |
2199 | - string_printing(addr->peerdn), US"\""); | |
2200 | - return s; | |
2201 | + "yes" | |
2202 | + : "no"); | |
2203 | +if (LOGGING(tls_peerdn) && addr->peerdn != NULL) | |
2204 | + s = string_append(s, sizep, ptrp, 3, US" DN=\"", | |
2205 | + string_printing(addr->peerdn), US"\""); | |
2206 | +return s; | |
2207 | } | |
2208 | #endif | |
2209 | ||
2210 | @@ -816,10 +855,6 @@ else | |
2211 | s = string_append(s, &size, &ptr, 2, US"> ", log_address); | |
2212 | } | |
2213 | ||
2214 | -if (LOGGING(incoming_interface) && sending_ip_address) | |
2215 | - s = string_append(s, &size, &ptr, 3, US" I=[", sending_ip_address, US"]"); | |
2216 | - /* for the port: string_sprintf("%d", sending_port) */ | |
2217 | - | |
2218 | if (LOGGING(sender_on_delivery) || msg) | |
2219 | s = string_append(s, &size, &ptr, 3, US" F=<", | |
2220 | #ifdef EXPERIMENTAL_INTERNATIONAL | |
2221 | @@ -862,6 +897,7 @@ if (addr->transport->info->local) | |
2222 | { | |
2223 | if (addr->host_list) | |
2224 | s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name); | |
2225 | + s = d_log_interface(s, &size, &ptr); | |
2226 | if (addr->shadow_message != NULL) | |
2227 | s = string_cat(s, &size, &ptr, addr->shadow_message, | |
2228 | Ustrlen(addr->shadow_message)); | |
2229 | diff --git a/src/src/globals.c b/src/src/globals.c | |
2230 | index 1344b5a..4188b4d 100644 | |
2231 | --- a/src/src/globals.c | |
2232 | +++ b/src/src/globals.c | |
2233 | @@ -827,6 +827,7 @@ int log_default[] = { /* for initializing log_selector */ | |
2234 | Li_etrn, | |
2235 | Li_host_lookup_failed, | |
2236 | Li_lost_incoming_connection, | |
2237 | + Li_outgoing_interface, /* see d_log_interface in deliver.c */ | |
2238 | Li_queue_run, | |
2239 | Li_rejected_header, | |
2240 | Li_retry_defer, | |
2241 | @@ -863,6 +864,7 @@ bit_table log_options[] = { /* must be in alphabetical order */ | |
2242 | BIT_TABLE(L, incoming_interface), | |
2243 | BIT_TABLE(L, incoming_port), | |
2244 | BIT_TABLE(L, lost_incoming_connection), | |
2245 | + BIT_TABLE(L, outgoing_interface), | |
2246 | BIT_TABLE(L, outgoing_port), | |
2247 | BIT_TABLE(L, pid), | |
2248 | #ifdef EXPERIMENTAL_PROXY | |
2249 | diff --git a/src/src/log.c b/src/src/log.c | |
2250 | index b2d1fcf..558c000 100644 | |
2251 | --- a/src/src/log.c | |
2252 | +++ b/src/src/log.c | |
2253 | @@ -753,8 +753,8 @@ DEBUG(D_any|D_v) | |
2254 | ||
2255 | for (i = 0; i < log_options_count; i++) | |
2256 | { | |
2257 | - unsigned int bit = log_options[i].bit; | |
2258 | - if (bit < BITWORDSIZE && selector == BIT(bit)) | |
2259 | + unsigned int bitnum = log_options[i].bit; | |
2260 | + if (bitnum < BITWORDSIZE && selector == BIT(bitnum)) | |
2261 | { | |
2262 | *ptr++ = ' '; | |
2263 | Ustrcpy(ptr, log_options[i].name); | |
2264 | diff --git a/src/src/macros.h b/src/src/macros.h | |
2265 | index d63025e..0ce24f8 100644 | |
2266 | --- a/src/src/macros.h | |
2267 | +++ b/src/src/macros.h | |
2268 | @@ -474,8 +474,9 @@ enum { | |
2269 | Li_8bitmime, | |
2270 | Li_smtp_mailauth, | |
2271 | Li_proxy, | |
2272 | + Li_outgoing_interface, | |
2273 | ||
2274 | - log_selector_size = BITWORD(Li_proxy) + 1 | |
2275 | + log_selector_size = BITWORD(Li_outgoing_interface) + 1 | |
2276 | }; | |
2277 | ||
2278 | #define LOGGING(opt) BIT_TEST(log_selector, log_selector_size, Li_##opt) | |
2279 | ||
2280 | commit 6b51df8340eacc95e3def9a4376506610e91996c | |
2281 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
2282 | Date: Wed Aug 19 15:22:41 2015 +0200 | |
2283 | ||
2284 | Fix post-transport-crash. | |
2285 | ||
2286 | The crash probably was introduced in a39bd74d3e94 and | |
2287 | needs 'split_spool_directory=yes' to expose. | |
2288 | ||
2289 | Thanks to Wolfgang Breyha, who found the same fix. | |
2290 | ||
2291 | diff --git a/src/src/transport.c b/src/src/transport.c | |
2292 | index fa6f869..a6ad3ed 100644 | |
2293 | --- a/src/src/transport.c | |
2294 | +++ b/src/src/transport.c | |
2295 | @@ -1752,7 +1752,7 @@ while (1) | |
2296 | { | |
2297 | if (split_spool_directory) | |
2298 | sprintf(CS spool_file, "%s%c/%s-D", | |
2299 | - spool_dir, new_message_id[5], msgq[i].message_id); | |
2300 | + spool_dir, msgq[i].message_id[5], msgq[i].message_id); | |
2301 | else | |
2302 | sprintf(CS spool_file, "%s%s-D", spool_dir, msgq[i].message_id); | |
2303 | ||
2304 | ||
2305 | commit b20b82a0b4169cb23380a373ed2a898b0cb337d2 | |
2306 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
2307 | Date: Fri Aug 21 12:26:50 2015 +0200 | |
2308 | ||
2309 | Add a .ctags file to src | |
2310 | ||
2311 | diff --git a/src/.ctags b/src/.ctags | |
2312 | new file mode 100644 | |
2313 | index 0000000..c764086 | |
2314 | --- /dev/null | |
2315 | +++ b/src/.ctags | |
2316 | @@ -0,0 +1,2 @@ | |
2317 | +--recurse | |
2318 | +--exclude=build-* | |
2319 | ||
2320 | commit dadff1d47e54962b0fdf98e8ce5cef42b6cb7fb5 | |
2321 | Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de> | |
2322 | Date: Thu Aug 20 13:58:06 2015 +0200 | |
2323 | ||
2324 | Fix post-transport-crash: safeguard for missing spool BUG 1671 | |
2325 | ||
2326 | Based on a proposal from Wolfgang Breyha. | |
2327 | ||
2328 | diff --git a/src/src/deliver.c b/src/src/deliver.c | |
2329 | index 0e7cea3..b5aa9b9 100644 | |
2330 | --- a/src/src/deliver.c | |
2331 | +++ b/src/src/deliver.c | |
2332 | @@ -9,6 +9,7 @@ | |
2333 | ||
2334 | ||
2335 | #include "exim.h" | |
2336 | +#include <assert.h> | |
2337 | ||
2338 | ||
2339 | /* Data block for keeping track of subprocesses for parallel remote | |
2340 | @@ -7934,17 +7935,36 @@ if (!regex_IGNOREQUOTA) regex_IGNOREQUOTA = | |
2341 | uschar * | |
2342 | deliver_get_sender_address (uschar * id) | |
2343 | { | |
2344 | +int rc; | |
2345 | +uschar * new_sender_address, | |
2346 | + * save_sender_address; | |
2347 | + | |
2348 | if (!spool_open_datafile(id)) | |
2349 | return NULL; | |
2350 | ||
2351 | +/* Save and restore the global sender_address. I'm not sure if we should | |
2352 | +not save/restore all the other global variables too, because | |
2353 | +spool_read_header() may change all of them. But OTOH, when this | |
2354 | +deliver_get_sender_address() gets called, the current message is done | |
2355 | +already and nobody needs the globals anymore. (HS12, 2015-08-21) */ | |
2356 | + | |
2357 | sprintf(CS spoolname, "%s-H", id); | |
2358 | -if (spool_read_header(spoolname, TRUE, TRUE) != spool_read_OK) | |
2359 | +save_sender_address = sender_address; | |
2360 | + | |
2361 | +rc = spool_read_header(spoolname, TRUE, TRUE); | |
2362 | + | |
2363 | +new_sender_address = sender_address; | |
2364 | +sender_address = save_sender_address; | |
2365 | + | |
2366 | +if (rc != spool_read_OK) | |
2367 | return NULL; | |
2368 | ||
2369 | +assert(new_sender_address); | |
2370 | + | |
2371 | (void)close(deliver_datafile); | |
2372 | deliver_datafile = -1; | |
2373 | ||
2374 | -return sender_address; | |
2375 | +return new_sender_address; | |
2376 | } | |
2377 | ||
2378 | /* vi: aw ai sw=2 | |
2379 | diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c | |
2380 | index 609dba3..c93f2ef 100644 | |
2381 | --- a/src/src/transports/smtp.c | |
2382 | +++ b/src/src/transports/smtp.c | |
2383 | @@ -1274,14 +1274,19 @@ we will veto this new message. */ | |
2384 | static BOOL | |
2385 | smtp_are_same_identities(uschar * message_id, smtp_compare_t * s_compare) | |
2386 | { | |
2387 | -uschar * save_sender_address = sender_address; | |
2388 | -uschar * current_local_identity = | |
2389 | + | |
2390 | +uschar * message_local_identity, | |
2391 | + * current_local_identity, | |
2392 | + * new_sender_address; | |
2393 | + | |
2394 | +current_local_identity = | |
2395 | smtp_local_identity(s_compare->current_sender_address, s_compare->tblock); | |
2396 | -uschar * new_sender_address = deliver_get_sender_address(message_id); | |
2397 | -uschar * message_local_identity = | |
2398 | - smtp_local_identity(new_sender_address, s_compare->tblock); | |
2399 | ||
2400 | -sender_address = save_sender_address; | |
2401 | +if (!(new_sender_address = deliver_get_sender_address(message_id))) | |
2402 | + return 0; | |
2403 | + | |
2404 | +message_local_identity = | |
2405 | + smtp_local_identity(new_sender_address, s_compare->tblock); | |
2406 | ||
2407 | return Ustrcmp(current_local_identity, message_local_identity) == 0; | |
2408 | } | |
2409 | ||
2410 | commit 3703d8187af01d13ca71f7918c7ef78529bb784d | |
2411 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
2412 | Date: Fri Aug 21 18:08:39 2015 +0100 | |
2413 | ||
2414 | Remember the fail reason for verify=headers_syntax. Bug 264 | |
2415 | ||
2416 | diff --git a/src/src/acl.c b/src/src/acl.c | |
2417 | index f2e0ef2..064ee6c 100644 | |
2418 | --- a/src/src/acl.c | |
2419 | +++ b/src/src/acl.c | |
2420 | @@ -1803,27 +1803,27 @@ switch(vp->value) | |
2421 | test whether it was successful or not. (This is for optional verification; for | |
2422 | mandatory verification, the connection doesn't last this long.) */ | |
2423 | ||
2424 | - if (tls_in.certificate_verified) return OK; | |
2425 | - *user_msgptr = US"no verified certificate"; | |
2426 | - return FAIL; | |
2427 | + if (tls_in.certificate_verified) return OK; | |
2428 | + *user_msgptr = US"no verified certificate"; | |
2429 | + return FAIL; | |
2430 | ||
2431 | case VERIFY_HELO: | |
2432 | /* We can test the result of optional HELO verification that might have | |
2433 | occurred earlier. If not, we can attempt the verification now. */ | |
2434 | ||
2435 | - if (!helo_verified && !helo_verify_failed) smtp_verify_helo(); | |
2436 | - return helo_verified? OK : FAIL; | |
2437 | + if (!helo_verified && !helo_verify_failed) smtp_verify_helo(); | |
2438 | + return helo_verified? OK : FAIL; | |
2439 | ||
2440 | case VERIFY_CSA: | |
2441 | /* Do Client SMTP Authorization checks in a separate function, and turn the | |
2442 | result code into user-friendly strings. */ | |
2443 | ||
2444 | - rc = acl_verify_csa(list); | |
2445 | - *log_msgptr = *user_msgptr = string_sprintf("client SMTP authorization %s", | |
2446 | + rc = acl_verify_csa(list); | |
2447 | + *log_msgptr = *user_msgptr = string_sprintf("client SMTP authorization %s", | |
2448 | csa_reason_string[rc]); | |
2449 | - csa_status = csa_status_string[rc]; | |
2450 | - DEBUG(D_acl) debug_printf("CSA result %s\n", csa_status); | |
2451 | - return csa_return_code[rc]; | |
2452 | + csa_status = csa_status_string[rc]; | |
2453 | + DEBUG(D_acl) debug_printf("CSA result %s\n", csa_status); | |
2454 | + return csa_return_code[rc]; | |
2455 | ||
2456 | case VERIFY_HDR_SYNTAX: | |
2457 | /* Check that all relevant header lines have the correct syntax. If there is | |
2458 | @@ -1832,8 +1832,11 @@ switch(vp->value) | |
2459 | always). */ | |
2460 | ||
2461 | rc = verify_check_headers(log_msgptr); | |
2462 | - if (rc != OK && smtp_return_error_details && *log_msgptr != NULL) | |
2463 | - *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr); | |
2464 | + if (rc != OK && *log_msgptr) | |
2465 | + if (smtp_return_error_details) | |
2466 | + *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr); | |
2467 | + else | |
2468 | + acl_verify_message = *log_msgptr; | |
2469 | return rc; | |
2470 | ||
2471 | case VERIFY_HDR_NAMES_ASCII: | |
2472 | @@ -3788,7 +3791,8 @@ for (; cb != NULL; cb = cb->next) | |
2473 | ||
2474 | case ACLC_VERIFY: | |
2475 | rc = acl_verify(where, addr, arg, user_msgptr, log_msgptr, basic_errno); | |
2476 | - acl_verify_message = *user_msgptr; | |
2477 | + if (*user_msgptr) | |
2478 | + acl_verify_message = *user_msgptr; | |
2479 | if (verb == ACL_WARN) *user_msgptr = NULL; | |
2480 | break; | |
2481 | ||
2482 | ||
2483 | commit c8899c20aa08c9ae6a4c291aad23ba90512bebe4 | |
2484 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
2485 | Date: Tue Aug 25 10:36:27 2015 +0100 | |
2486 | ||
2487 | Close logs after daemon-process exceptional write. Bug 728 | |
2488 | ||
2489 | diff --git a/src/src/daemon.c b/src/src/daemon.c | |
2490 | index 2d10387..e1ff9a1 100644 | |
2491 | --- a/src/src/daemon.c | |
2492 | +++ b/src/src/daemon.c | |
2493 | @@ -735,6 +735,7 @@ else (void)close(dup_accept_socket); | |
2494 | /* Release any store used in this process, including the store used for holding | |
2495 | the incoming host address and an expanded active_hostname. */ | |
2496 | ||
2497 | +log_close_all(); | |
2498 | store_reset(reset_point); | |
2499 | sender_host_address = NULL; | |
2500 | } | |
2501 | ||
2502 | commit f38917cc94ab337c15ff70c254dd564ee2dcafe7 | |
2503 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
2504 | Date: Tue Sep 8 23:05:20 2015 +0100 | |
2505 | ||
2506 | Capture substrings in ACL regex= . Bug 425. | |
2507 | ||
2508 | diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults | |
2509 | index c33e098..596e651 100644 | |
2510 | --- a/src/src/config.h.defaults | |
2511 | +++ b/src/src/config.h.defaults | |
2512 | @@ -116,6 +116,8 @@ it's a default value. */ | |
2513 | #define RADIUS_CONFIG_FILE | |
2514 | #define RADIUS_LIB_TYPE | |
2515 | ||
2516 | +#define REGEX_VARS 9 | |
2517 | + | |
2518 | #define ROUTER_ACCEPT | |
2519 | #define ROUTER_DNSLOOKUP | |
2520 | #define ROUTER_IPLITERAL | |
2521 | diff --git a/src/src/exim.c b/src/src/exim.c | |
2522 | index d7cb5d8..999b94c 100644 | |
2523 | --- a/src/src/exim.c | |
2524 | +++ b/src/src/exim.c | |
2525 | @@ -1753,6 +1753,8 @@ regex_whitelisted_macro = | |
2526 | regex_must_compile(US"^[A-Za-z0-9_/.-]*$", FALSE, TRUE); | |
2527 | #endif | |
2528 | ||
2529 | +for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; | |
2530 | + | |
2531 | ||
2532 | /* If the program is called as "mailq" treat it as equivalent to "exim -bp"; | |
2533 | this seems to be a generally accepted convention, since one finds symbolic | |
2534 | diff --git a/src/src/expand.c b/src/src/expand.c | |
2535 | index 89e0ac7..1bff521 100644 | |
2536 | --- a/src/src/expand.c | |
2537 | +++ b/src/src/expand.c | |
2538 | @@ -1726,7 +1726,14 @@ if (Ustrncmp(name, "auth", 4) == 0) | |
2539 | uschar *endptr; | |
2540 | int n = Ustrtoul(name + 4, &endptr, 10); | |
2541 | if (*endptr == 0 && n != 0 && n <= AUTH_VARS) | |
2542 | - return (auth_vars[n-1] == NULL)? US"" : auth_vars[n-1]; | |
2543 | + return !auth_vars[n-1] ? US"" : auth_vars[n-1]; | |
2544 | + } | |
2545 | +else if (Ustrncmp(name, "regex", 5) == 0) | |
2546 | + { | |
2547 | + uschar *endptr; | |
2548 | + int n = Ustrtoul(name + 5, &endptr, 10); | |
2549 | + if (*endptr == 0 && n != 0 && n <= REGEX_VARS) | |
2550 | + return !regex_vars[n-1] ? US"" : regex_vars[n-1]; | |
2551 | } | |
2552 | ||
2553 | /* For all other variables, search the table */ | |
2554 | diff --git a/src/src/globals.c b/src/src/globals.c | |
2555 | index 4188b4d..8445f00 100644 | |
2556 | --- a/src/src/globals.c | |
2557 | +++ b/src/src/globals.c | |
2558 | @@ -1090,8 +1090,9 @@ const pcre *regex_From = NULL; | |
2559 | const pcre *regex_IGNOREQUOTA = NULL; | |
2560 | const pcre *regex_PIPELINING = NULL; | |
2561 | const pcre *regex_SIZE = NULL; | |
2562 | -const pcre *regex_smtp_code = NULL; | |
2563 | const pcre *regex_ismsgid = NULL; | |
2564 | +const pcre *regex_smtp_code = NULL; | |
2565 | +uschar *regex_vars[REGEX_VARS]; | |
2566 | #ifdef WHITELIST_D_MACROS | |
2567 | const pcre *regex_whitelisted_macro = NULL; | |
2568 | #endif | |
2569 | diff --git a/src/src/globals.h b/src/src/globals.h | |
2570 | index 978a4cc..3c69e43 100644 | |
2571 | --- a/src/src/globals.h | |
2572 | +++ b/src/src/globals.h | |
2573 | @@ -717,8 +717,9 @@ extern const pcre *regex_From; /* For recognizing "From_" lines */ | |
2574 | extern const pcre *regex_IGNOREQUOTA; /* For recognizing IGNOREQUOTA (LMTP) */ | |
2575 | extern const pcre *regex_PIPELINING; /* For recognizing PIPELINING */ | |
2576 | extern const pcre *regex_SIZE; /* For recognizing SIZE settings */ | |
2577 | -extern const pcre *regex_smtp_code; /* For recognizing SMTP codes */ | |
2578 | extern const pcre *regex_ismsgid; /* Compiled r.e. for message it */ | |
2579 | +extern const pcre *regex_smtp_code; /* For recognizing SMTP codes */ | |
2580 | +extern uschar *regex_vars[]; /* $regexN variables */ | |
2581 | #ifdef WHITELIST_D_MACROS | |
2582 | extern const pcre *regex_whitelisted_macro; /* For -D macro values */ | |
2583 | #endif | |
2584 | diff --git a/src/src/regex.c b/src/src/regex.c | |
2585 | index ed73b6e..93422fa 100644 | |
2586 | --- a/src/src/regex.c | |
2587 | +++ b/src/src/regex.c | |
2588 | @@ -25,109 +25,120 @@ uschar regex_match_string_buffer[1024]; | |
2589 | extern FILE *mime_stream; | |
2590 | extern uschar *mime_current_boundary; | |
2591 | ||
2592 | -int | |
2593 | -regex(const uschar **listptr) | |
2594 | +static pcre_list * | |
2595 | +compile(const uschar * list) | |
2596 | { | |
2597 | int sep = 0; | |
2598 | - const uschar *list = *listptr; | |
2599 | uschar *regex_string; | |
2600 | uschar regex_string_buffer[1024]; | |
2601 | - unsigned long mbox_size; | |
2602 | - FILE *mbox_file; | |
2603 | - pcre *re; | |
2604 | - pcre_list *re_list_head = NULL; | |
2605 | - pcre_list *re_list_item; | |
2606 | const char *pcre_error; | |
2607 | int pcre_erroffset; | |
2608 | + pcre_list *re_list_head = NULL; | |
2609 | + pcre_list *ri; | |
2610 | + | |
2611 | + /* precompile our regexes */ | |
2612 | + while ((regex_string = string_nextinlist(&list, &sep, | |
2613 | + regex_string_buffer, | |
2614 | + sizeof(regex_string_buffer))) != NULL) { | |
2615 | + pcre *re; | |
2616 | + | |
2617 | + /* parse option */ | |
2618 | + if ( (strcmpic(regex_string,US"false") == 0) || | |
2619 | + (Ustrcmp(regex_string,"0") == 0) ) | |
2620 | + continue; /* explicitly no matching */ | |
2621 | + | |
2622 | + /* compile our regular expression */ | |
2623 | + if (!(re = pcre_compile( CS regex_string, | |
2624 | + 0, &pcre_error, &pcre_erroffset, NULL ))) { | |
2625 | + log_write(0, LOG_MAIN, | |
2626 | + "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", | |
2627 | + regex_string, pcre_error, pcre_erroffset); | |
2628 | + continue; | |
2629 | + } | |
2630 | + | |
2631 | + ri = store_get(sizeof(pcre_list)); | |
2632 | + ri->re = re; | |
2633 | + ri->pcre_text = string_copy(regex_string); | |
2634 | + ri->next = re_list_head; | |
2635 | + re_list_head = ri; | |
2636 | + } | |
2637 | + return re_list_head; | |
2638 | +} | |
2639 | + | |
2640 | +static int | |
2641 | +matcher(pcre_list * re_list_head, uschar * linebuffer, int len) | |
2642 | +{ | |
2643 | + pcre_list * ri; | |
2644 | + | |
2645 | + for(ri = re_list_head; ri; ri = ri->next) | |
2646 | + { | |
2647 | + int ovec[3*(REGEX_VARS+1)]; | |
2648 | + int n, nn; | |
2649 | + | |
2650 | + /* try matcher on the line */ | |
2651 | + n = pcre_exec(ri->re, NULL, | |
2652 | + CS linebuffer, len, 0, 0, | |
2653 | + ovec, nelem(ovec)); | |
2654 | + if (n > 0) | |
2655 | + { | |
2656 | + Ustrncpy(regex_match_string_buffer, ri->pcre_text, 1023); | |
2657 | + regex_match_string = regex_match_string_buffer; | |
2658 | + | |
2659 | + for (nn = 1; nn < n; nn++) | |
2660 | + regex_vars[nn-1] = | |
2661 | + string_copyn(linebuffer + ovec[nn*2], ovec[nn*2+1] - ovec[nn*2]); | |
2662 | + | |
2663 | + return OK; | |
2664 | + } | |
2665 | + } | |
2666 | + return FAIL; | |
2667 | +} | |
2668 | + | |
2669 | +int | |
2670 | +regex(const uschar **listptr) | |
2671 | +{ | |
2672 | + unsigned long mbox_size; | |
2673 | + FILE *mbox_file; | |
2674 | + pcre_list *re_list_head; | |
2675 | uschar *linebuffer; | |
2676 | long f_pos = 0; | |
2677 | + int ret = FAIL; | |
2678 | ||
2679 | /* reset expansion variable */ | |
2680 | regex_match_string = NULL; | |
2681 | ||
2682 | - if (mime_stream == NULL) { | |
2683 | - /* We are in the DATA ACL */ | |
2684 | + if (mime_stream == NULL) { /* We are in the DATA ACL */ | |
2685 | mbox_file = spool_mbox(&mbox_size, NULL); | |
2686 | - if (mbox_file == NULL) { | |
2687 | - /* error while spooling */ | |
2688 | + if (mbox_file == NULL) { /* error while spooling */ | |
2689 | log_write(0, LOG_MAIN|LOG_PANIC, | |
2690 | "regex acl condition: error while creating mbox spool file"); | |
2691 | return DEFER; | |
2692 | - }; | |
2693 | + } | |
2694 | } | |
2695 | else { | |
2696 | f_pos = ftell(mime_stream); | |
2697 | mbox_file = mime_stream; | |
2698 | - }; | |
2699 | + } | |
2700 | ||
2701 | /* precompile our regexes */ | |
2702 | - while ((regex_string = string_nextinlist(&list, &sep, | |
2703 | - regex_string_buffer, | |
2704 | - sizeof(regex_string_buffer))) != NULL) { | |
2705 | - | |
2706 | - /* parse option */ | |
2707 | - if ( (strcmpic(regex_string,US"false") == 0) || | |
2708 | - (Ustrcmp(regex_string,"0") == 0) ) { | |
2709 | - /* explicitly no matching */ | |
2710 | - continue; | |
2711 | - }; | |
2712 | - | |
2713 | - /* compile our regular expression */ | |
2714 | - re = pcre_compile( CS regex_string, | |
2715 | - 0, | |
2716 | - &pcre_error, | |
2717 | - &pcre_erroffset, | |
2718 | - NULL ); | |
2719 | - | |
2720 | - if (re == NULL) { | |
2721 | - log_write(0, LOG_MAIN, | |
2722 | - "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", regex_string, pcre_error, pcre_erroffset); | |
2723 | - continue; | |
2724 | - } | |
2725 | - else { | |
2726 | - re_list_item = store_get(sizeof(pcre_list)); | |
2727 | - re_list_item->re = re; | |
2728 | - re_list_item->pcre_text = string_copy(regex_string); | |
2729 | - re_list_item->next = re_list_head; | |
2730 | - re_list_head = re_list_item; | |
2731 | - }; | |
2732 | - }; | |
2733 | - | |
2734 | - /* no regexes -> nothing to do */ | |
2735 | - if (re_list_head == NULL) { | |
2736 | - return FAIL; | |
2737 | - }; | |
2738 | + if (!(re_list_head = compile(*listptr))) | |
2739 | + return FAIL; /* no regexes -> nothing to do */ | |
2740 | ||
2741 | /* match each line against all regexes */ | |
2742 | linebuffer = store_get(32767); | |
2743 | while (fgets(CS linebuffer, 32767, mbox_file) != NULL) { | |
2744 | - if ( (mime_stream != NULL) && (mime_current_boundary != NULL) ) { | |
2745 | - /* check boundary */ | |
2746 | - if (Ustrncmp(linebuffer,"--",2) == 0) { | |
2747 | - if (Ustrncmp((linebuffer+2),mime_current_boundary,Ustrlen(mime_current_boundary)) == 0) | |
2748 | - /* found boundary */ | |
2749 | - break; | |
2750 | - }; | |
2751 | - }; | |
2752 | - re_list_item = re_list_head; | |
2753 | - do { | |
2754 | - /* try matcher on the line */ | |
2755 | - if (pcre_exec(re_list_item->re, NULL, CS linebuffer, | |
2756 | - (int)Ustrlen(linebuffer), 0, 0, NULL, 0) >= 0) { | |
2757 | - Ustrncpy(regex_match_string_buffer, re_list_item->pcre_text, 1023); | |
2758 | - regex_match_string = regex_match_string_buffer; | |
2759 | - if (mime_stream == NULL) | |
2760 | - (void)fclose(mbox_file); | |
2761 | - else { | |
2762 | - clearerr(mime_stream); | |
2763 | - fseek(mime_stream,f_pos,SEEK_SET); | |
2764 | - }; | |
2765 | - return OK; | |
2766 | - }; | |
2767 | - re_list_item = re_list_item->next; | |
2768 | - } while (re_list_item != NULL); | |
2769 | - }; | |
2770 | ||
2771 | + if ( mime_stream && mime_current_boundary /* check boundary */ | |
2772 | + && Ustrncmp(linebuffer,"--",2) == 0 | |
2773 | + && Ustrncmp((linebuffer+2),mime_current_boundary,Ustrlen(mime_current_boundary)) == 0) | |
2774 | + break; /* found boundary */ | |
2775 | + | |
2776 | + if ((ret = matcher(re_list_head, linebuffer, (int)Ustrlen(linebuffer))) == OK) | |
2777 | + goto done; | |
2778 | + } | |
2779 | + /* no matches ... */ | |
2780 | + | |
2781 | +done: | |
2782 | if (mime_stream == NULL) | |
2783 | (void)fclose(mbox_file); | |
2784 | else { | |
2785 | @@ -135,67 +146,25 @@ regex(const uschar **listptr) | |
2786 | fseek(mime_stream,f_pos,SEEK_SET); | |
2787 | }; | |
2788 | ||
2789 | - /* no matches ... */ | |
2790 | - return FAIL; | |
2791 | + return ret; | |
2792 | } | |
2793 | ||
2794 | ||
2795 | int | |
2796 | mime_regex(const uschar **listptr) | |
2797 | { | |
2798 | - int sep = 0; | |
2799 | - const uschar *list = *listptr; | |
2800 | - uschar *regex_string; | |
2801 | - uschar regex_string_buffer[1024]; | |
2802 | - pcre *re; | |
2803 | pcre_list *re_list_head = NULL; | |
2804 | - pcre_list *re_list_item; | |
2805 | - const char *pcre_error; | |
2806 | - int pcre_erroffset; | |
2807 | FILE *f; | |
2808 | uschar *mime_subject = NULL; | |
2809 | int mime_subject_len = 0; | |
2810 | + int ret; | |
2811 | ||
2812 | /* reset expansion variable */ | |
2813 | regex_match_string = NULL; | |
2814 | ||
2815 | /* precompile our regexes */ | |
2816 | - while ((regex_string = string_nextinlist(&list, &sep, | |
2817 | - regex_string_buffer, | |
2818 | - sizeof(regex_string_buffer))) != NULL) { | |
2819 | - | |
2820 | - /* parse option */ | |
2821 | - if ( (strcmpic(regex_string,US"false") == 0) || | |
2822 | - (Ustrcmp(regex_string,"0") == 0) ) { | |
2823 | - /* explicitly no matching */ | |
2824 | - continue; | |
2825 | - }; | |
2826 | - | |
2827 | - /* compile our regular expression */ | |
2828 | - re = pcre_compile( CS regex_string, | |
2829 | - 0, | |
2830 | - &pcre_error, | |
2831 | - &pcre_erroffset, | |
2832 | - NULL ); | |
2833 | - | |
2834 | - if (re == NULL) { | |
2835 | - log_write(0, LOG_MAIN, | |
2836 | - "regex acl condition warning - error in regex '%s': %s at offset %d, skipped.", regex_string, pcre_error, pcre_erroffset); | |
2837 | - continue; | |
2838 | - } | |
2839 | - else { | |
2840 | - re_list_item = store_get(sizeof(pcre_list)); | |
2841 | - re_list_item->re = re; | |
2842 | - re_list_item->pcre_text = string_copy(regex_string); | |
2843 | - re_list_item->next = re_list_head; | |
2844 | - re_list_head = re_list_item; | |
2845 | - }; | |
2846 | - }; | |
2847 | - | |
2848 | - /* no regexes -> nothing to do */ | |
2849 | - if (re_list_head == NULL) { | |
2850 | - return FAIL; | |
2851 | - }; | |
2852 | + if (!(re_list_head = compile(*listptr))) | |
2853 | + return FAIL; /* no regexes -> nothing to do */ | |
2854 | ||
2855 | /* check if the file is already decoded */ | |
2856 | if (mime_decoded_filename == NULL) { | |
2857 | @@ -207,43 +176,25 @@ mime_regex(const uschar **listptr) | |
2858 | log_write(0, LOG_MAIN, | |
2859 | "mime_regex acl condition warning - could not decode MIME part to file."); | |
2860 | return DEFER; | |
2861 | - }; | |
2862 | - }; | |
2863 | - | |
2864 | + } | |
2865 | + } | |
2866 | ||
2867 | /* open file */ | |
2868 | - f = fopen(CS mime_decoded_filename, "rb"); | |
2869 | - if (f == NULL) { | |
2870 | - /* open failed */ | |
2871 | + if (!(f = fopen(CS mime_decoded_filename, "rb"))) { | |
2872 | log_write(0, LOG_MAIN, | |
2873 | - "mime_regex acl condition warning - can't open '%s' for reading.", mime_decoded_filename); | |
2874 | + "mime_regex acl condition warning - can't open '%s' for reading.", | |
2875 | + mime_decoded_filename); | |
2876 | return DEFER; | |
2877 | - }; | |
2878 | + } | |
2879 | ||
2880 | /* get 32k memory */ | |
2881 | mime_subject = (uschar *)store_get(32767); | |
2882 | ||
2883 | - /* read max 32k chars from file */ | |
2884 | mime_subject_len = fread(mime_subject, 1, 32766, f); | |
2885 | ||
2886 | - re_list_item = re_list_head; | |
2887 | - do { | |
2888 | - /* try matcher on the mmapped file */ | |
2889 | - debug_printf("Matching '%s'\n", re_list_item->pcre_text); | |
2890 | - if (pcre_exec(re_list_item->re, NULL, CS mime_subject, | |
2891 | - mime_subject_len, 0, 0, NULL, 0) >= 0) { | |
2892 | - Ustrncpy(regex_match_string_buffer, re_list_item->pcre_text, 1023); | |
2893 | - regex_match_string = regex_match_string_buffer; | |
2894 | - (void)fclose(f); | |
2895 | - return OK; | |
2896 | - }; | |
2897 | - re_list_item = re_list_item->next; | |
2898 | - } while (re_list_item != NULL); | |
2899 | - | |
2900 | + ret = matcher(re_list_head, mime_subject, mime_subject_len); | |
2901 | (void)fclose(f); | |
2902 | - | |
2903 | - /* no matches ... */ | |
2904 | - return FAIL; | |
2905 | + return ret; | |
2906 | } | |
2907 | ||
2908 | #endif /* WITH_CONTENT_SCAN */ | |
2909 | ||
2910 | commit 895fbaf26d3450d4eeacbad8fe04c328a77645f0 | |
2911 | Author: Jeremy Harris <jgh146exb@wizmail.org> | |
2912 | Date: Wed Sep 9 16:03:38 2015 +0100 | |
2913 | ||
2914 | DSN: Under EXPERIMENTAL_DSN_INFO add extras to bounce messages. Bug 1686 | |
2915 | ||
2916 | diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults | |
2917 | index 596e651..6af3b4d 100644 | |
2918 | --- a/src/src/config.h.defaults | |
2919 | +++ b/src/src/config.h.defaults | |
2920 | @@ -172,6 +172,7 @@ it's a default value. */ | |
2921 | #define EXPERIMENTAL_BRIGHTMAIL | |
2922 | #define EXPERIMENTAL_DANE | |
2923 | #define EXPERIMENTAL_DCC | |
2924 | +#define EXPERIMENTAL_DSN_INFO | |
2925 | #define EXPERIMENTAL_DMARC | |
2926 | #define EXPERIMENTAL_EVENT | |
2927 | #define EXPERIMENTAL_INTERNATIONAL | |
2928 | diff --git a/src/src/deliver.c b/src/src/deliver.c | |
2929 | index b5aa9b9..3f22dc9 100644 | |
2930 | --- a/src/src/deliver.c | |
2931 | +++ b/src/src/deliver.c | |
2932 | @@ -3223,41 +3223,56 @@ while (!done) | |
2933 | break; | |
2934 | } | |
2935 | ||
2936 | - addr->transport_return = *ptr++; | |
2937 | - addr->special_action = *ptr++; | |
2938 | - memcpy(&(addr->basic_errno), ptr, sizeof(addr->basic_errno)); | |
2939 | - ptr += sizeof(addr->basic_errno); | |
2940 | - memcpy(&(addr->more_errno), ptr, sizeof(addr->more_errno)); | |
2941 | - ptr += sizeof(addr->more_errno); | |
2942 | - memcpy(&(addr->flags), ptr, sizeof(addr->flags)); | |
2943 | - ptr += sizeof(addr->flags); | |
2944 | - addr->message = (*ptr)? string_copy(ptr) : NULL; | |
2945 | - while(*ptr++); | |
2946 | - addr->user_message = (*ptr)? string_copy(ptr) : NULL; | |
2947 | - while(*ptr++); | |
2948 | - | |
2949 | - /* Always two strings for host information, followed by the port number and DNSSEC mark */ | |
2950 | - | |
2951 | - if (*ptr != 0) | |
2952 | + switch (subid) | |
2953 | { | |
2954 | - h = store_get(sizeof(host_item)); | |
2955 | - h->name = string_copy(ptr); | |
2956 | - while (*ptr++); | |
2957 | - h->address = string_copy(ptr); | |
2958 | - while(*ptr++); | |
2959 | - memcpy(&(h->port), ptr, sizeof(h->port)); | |
2960 | - ptr += sizeof(h->port); | |
2961 | - h->dnssec = *ptr == '2' ? DS_YES | |
2962 | - : *ptr == '1' ? DS_NO | |
2963 | - : DS_UNK; | |
2964 | - ptr++; | |
2965 | - addr->host_used = h; | |
2966 | - } | |
2967 | - else ptr++; | |
2968 | +#ifdef EXPERIMENTAL_DSN_INFO | |
2969 | + case '1': /* must arrive before A0, and applies to that addr */ | |
2970 | + /* Two strings: smtp_greeting and helo_response */ | |
2971 | + addr->smtp_greeting = string_copy(ptr); | |
2972 | + while(*ptr++); | |
2973 | + addr->helo_response = string_copy(ptr); | |
2974 | + while(*ptr++); | |
2975 | + break; | |
2976 | +#endif | |
2977 | ||
2978 | - /* Finished with this address */ | |
2979 | + case '0': | |
2980 | + addr->transport_return = *ptr++; | |
2981 | + addr->special_action = *ptr++; | |
2982 | + memcpy(&(addr->basic_errno), ptr, sizeof(addr->basic_errno)); | |
2983 | + ptr += sizeof(addr->basic_errno); | |
2984 | + memcpy(&(addr->more_errno), ptr, sizeof(addr->more_errno)); | |
2985 | + ptr += sizeof(addr->more_errno); | |
2986 | + memcpy(&(addr->flags), ptr, sizeof(addr->flags)); | |
2987 | + ptr += sizeof(addr->flags); | |
2988 | + addr->message = (*ptr)? string_copy(ptr) : NULL; | |
2989 | + while(*ptr++); | |
2990 | + addr->user_message = (*ptr)? string_copy(ptr) : NULL; | |
2991 | + while(*ptr++); | |
2992 | ||
2993 | - addr = addr->next; | |
2994 | + /* Always two strings for host information, followed by the port number and DNSSEC mark */ | |
2995 | + | |
2996 | + if (*ptr != 0) | |
2997 | + { | |
2998 | + h = store_get(sizeof(host_item)); | |
2999 | + h->name = string_copy(ptr); | |
3000 | + while (*ptr++); | |
3001 | + h->address = string_copy(ptr); | |
3002 | + while(*ptr++); | |
3003 | + memcpy(&(h->port), ptr, sizeof(h->port)); | |
3004 | + ptr += sizeof(h->port); | |
3005 | + h->dnssec = *ptr == '2' ? DS_YES | |
3006 | + : *ptr == '1' ? DS_NO | |
3007 | + : DS_UNK; | |
3008 | + ptr++; | |
3009 | + addr->host_used = h; | |
3010 | + } | |
3011 | + else ptr++; | |
3012 | + | |
3013 | + /* Finished with this address */ | |
3014 | + | |
3015 | + addr = addr->next; | |
3016 | + break; | |
3017 | + } | |
3018 | break; | |
3019 | ||
3020 | /* Local interface address/port */ | |
3021 | @@ -4423,7 +4438,6 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) | |
3022 | ||
3023 | for (r = addr->retries; r != NULL; r = r->next) | |
3024 | { | |
3025 | - uschar *ptr; | |
3026 | sprintf(CS big_buffer, "%c%.500s", r->flags, r->key); | |
3027 | ptr = big_buffer + Ustrlen(big_buffer+2) + 3; | |
3028 | memcpy(ptr, &(r->basic_errno), sizeof(r->basic_errno)); | |
3029 | @@ -4438,11 +4452,31 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) | |
3030 | rmt_dlv_checked_write(fd, 'R', '0', big_buffer, ptr - big_buffer); | |
3031 | } | |
3032 | ||
3033 | - /* The rest of the information goes in an 'A' item. */ | |
3034 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3035 | +/*um, are they really per-addr? Other per-conn stuff is not (auth, tls). But host_used is! */ | |
3036 | + if (addr->smtp_greeting) | |
3037 | + { | |
3038 | + ptr = big_buffer; | |
3039 | + DEBUG(D_deliver) debug_printf("smtp_greeting '%s'\n", addr->smtp_greeting); | |
3040 | + sprintf(CS ptr, "%.128s", addr->smtp_greeting); | |
3041 | + while(*ptr++); | |
3042 | + if (addr->helo_response) | |
3043 | + { | |
3044 | + DEBUG(D_deliver) debug_printf("helo_response '%s'\n", addr->helo_response); | |
3045 | + sprintf(CS ptr, "%.128s", addr->helo_response); | |
3046 | + while(*ptr++); | |
3047 | + } | |
3048 | + else | |
3049 | + *ptr++ = '\0'; | |
3050 | + rmt_dlv_checked_write(fd, 'A', '1', big_buffer, ptr - big_buffer); | |
3051 | + } | |
3052 | +#endif | |
3053 | + | |
3054 | + /* The rest of the information goes in an 'A0' item. */ | |
3055 | ||
3056 | - ptr = big_buffer + 2; | |
3057 | sprintf(CS big_buffer, "%c%c", addr->transport_return, | |
3058 | addr->special_action); | |
3059 | + ptr = big_buffer + 2; | |
3060 | memcpy(ptr, &(addr->basic_errno), sizeof(addr->basic_errno)); | |
3061 | ptr += sizeof(addr->basic_errno); | |
3062 | memcpy(ptr, &(addr->more_errno), sizeof(addr->more_errno)); | |
3063 | @@ -4480,7 +4514,11 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) | |
3064 | } | |
3065 | ||
3066 | /* Local interface address/port */ | |
3067 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3068 | + if (sending_ip_address) | |
3069 | +#else | |
3070 | if (LOGGING(incoming_interface) && sending_ip_address) | |
3071 | +#endif | |
3072 | { | |
3073 | uschar * ptr = big_buffer; | |
3074 | sprintf(CS ptr, "%.128s", sending_ip_address); | |
3075 | @@ -7209,16 +7247,32 @@ wording. */ | |
3076 | ||
3077 | for (addr = handled_addr; addr; addr = addr->next) | |
3078 | { | |
3079 | + host_item * hu; | |
3080 | fprintf(f, "Action: failed\n" | |
3081 | "Final-Recipient: rfc822;%s\n" | |
3082 | "Status: 5.0.0\n", | |
3083 | addr->address); | |
3084 | - if (addr->host_used && addr->host_used->name) | |
3085 | - { | |
3086 | - fprintf(f, "Remote-MTA: dns; %s\n", | |
3087 | - addr->host_used->name); | |
3088 | - print_dsn_diagnostic_code(addr, f); | |
3089 | - } | |
3090 | + if ((hu = addr->host_used) && hu->name) | |
3091 | + { | |
3092 | + const uschar * s; | |
3093 | + fprintf(f, "Remote-MTA: dns; %s\n", | |
3094 | + hu->name); | |
3095 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3096 | + if (hu->address) | |
3097 | + { | |
3098 | + uschar * p = hu->port == 25 | |
3099 | + ? US"" : string_sprintf(":%d", hu->port); | |
3100 | + fprintf(f, "Remote-MTA: X-ip; [%s]%s\n", hu->address, p); | |
3101 | + } | |
3102 | + if ((s = addr->smtp_greeting) && *s) | |
3103 | + fprintf(f, "X-Remote-MTA-smtp-greeting: X-str; %s\n", s); | |
3104 | + if ((s = addr->helo_response) && *s) | |
3105 | + fprintf(f, "X-Remote-MTA-helo-response: X-str; %s\n", s); | |
3106 | + if ((s = addr->message) && *s) | |
3107 | + fprintf(f, "X-Exim-Diagnostic: X-str; %s\n", s); | |
3108 | +#endif | |
3109 | + print_dsn_diagnostic_code(addr, f); | |
3110 | + } | |
3111 | fputc('\n', f); | |
3112 | } | |
3113 | ||
3114 | diff --git a/src/src/exim.c b/src/src/exim.c | |
3115 | index 999b94c..084d649 100644 | |
3116 | --- a/src/src/exim.c | |
3117 | +++ b/src/src/exim.c | |
3118 | @@ -847,6 +847,12 @@ fprintf(f, "Support for:"); | |
3119 | #ifdef EXPERIMENTAL_DMARC | |
3120 | fprintf(f, " Experimental_DMARC"); | |
3121 | #endif | |
3122 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3123 | + fprintf(f, " Experimental_DSN_info"); | |
3124 | +#endif | |
3125 | +#ifdef EXPERIMENTAL_INTERNATIONAL | |
3126 | + fprintf(f, " Experimental_International"); | |
3127 | +#endif | |
3128 | #ifdef EXPERIMENTAL_PROXY | |
3129 | fprintf(f, " Experimental_Proxy"); | |
3130 | #endif | |
3131 | @@ -859,9 +865,6 @@ fprintf(f, "Support for:"); | |
3132 | #ifdef EXPERIMENTAL_SOCKS | |
3133 | fprintf(f, " Experimental_SOCKS"); | |
3134 | #endif | |
3135 | -#ifdef EXPERIMENTAL_INTERNATIONAL | |
3136 | - fprintf(f, " Experimental_International"); | |
3137 | -#endif | |
3138 | fprintf(f, "\n"); | |
3139 | ||
3140 | fprintf(f, "Lookups (built-in):"); | |
3141 | diff --git a/src/src/globals.c b/src/src/globals.c | |
3142 | index 8445f00..f3b6791 100644 | |
3143 | --- a/src/src/globals.c | |
3144 | +++ b/src/src/globals.c | |
3145 | @@ -354,13 +354,17 @@ address_item address_defaults = { | |
3146 | NULL, /* return_filename */ | |
3147 | NULL, /* self_hostname */ | |
3148 | NULL, /* shadow_message */ | |
3149 | - #ifdef SUPPORT_TLS | |
3150 | +#ifdef SUPPORT_TLS | |
3151 | NULL, /* cipher */ | |
3152 | NULL, /* ourcert */ | |
3153 | NULL, /* peercert */ | |
3154 | NULL, /* peerdn */ | |
3155 | OCSP_NOT_REQ, /* ocsp */ | |
3156 | - #endif | |
3157 | +#endif | |
3158 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3159 | + NULL, /* smtp_greeting */ | |
3160 | + NULL, /* helo_response */ | |
3161 | +#endif | |
3162 | NULL, /* authenticator */ | |
3163 | NULL, /* auth_id */ | |
3164 | NULL, /* auth_sndr */ | |
3165 | diff --git a/src/src/structs.h b/src/src/structs.h | |
3166 | index 438b521..db9e843 100644 | |
3167 | --- a/src/src/structs.h | |
3168 | +++ b/src/src/structs.h | |
3169 | @@ -561,13 +561,18 @@ typedef struct address_item { | |
3170 | uschar *self_hostname; /* after self=pass */ | |
3171 | uschar *shadow_message; /* info about shadow transporting */ | |
3172 | ||
3173 | - #ifdef SUPPORT_TLS | |
3174 | +#ifdef SUPPORT_TLS | |
3175 | uschar *cipher; /* Cipher used for transport */ | |
3176 | void *ourcert; /* Certificate offered to peer, binary */ | |
3177 | void *peercert; /* Certificate from peer, binary */ | |
3178 | uschar *peerdn; /* DN of server's certificate */ | |
3179 | int ocsp; /* OCSP status of peer cert */ | |
3180 | - #endif | |
3181 | +#endif | |
3182 | + | |
3183 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3184 | + const uschar *smtp_greeting; /* peer self-identification */ | |
3185 | + const uschar *helo_response; /* peer message */ | |
3186 | +#endif | |
3187 | ||
3188 | uschar *authenticator; /* auth driver name used by transport */ | |
3189 | uschar *auth_id; /* auth "login" name used by transport */ | |
3190 | diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c | |
3191 | index c93f2ef..ac40460 100644 | |
3192 | --- a/src/src/transports/smtp.c | |
3193 | +++ b/src/src/transports/smtp.c | |
3194 | @@ -440,6 +440,8 @@ Arguments: | |
3195 | rc to put in each address's transport_return field | |
3196 | pass_message if TRUE, set the "pass message" flag in the address | |
3197 | host if set, mark addrs as having used this host | |
3198 | + smtp_greeting from peer | |
3199 | + helo_response from peer | |
3200 | ||
3201 | If errno_value has the special value ERRNO_CONNECTTIMEOUT, ETIMEDOUT is put in | |
3202 | the errno field, and RTEF_CTOUT is ORed into the more_errno field, to indicate | |
3203 | @@ -450,7 +452,11 @@ Returns: nothing | |
3204 | ||
3205 | static void | |
3206 | set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc, | |
3207 | - BOOL pass_message, host_item * host) | |
3208 | + BOOL pass_message, host_item * host | |
3209 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3210 | + , const uschar * smtp_greeting, const uschar * helo_response | |
3211 | +#endif | |
3212 | + ) | |
3213 | { | |
3214 | address_item *addr; | |
3215 | int orvalue = 0; | |
3216 | @@ -459,7 +465,7 @@ if (errno_value == ERRNO_CONNECTTIMEOUT) | |
3217 | errno_value = ETIMEDOUT; | |
3218 | orvalue = RTEF_CTOUT; | |
3219 | } | |
3220 | -for (addr = addrlist; addr != NULL; addr = addr->next) | |
3221 | +for (addr = addrlist; addr; addr = addr->next) | |
3222 | if (addr->transport_return >= PENDING) | |
3223 | { | |
3224 | addr->basic_errno = errno_value; | |
3225 | @@ -471,10 +477,31 @@ for (addr = addrlist; addr != NULL; addr = addr->next) | |
3226 | } | |
3227 | addr->transport_return = rc; | |
3228 | if (host) | |
3229 | + { | |
3230 | addr->host_used = host; | |
3231 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3232 | + if (smtp_greeting) | |
3233 | + {uschar * s = Ustrchr(smtp_greeting, '\n'); if (s) *s = '\0';} | |
3234 | + addr->smtp_greeting = smtp_greeting; | |
3235 | + | |
3236 | + if (helo_response) | |
3237 | + {uschar * s = Ustrchr(helo_response, '\n'); if (s) *s = '\0';} | |
3238 | + addr->helo_response = helo_response; | |
3239 | +#endif | |
3240 | + } | |
3241 | } | |
3242 | } | |
3243 | ||
3244 | +static void | |
3245 | +set_errno_nohost(address_item *addrlist, int errno_value, uschar *msg, int rc, | |
3246 | + BOOL pass_message) | |
3247 | +{ | |
3248 | +set_errno(addrlist, errno_value, msg, rc, pass_message, NULL | |
3249 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3250 | + , NULL, NULL | |
3251 | +#endif | |
3252 | + ); | |
3253 | +} | |
3254 | ||
3255 | ||
3256 | /************************************************* | |
3257 | @@ -847,7 +874,7 @@ while (count-- > 0) | |
3258 | { | |
3259 | uschar *message = string_sprintf("SMTP timeout after RCPT TO:<%s>", | |
3260 | transport_rcpt_address(addr, include_affixes)); | |
3261 | - set_errno(addrlist, ETIMEDOUT, message, DEFER, FALSE, NULL); | |
3262 | + set_errno_nohost(addrlist, ETIMEDOUT, message, DEFER, FALSE); | |
3263 | retry_add_item(addr, addr->address_retry_key, 0); | |
3264 | update_waiting = FALSE; | |
3265 | return -1; | |
3266 | @@ -1096,8 +1123,8 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) | |
3267 | /* Internal problem, message in buffer. */ | |
3268 | ||
3269 | case ERROR: | |
3270 | - set_errno(addrlist, ERRNO_AUTHPROB, string_copy(buffer), | |
3271 | - DEFER, FALSE, NULL); | |
3272 | + set_errno_nohost(addrlist, ERRNO_AUTHPROB, string_copy(buffer), | |
3273 | + DEFER, FALSE); | |
3274 | return ERROR; | |
3275 | } | |
3276 | ||
3277 | @@ -1111,9 +1138,9 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) | |
3278 | ||
3279 | if (require_auth == OK && !smtp_authenticated) | |
3280 | { | |
3281 | - set_errno(addrlist, ERRNO_AUTHFAIL, | |
3282 | + set_errno_nohost(addrlist, ERRNO_AUTHFAIL, | |
3283 | string_sprintf("authentication required but %s", fail_reason), DEFER, | |
3284 | - FALSE, NULL); | |
3285 | + FALSE); | |
3286 | return DEFER; | |
3287 | } | |
3288 | ||
3289 | @@ -1152,7 +1179,7 @@ if (ob->authenticated_sender != NULL) | |
3290 | { | |
3291 | uschar *message = string_sprintf("failed to expand " | |
3292 | "authenticated_sender: %s", expand_string_message); | |
3293 | - set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL); | |
3294 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE); | |
3295 | return TRUE; | |
3296 | } | |
3297 | } | |
3298 | @@ -1381,6 +1408,10 @@ smtp_outblock outblock; | |
3299 | int max_rcpt = tblock->max_addresses; | |
3300 | uschar *igquotstr = US""; | |
3301 | ||
3302 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3303 | +uschar *smtp_greeting = NULL; | |
3304 | +uschar *helo_response = NULL; | |
3305 | +#endif | |
3306 | uschar *helo_data = NULL; | |
3307 | ||
3308 | uschar *message = NULL; | |
3309 | @@ -1432,8 +1463,8 @@ tls_modify_variables(&tls_out); | |
3310 | #ifndef SUPPORT_TLS | |
3311 | if (smtps) | |
3312 | { | |
3313 | - set_errno(addrlist, ERRNO_TLSFAILURE, US"TLS support not available", | |
3314 | - DEFER, FALSE, NULL); | |
3315 | + set_errno_nohost(addrlist, ERRNO_TLSFAILURE, US"TLS support not available", | |
3316 | + DEFER, FALSE); | |
3317 | return ERROR; | |
3318 | } | |
3319 | #endif | |
3320 | @@ -1450,8 +1481,8 @@ if (continue_hostname == NULL) | |
3321 | ||
3322 | if (inblock.sock < 0) | |
3323 | { | |
3324 | - set_errno(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno, | |
3325 | - NULL, DEFER, FALSE, NULL); | |
3326 | + set_errno_nohost(addrlist, (errno == ETIMEDOUT)? ERRNO_CONNECTTIMEOUT : errno, | |
3327 | + NULL, DEFER, FALSE); | |
3328 | return DEFER; | |
3329 | } | |
3330 | ||
3331 | @@ -1469,18 +1500,18 @@ if (continue_hostname == NULL) | |
3332 | && dane_required /* do not error on only dane-requested */ | |
3333 | ) | |
3334 | { | |
3335 | - set_errno(addrlist, ERRNO_DNSDEFER, | |
3336 | + set_errno_nohost(addrlist, ERRNO_DNSDEFER, | |
3337 | string_sprintf("DANE error: tlsa lookup %s", | |
3338 | rc == DEFER ? "DEFER" : "FAIL"), | |
3339 | - rc, FALSE, NULL); | |
3340 | + rc, FALSE); | |
3341 | return rc; | |
3342 | } | |
3343 | } | |
3344 | else if (dane_required) | |
3345 | { | |
3346 | - set_errno(addrlist, ERRNO_DNSDEFER, | |
3347 | + set_errno_nohost(addrlist, ERRNO_DNSDEFER, | |
3348 | string_sprintf("DANE error: %s lookup not DNSSEC", host->name), | |
3349 | - FAIL, FALSE, NULL); | |
3350 | + FAIL, FALSE); | |
3351 | return FAIL; | |
3352 | } | |
3353 | ||
3354 | @@ -1501,7 +1532,7 @@ if (continue_hostname == NULL) | |
3355 | if ((helo_data = string_domain_utf8_to_alabel(helo_data, &errstr)), errstr) | |
3356 | { | |
3357 | errstr = string_sprintf("failed to expand helo_data: %s", errstr); | |
3358 | - set_errno(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE, NULL); | |
3359 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE); | |
3360 | yield = DEFER; | |
3361 | goto SEND_QUIT; | |
3362 | } | |
3363 | @@ -1514,8 +1545,12 @@ if (continue_hostname == NULL) | |
3364 | ||
3365 | if (!smtps) | |
3366 | { | |
3367 | - if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', | |
3368 | - ob->command_timeout)) goto RESPONSE_FAILED; | |
3369 | + BOOL good_response = smtp_read_response(&inblock, buffer, sizeof(buffer), | |
3370 | + '2', ob->command_timeout); | |
3371 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3372 | + smtp_greeting = string_copy(buffer); | |
3373 | +#endif | |
3374 | + if (!good_response) goto RESPONSE_FAILED; | |
3375 | ||
3376 | #ifdef EXPERIMENTAL_EVENT | |
3377 | { | |
3378 | @@ -1525,9 +1560,9 @@ if (continue_hostname == NULL) | |
3379 | s = event_raise(tblock->event_action, US"smtp:connect", buffer); | |
3380 | if (s) | |
3381 | { | |
3382 | - set_errno(addrlist, ERRNO_EXPANDFAIL, | |
3383 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, | |
3384 | string_sprintf("deferred by smtp:connect event expansion: %s", s), | |
3385 | - DEFER, FALSE, NULL); | |
3386 | + DEFER, FALSE); | |
3387 | yield = DEFER; | |
3388 | goto SEND_QUIT; | |
3389 | } | |
3390 | @@ -1541,7 +1576,7 @@ if (continue_hostname == NULL) | |
3391 | { | |
3392 | uschar *message = string_sprintf("failed to expand helo_data: %s", | |
3393 | expand_string_message); | |
3394 | - set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL); | |
3395 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE); | |
3396 | yield = DEFER; | |
3397 | goto SEND_QUIT; | |
3398 | } | |
3399 | @@ -1606,9 +1641,18 @@ goto SEND_QUIT; | |
3400 | if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', | |
3401 | ob->command_timeout)) | |
3402 | { | |
3403 | - if (errno != 0 || buffer[0] == 0 || lmtp) goto RESPONSE_FAILED; | |
3404 | + if (errno != 0 || buffer[0] == 0 || lmtp) | |
3405 | + { | |
3406 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3407 | + helo_response = string_copy(buffer); | |
3408 | +#endif | |
3409 | + goto RESPONSE_FAILED; | |
3410 | + } | |
3411 | esmtp = FALSE; | |
3412 | } | |
3413 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3414 | + helo_response = string_copy(buffer); | |
3415 | +#endif | |
3416 | } | |
3417 | else | |
3418 | { | |
3419 | @@ -1618,10 +1662,16 @@ goto SEND_QUIT; | |
3420 | ||
3421 | if (!esmtp) | |
3422 | { | |
3423 | + BOOL good_response; | |
3424 | + | |
3425 | if (smtp_write_command(&outblock, FALSE, "HELO %s\r\n", helo_data) < 0) | |
3426 | goto SEND_FAILED; | |
3427 | - if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', | |
3428 | - ob->command_timeout)) goto RESPONSE_FAILED; | |
3429 | + good_response = smtp_read_response(&inblock, buffer, sizeof(buffer), | |
3430 | + '2', ob->command_timeout); | |
3431 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3432 | + helo_response = string_copy(buffer); | |
3433 | +#endif | |
3434 | + if (!good_response) goto RESPONSE_FAILED; | |
3435 | } | |
3436 | ||
3437 | /* Set IGNOREQUOTA if the response to LHLO specifies support and the | |
3438 | @@ -1671,6 +1721,11 @@ error messages. Note that smtp_use_size and smtp_use_pipelining will have been | |
3439 | set from the command line if they were set in the process that passed the | |
3440 | connection on. */ | |
3441 | ||
3442 | +/*XXX continue case needs to propagate DSN_INFO, prob. in deliver.c | |
3443 | +as the contine goes via transport_pass_socket() and doublefork and exec. | |
3444 | +It does not wait. Unclear how we keep separate host's responses | |
3445 | +separate - we could match up by host ip+port as a bodge. */ | |
3446 | + | |
3447 | else | |
3448 | { | |
3449 | inblock.sock = outblock.sock = fileno(stdin); | |
3450 | @@ -1749,7 +1804,7 @@ if ( tls_offered | |
3451 | ||
3452 | /* TLS session is set up */ | |
3453 | ||
3454 | - for (addr = addrlist; addr != NULL; addr = addr->next) | |
3455 | + for (addr = addrlist; addr; addr = addr->next) | |
3456 | if (addr->transport_return == PENDING_DEFER) | |
3457 | { | |
3458 | addr->cipher = tls_out.cipher; | |
3459 | @@ -1774,6 +1829,8 @@ start of the Exim process (in exim.c). */ | |
3460 | if (tls_out.active >= 0) | |
3461 | { | |
3462 | char *greeting_cmd; | |
3463 | + BOOL good_response; | |
3464 | + | |
3465 | if (helo_data == NULL) | |
3466 | { | |
3467 | helo_data = expand_string(ob->helo_data); | |
3468 | @@ -1781,7 +1838,7 @@ if (tls_out.active >= 0) | |
3469 | { | |
3470 | uschar *message = string_sprintf("failed to expand helo_data: %s", | |
3471 | expand_string_message); | |
3472 | - set_errno(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE, NULL); | |
3473 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, message, DEFER, FALSE); | |
3474 | yield = DEFER; | |
3475 | goto SEND_QUIT; | |
3476 | } | |
3477 | @@ -1790,8 +1847,12 @@ if (tls_out.active >= 0) | |
3478 | /* For SMTPS we need to wait for the initial OK response. */ | |
3479 | if (smtps) | |
3480 | { | |
3481 | - if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', | |
3482 | - ob->command_timeout)) goto RESPONSE_FAILED; | |
3483 | + good_response = smtp_read_response(&inblock, buffer, sizeof(buffer), | |
3484 | + '2', ob->command_timeout); | |
3485 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3486 | + smtp_greeting = string_copy(buffer); | |
3487 | +#endif | |
3488 | + if (!good_response) goto RESPONSE_FAILED; | |
3489 | } | |
3490 | ||
3491 | if (esmtp) | |
3492 | @@ -1806,9 +1867,12 @@ if (tls_out.active >= 0) | |
3493 | if (smtp_write_command(&outblock, FALSE, "%s %s\r\n", | |
3494 | lmtp? "LHLO" : greeting_cmd, helo_data) < 0) | |
3495 | goto SEND_FAILED; | |
3496 | - if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', | |
3497 | - ob->command_timeout)) | |
3498 | - goto RESPONSE_FAILED; | |
3499 | + good_response = smtp_read_response(&inblock, buffer, sizeof(buffer), | |
3500 | + '2', ob->command_timeout); | |
3501 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3502 | + helo_response = string_copy(buffer); | |
3503 | +#endif | |
3504 | + if (!good_response) goto RESPONSE_FAILED; | |
3505 | } | |
3506 | ||
3507 | /* If the host is required to use a secure channel, ensure that we | |
3508 | @@ -1935,8 +1999,8 @@ if (tblock->filter_command != NULL) | |
3509 | ||
3510 | if (!rc) | |
3511 | { | |
3512 | - set_errno(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER, | |
3513 | - FALSE, NULL); | |
3514 | + set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER, | |
3515 | + FALSE); | |
3516 | yield = ERROR; | |
3517 | goto SEND_QUIT; | |
3518 | } | |
3519 | @@ -2065,7 +2129,7 @@ pending_MAIL = TRUE; /* The block starts with MAIL */ | |
3520 | { | |
3521 | if (s = string_address_utf8_to_alabel(return_path, &errstr), errstr) | |
3522 | { | |
3523 | - set_errno(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE, NULL); | |
3524 | + set_errno_nohost(addrlist, ERRNO_EXPANDFAIL, errstr, DEFER, FALSE); | |
3525 | yield = ERROR; | |
3526 | goto SEND_QUIT; | |
3527 | } | |
3528 | @@ -2217,8 +2281,8 @@ if (mua_wrapper) | |
3529 | if (badaddr->transport_return != PENDING_OK) | |
3530 | { | |
3531 | /*XXX could we find a better errno than 0 here? */ | |
3532 | - set_errno(addrlist, 0, badaddr->message, FAIL, | |
3533 | - testflag(badaddr, af_pass_message), NULL); | |
3534 | + set_errno_nohost(addrlist, 0, badaddr->message, FAIL, | |
3535 | + testflag(badaddr, af_pass_message)); | |
3536 | ok = FALSE; | |
3537 | break; | |
3538 | } | |
3539 | @@ -2475,7 +2539,7 @@ if (!ok) ok = TRUE; else | |
3540 | else | |
3541 | sprintf(CS buffer, "%.500s\n", addr->unique); | |
3542 | ||
3543 | - DEBUG(D_deliver) debug_printf("journalling %s", buffer); | |
3544 | + DEBUG(D_deliver) debug_printf("journalling %s\n", buffer); | |
3545 | len = Ustrlen(CS buffer); | |
3546 | if (write(journal_fd, buffer, len) != len) | |
3547 | log_write(0, LOG_MAIN|LOG_PANIC, "failed to write journal for " | |
3548 | @@ -2512,7 +2576,7 @@ if (!ok) ok = TRUE; else | |
3549 | else | |
3550 | sprintf(CS buffer, "%.500s\n", addr->unique); | |
3551 | ||
3552 | - DEBUG(D_deliver) debug_printf("journalling(PRDR) %s", buffer); | |
3553 | + DEBUG(D_deliver) debug_printf("journalling(PRDR) %s\n", buffer); | |
3554 | len = Ustrlen(CS buffer); | |
3555 | if (write(journal_fd, buffer, len) != len) | |
3556 | log_write(0, LOG_MAIN|LOG_PANIC, "failed to write journal for " | |
3557 | @@ -2542,22 +2606,27 @@ the problem is not related to this specific message. */ | |
3558 | ||
3559 | if (!ok) | |
3560 | { | |
3561 | - int code; | |
3562 | + int code, set_rc; | |
3563 | + uschar * set_message; | |
3564 | ||
3565 | RESPONSE_FAILED: | |
3566 | - save_errno = errno; | |
3567 | - message = NULL; | |
3568 | - send_quit = check_response(host, &save_errno, addrlist->more_errno, | |
3569 | - buffer, &code, &message, &pass_message); | |
3570 | - goto FAILED; | |
3571 | + { | |
3572 | + save_errno = errno; | |
3573 | + message = NULL; | |
3574 | + send_quit = check_response(host, &save_errno, addrlist->more_errno, | |
3575 | + buffer, &code, &message, &pass_message); | |
3576 | + goto FAILED; | |
3577 | + } | |
3578 | ||
3579 | SEND_FAILED: | |
3580 | - save_errno = errno; | |
3581 | - code = '4'; | |
3582 | - message = US string_sprintf("send() to %s [%s] failed: %s", | |
3583 | - host->name, host->address, strerror(save_errno)); | |
3584 | - send_quit = FALSE; | |
3585 | - goto FAILED; | |
3586 | + { | |
3587 | + save_errno = errno; | |
3588 | + code = '4'; | |
3589 | + message = US string_sprintf("send() to %s [%s] failed: %s", | |
3590 | + host->name, host->address, strerror(save_errno)); | |
3591 | + send_quit = FALSE; | |
3592 | + goto FAILED; | |
3593 | + } | |
3594 | ||
3595 | /* This label is jumped to directly when a TLS negotiation has failed, | |
3596 | or was not done for a host for which it is required. Values will be set | |
3597 | @@ -2578,16 +2647,14 @@ if (!ok) | |
3598 | ||
3599 | FAILED: | |
3600 | ok = FALSE; /* For when reached by GOTO */ | |
3601 | + set_message = message; | |
3602 | ||
3603 | if (setting_up) | |
3604 | { | |
3605 | if (code == '5') | |
3606 | - set_errno(addrlist, save_errno, message, FAIL, pass_message, host); | |
3607 | + set_rc = FAIL; | |
3608 | else | |
3609 | - { | |
3610 | - set_errno(addrlist, save_errno, message, DEFER, pass_message, host); | |
3611 | - yield = DEFER; | |
3612 | - } | |
3613 | + yield = set_rc = DEFER; | |
3614 | } | |
3615 | ||
3616 | /* We want to handle timeouts after MAIL or "." and loss of connection after | |
3617 | @@ -2646,14 +2713,15 @@ if (!ok) | |
3618 | if (message_error) | |
3619 | { | |
3620 | if (mua_wrapper) code = '5'; /* Force hard failure in wrapper mode */ | |
3621 | - set_errno(addrlist, save_errno, message, (code == '5')? FAIL : DEFER, | |
3622 | - pass_message, host); | |
3623 | ||
3624 | /* If there's an errno, the message contains just the identity of | |
3625 | the host. */ | |
3626 | ||
3627 | - if (code != '5') /* Anything other than 5 is treated as temporary */ | |
3628 | + if (code == '5') | |
3629 | + set_rc = FAIL; | |
3630 | + else /* Anything other than 5 is treated as temporary */ | |
3631 | { | |
3632 | + set_rc = DEFER; | |
3633 | if (save_errno > 0) | |
3634 | message = US string_sprintf("%s: %s", message, strerror(save_errno)); | |
3635 | if (host->next != NULL) log_write(0, LOG_MAIN, "%s", message); | |
3636 | @@ -2670,11 +2738,17 @@ if (!ok) | |
3637 | ||
3638 | else | |
3639 | { | |
3640 | + set_rc = DEFER; | |
3641 | yield = (save_errno == ERRNO_CHHEADER_FAIL || | |
3642 | save_errno == ERRNO_FILTER_FAIL)? ERROR : DEFER; | |
3643 | - set_errno(addrlist, save_errno, message, DEFER, pass_message, host); | |
3644 | } | |
3645 | } | |
3646 | + | |
3647 | + set_errno(addrlist, save_errno, set_message, set_rc, pass_message, host | |
3648 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3649 | + , smtp_greeting, helo_response | |
3650 | +#endif | |
3651 | + ); | |
3652 | } | |
3653 | ||
3654 | ||
3655 | @@ -2787,6 +2861,9 @@ if (completed_address && ok && send_quit) | |
3656 | /* If the socket is successfully passed, we musn't send QUIT (or | |
3657 | indeed anything!) from here. */ | |
3658 | ||
3659 | +/*XXX DSN_INFO: assume likely to do new HELO; but for greet we'll want to | |
3660 | +propagate it from the initial | |
3661 | +*/ | |
3662 | if (ok && transport_pass_socket(tblock->name, host->name, host->address, | |
3663 | new_message_id, inblock.sock)) | |
3664 | { | |
3665 | @@ -2796,7 +2873,11 @@ if (completed_address && ok && send_quit) | |
3666 | ||
3667 | /* If RSET failed and there are addresses left, they get deferred. */ | |
3668 | ||
3669 | - else set_errno(first_addr, errno, msg, DEFER, FALSE, host); | |
3670 | + else set_errno(first_addr, errno, msg, DEFER, FALSE, host | |
3671 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3672 | + , smtp_greeting, helo_response | |
3673 | +#endif | |
3674 | + ); | |
3675 | } | |
3676 | } | |
3677 | ||
3678 | @@ -2938,6 +3019,10 @@ for (addr = addrlist; addr != NULL; addr = addr->next) | |
3679 | addr->peerdn = NULL; | |
3680 | addr->ocsp = OCSP_NOT_REQ; | |
3681 | #endif | |
3682 | +#ifdef EXPERIMENTAL_DSN_INFO | |
3683 | + addr->smtp_greeting = NULL; | |
3684 | + addr->helo_response = NULL; | |
3685 | +#endif | |
3686 | } | |
3687 | return first_addr; | |
3688 | } | |
3689 | @@ -3479,7 +3564,7 @@ for (cutoff_retry = 0; expired && | |
3690 | if (dont_deliver) | |
3691 | { | |
3692 | host_item *host2; | |
3693 | - set_errno(addrlist, 0, NULL, OK, FALSE, NULL); | |
3694 | + set_errno_nohost(addrlist, 0, NULL, OK, FALSE); | |
3695 | for (addr = addrlist; addr != NULL; addr = addr->next) | |
3696 | { | |
3697 | addr->host_used = host; |