Mercurial > nginx
changeset 9463:0954f084ffc0
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.
| author | Sergey Kandaurov <pluknet@nginx.com> |
|---|---|
| date | Thu, 11 Sep 2025 18:23:10 +0400 |
| parents | 4f55535cf345 |
| children | fd6242dfb464 |
| files | src/core/ngx_string.c src/core/ngx_string.h src/mail/ngx_mail_proxy_module.c |
| diffstat | 3 files changed, 43 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/core/ngx_string.c Wed Sep 10 18:39:52 2025 +0400 +++ b/src/core/ngx_string.c Thu Sep 11 18:23:10 2025 +0400 @@ -1494,8 +1494,9 @@ uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) { + u_char prefix; + uint32_t *escape; ngx_uint_t n; - uint32_t *escape; static u_char hex[] = "0123456789ABCDEF"; /* @@ -1633,11 +1634,36 @@ /* mail_auth is the same as memcached */ + /* " ", "+", "=", not allowed */ + + static uint32_t mail_xtext[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x20000801, /* 0010 0000 0000 0000 0000 1000 0000 0001 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + static uint32_t *map[] = - { uri, args, uri_component, html, refresh, memcached, memcached }; + { uri, args, uri_component, html, refresh, memcached, memcached, + mail_xtext }; + + static u_char map_char[] = + { '%', '%', '%', '%', '%', '%', '%', '+' }; escape = map[type]; + prefix = map_char[type]; if (dst == NULL) { @@ -1658,7 +1684,7 @@ while (size) { if (escape[*src >> 5] & (1U << (*src & 0x1f))) { - *dst++ = '%'; + *dst++ = prefix; *dst++ = hex[*src >> 4]; *dst++ = hex[*src & 0xf]; src++;
--- a/src/core/ngx_string.h Wed Sep 10 18:39:52 2025 +0400 +++ b/src/core/ngx_string.h Thu Sep 11 18:23:10 2025 +0400 @@ -203,6 +203,7 @@ #define NGX_ESCAPE_REFRESH 4 #define NGX_ESCAPE_MEMCACHED 5 #define NGX_ESCAPE_MAIL_AUTH 6 +#define NGX_ESCAPE_MAIL_XTEXT 7 #define NGX_UNESCAPE_URI 1 #define NGX_UNESCAPE_REDIRECT 2
--- a/src/mail/ngx_mail_proxy_module.c Wed Sep 10 18:39:52 2025 +0400 +++ b/src/mail/ngx_mail_proxy_module.c Thu Sep 11 18:23:10 2025 +0400 @@ -531,6 +531,7 @@ ngx_int_t rc; ngx_str_t line, auth, encoded; ngx_buf_t *b; + uintptr_t n; ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_proxy_conf_t *pcf; @@ -627,6 +628,10 @@ CRLF) - 1 + s->connection->addr_text.len + s->login.len + s->host.len; + n = ngx_escape_uri(NULL, s->login.data, s->login.len, + NGX_ESCAPE_MAIL_XTEXT); + line.len += n * 2; + #if (NGX_HAVE_INET6) if (s->connection->sockaddr->sa_family == AF_INET6) { line.len += sizeof("IPV6:") - 1; @@ -654,7 +659,14 @@ if (s->login.len && !pcf->smtp_auth) { p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); - p = ngx_copy(p, s->login.data, s->login.len); + + if (n == 0) { + p = ngx_copy(p, s->login.data, s->login.len); + + } else { + p = (u_char *) ngx_escape_uri(p, s->login.data, s->login.len, + NGX_ESCAPE_MAIL_XTEXT); + } } p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1);
