summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNigel Metheringham <nigel@exim.org>2008-09-29 11:41:07 +0000
committerNigel Metheringham <nigel@exim.org>2008-09-29 11:41:07 +0000
commitce5524496cf016f06c8004e00ce9d043f4ac6aff (patch)
treecd8a68bf0886d36b82668e70fbef936a806c23e1
parentc4c02c552afaadc2a78b9df2aa22559dd1587f40 (diff)
Fix to EXPN not working under TLS. Fixes bug #744
-rw-r--r--doc/doc-txt/ChangeLog7
-rw-r--r--src/src/local_scan.h8
-rw-r--r--src/src/macros.h17
-rw-r--r--src/src/mytypes.h6
-rw-r--r--src/src/smtp_in.c27
-rw-r--r--src/src/verify.c71
6 files changed, 104 insertions, 32 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index c6fd500ec..419ca6fdd 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.553 2008/09/05 16:59:47 fanf2 Exp $
+$Cambridge: 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 @@ TF/04 Bugzilla 668: Fix parallel build (make -j).
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/08 TLS error reporting now respects the incoming_interface and
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
-----------------
diff --git a/src/src/local_scan.h b/src/src/local_scan.h
index 20d6c8773..8debd2b18 100644
--- a/src/src/local_scan.h
+++ b/src/src/local_scan.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/local_scan.h,v 1.11 2007/06/14 13:27:11 ph10 Exp $ */
+/* $Cambridge: 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 @@ This API is also used for functions called by the ${dlfunc expansion item. */
/* 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 int child_close(pid_t, int);
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 void receive_add_recipient(uschar *, int);
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 *, ...);
diff --git a/src/src/macros.h b/src/src/macros.h
index 161a6a181..aa4acd1c8 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/macros.h,v 1.36 2007/08/22 10:10:23 ph10 Exp $ */
+/* $Cambridge: 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 @@ explicit port number. */
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 */
diff --git a/src/src/mytypes.h b/src/src/mytypes.h
index 51a4ad494..d9912c4ff 100644
--- a/src/src/mytypes.h
+++ b/src/src/mytypes.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/mytypes.h,v 1.4 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: 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 @@ local_scan.h includes it and exim.h includes them both (to get this earlier). */
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
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index de7663b1a..b710c89ce 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.62 2007/09/28 12:21:57 tom Exp $ */
+/* $Cambridge: 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 @@ smtp_printf(char *format, ...)
{
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
diff --git a/src/src/verify.c b/src/src/verify.c
index 4b4044507..ab7e2756f 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.51 2007/06/14 14:18:19 ph10 Exp $ */
+/* $Cambridge: 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 @@ return yield;
+/**************************************************
+* 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 (parse_find_at(address) == NULL)
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 @@ while (addr_new != NULL)
{
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 @@ while (addr_new != NULL)
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 @@ while (addr_new != NULL)
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;
}