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,
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);
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];
{
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; /*{*/
}
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";
}
}
- 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 == '{') /*}*/
if (*s++ != '}')
{
expand_string_message = string_sprintf(
- US"missing '}' closing arg %d of extract", i+1);
+ "missing '}' closing arg %d of extract", i+1);
goto EXPAND_FAILED_CURLY;
}
else
{
expand_string_message = string_sprintf(
- US"missing '{' for arg %d of extract", i+1);
+ "missing '{' for arg %d of extract", i+1);
goto EXPAND_FAILED_CURLY;
}
}
if (*s != '{') /*}*/
{
expand_string_message = string_sprintf(
- US"missing '{' for arg %d of listextract", i+1);
+ "missing '{' for arg %d of listextract", i+1);
goto EXPAND_FAILED_CURLY;
}
if (*s++ != '}')
{
expand_string_message = string_sprintf(
- US"missing '}' closing arg %d of listextract", i+1);
+ "missing '}' closing arg %d of listextract", i+1);
goto EXPAND_FAILED_CURLY;
}
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:
+/* 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;
+}
+
+
+
/*************************************************
**************************************************