X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fexpand.c;h=31059c432af1176fd0da00119c548230bfba0e12;hb=7a9e0ae14e5544e8377d1f91298d0ec9a482bf12;hp=2128ee72c768eb72ce0b0b1973188f9f3de48b07;hpb=feb1d59e24fc05776a7c73557931ba35da4e1f4a;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/expand.c b/src/src/expand.c index 2128ee72c..31059c432 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -235,6 +235,7 @@ static uschar *op_table_main[] = { US"rxquote", US"s", US"sha1", + US"sha2", US"sha256", US"sha3", US"stat", @@ -281,6 +282,7 @@ enum { EOP_RXQUOTE, EOP_S, EOP_SHA1, + EOP_SHA2, EOP_SHA256, EOP_SHA3, EOP_STAT, @@ -668,9 +670,6 @@ static var_entry var_table[] = { { "regex_match_string", vtype_stringptr, ®ex_match_string }, #endif { "reply_address", vtype_reply, NULL }, -#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS) - { "requiretls", vtype_bool, &tls_requiretls }, -#endif { "return_path", vtype_stringptr, &return_path }, { "return_size_limit", vtype_int, &bounce_return_size_limit }, { "router_name", vtype_stringptr, &router_name }, @@ -749,16 +748,21 @@ static var_entry var_table[] = { { "tls_in_bits", vtype_int, &tls_in.bits }, { "tls_in_certificate_verified", vtype_int, &tls_in.certificate_verified }, { "tls_in_cipher", vtype_stringptr, &tls_in.cipher }, + { "tls_in_cipher_std", vtype_stringptr, &tls_in.cipher_stdname }, { "tls_in_ocsp", vtype_int, &tls_in.ocsp }, { "tls_in_ourcert", vtype_cert, &tls_in.ourcert }, { "tls_in_peercert", vtype_cert, &tls_in.peercert }, { "tls_in_peerdn", vtype_stringptr, &tls_in.peerdn }, -#if defined(SUPPORT_TLS) +#ifdef EXPERIMENTAL_TLS_RESUME + { "tls_in_resumption", vtype_int, &tls_in.resumption }, +#endif +#ifndef DISABLE_TLS { "tls_in_sni", vtype_stringptr, &tls_in.sni }, #endif { "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 }, + { "tls_out_cipher_std", vtype_stringptr, &tls_out.cipher_stdname }, #ifdef SUPPORT_DANE { "tls_out_dane", vtype_bool, &tls_out.dane_verified }, #endif @@ -766,7 +770,10 @@ static var_entry var_table[] = { { "tls_out_ourcert", vtype_cert, &tls_out.ourcert }, { "tls_out_peercert", vtype_cert, &tls_out.peercert }, { "tls_out_peerdn", vtype_stringptr, &tls_out.peerdn }, -#if defined(SUPPORT_TLS) +#ifdef EXPERIMENTAL_TLS_RESUME + { "tls_out_resumption", vtype_int, &tls_out.resumption }, +#endif +#ifndef DISABLE_TLS { "tls_out_sni", vtype_stringptr, &tls_out.sni }, #endif #ifdef SUPPORT_DANE @@ -774,7 +781,7 @@ static var_entry var_table[] = { #endif { "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */ -#if defined(SUPPORT_TLS) +#ifndef DISABLE_TLS { "tls_sni", vtype_stringptr, &tls_in.sni }, /* mind the alphabetical order! */ #endif @@ -960,7 +967,7 @@ weirdness they'll twist this into. The result should ideally handle fork(). However, if we're stuck unable to provide this, then we'll fall back to appallingly bad randomness. -If SUPPORT_TLS is defined then this will not be used except as an emergency +If DISABLE_TLS is not defined then this will not be used except as an emergency fallback. Arguments: @@ -968,56 +975,55 @@ Arguments: Returns a random number in range [0, max-1] */ -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS # define vaguely_random_number vaguely_random_number_fallback #endif int vaguely_random_number(int max) { -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS # undef vaguely_random_number #endif - static pid_t pid = 0; - pid_t p2; -#if defined(HAVE_SRANDOM) && !defined(HAVE_SRANDOMDEV) - struct timeval tv; -#endif +static pid_t pid = 0; +pid_t p2; - p2 = getpid(); - if (p2 != pid) +if ((p2 = getpid()) != pid) + { + if (pid != 0) { - if (pid != 0) - { #ifdef HAVE_ARC4RANDOM - /* cryptographically strong randomness, common on *BSD platforms, not - so much elsewhere. Alas. */ -#ifndef NOT_HAVE_ARC4RANDOM_STIR - arc4random_stir(); -#endif + /* cryptographically strong randomness, common on *BSD platforms, not + so much elsewhere. Alas. */ +# ifndef NOT_HAVE_ARC4RANDOM_STIR + arc4random_stir(); +# endif #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV) -#ifdef HAVE_SRANDOMDEV - /* uses random(4) for seeding */ - srandomdev(); -#else - gettimeofday(&tv, NULL); - srandom(tv.tv_sec | tv.tv_usec | getpid()); -#endif +# ifdef HAVE_SRANDOMDEV + /* uses random(4) for seeding */ + srandomdev(); +# else + { + struct timeval tv; + gettimeofday(&tv, NULL); + srandom(tv.tv_sec | tv.tv_usec | getpid()); + } +# endif #else - /* Poor randomness and no seeding here */ + /* Poor randomness and no seeding here */ #endif - } - pid = p2; } + pid = p2; + } #ifdef HAVE_ARC4RANDOM - return arc4random() % max; +return arc4random() % max; #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV) - return random() % max; +return random() % max; #else - /* This one returns a 16-bit number, definitely not crypto-strong */ - return random_number(max); +/* This one returns a 16-bit number, definitely not crypto-strong */ +return random_number(max); #endif } @@ -1283,7 +1289,7 @@ return string_nextinlist(&list, &sep, NULL, 0); /* Certificate fields, by name. Worry about by-OID later */ /* Names are chosen to not have common prefixes */ -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS typedef struct { uschar * name; @@ -1344,7 +1350,7 @@ expand_string_message = string_sprintf("bad field selector \"%s\" for certextract", field); return NULL; } -#endif /*SUPPORT_TLS*/ +#endif /*DISABLE_TLS*/ /************************************************* * Extract a substring from a string * @@ -3654,7 +3660,7 @@ return yield; } -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS static gstring * cat_file_tls(void * tls_ctx, gstring * yield, uschar * eol) { @@ -4835,7 +4841,7 @@ while (*s != 0) (void)sscanf(CS now,"%u",&inow); (void)sscanf(CS daystamp,"%u",&iexpire); - /* When "iexpire" is < 7, a "flip" has occured. + /* When "iexpire" is < 7, a "flip" has occurred. Adjust "inow" accordingly. */ if ( (iexpire < 7) && (inow >= 993) ) inow = 0; @@ -4932,17 +4938,16 @@ while (*s != 0) case EITEM_READSOCK: { - int fd; + client_conn_ctx cctx; int timeout = 5; int save_ptr = yield->ptr; - FILE * fp; + FILE * fp = NULL; uschar * arg; uschar * sub_arg[4]; uschar * server_name = NULL; host_item host; BOOL do_shutdown = TRUE; - BOOL do_tls = FALSE; /* Only set under SUPPORT_TLS */ - void * tls_ctx = NULL; /* ditto */ + BOOL do_tls = FALSE; /* Only set under ! DISABLE_TLS */ blob reqstr; if (expand_forbid & RDO_READSOCK) @@ -4986,7 +4991,7 @@ while (*s != 0) while ((item = string_nextinlist(&list, &sep, NULL, 0))) if (Ustrncmp(item, US"shutdown=", 9) == 0) { if (Ustrcmp(item + 9, US"no") == 0) do_shutdown = FALSE; } -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS else if (Ustrncmp(item, US"tls=", 4) == 0) { if (Ustrcmp(item + 9, US"no") != 0) do_tls = TRUE; } #endif @@ -5042,12 +5047,12 @@ while (*s != 0) port = ntohs(service_info->s_port); } - /*XXX we trust that the request is idempotent. Hmm. */ - fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port, + /*XXX we trust that the request is idempotent for TFO. Hmm. */ + cctx.sock = ip_connectedsocket(SOCK_STREAM, server_name, port, port, timeout, &host, &expand_string_message, do_tls ? NULL : &reqstr); callout_address = NULL; - if (fd < 0) + if (cctx.sock < 0) goto SOCK_FAIL; if (!do_tls) reqstr.len = 0; @@ -5060,7 +5065,7 @@ while (*s != 0) struct sockaddr_un sockun; /* don't call this "sun" ! */ int rc; - if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) + if ((cctx.sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { expand_string_message = string_sprintf("failed to create socket: %s", strerror(errno)); @@ -5074,7 +5079,7 @@ while (*s != 0) sigalrm_seen = FALSE; ALARM(timeout); - rc = connect(fd, (struct sockaddr *)(&sockun), sizeof(sockun)); + rc = connect(cctx.sock, (struct sockaddr *)(&sockun), sizeof(sockun)); ALARM_CLR(0); if (sigalrm_seen) { @@ -5093,17 +5098,14 @@ while (*s != 0) DEBUG(D_expand) debug_printf_indent("connected to socket %s\n", sub_arg[0]); -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if (do_tls) { + smtp_connect_args conn_args = {.host = &host }; tls_support tls_dummy = {.sni=NULL}; uschar * errstr; - if (!(tls_ctx = tls_client_start(fd, &host, NULL, NULL, -# ifdef SUPPORT_DANE - NULL, -# endif - &tls_dummy, &errstr))) + if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr)) { expand_string_message = string_sprintf("TLS connect failed: %s", errstr); goto SOCK_FAIL; @@ -5121,10 +5123,10 @@ while (*s != 0) DEBUG(D_expand) debug_printf_indent("writing \"%s\" to socket\n", reqstr.data); if ( ( -#ifdef SUPPORT_TLS - tls_ctx ? tls_write(tls_ctx, reqstr.data, reqstr.len, FALSE) : +#ifndef DISABLE_TLS + do_tls ? tls_write(cctx.tls_ctx, reqstr.data, reqstr.len, FALSE) : #endif - write(fd, reqstr.data, reqstr.len)) != reqstr.len) + write(cctx.sock, reqstr.data, reqstr.len)) != reqstr.len) { expand_string_message = string_sprintf("request write to socket " "failed: %s", strerror(errno)); @@ -5137,7 +5139,7 @@ while (*s != 0) system doesn't have this function, make it conditional. */ #ifdef SHUT_WR - if (!tls_ctx && do_shutdown) shutdown(fd, SHUT_WR); + if (!do_tls && do_shutdown) shutdown(cctx.sock, SHUT_WR); #endif if (f.running_in_test_harness) millisleep(100); @@ -5145,22 +5147,22 @@ while (*s != 0) /* Now we need to read from the socket, under a timeout. The function that reads a file can be used. */ - if (!tls_ctx) - fp = fdopen(fd, "rb"); + if (!do_tls) + fp = fdopen(cctx.sock, "rb"); sigalrm_seen = FALSE; ALARM(timeout); yield = -#ifdef SUPPORT_TLS - tls_ctx ? cat_file_tls(tls_ctx, yield, sub_arg[3]) : +#ifndef DISABLE_TLS + do_tls ? cat_file_tls(cctx.tls_ctx, yield, sub_arg[3]) : #endif cat_file(fp, yield, sub_arg[3]); ALARM_CLR(0); -#ifdef SUPPORT_TLS - if (tls_ctx) +#ifndef DISABLE_TLS + if (do_tls) { - tls_close(tls_ctx, TRUE); - close(fd); + tls_close(cctx.tls_ctx, TRUE); + close(cctx.sock); } else #endif @@ -5662,6 +5664,12 @@ while (*s != 0) uschar *sub[3]; int save_expand_nmax = save_expand_strings(save_expand_nstring, save_expand_nlength); + + /* On reflection the original behaviour of extract-json for a string + result, leaving it quoted, was a mistake. But it was already published, + hence the addition of jsons. In a future major version, make json + work like josons, and withdraw jsons. */ + enum {extract_basic, extract_json, extract_jsons} fmt = extract_basic; while (isspace(*s)) s++; @@ -5809,10 +5817,11 @@ while (*s != 0) } while (field_number > 0 && (item = json_nextinlist(&list))) field_number--; - s = item; - lookup_value = s; - while (*s) s++; - while (--s >= lookup_value && isspace(*s)) *s = '\0'; + if ((lookup_value = s = item)) + { + while (*s) s++; + while (--s >= lookup_value && isspace(*s)) *s = '\0'; + } } else { @@ -5848,14 +5857,16 @@ while (*s != 0) } } - if (fmt == extract_jsons) - if (!(lookup_value = dewrap(lookup_value, US"\"\""))) - { - expand_string_message = - string_sprintf("%s wrapping string result for extract jsons", - expand_string_message); - goto EXPAND_FAILED_CURLY; - } + if ( fmt == extract_jsons + && lookup_value + && !(lookup_value = dewrap(lookup_value, US"\"\""))) + { + expand_string_message = + string_sprintf("%s wrapping string result for extract jsons", + expand_string_message); + goto EXPAND_FAILED_CURLY; + } + break; /* json/s */ } /* If no string follows, $value gets substituted; otherwise there can @@ -5981,7 +5992,7 @@ while (*s != 0) continue; } -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS case EITEM_CERTEXTRACT: { uschar *save_lookup_value = lookup_value; @@ -6061,7 +6072,7 @@ while (*s != 0) save_expand_nlength); continue; } -#endif /*SUPPORT_TLS*/ +#endif /*DISABLE_TLS*/ /* Handle list operations */ @@ -6573,7 +6584,7 @@ while (*s != 0) int c; uschar *arg = NULL; uschar *sub; -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS var_entry *vp = NULL; #endif @@ -6596,7 +6607,7 @@ while (*s != 0) as we do not want to do the usual expansion. For most, expand the string.*/ switch(c) { -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS case EOP_MD5: case EOP_SHA1: case EOP_SHA256: @@ -6751,7 +6762,7 @@ while (*s != 0) } case EOP_MD5: -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if (vp && *(void **)vp->value) { uschar * cp = tls_cert_fprt_md5(*(void **)vp->value); @@ -6770,7 +6781,7 @@ while (*s != 0) continue; case EOP_SHA1: -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if (vp && *(void **)vp->value) { uschar * cp = tls_cert_fprt_sha1(*(void **)vp->value); @@ -6788,23 +6799,35 @@ while (*s != 0) } continue; + case EOP_SHA2: case EOP_SHA256: #ifdef EXIM_HAVE_SHA2 if (vp && *(void **)vp->value) { - uschar * cp = tls_cert_fprt_sha256(*(void **)vp->value); - yield = string_cat(yield, cp); + if (c == EOP_SHA256) + { + uschar * cp = tls_cert_fprt_sha256(*(void **)vp->value); + yield = string_cat(yield, cp); + } + else + expand_string_message = US"sha2_N not supported with certificates"; } else { hctx h; blob b; + hashmethod m = !arg ? HASH_SHA2_256 + : Ustrcmp(arg, "256") == 0 ? HASH_SHA2_256 + : Ustrcmp(arg, "384") == 0 ? HASH_SHA2_384 + : Ustrcmp(arg, "512") == 0 ? HASH_SHA2_512 + : HASH_BADTYPE; - if (!exim_sha_init(&h, HASH_SHA2_256)) + if (m == HASH_BADTYPE || !exim_sha_init(&h, m)) { - expand_string_message = US"unrecognised sha256 variant"; + expand_string_message = US"unrecognised sha2 variant"; goto EXPAND_FAILED; } + exim_sha_update(&h, sub, Ustrlen(sub)); exim_sha_finish(&h, &b); while (b.len-- > 0) @@ -7092,16 +7115,11 @@ while (*s != 0) uschar * t = parse_extract_address(sub, &error, &start, &end, &domain, FALSE); if (t) - if (c != EOP_DOMAIN) - { - if (c == EOP_LOCAL_PART && domain != 0) end = start + domain - 1; - yield = string_catn(yield, sub+start, end-start); - } - else if (domain != 0) - { - domain += start; - yield = string_catn(yield, sub+domain, end-domain); - } + yield = c == EOP_DOMAIN + ? string_cat(yield, t + domain) + : c == EOP_LOCAL_PART && domain > 0 + ? string_catn(yield, t, domain - 1 ) + : string_cat(yield, t); continue; } @@ -7125,7 +7143,7 @@ while (*s != 0) for (;;) { - uschar *p = parse_find_address_end(sub, FALSE); + uschar * p = parse_find_address_end(sub, FALSE); uschar saveend = *p; *p = '\0'; address = parse_extract_address(sub, &error, &start, &end, &domain, @@ -7138,7 +7156,7 @@ while (*s != 0) list, add in a space if the new address begins with the separator character, or is an empty string. */ - if (address != NULL) + if (address) { if (yield->ptr != save_ptr && address[0] == *outsep) yield = string_catn(yield, US" ", 1); @@ -7511,7 +7529,7 @@ while (*s != 0) continue; } - /* Handle time period formating */ + /* Handle time period formatting */ case EOP_TIME_EVAL: { @@ -7546,7 +7564,7 @@ while (*s != 0) case EOP_STR2B64: case EOP_BASE64: { -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS uschar * s = vp && *(void **)vp->value ? tls_cert_der_b64(*(void **)vp->value) : b64encode(CUS sub, Ustrlen(sub));