US"s",
US"sha1",
US"sha256",
+ US"sha3",
US"stat",
US"str2b64",
US"strlen",
EOP_S,
EOP_SHA1,
EOP_SHA256,
+ EOP_SHA3,
EOP_STAT,
EOP_STR2B64,
EOP_STRLEN,
{ "prvscheck_result", vtype_stringptr, &prvscheck_result },
{ "qualify_domain", vtype_stringptr, &qualify_domain_sender },
{ "qualify_recipient", vtype_stringptr, &qualify_domain_recipient },
+ { "queue_name", vtype_stringptr, &queue_name },
{ "rcpt_count", vtype_int, &rcpt_count },
{ "rcpt_defer_count", vtype_int, &rcpt_defer_count },
{ "rcpt_fail_count", vtype_int, &rcpt_fail_count },
{
if (*s != '{')
{
- if (i < m) return 1;
+ if (i < m)
+ {
+ expand_string_message = string_sprintf("Not enough arguments for '%s' "
+ "(min is %d)", name, m);
+ return 1;
+ }
sub[i] = NULL;
break;
}
- sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, resetok);
- if (sub[i] == NULL) return 3;
+ if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, resetok)))
+ return 3;
if (*s++ != '}') return 1;
while (isspace(*s)) s++;
}
{
if (s[-1] == '{')
{
- expand_string_message = string_sprintf("Too many arguments for \"%s\" "
+ expand_string_message = string_sprintf("Too many arguments for '%s' "
"(max is %d)", name, n);
return 2;
}
+ expand_string_message = string_sprintf("missing '}' after '%s'", name);
return 1;
}
checking for them individually. */
if (!isalpha(name[0]) && yield != NULL)
- {
if (sub[i][0] == 0)
{
num[i] = 0;
num[i] = expanded_string_integer(sub[i], FALSE);
if (expand_string_message != NULL) return NULL;
}
- }
}
/* Result not required */
uschar digest[16];
md5_start(&base);
- md5_end(&base, (uschar *)sub[0], Ustrlen(sub[0]), digest);
+ md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
/* If the length that we are comparing against is 24, the MD5 digest
is expressed as a base64 string. This is the way LDAP does it. However,
if (sublen == 24)
{
- uschar *coded = b64encode((uschar *)digest, 16);
+ uschar *coded = b64encode(digest, 16);
DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
" subject=%s\n crypted=%s\n", coded, sub[1]+5);
tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
{
int sublen = Ustrlen(sub[1]+6);
- sha1 base;
+ hctx h;
uschar digest[20];
- sha1_start(&base);
- sha1_end(&base, (uschar *)sub[0], Ustrlen(sub[0]), digest);
+ sha1_start(&h);
+ sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
/* If the length that we are comparing against is 28, assume the SHA1
digest is expressed as a base64 string. If the length is 40, assume a
if (sublen == 28)
{
- uschar *coded = b64encode((uschar *)digest, 20);
+ uschar *coded = b64encode(digest, 20);
DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
" subject=%s\n crypted=%s\n", coded, sub[1]+6);
tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
int rc = 0;
const uschar *s = *sptr; /* Local value */
uschar *sub1, *sub2;
+const uschar * errwhere;
/* If there are no following strings, we substitute the contents of $value for
lookups and for extractions in the success case. For the ${if item, the string
/* The first following string must be braced. */
-if (*s++ != '{') goto FAILED_CURLY;
+if (*s++ != '{')
+ {
+ errwhere = US"'yes' part did not start with '{'";
+ goto FAILED_CURLY;
+ }
/* Expand the first substring. Forced failures are noticed only if we actually
want this string. Set skipping in the call in the fail case (this will always
sub1 = expand_string_internal(s, TRUE, &s, !yes, TRUE, resetok);
if (sub1 == NULL && (yes || !expand_string_forcedfail)) goto FAILED;
expand_string_forcedfail = FALSE;
-if (*s++ != '}') goto FAILED_CURLY;
+if (*s++ != '}')
+ {
+ errwhere = US"'yes' part did not end with '}'";
+ goto FAILED_CURLY;
+ }
/* If we want the first string, add it to the output */
sub2 = expand_string_internal(s+1, TRUE, &s, yes || skipping, TRUE, resetok);
if (sub2 == NULL && (!yes || !expand_string_forcedfail)) goto FAILED;
expand_string_forcedfail = FALSE;
- if (*s++ != '}') goto FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ errwhere = US"'no' part did not start with '{'";
+ goto FAILED_CURLY;
+ }
/* If we want the second string, add it to the output */
if (!yes && !skipping)
{
while (isspace(*s)) s++;
- if (*s++ != '}') goto FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ errwhere = US"did not close with '}' after forcedfail";
+ goto FAILED_CURLY;
+ }
expand_string_message =
string_sprintf("\"%s\" failed and \"fail\" requested", type);
expand_string_forcedfail = TRUE;
/* All we have to do now is to check on the final closing brace. */
while (isspace(*s)) s++;
-if (*s++ == '}') goto RETURN;
-
-/* Get here if there is a bracketing failure */
-
-FAILED_CURLY:
-rc++;
-
-/* Get here for other failures */
-
-FAILED:
-rc++;
+if (*s++ != '}')
+ {
+ errwhere = US"did not close with '}'";
+ goto FAILED_CURLY;
+ }
-/* Update the input pointer value before returning */
RETURN:
+/* Update the input pointer value before returning */
*sptr = s;
return rc;
+
+FAILED_CURLY:
+ /* Get here if there is a bracketing failure */
+ expand_string_message = string_sprintf(
+ "curly-bracket problem in conditional yes/no parsing: %s\n"
+ " remaining string is '%s'", errwhere, --s);
+ rc = 2;
+ goto RETURN;
+
+FAILED:
+ /* Get here for other failures */
+ rc = 1;
+ goto RETURN;
}
if (type == HMAC_MD5)
md5_start((md5 *)base);
else
- sha1_start((sha1 *)base);
+ sha1_start((hctx *)base);
}
static void
if (type == HMAC_MD5)
md5_mid((md5 *)base, string);
else
- sha1_mid((sha1 *)base, string);
+ sha1_mid((hctx *)base, string);
}
static void
if (type == HMAC_MD5)
md5_end((md5 *)base, string, length, digest);
else
- sha1_end((sha1 *)base, string, length, digest);
+ sha1_end((hctx *)base, string, length, digest);
}
{
uschar *hash_source, *p;
int size = 0,offset = 0,i;
-sha1 sha1_base;
-void *use_base = &sha1_base;
+hctx h;
uschar innerhash[20];
uschar finalhash[20];
uschar innerkey[64];
outerkey[i] ^= key[i];
}
-chash_start(HMAC_SHA1, use_base);
-chash_mid(HMAC_SHA1, use_base, innerkey);
-chash_end(HMAC_SHA1, use_base, hash_source, offset, innerhash);
+chash_start(HMAC_SHA1, &h);
+chash_mid(HMAC_SHA1, &h, innerkey);
+chash_end(HMAC_SHA1, &h, hash_source, offset, innerhash);
-chash_start(HMAC_SHA1, use_base);
-chash_mid(HMAC_SHA1, use_base, outerkey);
-chash_end(HMAC_SHA1, use_base, innerhash, 20, finalhash);
+chash_start(HMAC_SHA1, &h);
+chash_mid(HMAC_SHA1, &h, outerkey);
+chash_end(HMAC_SHA1, &h, innerhash, 20, finalhash);
p = finalhash_hex;
for (i = 0; i < 3; i++)
{
int ptr = 0;
int size = Ustrlen(string)+ 64;
-int item_type;
uschar *yield = store_get(size);
+int item_type;
const uschar *s = string;
uschar *save_expand_nstring[EXPAND_MAXN+1];
int save_expand_nlength[EXPAND_MAXN+1];
BOOL resetok = TRUE;
+DEBUG(D_expand)
+ debug_printf("%s: %s\n", skipping ? " scanning" : "considering", string);
+
expand_string_forcedfail = FALSE;
expand_string_message = US"";
if (*s == '{') /*}*/
{
key = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
- if (key == NULL) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (!key) goto EXPAND_FAILED; /*{{*/
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' after lookup key";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
}
else key = NULL;
queries that also require a file name (e.g. sqlite), the file name comes
first. */
- if (*s != '{') goto EXPAND_FAILED_CURLY;
+ if (*s != '{')
+ {
+ expand_string_message = US"missing '{' for lookup file-or-query arg";
+ goto EXPAND_FAILED_CURLY;
+ }
filename = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (filename == NULL) goto EXPAND_FAILED;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing lookup file-or-query arg";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
/* If this isn't a single-key+file lookup, re-arrange the variables
there is just a "key", and no file name. For the special query-style +
file types, the query (i.e. "key") starts with a file name. */
- if (key == NULL)
+ if (!key)
{
while (isspace(*filename)) filename++;
key = filename;
if (mac_islookup(stype, lookup_querystyle))
- {
filename = NULL;
- }
else
{
if (*filename != '/')
{
if (expand_string_internal(s+1, TRUE, &s, TRUE, TRUE, &resetok) == NULL)
goto EXPAND_FAILED;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing failstring for readsocket";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
}
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+
+ readsock_done:
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing readsocket";
+ goto EXPAND_FAILED_CURLY;
+ }
continue;
/* Come here on failure to create socket, connect socket, write to the
if (!(arg = expand_string_internal(s+1, TRUE, &s, FALSE, TRUE, &resetok)))
goto EXPAND_FAILED;
yield = string_cat(yield, &size, &ptr, arg);
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing failstring for readsocket";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
- continue;
+ goto readsock_done;
}
/* Handle "run" to execute a program. */
}
while (isspace(*s)) s++;
- if (*s != '{') goto EXPAND_FAILED_CURLY;
+ if (*s != '{')
+ {
+ expand_string_message = US"missing '{' for command arg of run";
+ goto EXPAND_FAILED_CURLY;
+ }
arg = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (arg == NULL) goto EXPAND_FAILED;
while (isspace(*s)) s++;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing command arg of run";
+ goto EXPAND_FAILED_CURLY;
+ }
if (skipping) /* Just pretend it worked when we're skipping */
- {
runrc = 0;
- }
else
{
if (!transport_set_up_command(&argv, /* anchor for arg list */
{
uschar *sub[3];
md5 md5_base;
- sha1 sha1_base;
+ hctx sha1_ctx;
void *use_base;
int type, i;
int hashlen; /* Number of octets for the hash algorithm's output */
else if (Ustrcmp(sub[0], "sha1") == 0)
{
type = HMAC_SHA1;
- use_base = &sha1_base;
+ use_base = &sha1_ctx;
hashlen = 20;
hashblocklen = 64;
}
case EITEM_EXTRACT:
{
int i;
- int j = 2;
+ int j;
int field_number = 1;
BOOL field_number_set = FALSE;
uschar *save_lookup_value = lookup_value;
/* While skipping we cannot rely on the data for expansions being
available (eg. $item) hence cannot decide on numeric vs. keyed.
- Just read as many arguments as there are. */
+ Read a maximum of 5 arguments (inclding the yes/no) */
if (skipping)
{
while (isspace(*s)) s++;
- while (*s == '{')
+ for (j = 5; j > 0 && *s == '{'; j--)
{
if (!expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok))
goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '{' for arg of extract";
+ goto EXPAND_FAILED_CURLY;
+ }
+ while (isspace(*s)) s++;
+ }
+ if ( Ustrncmp(s, "fail", 4) == 0
+ && (s[4] == '}' || s[4] == ' ' || s[4] == '\t' || !s[4])
+ )
+ {
+ s += 4;
while (isspace(*s)) s++;
}
if (*s != '}')
+ {
+ expand_string_message = US"missing '}' closing extract";
goto EXPAND_FAILED_CURLY;
+ }
}
- else for (i = 0; i < j; i++) /* Read the proper number of arguments */
+ else for (i = 0, j = 2; i < j; i++) /* Read the proper number of arguments */
{
while (isspace(*s)) s++;
if (*s == '{') /*}*/
{
sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (sub[i] == NULL) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = string_sprintf(
+ "missing '}' closing arg %d of extract", i+1);
+ goto EXPAND_FAILED_CURLY;
+ }
/* After removal of leading and trailing white space, the first
argument must not be empty; if it consists entirely of digits
}
}
}
- else goto EXPAND_FAILED_CURLY;
+ else
+ {
+ expand_string_message = string_sprintf(
+ "missing '{' for arg %d of extract", i+1);
+ goto EXPAND_FAILED_CURLY;
+ }
}
/* Extract either the numbered or the keyed substring into $value. If
{
while (isspace(*s)) s++;
if (*s != '{') /*}*/
+ {
+ expand_string_message = string_sprintf(
+ "missing '{' for arg %d of listextract", i+1);
goto EXPAND_FAILED_CURLY;
+ }
sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (!sub[i]) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = string_sprintf(
+ "missing '}' closing arg %d of listextract", i+1);
+ goto EXPAND_FAILED_CURLY;
+ }
/* After removal of leading and trailing white space, the first
argument must be numeric and nonempty. */
/* Read the field argument */
while (isspace(*s)) s++;
if (*s != '{') /*}*/
+ {
+ expand_string_message = US"missing '{' for field arg of certextract";
goto EXPAND_FAILED_CURLY;
+ }
sub[0] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (!sub[0]) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing field arg of certextract";
+ goto EXPAND_FAILED_CURLY;
+ }
/* strip spaces fore & aft */
{
int len;
/* inspect the cert argument */
while (isspace(*s)) s++;
if (*s != '{') /*}*/
+ {
+ expand_string_message = US"missing '{' for cert variable arg of certextract";
goto EXPAND_FAILED_CURLY;
+ }
if (*++s != '$')
{
expand_string_message = US"second argument of \"certextract\" must "
}
sub[1] = expand_string_internal(s+1, TRUE, &s, skipping, FALSE, &resetok);
if (!sub[1]) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing cert variable arg of certextract";
+ goto EXPAND_FAILED_CURLY;
+ }
if (skipping)
lookup_value = NULL;
uschar *save_lookup_value = lookup_value;
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message =
+ string_sprintf("missing '{' for first arg of %s", name);
+ goto EXPAND_FAILED_CURLY;
+ }
list = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
if (list == NULL) goto EXPAND_FAILED;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message =
+ string_sprintf("missing '}' closing first arg of %s", name);
+ goto EXPAND_FAILED_CURLY;
+ }
if (item_type == EITEM_REDUCE)
{
uschar * t;
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message = US"missing '{' for second arg of reduce";
+ goto EXPAND_FAILED_CURLY;
+ }
t = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
if (!t) goto EXPAND_FAILED;
lookup_value = t;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing second arg of reduce";
+ goto EXPAND_FAILED_CURLY;
+ }
}
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message =
+ string_sprintf("missing '{' for last arg of %s", name);
+ goto EXPAND_FAILED_CURLY;
+ }
expr = s;
uschar *save_iterate_item = iterate_item;
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message = US"missing '{' for list arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
srclist = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
if (!srclist) goto EXPAND_FAILED;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing list arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message = US"missing '{' for comparator arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
cmp = expand_string_internal(s, TRUE, &s, skipping, FALSE, &resetok);
if (!cmp) goto EXPAND_FAILED;
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing comparator arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
while (isspace(*s)) s++;
- if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '{')
+ {
+ expand_string_message = US"missing '{' for extractor arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
xtract = s;
tmp = expand_string_internal(s, TRUE, &s, TRUE, TRUE, &resetok);
if (!tmp) goto EXPAND_FAILED;
xtract = string_copyn(xtract, s - xtract);
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '}' closing extractor arg of sort";
+ goto EXPAND_FAILED_CURLY;
+ }
/*{*/
if (*s++ != '}')
{ /*{*/
key = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
if (!key) goto EXPAND_FAILED; /*{*/
- if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ if (*s++ != '}')
+ {
+ expand_string_message = US"missing '{' for name arg of env";
+ goto EXPAND_FAILED_CURLY;
+ }
lookup_value = US getenv(CS key);
sub = expand_string_internal(s+2, TRUE, &s1, skipping,
FALSE, &resetok);
if (!sub) goto EXPAND_FAILED; /*{*/
- if (*s1 != '}') goto EXPAND_FAILED_CURLY;
+ if (*s1 != '}')
+ {
+ expand_string_message =
+ string_sprintf("missing '}' closing cert arg of %s", name);
+ goto EXPAND_FAILED_CURLY;
+ }
if ((vp = find_var_ent(sub)) && vp->type == vtype_cert)
{
s = s1+1;
else
#endif
{
- sha1 base;
+ hctx h;
uschar digest[20];
int j;
char st[41];
- sha1_start(&base);
- sha1_end(&base, sub, Ustrlen(sub), digest);
+ sha1_start(&h);
+ sha1_end(&h, sub, Ustrlen(sub), digest);
for(j = 0; j < 20; j++) sprintf(st+2*j, "%02X", digest[j]);
- yield = string_cat(yield, &size, &ptr, US st);
+ yield = string_catn(yield, &size, &ptr, US st, 40);
}
continue;
case EOP_SHA256:
-#ifdef SUPPORT_TLS
+#ifdef EXIM_HAVE_SHA2
if (vp && *(void **)vp->value)
{
uschar * cp = tls_cert_fprt_sha256(*(void **)vp->value);
yield = string_cat(yield, &size, &ptr, cp);
}
else
+ {
+ hctx h;
+ blob b;
+ char st[3];
+
+ exim_sha_init(&h, HASH_SHA256);
+ exim_sha_update(&h, sub, Ustrlen(sub));
+ exim_sha_finish(&h, &b);
+ while (b.len-- > 0)
+ {
+ sprintf(st, "%02X", *b.data++);
+ yield = string_catn(yield, &size, &ptr, US st, 2);
+ }
+ }
+#else
+ expand_string_message = US"sha256 only supported with TLS";
#endif
- expand_string_message = US"sha256 only supported for certificates";
continue;
+ case EOP_SHA3:
+#ifdef EXIM_HAVE_SHA3
+ {
+ hctx h;
+ blob b;
+ char st[3];
+ hashmethod m = !arg ? HASH_SHA3_256
+ : Ustrcmp(arg, "224") == 0 ? HASH_SHA3_224
+ : Ustrcmp(arg, "256") == 0 ? HASH_SHA3_256
+ : Ustrcmp(arg, "384") == 0 ? HASH_SHA3_384
+ : Ustrcmp(arg, "512") == 0 ? HASH_SHA3_512
+ : HASH_BADTYPE;
+
+ if (m == HASH_BADTYPE)
+ {
+ expand_string_message = US"unrecognised sha3 variant";
+ goto EXPAND_FAILED;
+ }
+
+ exim_sha_init(&h, m);
+ exim_sha_update(&h, sub, Ustrlen(sub));
+ exim_sha_finish(&h, &b);
+ while (b.len-- > 0)
+ {
+ sprintf(st, "%02X", *b.data++);
+ yield = string_catn(yield, &size, &ptr, US st, 2);
+ }
+ }
+ continue;
+#else
+ expand_string_message = US"sha3 only supported with GnuTLS 3.5.0 +";
+ goto EXPAND_FAILED;
+#endif
+
/* Convert hex encoding to base64 encoding */
case EOP_HEX2B64:
DEBUG(D_expand)
{
- debug_printf("expanding: %.*s\n result: %s\n", (int)(s - string), string,
+ debug_printf(" expanding: %.*s\n result: %s\n", (int)(s - string), string,
yield);
- if (skipping) debug_printf("skipping: result is not used\n");
+ if (skipping) debug_printf(" skipping: result is not used\n");
}
return yield;
*/
EXPAND_FAILED_CURLY:
-expand_string_message = malformed_header?
- US"missing or misplaced { or } - could be header name not terminated by colon"
- :
- US"missing or misplaced { or }";
+if (malformed_header)
+ expand_string_message =
+ US"missing or misplaced { or } - could be header name not terminated by colon";
+
+else if (!expand_string_message || !*expand_string_message)
+ expand_string_message = US"missing or misplaced { or }";
/* At one point, Exim reset the store to yield (if yield was not NULL), but
that is a bad idea, because expand_string_message is in dynamic store. */
+/* Avoid potentially exposing a password in a string about to be logged */
+
+uschar *
+expand_hide_passwords(uschar * s)
+{
+return ( ( Ustrstr(s, "failed to expand") != NULL
+ || Ustrstr(s, "expansion of ") != NULL
+ )
+ && ( Ustrstr(s, "mysql") != NULL
+ || Ustrstr(s, "pgsql") != NULL
+ || Ustrstr(s, "redis") != NULL
+ || Ustrstr(s, "sqlite") != NULL
+ || Ustrstr(s, "ldap:") != NULL
+ || Ustrstr(s, "ldaps:") != NULL
+ || Ustrstr(s, "ldapi:") != NULL
+ || Ustrstr(s, "ldapdn:") != NULL
+ || Ustrstr(s, "ldapm:") != NULL
+ ) )
+ ? US"Temporary internal error" : s;
+}
+
+
+
/*************************************************
**************************************************