X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/76fbc01d6f1814bdbc2dedb31a405105b38a70f2..817d9f576cdfbc27cf0536be348645baf27d7836:/src/src/expand.c diff --git a/src/src/expand.c b/src/src/expand.c index 22f7d9a66..3fb431c2e 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 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2012 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -363,6 +363,7 @@ enum { /* local_scan()) */ 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 */ vtype_todf, /* value not used; generate full tod */ vtype_todl, /* value not used; generate log tod */ vtype_todlf, /* value not used; generate log file datestamp tod */ @@ -611,15 +612,25 @@ static var_entry var_table[] = { { "srs_status", vtype_stringptr, &srs_status }, #endif { "thisaddress", vtype_stringptr, &filter_thisaddress }, - { "tls_bits", vtype_int, &tls_bits }, - { "tls_certificate_verified", vtype_int, &tls_certificate_verified }, - { "tls_cipher", vtype_stringptr, &tls_cipher }, - { "tls_peerdn", vtype_stringptr, &tls_peerdn }, + + { "tls_bits", vtype_int, &tls_in.bits }, + { "tls_certificate_verified", vtype_int, &tls_in.certificate_verified }, + { "tls_cipher", vtype_stringptr, &tls_in.cipher }, + { "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, +#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) + { "tls_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_peerdn", vtype_stringptr, &tls_out.peerdn }, #if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) - { "tls_sni", vtype_stringptr, &tls_sni }, + { "tls_out_sni", vtype_stringptr, &tls_out.sni }, #endif + { "tod_bsdinbox", vtype_todbsdin, NULL }, { "tod_epoch", vtype_tode, NULL }, + { "tod_epoch_l", vtype_todel, NULL }, { "tod_full", vtype_todf, NULL }, { "tod_log", vtype_todl, NULL }, { "tod_logfile", vtype_todlf, NULL }, @@ -776,6 +787,7 @@ return rc; + /************************************************* * Pseudo-random number generation * *************************************************/ @@ -788,19 +800,23 @@ 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 and OpenSSL is used, then this will not be used. -The GNUTLS randomness functions found do not seem amenable to extracting -random numbers outside of a TLS context. Any volunteers? +If SUPPORT_TLS is defined then this will not be used except as an emergency +fallback. Arguments: max range maximum Returns a random number in range [0, max-1] */ -#if !defined(SUPPORT_TLS) || defined(USE_GNUTLS) +#ifdef SUPPORT_TLS +# define vaguely_random_number vaguely_random_number_fallback +#endif int -pseudo_random_number(int max) +vaguely_random_number(int max) { +#ifdef SUPPORT_TLS +# undef vaguely_random_number +#endif static pid_t pid = 0; pid_t p2; #if defined(HAVE_SRANDOM) && !defined(HAVE_SRANDOMDEV) @@ -843,7 +859,8 @@ pseudo_random_number(int max) #endif } -#endif + + /************************************************* * Pick out a name from a string * @@ -1519,8 +1536,8 @@ while (last > first) domain = Ustrrchr(s, '@'); if (domain == NULL) return s; if (domain - s > sizeof(var_buffer) - 1) - log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than %d in " - "string expansion", sizeof(var_buffer)); + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT + " in string expansion", sizeof(var_buffer)); Ustrncpy(var_buffer, s, domain - s); var_buffer[domain - s] = 0; return var_buffer; @@ -1583,6 +1600,9 @@ while (last > first) case vtype_tode: /* Unix epoch time of day */ return tod_stamp(tod_epoch); + case vtype_todel: /* Unix epoch/usec time of day */ + return tod_stamp(tod_epoch_l); + case vtype_todf: /* Full time of day */ return tod_stamp(tod_full); @@ -1781,7 +1801,7 @@ BOOL tempcond, combined_cond; BOOL *subcondptr; BOOL sub2_honour_dollar = TRUE; int i, rc, cond_type, roffset; -int num[2]; +int_eximarith_t num[2]; struct stat statbuf; uschar name[256]; uschar *sub[4]; @@ -3069,14 +3089,14 @@ Returns: on success: the value of the expression, with *error still NULL on failure: an undefined value, with *error = a message */ -static int eval_op_or(uschar **, BOOL, uschar **); +static int_eximarith_t eval_op_or(uschar **, BOOL, uschar **); -static int +static int_eximarith_t eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket) { uschar *s = *sptr; -int x = eval_op_or(&s, decimal, error); +int_eximarith_t x = eval_op_or(&s, decimal, error); if (*error == NULL) { if (endket) @@ -3093,21 +3113,26 @@ return x; } -static int +static int_eximarith_t eval_number(uschar **sptr, BOOL decimal, uschar **error) { register int c; -int n; +int_eximarith_t n; uschar *s = *sptr; while (isspace(*s)) s++; c = *s; if (isdigit(c)) { int count; - (void)sscanf(CS s, (decimal? "%d%n" : "%i%n"), &n, &count); + (void)sscanf(CS s, (decimal? SC_EXIM_DEC "%n" : SC_EXIM_ARITH "%n"), &n, &count); s += count; - if (tolower(*s) == 'k') { n *= 1024; s++; } - else if (tolower(*s) == 'm') { n *= 1024*1024; s++; } + switch (tolower(*s)) + { + default: break; + case 'k': n *= 1024; s++; break; + case 'm': n *= 1024*1024; s++; break; + case 'g': n *= 1024*1024*1024; s++; break; + } while (isspace (*s)) s++; } else if (c == '(') @@ -3125,10 +3150,11 @@ return n; } -static int eval_op_unary(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_unary(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x; +int_eximarith_t x; while (isspace(*s)) s++; if (*s == '+' || *s == '-' || *s == '~') { @@ -3146,16 +3172,17 @@ return x; } -static int eval_op_mult(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_mult(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_unary(&s, decimal, error); +int_eximarith_t x = eval_op_unary(&s, decimal, error); if (*error == NULL) { while (*s == '*' || *s == '/' || *s == '%') { int op = *s++; - int y = eval_op_unary(&s, decimal, error); + int_eximarith_t y = eval_op_unary(&s, decimal, error); if (*error != NULL) break; /* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give * a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which @@ -3175,12 +3202,12 @@ if (*error == NULL) * can just let the other invalid results occur otherwise, as they have * until now. For this one case, we can coerce. */ - if (y == -1 && x == INT_MIN && op != '*') + if (y == -1 && x == LLONG_MIN && op != '*') { DEBUG(D_expand) - debug_printf("Integer exception dodging: %d%c-1 coerced to %d\n", - INT_MIN, op, INT_MAX); - x = INT_MAX; + debug_printf("Integer exception dodging: " PR_EXIM_ARITH "%c-1 coerced to " PR_EXIM_ARITH "\n", + LLONG_MIN, op, LLONG_MAX); + x = LLONG_MAX; continue; } if (op == '*') @@ -3205,16 +3232,17 @@ return x; } -static int eval_op_sum(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_sum(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_mult(&s, decimal, error); +int_eximarith_t x = eval_op_mult(&s, decimal, error); if (*error == NULL) { while (*s == '+' || *s == '-') { int op = *s++; - int y = eval_op_mult(&s, decimal, error); + int_eximarith_t y = eval_op_mult(&s, decimal, error); if (*error != NULL) break; if (op == '+') x += y; else x -= y; } @@ -3224,15 +3252,16 @@ return x; } -static int eval_op_shift(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_shift(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_sum(&s, decimal, error); +int_eximarith_t x = eval_op_sum(&s, decimal, error); if (*error == NULL) { while ((*s == '<' || *s == '>') && s[1] == s[0]) { - int y; + int_eximarith_t y; int op = *s++; s++; y = eval_op_sum(&s, decimal, error); @@ -3245,15 +3274,16 @@ return x; } -static int eval_op_and(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_and(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_shift(&s, decimal, error); +int_eximarith_t x = eval_op_shift(&s, decimal, error); if (*error == NULL) { while (*s == '&') { - int y; + int_eximarith_t y; s++; y = eval_op_shift(&s, decimal, error); if (*error != NULL) break; @@ -3265,15 +3295,16 @@ return x; } -static int eval_op_xor(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_xor(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_and(&s, decimal, error); +int_eximarith_t x = eval_op_and(&s, decimal, error); if (*error == NULL) { while (*s == '^') { - int y; + int_eximarith_t y; s++; y = eval_op_and(&s, decimal, error); if (*error != NULL) break; @@ -3285,15 +3316,16 @@ return x; } -static int eval_op_or(uschar **sptr, BOOL decimal, uschar **error) +static int_eximarith_t +eval_op_or(uschar **sptr, BOOL decimal, uschar **error) { uschar *s = *sptr; -int x = eval_op_xor(&s, decimal, error); +int_eximarith_t x = eval_op_xor(&s, decimal, error); if (*error == NULL) { while (*s == '|') { - int y; + int_eximarith_t y; s++; y = eval_op_xor(&s, decimal, error); if (*error != NULL) break; @@ -5693,7 +5725,7 @@ while (*s != 0) { uschar *save_sub = sub; uschar *error = NULL; - int n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE); + int_eximarith_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE); if (error != NULL) { expand_string_message = string_sprintf("error in expression " @@ -5701,7 +5733,7 @@ while (*s != 0) save_sub); goto EXPAND_FAILED; } - sprintf(CS var_buffer, "%d", n); + sprintf(CS var_buffer, PR_EXIM_ARITH, n); yield = string_cat(yield, &size, &ptr, var_buffer, Ustrlen(var_buffer)); continue; } @@ -5902,17 +5934,17 @@ while (*s != 0) continue; } - /* pseudo-random number less than N */ + /* vaguely random number less than N */ case EOP_RANDINT: { - int max; + int_eximarith_t max; uschar *s; max = expand_string_integer(sub, TRUE); if (expand_string_message != NULL) goto EXPAND_FAILED; - s = string_sprintf("%d", pseudo_random_number(max)); + s = string_sprintf("%d", vaguely_random_number((int)max)); yield = string_cat(yield, &size, &ptr, s, Ustrlen(s)); continue; } @@ -6103,10 +6135,10 @@ Returns: the integer value, or expand_string_message is set NULL for an OK integer */ -int +int_eximarith_t expand_string_integer(uschar *string, BOOL isplus) { -long int value; +int_eximarith_t value; uschar *s = expand_string(string); uschar *msg = US"invalid integer \"%s\""; uschar *endptr; @@ -6138,7 +6170,7 @@ if (isspace(*s)) } } -value = strtol(CS s, CSS &endptr, 10); +value = strtoll(CS s, CSS &endptr, 10); if (endptr == s) { @@ -6150,24 +6182,18 @@ else if (value < 0 && isplus) } else { - /* Ensure we can cast this down to an int */ - if (value > INT_MAX || value < INT_MIN) errno = ERANGE; - - if (errno != ERANGE) + if (tolower(*endptr) == 'k') { - if (tolower(*endptr) == 'k') - { - if (value > INT_MAX/1024 || value < INT_MIN/1024) errno = ERANGE; - else value *= 1024; - endptr++; - } + if (value > LLONG_MAX/1024 || value < LLONG_MIN/1024) errno = ERANGE; + else value *= 1024; + endptr++; + } else if (tolower(*endptr) == 'm') - { - if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024)) - errno = ERANGE; - else value *= 1024*1024; - endptr++; - } + { + if (value > LLONG_MAX/(1024*1024) || value < LLONG_MIN/(1024*1024)) + errno = ERANGE; + else value *= 1024*1024; + endptr++; } if (errno == ERANGE) msg = US"absolute value of integer \"%s\" is too large (overflow)";