Skip to content

Commit 6f81314

Browse files
committed
Mail: xtext encoding (RFC 3461) in XCLIENT LOGIN.
The XCLIENT command uses xtext encoding for attribute values, as specified in https://www.postfix.org/XCLIENT_README.html. Reported by Igor Morgenstern of Aisle Research.
1 parent 8255bd2 commit 6f81314

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

src/core/ngx_string.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,8 +1494,9 @@ ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len)
14941494
uintptr_t
14951495
ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
14961496
{
1497-
ngx_uint_t n;
1497+
u_char prefix;
14981498
uint32_t *escape;
1499+
ngx_uint_t n;
14991500
static u_char hex[] = "0123456789ABCDEF";
15001501

15011502
/*
@@ -1633,11 +1634,36 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
16331634

16341635
/* mail_auth is the same as memcached */
16351636

1637+
/* " ", "+", "=", not allowed */
1638+
1639+
static uint32_t mail_xtext[] = {
1640+
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1641+
1642+
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
1643+
0x20000801, /* 0010 0000 0000 0000 0000 1000 0000 0001 */
1644+
1645+
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
1646+
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
1647+
1648+
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
1649+
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
1650+
1651+
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1652+
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1653+
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1654+
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1655+
};
1656+
16361657
static uint32_t *map[] =
1637-
{ uri, args, uri_component, html, refresh, memcached, memcached };
1658+
{ uri, args, uri_component, html, refresh, memcached, memcached,
1659+
mail_xtext };
1660+
1661+
static u_char map_char[] =
1662+
{ '%', '%', '%', '%', '%', '%', '%', '+' };
16381663

16391664

16401665
escape = map[type];
1666+
prefix = map_char[type];
16411667

16421668
if (dst == NULL) {
16431669

@@ -1658,7 +1684,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
16581684

16591685
while (size) {
16601686
if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
1661-
*dst++ = '%';
1687+
*dst++ = prefix;
16621688
*dst++ = hex[*src >> 4];
16631689
*dst++ = hex[*src & 0xf];
16641690
src++;

src/core/ngx_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
203203
#define NGX_ESCAPE_REFRESH 4
204204
#define NGX_ESCAPE_MEMCACHED 5
205205
#define NGX_ESCAPE_MAIL_AUTH 6
206+
#define NGX_ESCAPE_MAIL_XTEXT 7
206207

207208
#define NGX_UNESCAPE_URI 1
208209
#define NGX_UNESCAPE_REDIRECT 2

src/mail/ngx_mail_proxy_module.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
531531
ngx_int_t rc;
532532
ngx_str_t line, auth, encoded;
533533
ngx_buf_t *b;
534+
uintptr_t n;
534535
ngx_connection_t *c;
535536
ngx_mail_session_t *s;
536537
ngx_mail_proxy_conf_t *pcf;
@@ -627,6 +628,10 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
627628
CRLF) - 1
628629
+ s->connection->addr_text.len + s->login.len + s->host.len;
629630

631+
n = ngx_escape_uri(NULL, s->login.data, s->login.len,
632+
NGX_ESCAPE_MAIL_XTEXT);
633+
line.len += n * 2;
634+
630635
#if (NGX_HAVE_INET6)
631636
if (s->connection->sockaddr->sa_family == AF_INET6) {
632637
line.len += sizeof("IPV6:") - 1;
@@ -654,7 +659,14 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
654659

655660
if (s->login.len && !pcf->smtp_auth) {
656661
p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1);
657-
p = ngx_copy(p, s->login.data, s->login.len);
662+
663+
if (n == 0) {
664+
p = ngx_copy(p, s->login.data, s->login.len);
665+
666+
} else {
667+
p = (u_char *) ngx_escape_uri(p, s->login.data, s->login.len,
668+
NGX_ESCAPE_MAIL_XTEXT);
669+
}
658670
}
659671

660672
p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1);

0 commit comments

Comments
 (0)