summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2020-06-24 00:04:13 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2020-06-24 15:23:33 +0100
commitbec94709e708f087fe7fa456bec95d4e63edc3ed (patch)
treeff17ef17917c21e12e023a58244dbdae4ec3f135 /src
parent99bfcf2b678e7bd8125a7eb44409e46549bfc111 (diff)
Handle quoted local_part input to ${srs_encode }. Bug 2607
Diffstat (limited to 'src')
-rw-r--r--src/src/expand.c88
1 files changed, 60 insertions, 28 deletions
diff --git a/src/src/expand.c b/src/src/expand.c
index f7e9e5c25..291db426a 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -3451,7 +3451,7 @@ switch(cond_type = identify_operator(&s, &opname))
uschar * sub[2];
const pcre * re;
int ovec[3*(4+1)];
- int n;
+ int n, quoting = 0;
uschar cksum[4];
BOOL boolvalue = FALSE;
@@ -3474,10 +3474,20 @@ switch(cond_type = identify_operator(&s, &opname))
goto srs_result;
}
- /* Side-effect: record the decoded recipient */
+ if (sub[0][0] == '"')
+ quoting = 1;
+ else for (uschar * s = sub[0]; *s; s++)
+ if (!isalnum(*s) && Ustrchr(".!#$%&'*+-/=?^_`{|}~", *s) == NULL)
+ { quoting = 1; break; }
+ if (quoting)
+ DEBUG(D_expand) debug_printf_indent("auto-quoting local part\n");
+
+ /* Record the (quoted, if needed) decoded recipient as $srs_recipient */
- srs_recipient = string_sprintf("%.*S@%.*S", /* lowercased */
+ srs_recipient = string_sprintf("%.*s%.*S%.*s@%.*S", /* lowercased */
+ quoting, "\"",
ovec[9]-ovec[8], sub[0] + ovec[8], /* substring 4 */
+ quoting, "\"",
ovec[7]-ovec[6], sub[0] + ovec[6]); /* substring 3 */
/* If a zero-length secret was given, we're done. Otherwise carry on
@@ -6777,6 +6787,8 @@ while (*s)
{
uschar * sub[3];
uschar cksum[4];
+ gstring * g = NULL;
+ BOOL quoted = FALSE;
switch (read_subs(sub, 3, 3, CUSS &s, skipping, TRUE, name, &resetok))
{
@@ -6785,41 +6797,65 @@ while (*s)
case 3: goto EXPAND_FAILED;
}
- yield = string_catn(yield, US"SRS0=", 5);
+ g = string_catn(g, US"SRS0=", 5);
/* ${l_4:${hmac{md5}{SRS_SECRET}{${lc:$return_path}}}}= */
hmac_md5(sub[0], string_copylc(sub[1]), cksum, sizeof(cksum));
- yield = string_catn(yield, cksum, sizeof(cksum));
- yield = string_catn(yield, US"=", 1);
+ g = string_catn(g, cksum, sizeof(cksum));
+ g = string_catn(g, US"=", 1);
/* ${base32:${eval:$tod_epoch/86400&0x3ff}}= */
{
struct timeval now;
unsigned long i;
- gstring * g = NULL;
+ gstring * h = NULL;
gettimeofday(&now, NULL);
for (unsigned long i = (now.tv_sec / 86400) & 0x3ff; i; i >>= 5)
- g = string_catn(g, &base32_chars[i & 0x1f], 1);
- if (g) while (g->ptr > 0)
- yield = string_catn(yield, &g->s[--g->ptr], 1);
+ h = string_catn(h, &base32_chars[i & 0x1f], 1);
+ if (h) while (h->ptr > 0)
+ g = string_catn(g, &h->s[--h->ptr], 1);
}
- yield = string_catn(yield, US"=", 1);
+ g = string_catn(g, US"=", 1);
/* ${domain:$return_path}=${local_part:$return_path} */
{
int start, end, domain;
uschar * t = parse_extract_address(sub[1], &expand_string_message,
&start, &end, &domain, FALSE);
+ uschar * s;
+
if (!t)
goto EXPAND_FAILED;
- if (domain > 0) yield = string_cat(yield, t + domain);
- yield = string_catn(yield, US"=", 1);
- yield = domain > 0
- ? string_catn(yield, t, domain - 1) : string_cat(yield, t);
+ if (domain > 0) g = string_cat(g, t + domain);
+ g = string_catn(g, US"=", 1);
+
+ s = domain > 0 ? string_copyn(t, domain - 1) : t;
+ if ((quoted = Ustrchr(s, '"') != NULL))
+ {
+ gstring * h = NULL;
+ DEBUG(D_expand) debug_printf_indent("auto-quoting local part\n");
+ while (*s) /* de-quote */
+ {
+ while (*s && *s != '"') h = string_catn(h, s++, 1);
+ if (*s) s++;
+ while (*s && *s != '"') h = string_catn(h, s++, 1);
+ if (*s) s++;
+ }
+ gstring_release_unused(h);
+ s = string_from_gstring(h);
+ }
+ g = string_cat(g, s);
}
+ /* Assume that if the original local_part had quotes
+ it was for good reason */
+
+ if (quoted) yield = string_catn(yield, US"\"", 1);
+ yield = string_catn(yield, g->s, g->ptr);
+ if (quoted) yield = string_catn(yield, US"\"", 1);
+
/* @$original_domain */
yield = string_catn(yield, US"@", 1);
yield = string_cat(yield, sub[2]);
@@ -7471,24 +7507,20 @@ while (*s)
uschar *t = sub - 1;
if (c == EOP_QUOTE)
- {
- while (!needs_quote && *(++t) != 0)
+ while (!needs_quote && *++t)
needs_quote = !isalnum(*t) && !strchr("_-.", *t);
- }
+
else /* EOP_QUOTE_LOCAL_PART */
- {
- while (!needs_quote && *(++t) != 0)
- needs_quote = !isalnum(*t) &&
- strchr("!#$%&'*+-/=?^_`{|}~", *t) == NULL &&
- (*t != '.' || t == sub || t[1] == 0);
- }
+ while (!needs_quote && *++t)
+ needs_quote = !isalnum(*t)
+ && strchr("!#$%&'*+-/=?^_`{|}~", *t) == NULL
+ && (*t != '.' || t == sub || !t[1]);
if (needs_quote)
{
yield = string_catn(yield, US"\"", 1);
t = sub - 1;
- while (*(++t) != 0)
- {
+ while (*++t)
if (*t == '\n')
yield = string_catn(yield, US"\\n", 2);
else if (*t == '\r')
@@ -7499,10 +7531,10 @@ while (*s)
yield = string_catn(yield, US"\\", 1);
yield = string_catn(yield, t, 1);
}
- }
yield = string_catn(yield, US"\"", 1);
}
- else yield = string_cat(yield, sub);
+ else
+ yield = string_cat(yield, sub);
continue;
}