nm4 2008/09/29 12:41:07 BST
Modified files:
exim-doc/doc-txt ChangeLog
exim-src/src local_scan.h macros.h mytypes.h smtp_in.c
verify.c
Log:
Fix to EXPN not working under TLS. Fixes bug #744
Revision Changes Path
1.554 +4 -1 exim/exim-doc/doc-txt/ChangeLog
1.12 +4 -2 exim/exim-src/src/local_scan.h
1.37 +15 -0 exim/exim-src/src/macros.h
1.5 +2 -2 exim/exim-src/src/mytypes.h
1.63 +20 -5 exim/exim-src/src/smtp_in.c
1.52 +53 -16 exim/exim-src/src/verify.c
Index: ChangeLog
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
retrieving revision 1.553
retrieving revision 1.554
diff -u -r1.553 -r1.554
--- ChangeLog 5 Sep 2008 16:59:47 -0000 1.553
+++ ChangeLog 29 Sep 2008 11:41:07 -0000 1.554
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.553 2008/09/05 16:59:47 fanf2 Exp $
+$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.554 2008/09/29 11:41:07 nm4 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
@@ -51,7 +51,7 @@
NM/05 Bugzilla 437: Prevent Maildix aux files being created with mode 000
-NM/05 Bugzilla 598: Improvedment to Dovecot authenticator handling.
+NM/05 Bugzilla 598: Improvement to Dovecot authenticator handling.
Patch provided by Jan Srzednicki
TF/05 Leading white space used to be stripped from $spam_report which
@@ -68,6 +68,9 @@
TF/09 Produce a more useful error message if an SMTP transport's hosts
setting expands to an empty string.
+NM/06 Bugzilla 744: EXPN did not work under TLS.
+ Patch provided by Phil Pennock
+
Exim version 4.69
-----------------
Index: local_scan.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/local_scan.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- local_scan.h 14 Jun 2007 13:27:11 -0000 1.11
+++ local_scan.h 29 Sep 2008 11:41:07 -0000 1.12
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/local_scan.h,v 1.11 2007/06/14 13:27:11 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/local_scan.h,v 1.12 2008/09/29 11:41:07 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -17,6 +17,7 @@
/* Some basic types that make some things easier, the Exim configuration
settings, and the store functions. */
+#include <stdarg.h>
#include <sys/types.h>
#include "config.h"
#include "mytypes.h"
@@ -167,7 +168,7 @@
extern pid_t child_open(uschar **, uschar **, int, int *, int *, BOOL);
extern pid_t child_open_exim(int *);
extern pid_t child_open_exim2(int *, uschar *, uschar *);
-extern void debug_printf(char *, ...) PRINTF_FUNCTION;
+extern void debug_printf(char *, ...) PRINTF_FUNCTION(1,2);
extern uschar *expand_string(uschar *);
extern void header_add(int, char *, ...);
extern void header_add_at_position(BOOL, uschar *, BOOL, int, char *, ...);
@@ -185,7 +186,8 @@
extern BOOL receive_remove_recipient(uschar *);
extern uschar *rfc2047_decode(uschar *, BOOL, uschar *, int, int *, uschar **);
extern int smtp_fflush(void);
-extern void smtp_printf(char *, ...) PRINTF_FUNCTION;
+extern void smtp_printf(char *, ...) PRINTF_FUNCTION(1,2);
+extern void smtp_vprintf(char *, va_list);
extern uschar *string_copy(uschar *);
extern uschar *string_copyn(uschar *, int);
extern uschar *string_sprintf(char *, ...);
Index: macros.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/macros.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- macros.h 22 Aug 2007 10:10:23 -0000 1.36
+++ macros.h 29 Sep 2008 11:41:07 -0000 1.37
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/macros.h,v 1.36 2007/08/22 10:10:23 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/macros.h,v 1.37 2008/09/29 11:41:07 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -840,4 +840,19 @@
enum { FILTER_UNSET, FILTER_FORWARD, FILTER_EXIM, FILTER_SIEVE };
+/* C99 defines va_copy() for copying a varargs ap so that it can be reused,
+since on some platforms multiple iterations of va_start()/va_end() are not
+supported. But va_copy() is itself not so portable. Hack around it.
+See portability notes at:
http://unixpapa.com/incnote/variadic.html */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+/* va_copy exists for us or the system is broken and we need OS hacks */
+#elif defined(va_copy)
+/* trust it; hope that va_copy is always a macro when defined */
+#elif !defined(va_copy) && defined(__va_copy)
+#define va_copy(dest, src) __va_copy(dest, src)
+#else
+#define va_copy(dest, src) do { memcpy(dest, src, sizeof(va_list) } while (0)
+#endif
+
/* End of macros.h */
Index: mytypes.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/mytypes.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- mytypes.h 8 Jan 2007 10:50:18 -0000 1.4
+++ mytypes.h 29 Sep 2008 11:41:07 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/mytypes.h,v 1.4 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/mytypes.h,v 1.5 2008/09/29 11:41:07 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -25,9 +25,9 @@
the arguments of printf-like functions. This is done by a macro. */
#ifdef __GNUC__
-#define PRINTF_FUNCTION __attribute__((format(printf,1,2)))
+#define PRINTF_FUNCTION(A,B) __attribute__((format(printf,A,B)))
#else
-#define PRINTF_FUNCTION
+#define PRINTF_FUNCTION(A,B)
#endif
Index: smtp_in.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -r1.62 -r1.63
--- smtp_in.c 28 Sep 2007 12:21:57 -0000 1.62
+++ smtp_in.c 29 Sep 2008 11:41:07 -0000 1.63
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.62 2007/09/28 12:21:57 tom Exp $ */
+/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.63 2008/09/29 11:41:07 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -376,26 +376,41 @@
{
va_list ap;
+va_start(ap, format);
+smtp_vprintf(format, ap);
+va_end(ap);
+}
+
+/* This is split off so that verify.c:respond_printf() can, in effect, call
+smtp_printf(), bearing in mind that in C a vararg function can't directly
+call another vararg function, only a function which accepts a va_list.
+
+Note also that repeated calls to va_start()/va_end() pairs is claimed to be
+non-portable; meanwhile, va_copy() is also non-portable in that it's C99, so
+we end up needing OS support to define it for us. */
+
+void
+smtp_vprintf(char *format, va_list ap)
+{
+va_list ap_d;
+
DEBUG(D_receive)
{
uschar *cr, *end;
- va_start(ap, format);
- (void) string_vformat(big_buffer, big_buffer_size, format, ap);
- va_end(ap);
+ va_copy(ap_d, ap);
+ (void) string_vformat(big_buffer, big_buffer_size, format, ap_d);
end = big_buffer + Ustrlen(big_buffer);
while ((cr = Ustrchr(big_buffer, '\r')) != NULL) /* lose CRs */
memmove(cr, cr + 1, (end--) - cr);
debug_printf("SMTP>> %s", big_buffer);
}
-va_start(ap, format);
if (!string_vformat(big_buffer, big_buffer_size, format, ap))
{
log_write(0, LOG_MAIN|LOG_PANIC, "string too large in smtp_printf()");
smtp_closedown(US"Unexpected error");
exim_exit(EXIT_FAILURE);
}
-va_end(ap);
/* If this is the first output for a (non-batch) RCPT command, see if all RCPTs
have had the same. Note: this code is also present in smtp_respond(). It would
Index: verify.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/verify.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- verify.c 14 Jun 2007 14:18:19 -0000 1.51
+++ verify.c 29 Sep 2008 11:41:07 -0000 1.52
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/verify.c,v 1.51 2007/06/14 14:18:19 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/verify.c,v 1.52 2008/09/29 11:41:07 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -863,6 +863,42 @@
+/**************************************************
+* printf that automatically handles TLS if needed *
+***************************************************/
+
+/* This function is used by verify_address() as a substitute for all fprintf()
+calls; a direct fprintf() will not produce output in a TLS SMTP session, such
+as a response to an EXPN command. smtp_in.c makes smtp_printf available but
+that assumes that we always use the smtp_out FILE* when not using TLS or the
+ssl buffer when we are. Instead we take a FILE* parameter and check to see if
+that is smtp_out; if so, smtp_printf() with TLS support, otherwise regular
+fprintf().
+
+Arguments:
+ f the candidate FILE* to write to
+ format format string
+ ... optional arguments
+
+Returns:
+ nothing
+*/
+
+static void PRINTF_FUNCTION(2,3)
+respond_printf(FILE *f, char *format, ...)
+{
+va_list ap;
+
+va_start(ap, format);
+if (smtp_out && (f == smtp_out))
+ smtp_vprintf(format, ap);
+else
+ fprintf(f, format, ap);
+va_end(ap);
+}
+
+
+
/*************************************************
* Verify an email address *
*************************************************/
@@ -962,8 +998,8 @@
if ((options & vopt_qualify) == 0)
{
if (f != NULL)
- fprintf(f, "%sA domain is required for \"%s\"%s\n", ko_prefix, address,
- cr);
+ respond_printf(f, "%sA domain is required for \"%s\"%s\n",
+ ko_prefix, address, cr);
*failure_ptr = US"qualify";
return FAIL;
}
@@ -1227,24 +1263,25 @@
{
address_item *p = addr->parent;
- fprintf(f, "%s%s %s", ko_prefix, full_info? addr->address : address,
+ respond_printf(f, "%s%s %s", ko_prefix,
+ full_info? addr->address : address,
address_test_mode? "is undeliverable" : "failed to verify");
if (!expn && admin_user)
{
if (addr->basic_errno > 0)
- fprintf(f, ": %s", strerror(addr->basic_errno));
+ respond_printf(f, ": %s", strerror(addr->basic_errno));
if (addr->message != NULL)
- fprintf(f, ": %s", addr->message);
+ respond_printf(f, ": %s", addr->message);
}
/* Show parents iff doing full info */
if (full_info) while (p != NULL)
{
- fprintf(f, "%s\n <-- %s", cr, p->address);
+ respond_printf(f, "%s\n <-- %s", cr, p->address);
p = p->parent;
}
- fprintf(f, "%s\n", cr);
+ respond_printf(f, "%s\n", cr);
}
if (!full_info) return copy_error(vaddr, addr, FAIL);
@@ -1259,26 +1296,26 @@
if (f != NULL)
{
address_item *p = addr->parent;
- fprintf(f, "%s%s cannot be resolved at this time", ko_prefix,
+ respond_printf(f, "%s%s cannot be resolved at this time", ko_prefix,
full_info? addr->address : address);
if (!expn && admin_user)
{
if (addr->basic_errno > 0)
- fprintf(f, ": %s", strerror(addr->basic_errno));
+ respond_printf(f, ": %s", strerror(addr->basic_errno));
if (addr->message != NULL)
- fprintf(f, ": %s", addr->message);
+ respond_printf(f, ": %s", addr->message);
else if (addr->basic_errno <= 0)
- fprintf(f, ": unknown error");
+ respond_printf(f, ": unknown error");
}
/* Show parents iff doing full info */
if (full_info) while (p != NULL)
{
- fprintf(f, "%s\n <-- %s", cr, p->address);
+ respond_printf(f, "%s\n <-- %s", cr, p->address);
p = p->parent;
}
- fprintf(f, "%s\n", cr);
+ respond_printf(f, "%s\n", cr);
}
if (!full_info) return copy_error(vaddr, addr, DEFER);
else if (yield == OK) yield = DEFER;
@@ -1293,16 +1330,16 @@
if (addr_new == NULL)
{
if (addr_local == NULL && addr_remote == NULL)
- fprintf(f, "250 mail to <%s> is discarded\r\n", address);
+ respond_printf(f, "250 mail to <%s> is discarded\r\n", address);
else
- fprintf(f, "250 <%s>\r\n", address);
+ respond_printf(f, "250 <%s>\r\n", address);
}
else while (addr_new != NULL)
{
address_item *addr2 = addr_new;
addr_new = addr2->next;
if (addr_new == NULL) ok_prefix = US"250 ";
- fprintf(f, "%s<%s>\r\n", ok_prefix, addr2->address);
+ respond_printf(f, "%s<%s>\r\n", ok_prefix, addr2->address);
}
return OK;
}