summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTodd Lyons <tlyons@exim.org>2012-10-15 20:21:07 -0700
committerTodd Lyons <tlyons@exim.org>2012-10-15 20:21:07 -0700
commitff6dccc43b493a7f3aad49d4feaca9fb393b0c3f (patch)
tree9493282998cace60e1705c68096dec6930ce4c7a /src
parent333b9d0deda18e32f88c1f9e35557ec5f61f4649 (diff)
parent2e07c15567bab345cd27051658b0755e0ab88a11 (diff)
Merge branch 'master' of ssh://git.exim.org/home/git/exim
Diffstat (limited to 'src')
-rw-r--r--src/ACKNOWLEDGMENTS1
-rw-r--r--src/src/acl.c45
-rw-r--r--src/src/configure.default15
-rw-r--r--src/src/expand.c73
-rw-r--r--src/src/functions.h2
-rw-r--r--src/src/globals.c2
-rw-r--r--src/src/globals.h1
-rw-r--r--src/src/macros.h1
-rw-r--r--src/src/receive.c9
-rw-r--r--src/src/smtp_in.c18
10 files changed, 133 insertions, 34 deletions
diff --git a/src/ACKNOWLEDGMENTS b/src/ACKNOWLEDGMENTS
index a66512f36..dbdc40cb3 100644
--- a/src/ACKNOWLEDGMENTS
+++ b/src/ACKNOWLEDGMENTS
@@ -370,6 +370,7 @@ Wolfgang Breyha DCC integration; expandable spamd_address
Patch fixing DKIM verification when signature header
not prepended
Unbroke Cyrus SASL auth after incorrect SSF addition
+ Logging of 8bitmime reception
David Brownlee Patch improving local interface IP address detection
Eugene Bujak Security patch fixing buffer overflow in string_format
Adam Ciarcinski Patch for TLS-enabled LDAP (alternative to ldaps)
diff --git a/src/src/acl.c b/src/src/acl.c
index 3b23a915b..6ae3680b7 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -958,10 +958,13 @@ setup_header(uschar *hstring)
uschar *p, *q;
int hlen = Ustrlen(hstring);
-/* An empty string does nothing; otherwise add a final newline if necessary. */
+/* Ignore any leading newlines */
+while (*hstring == '\n') hstring++, hlen--;
+/* An empty string does nothing; ensure exactly one final newline. */
if (hlen <= 0) return;
-if (hstring[hlen-1] != '\n') hstring = string_sprintf("%s\n", hstring);
+if (hstring[--hlen] != '\n') hstring = string_sprintf("%s\n", hstring);
+else while(hstring[--hlen] == '\n') hstring[hlen+1] = '\0';
/* Loop for multiple header lines, taking care about continuations */
@@ -1048,6 +1051,44 @@ for (p = q = hstring; *p != 0; )
/*************************************************
+* List the added header lines *
+*************************************************/
+uschar *
+fn_hdrs_added(void)
+{
+uschar * ret = NULL;
+header_line * h = acl_added_headers;
+uschar * s;
+uschar * cp;
+int size = 0;
+int ptr = 0;
+
+if (!h) return NULL;
+
+do
+ {
+ s = h->text;
+ while ((cp = Ustrchr(s, '\n')) != NULL)
+ {
+ if (cp[1] == '\0') break;
+
+ /* contains embedded newline; needs doubling */
+ ret = string_cat(ret, &size, &ptr, s, cp-s+1);
+ ret = string_cat(ret, &size, &ptr, "\n", 1);
+ s = cp+1;
+ }
+ /* last bit of header */
+
+ ret = string_cat(ret, &size, &ptr, s, cp-s+1); /* newline-sep list */
+ }
+while(h = h->next);
+
+ret[ptr-1] = '\0'; /* overwrite last newline */
+return ret;
+}
+
+
+/*************************************************
* Set up removed header line(s) *
*************************************************/
diff --git a/src/src/configure.default b/src/src/configure.default
index 0ccbbe855..792b3ecc1 100644
--- a/src/src/configure.default
+++ b/src/src/configure.default
@@ -542,6 +542,21 @@ dnslookup:
no_more
+# This alternative router can be used when you want to send all mail to a
+# server which handles DNS lookups for you; an ISP will typically run such
+# a server for their customers. If you uncomment "smarthost" then you
+# should comment out "dnslookup" above. Setting a real hostname in route_data
+# wouldn't hurt either.
+
+# smarthost:
+# driver = manualroute
+# domains = ! +local_domains
+# transport = remote_smtp
+# route_data = MAIL.HOSTNAME.FOR.CENTRAL.SERVER.EXAMPLE
+# ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
+# no_more
+
+
# The remaining routers handle addresses in the local domain(s), that is those
# domains that are defined by "domainlist local_domains" above.
diff --git a/src/src/expand.c b/src/src/expand.c
index 780386273..0e969788a 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -367,9 +367,7 @@ enum {
vtype_msgheaders_raw, /* the message's headers, unprocessed */
vtype_localpart, /* extract local part from string */
vtype_domain, /* extract domain from string */
- vtype_recipients, /* extract recipients from recipients list */
- /* (available only in system filters, ACLs, and */
- /* local_scan()) */
+ vtype_string_func, /* value is string returned by given function */
vtype_todbsdin, /* value not used; generate BSD inbox tod */
vtype_tode, /* value not used; generate tod in epoch format */
vtype_todel, /* value not used; generate tod in epoch/usec format */
@@ -389,6 +387,8 @@ enum {
#endif
};
+static uschar * fn_recipients(void);
+
/* This table must be kept in alphabetical order. */
static var_entry var_table[] = {
@@ -471,6 +471,7 @@ static var_entry var_table[] = {
#ifdef WITH_OLD_DEMIME
{ "found_extension", vtype_stringptr, &found_extension },
#endif
+ { "headers_added", vtype_string_func, &fn_hdrs_added },
{ "home", vtype_stringptr, &deliver_home },
{ "host", vtype_stringptr, &deliver_host },
{ "host_address", vtype_stringptr, &deliver_host_address },
@@ -562,7 +563,7 @@ static var_entry var_table[] = {
{ "received_time", vtype_int, &received_time },
{ "recipient_data", vtype_stringptr, &recipient_data },
{ "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
- { "recipients", vtype_recipients, NULL },
+ { "recipients", vtype_string_func, &fn_recipients },
{ "recipients_count", vtype_int, &recipients_count },
#ifdef WITH_CONTENT_SCAN
{ "regex_match_string", vtype_stringptr, &regex_match_string },
@@ -783,8 +784,11 @@ return -1;
/* This function is called to expand a string, and test the result for a "true"
or "false" value. Failure of the expansion yields FALSE; logged unless it was a
-forced fail or lookup defer. All store used by the function can be released on
-exit.
+forced fail or lookup defer.
+
+We used to release all store used, but this is not not safe due
+to ${dlfunc } and ${acl }. In any case expand_string_internal()
+is reasonably careful to release what it can.
The actual false-value tests should be replicated for ECOND_BOOL_LAX.
@@ -800,7 +804,6 @@ BOOL
expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
{
int rc;
-void *reset_point = store_get(0);
uschar *ss = expand_string(condition);
if (ss == NULL)
{
@@ -811,7 +814,6 @@ if (ss == NULL)
}
rc = ss[0] != 0 && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
strcmpic(ss, US"false") != 0;
-store_reset(reset_point);
return rc;
}
@@ -1447,6 +1449,34 @@ return yield;
/*************************************************
+* Return list of recipients *
+*************************************************/
+/* A recipients list is available only during system message filtering,
+during ACL processing after DATA, and while expanding pipe commands
+generated from a system filter, but not elsewhere. */
+
+static uschar *
+fn_recipients(void)
+{
+if (!enable_dollar_recipients) return NULL; else
+ {
+ int size = 128;
+ int ptr = 0;
+ int i;
+ uschar * s = store_get(size);
+ for (i = 0; i < recipients_count; i++)
+ {
+ if (i != 0) s = string_cat(s, &size, &ptr, US", ", 2);
+ s = string_cat(s, &size, &ptr, recipients_list[i].address,
+ Ustrlen(recipients_list[i].address));
+ }
+ s[ptr] = 0; /* string_cat() leaves room */
+ return s;
+ }
+}
+
+
+/*************************************************
* Find value of a variable *
*************************************************/
@@ -1671,26 +1701,11 @@ while (last > first)
}
return (s == NULL)? US"" : s;
- /* A recipients list is available only during system message filtering,
- during ACL processing after DATA, and while expanding pipe commands
- generated from a system filter, but not elsewhere. */
-
- case vtype_recipients:
- if (!enable_dollar_recipients) return NULL; else
+ case vtype_string_func:
{
- int size = 128;
- int ptr = 0;
- int i;
- s = store_get(size);
- for (i = 0; i < recipients_count; i++)
- {
- if (i != 0) s = string_cat(s, &size, &ptr, US", ", 2);
- s = string_cat(s, &size, &ptr, recipients_list[i].address,
- Ustrlen(recipients_list[i].address));
- }
- s[ptr] = 0; /* string_cat() leaves room */
+ uschar * (*fn)() = var_table[middle].value;
+ return fn();
}
- return s;
case vtype_pspace:
{
@@ -3534,8 +3549,8 @@ $message_headers which can get very long.
There's a problem if a ${dlfunc item has side-effects that cause allocation,
since resetting the store at the end of the expansion will free store that was
allocated by the plugin code as well as the slop after the expanded string. So
-we skip any resets if ${dlfunc has been used. This is an unfortunate
-consequence of string expansion becoming too powerful.
+we skip any resets if ${dlfunc has been used. The same applies for ${acl. This
+is an unfortunate consequence of string expansion becoming too powerful.
Arguments:
string the string to be expanded
@@ -3757,6 +3772,7 @@ while (*s != 0)
acl_check_internal() directly and get a current level from somewhere.
See also the acl expansion condition ECOND_ACL and the traditional
acl modifier ACLC_ACL.
+ Assume that the function has side-effects on the store that must be preserved.
*/
case EITEM_ACL:
@@ -3773,6 +3789,7 @@ while (*s != 0)
}
if (skipping) continue;
+ resetok = FALSE;
switch(eval_acl(sub, sizeof(sub)/sizeof(*sub), &user_msg))
{
case OK:
diff --git a/src/src/functions.h b/src/src/functions.h
index bc791fcdb..034ef196d 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -139,6 +139,8 @@ extern BOOL filter_personal(string_item *, BOOL);
extern BOOL filter_runtest(int, uschar *, BOOL, BOOL);
extern BOOL filter_system_interpret(address_item **, uschar **);
+extern uschar * fn_hdrs_added(void);
+
extern void header_add(int, const char *, ...);
extern int header_checkname(header_line *, BOOL);
extern BOOL header_match(uschar *, BOOL, BOOL, string_item *, int, ...);
diff --git a/src/src/globals.c b/src/src/globals.c
index bcbe12d82..ba6c8c6ba 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -271,6 +271,7 @@ uschar *acl_wherecodes[] = { US"550", /* RCPT */
BOOL active_local_from_check = FALSE;
BOOL active_local_sender_retain = FALSE;
+int body_8bitmime = 0;
BOOL accept_8bitmime = TRUE; /* deliberately not RFC compliant */
address_item *addr_duplicate = NULL;
@@ -734,6 +735,7 @@ selectors was getting close to filling a 32-bit word. */
/* Note that this list must be in alphabetical order. */
bit_table log_options[] = {
+ { US"8bitmime", LX_8bitmime },
{ US"acl_warn_skipped", LX_acl_warn_skipped },
{ US"address_rewrite", L_address_rewrite },
{ US"all", L_all },
diff --git a/src/src/globals.h b/src/src/globals.h
index 16caa41e9..a27f62cfe 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -133,6 +133,7 @@ extern uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT];
/* General global variables */
extern BOOL accept_8bitmime; /* Allow *BITMIME incoming */
+extern int body_8bitmime; /* sender declared BODY= ; 7=7BIT, 8=8BITMIME */
extern header_line *acl_added_headers; /* Headers added by an ACL */
extern tree_node *acl_anchor; /* Tree of named ACLs */
extern uschar *acl_arg[9]; /* Argument to ACL call */
diff --git a/src/src/macros.h b/src/src/macros.h
index cec4733f6..305200211 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -409,6 +409,7 @@ set all the bits in a multi-word selector. */
#define LX_tls_peerdn 0x80400000
#define LX_tls_sni 0x80800000
#define LX_unknown_in_list 0x81000000
+#define LX_8bitmime 0x82000000
#define L_default (L_connection_reject | \
L_delay_delivery | \
diff --git a/src/src/receive.c b/src/src/receive.c
index 7b51805dc..8ac381add 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -3610,6 +3610,15 @@ if (sender_host_authenticated != NULL)
sprintf(CS big_buffer, "%d", msg_size);
s = string_append(s, &size, &sptr, 2, US" S=", big_buffer);
+/* log 8BITMIME mode announced in MAIL_FROM
+ 0 ... no BODY= used
+ 7 ... 7BIT
+ 8 ... 8BITMIME */
+if (log_extra_selector & LX_8bitmime) {
+ sprintf(CS big_buffer, "%d", body_8bitmime);
+ s = string_append(s, &size, &sptr, 2, US" M8S=", big_buffer);
+}
+
/* If an addr-spec in a message-id contains a quoted string, it can contain
any characters except " \ and CR and so in particular it can contain NL!
Therefore, make sure we use a printing-characters only version for the log.
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index b1fea9daf..e3746d99d 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -3320,10 +3320,20 @@ while (done <= 0)
some sites want the action that is provided. We recognize both "8BITMIME"
and "7BIT" as body types, but take no action. */
case ENV_MAIL_OPT_BODY:
- if (accept_8bitmime &&
- (strcmpic(value, US"8BITMIME") == 0 ||
- strcmpic(value, US"7BIT") == 0) )
- break;
+ if (accept_8bitmime) {
+ if (strcmpic(value, US"8BITMIME") == 0) {
+ body_8bitmime = 8;
+ } else if (strcmpic(value, US"7BIT") == 0) {
+ body_8bitmime = 7;
+ } else {
+ body_8bitmime = 0;
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
+ US"invalid data for BODY");
+ goto COMMAND_LOOP;
+ }
+ DEBUG(D_receive) debug_printf("8BITMIME: %d\n", body_8bitmime);
+ break;
+ }
arg_error = TRUE;
break;