X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fexpand.c;h=009049db4d69f3601b99387f1da76b0ac950e2db;hb=0d0ace194a602607133e569319652c7b7b8f0e22;hp=881c5fb2a55416bc22ffc895f9f9f5bb34d29dad;hpb=db4dcd57f3ce2d62b5a86feadd736836c2909025;p=exim.git diff --git a/src/src/expand.c b/src/src/expand.c index 881c5fb2a..009049db4 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -17,22 +17,22 @@ static uschar *expand_string_internal(const uschar *, BOOL, const uschar **, BOO static int_eximarith_t expanded_string_integer(const uschar *, BOOL); #ifdef STAND_ALONE -#ifndef SUPPORT_CRYPTEQ -#define SUPPORT_CRYPTEQ -#endif +# ifndef SUPPORT_CRYPTEQ +# define SUPPORT_CRYPTEQ +# endif #endif #ifdef LOOKUP_LDAP -#include "lookups/ldap.h" +# include "lookups/ldap.h" #endif #ifdef SUPPORT_CRYPTEQ -#ifdef CRYPT_H -#include -#endif -#ifndef HAVE_CRYPT16 +# ifdef CRYPT_H +# include +# endif +# ifndef HAVE_CRYPT16 extern char* crypt16(char*, char*); -#endif +# endif #endif /* The handling of crypt16() is a mess. I will record below the analysis of the @@ -103,6 +103,7 @@ alphabetical order. */ static uschar *item_table[] = { US"acl", + US"authresults", US"certextract", US"dlfunc", US"env", @@ -133,6 +134,7 @@ static uschar *item_table[] = { enum { EITEM_ACL, + EITEM_AUTHRESULTS, EITEM_CERTEXTRACT, EITEM_DLFUNC, EITEM_ENV, @@ -700,7 +702,7 @@ static var_entry var_table[] = { { "spam_score", vtype_stringptr, &spam_score }, { "spam_score_int", vtype_stringptr, &spam_score_int }, #endif -#ifdef EXPERIMENTAL_SPF +#ifdef SUPPORT_SPF { "spf_guess", vtype_stringptr, &spf_guess }, { "spf_header_comment", vtype_stringptr, &spf_header_comment }, { "spf_received", vtype_stringptr, &spf_received }, @@ -738,7 +740,7 @@ static var_entry var_table[] = { { "tls_out_bits", vtype_int, &tls_out.bits }, { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified }, { "tls_out_cipher", vtype_stringptr, &tls_out.cipher }, -#ifdef EXPERIMENTAL_DANE +#ifdef SUPPORT_DANE { "tls_out_dane", vtype_bool, &tls_out.dane_verified }, #endif { "tls_out_ocsp", vtype_int, &tls_out.ocsp }, @@ -748,7 +750,7 @@ static var_entry var_table[] = { #if defined(SUPPORT_TLS) { "tls_out_sni", vtype_stringptr, &tls_out.sni }, #endif -#ifdef EXPERIMENTAL_DANE +#ifdef SUPPORT_DANE { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage }, #endif @@ -1656,6 +1658,24 @@ return yield; +/* Append an "iprev" element to an Autherntication-Results: header +if we have attempted to get the calling host's name. +*/ + +static gstring * +authres_iprev(gstring * g) +{ +if (sender_host_name) + return string_append(g, 3, US";\n\tiprev=pass (", sender_host_name, US")"); +if (host_lookup_deferred) + return string_catn(g, US";\n\tiprev=temperror", 19); +if (host_lookup_failed) + return string_catn(g, US";\n\tiprev=fail", 13); +return g; +} + + + /************************************************* * Return list of recipients * *************************************************/ @@ -1797,10 +1817,10 @@ switch (vp->type) return var_buffer; case vtype_host_lookup: /* Lookup if not done so */ - if (sender_host_name == NULL && sender_host_address != NULL && - !host_lookup_failed && host_name_lookup() == OK) + if ( !sender_host_name && sender_host_address + && !host_lookup_failed && host_name_lookup() == OK) host_build_sender_fullhost(); - return (sender_host_name == NULL)? US"" : sender_host_name; + return sender_host_name ? sender_host_name : US""; case vtype_localpart: /* Get local part from address */ s = *((uschar **)(val)); @@ -2498,9 +2518,12 @@ switch(cond_type) "after \"%s\"", name); return NULL; } - sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL, - honour_dollar, resetok); - if (sub[i] == NULL) return NULL; + if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL, + honour_dollar, resetok))) + return NULL; + DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$')) + debug_printf_indent("WARNING: the second arg is NOT expanded," + " for security reasons\n"); if (*s++ != '}') goto COND_FAILED_CURLY_END; /* Convert to numerical if required; we know that the names of all the @@ -4097,6 +4120,37 @@ while (*s != 0) } } + case EITEM_AUTHRESULTS: + /* ${authresults {mysystemname}} */ + { + uschar *sub_arg[1]; + + switch(read_subs(sub_arg, nelem(sub_arg), 1, &s, skipping, TRUE, name, + &resetok)) + { + case 1: goto EXPAND_FAILED_CURLY; + case 2: + case 3: goto EXPAND_FAILED; + } + + yield = string_append(yield, 3, + US"Authentication-Results: ", sub_arg[0], US"; none"); + yield->ptr -= 6; + + yield = authres_iprev(yield); + yield = authres_smtpauth(yield); +#ifdef SUPPORT_SPF + yield = authres_spf(yield); +#endif +#ifndef DISABLE_DKIM + yield = authres_dkim(yield); +#endif +#ifdef EXPERIMENTAL_ARC + yield = authres_arc(yield); +#endif + continue; + } + /* Handle conditionals - preserve the values of the numerical expansion variables in case they get changed by a regular expression match in the condition. If not, they retain their external settings. At the end @@ -5790,7 +5844,8 @@ while (*s != 0) if (*s++ != '}') { /*{*/ expand_string_message = string_sprintf("missing } at end of condition " - "or expression inside \"%s\"", name); + "or expression inside \"%s\"; could be an unquoted } in the content", + name); goto EXPAND_FAILED; } @@ -6495,7 +6550,7 @@ while (*s != 0) } continue; #else - expand_string_message = US"sha3 only supported with GnuTLS 3.5.0 +"; + expand_string_message = US"sha3 only supported with GnuTLS 3.5.0 + or OpenSSL 1.1.1 +"; goto EXPAND_FAILED; #endif @@ -7478,10 +7533,9 @@ terminating brace. */ if (ket_ends && *s == 0) { - expand_string_message = malformed_header? - US"missing } at end of string - could be header name not terminated by colon" - : - US"missing } at end of string"; + expand_string_message = malformed_header + ? US"missing } at end of string - could be header name not terminated by colon" + : US"missing } at end of string"; goto EXPAND_FAILED; } @@ -7546,7 +7600,7 @@ DEBUG(D_expand) if (expand_string_forcedfail) debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n"); } -if (resetok_p) *resetok_p = resetok; +if (resetok_p && !resetok) *resetok_p = FALSE; expand_level--; return NULL; } @@ -7560,28 +7614,35 @@ Returns: the expanded string, or NULL if expansion failed; if failure was due to a lookup deferring, search_find_defer will be TRUE */ -uschar * -expand_string(uschar *string) +const uschar * +expand_cstring(const uschar * string) { -search_find_defer = FALSE; -malformed_header = FALSE; -return (Ustrpbrk(string, "$\\") == NULL)? string : - expand_string_internal(string, FALSE, NULL, FALSE, TRUE, NULL); +if (Ustrpbrk(string, "$\\") != NULL) + { + int old_pool = store_pool; + uschar * s; + + search_find_defer = FALSE; + malformed_header = FALSE; + store_pool = POOL_MAIN; + s = expand_string_internal(string, FALSE, NULL, FALSE, TRUE, NULL); + store_pool = old_pool; + return s; + } +return string; } - -const uschar * -expand_cstring(const uschar *string) +uschar * +expand_string(uschar * string) { -search_find_defer = FALSE; -malformed_header = FALSE; -return (Ustrpbrk(string, "$\\") == NULL)? string : - expand_string_internal(string, FALSE, NULL, FALSE, TRUE, NULL); +return US expand_cstring(CUS string); } + + /************************************************* * Expand and copy * *************************************************/ @@ -7807,13 +7868,50 @@ return ( ( Ustrstr(s, "failed to expand") != NULL } +/* Read given named file into big_buffer. Use for keying material etc. +The content will have an ascii NUL appended. + +Arguments: + filename as it says + +Return: pointer to buffer, or NULL on error. +*/ + +uschar * +expand_file_big_buffer(const uschar * filename) +{ +int fd, off = 0, len; + +if ((fd = open(CS filename, O_RDONLY)) < 0) + { + log_write(0, LOG_MAIN | LOG_PANIC, "unable to open file for reading: %s", + filename); + return NULL; + } + +do + { + if ((len = read(fd, big_buffer + off, big_buffer_size - 2 - off)) < 0) + { + (void) close(fd); + log_write(0, LOG_MAIN|LOG_PANIC, "unable to read file: %s", filename); + return NULL; + } + off += len; + } +while (len > 0); + +(void) close(fd); +big_buffer[off] = '\0'; +return big_buffer; +} + + /************************************************* * Error-checking for testsuite * *************************************************/ typedef struct { - const char * filename; - int linenumber; uschar * region_start; uschar * region_end; const uschar *var_name; @@ -7834,7 +7932,8 @@ if (var_data >= e->region_start && var_data < e->region_end) void assert_no_variables(void * ptr, int len, const char * filename, int linenumber) { -err_ctx e = {filename, linenumber, ptr, US ptr + len, NULL }; +err_ctx e = { .region_start = ptr, .region_end = US ptr + len, + .var_name = NULL, .var_data = NULL }; int i; var_entry * v; @@ -7855,10 +7954,16 @@ for (v = var_table; v < var_table + var_table_size; v++) if (v->type == vtype_stringptr) assert_variable_notin(US v->name, *(USS v->value), &e); +/* check dns and address trees */ +tree_walk(tree_dns_fails, assert_variable_notin, &e); +tree_walk(tree_duplicates, assert_variable_notin, &e); +tree_walk(tree_nonrecipients, assert_variable_notin, &e); +tree_walk(tree_unusable, assert_variable_notin, &e); + if (e.var_name) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "live variable '%s' destroyed by reset_store at %s:%d\n- value '%.64s'", - e.var_name, e.filename, e.linenumber, e.var_data); + e.var_name, filename, linenumber, e.var_data); }