[PATCH] Added support for proxying managesieve protocol

Sander Hoentjen sander at hoentjen.eu
Tue Apr 14 18:27:15 UTC 2020


Hello list,

Since the Nginx development procedure is unknown to me: Did i do the 
right things to get my submission to be considered? What are the next 
steps? Will somebody review this, or reject it? Or is it possible that 
it just won't get any attention, and that this will mean it will not be 
considered? I hope I will at least get some feedback, even if it is a 
rejection :)

Kind regards,

Sander

On 4/8/20 8:33 PM, Sander Hoentjen wrote:
> Hello list,
>
> This is my attempt at adding support for the managesieve protocol. I 
> hope this is something that you would consider to add. Comments on the 
> code are very welcome! Also, I hope I submitted this the right way. If 
> I need to change anything, please let me know.
>
> Kind regards,
>
> Sander Hoentjen
>
> On 4/8/20 8:26 PM, Sander Hoentjen wrote:
>> # HG changeset patch
>> # User Sander Hoentjen <shoentjen at antagonist.nl>
>> # Date 1586369831 -7200
>> # Wed Apr 08 20:17:11 2020 +0200
>> # Node ID f1dffaf619688aaab90caf31781ebe27c3f79598
>> # Parent 0cb942c1c1aa98118076e72e0b89940e85e6291c
>> Added support for proxying managesieve protocol
>>
>> Sieve is a widely used protocol to implement server-side filtering. Some
>> servers and clients that support this are listed at 
>> <http://sieve.info/>. This
>> commit is tested with Dovecot as the server and Roundcube as the 
>> client, but I
>> don't see a readon why it not would work with others. It is a nice 
>> addition to
>> nginx because it adds the possibility to add server side filtering to 
>> setups
>> that use IMAP behind an nginx proxy.
>>
>> Fixes https://trac.nginx.org/nginx/ticket/1697
>>
>> diff -r 0cb942c1c1aa -r f1dffaf61968 auto/modules
>> --- a/auto/modules Fri Mar 13 02:12:10 2020 +0300
>> +++ b/auto/modules Wed Apr 08 20:17:11 2020 +0200
>> @@ -965,6 +965,15 @@
>> . auto/module
>> fi
>> + if [ $MAIL_SIEVE = YES ]; then
>> + ngx_module_name=ngx_mail_sieve_module
>> + ngx_module_deps=src/mail/ngx_mail_sieve_module.h
>> + ngx_module_srcs="src/mail/ngx_mail_sieve_module.c \
>> + src/mail/ngx_mail_sieve_handler.c"
>> +
>> + . auto/module
>> + fi
>> +
>> if [ $MAIL_SMTP = YES ]; then
>> ngx_module_name=ngx_mail_smtp_module
>> ngx_module_deps=src/mail/ngx_mail_smtp_module.h
>> diff -r 0cb942c1c1aa -r f1dffaf61968 auto/options
>> --- a/auto/options Fri Mar 13 02:12:10 2020 +0300
>> +++ b/auto/options Wed Apr 08 20:17:11 2020 +0200
>> @@ -112,6 +112,7 @@
>> MAIL_SSL=NO
>> MAIL_POP3=YES
>> MAIL_IMAP=YES
>> +MAIL_SIEVE=YES
>> MAIL_SMTP=YES
>> STREAM=NO
>> @@ -305,6 +306,8 @@
>> ;;
>> --without-mail_pop3_module) MAIL_POP3=NO ;;
>> --without-mail_imap_module) MAIL_IMAP=NO ;;
>> + --without-mail_sieve_module)
>> + MAIL_SIEVE=NO ;;
>> --without-mail_smtp_module) MAIL_SMTP=NO ;;
>> --with-stream) STREAM=YES ;;
>> @@ -517,11 +520,12 @@
>> --without-http disable HTTP server
>> --without-http-cache disable HTTP cache
>> - --with-mail enable POP3/IMAP4/SMTP proxy module
>> - --with-mail=dynamic enable dynamic POP3/IMAP4/SMTP proxy module
>> + --with-mail enable POP3/IMAP4/SIEVE/SMTP proxy module
>> + --with-mail=dynamic enable dynamic POP3/IMAP4/SIEVE/SMTP proxy module
>> --with-mail_ssl_module enable ngx_mail_ssl_module
>> --without-mail_pop3_module disable ngx_mail_pop3_module
>> --without-mail_imap_module disable ngx_mail_imap_module
>> + --without-mail_sieve_module disable ngx_mail_sieve_module
>> --without-mail_smtp_module disable ngx_mail_smtp_module
>> --with-stream enable TCP/UDP proxy module
>> diff -r 0cb942c1c1aa -r f1dffaf61968 contrib/vim/syntax/nginx.vim
>> --- a/contrib/vim/syntax/nginx.vim Fri Mar 13 02:12:10 2020 +0300
>> +++ b/contrib/vim/syntax/nginx.vim Wed Apr 08 20:17:11 2020 +0200
>> @@ -571,6 +571,9 @@
>> syn keyword ngxDirective contained session_log_format
>> syn keyword ngxDirective contained session_log_zone
>> syn keyword ngxDirective contained set_real_ip_from
>> +syn keyword ngxDirective contained sieve_auth
>> +syn keyword ngxDirective contained sieve_capabilities
>> +syn keyword ngxDirective contained sieve_client_buffer
>> syn keyword ngxDirective contained slice
>> syn keyword ngxDirective contained smtp_auth
>> syn keyword ngxDirective contained smtp_capabilities
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail.h
>> --- a/src/mail/ngx_mail.h Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail.h Wed Apr 08 20:17:11 2020 +0200
>> @@ -102,6 +102,7 @@
>> #define NGX_MAIL_POP3_PROTOCOL 0
>> #define NGX_MAIL_IMAP_PROTOCOL 1
>> #define NGX_MAIL_SMTP_PROTOCOL 2
>> +#define NGX_MAIL_SIEVE_PROTOCOL 3
>> typedef struct ngx_mail_protocol_s ngx_mail_protocol_t;
>> @@ -154,6 +155,21 @@
>> typedef enum {
>> + ngx_sieve_start = 0,
>> + ngx_sieve_starttls,
>> + ngx_sieve_auth_login_username,
>> + ngx_sieve_auth_login_password,
>> + ngx_sieve_auth_plain,
>> + ngx_sieve_auth_cram_md5,
>> + ngx_sieve_auth_external,
>> + ngx_sieve_login,
>> + ngx_sieve_login_capabilities,
>> + ngx_sieve_user,
>> + ngx_sieve_passwd
>> +} ngx_sieve_state_e;
>> +
>> +
>> +typedef enum {
>> ngx_smtp_start = 0,
>> ngx_smtp_auth_login_username,
>> ngx_smtp_auth_login_password,
>> @@ -227,7 +243,7 @@
>> ngx_uint_t login_attempt;
>> - /* used to parse POP3/IMAP/SMTP command */
>> + /* used to parse POP3/IMAP/SIEVE/SMTP command */
>> ngx_uint_t state;
>> u_char *cmd_start;
>> @@ -271,6 +287,14 @@
>> #define NGX_IMAP_AUTHENTICATE 7
>> +#define NGX_SIEVE_LOGOUT 1
>> +#define NGX_SIEVE_CAPABILITY 2
>> +#define NGX_SIEVE_NOOP 3
>> +#define NGX_SIEVE_STARTTLS 4
>> +#define NGX_SIEVE_NEXT 5
>> +#define NGX_SIEVE_AUTHENTICATE 6
>> +
>> +
>> #define NGX_SMTP_HELO 1
>> #define NGX_SMTP_EHLO 2
>> #define NGX_SMTP_AUTH 3
>> @@ -383,7 +407,7 @@
>> ngx_int_t ngx_mail_auth_login_password(ngx_mail_session_t *s,
>> ngx_connection_t *c);
>> ngx_int_t ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s,
>> - ngx_connection_t *c, char *prefix, size_t len);
>> + ngx_connection_t *c, char *prefix, size_t len, ngx_uint_t quote);
>> ngx_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, 
>> ngx_connection_t *c);
>> ngx_int_t ngx_mail_auth_external(ngx_mail_session_t *s, 
>> ngx_connection_t *c,
>> ngx_uint_t n);
>> diff -r 0cb942c1c1aa -r f1dffaf61968 
>> src/mail/ngx_mail_auth_http_module.c
>> --- a/src/mail/ngx_mail_auth_http_module.c Fri Mar 13 02:12:10 2020 
>> +0300
>> +++ b/src/mail/ngx_mail_auth_http_module.c Wed Apr 08 20:17:11 2020 
>> +0200
>> @@ -533,6 +533,11 @@
>> + sizeof(CRLF) - 1;
>> break;
>> + case NGX_MAIL_SIEVE_PROTOCOL:
>> + size = sizeof("BYE \"\"") - 1 + len
>> + + sizeof(CRLF) - 1;
>> + break;
>> +
>> default: /* NGX_MAIL_SMTP_PROTOCOL */
>> ctx->err = ctx->errmsg;
>> continue;
>> @@ -559,11 +564,27 @@
>> *p++ = 'N'; *p++ = 'O'; *p++ = ' ';
>> break;
>> + case NGX_MAIL_SIEVE_PROTOCOL:
>> + p = ngx_cpymem(p, s->tag.data, s->tag.len);
>> + *p++ = 'B'; *p++ = 'Y'; *p++ = 'E'; *p++ = ' '; *p++ = '"';
>> + break;
>> +
>> default: /* NGX_MAIL_SMTP_PROTOCOL */
>> break;
>> }
>> p = ngx_cpymem(p, ctx->header_start, len);
>> +
>> + switch (s->protocol) {
>> +
>> + case NGX_MAIL_SIEVE_PROTOCOL:
>> + *p++ = '"';
>> + break;
>> +
>> + default:
>> + break;
>> + }
>> +
>> *p++ = CR; *p++ = LF;
>> ctx->err.len = p - ctx->err.data;
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_handler.c
>> --- a/src/mail/ngx_mail_handler.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_handler.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -520,28 +520,39 @@
>> ngx_int_t
>> ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c,
>> - char *prefix, size_t len)
>> + char *prefix, size_t len, ngx_uint_t quote)
>> {
>> u_char *p;
>> ngx_str_t salt;
>> - ngx_uint_t n;
>> + ngx_uint_t n = 0;
>> + if (quote) {
>> + len += 2;
>> + }
>> p = ngx_pnalloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) 
>> + 2);
>> if (p == NULL) {
>> return NGX_ERROR;
>> }
>> - salt.data = ngx_cpymem(p, prefix, len);
>> + if (quote) {
>> + len -= 2;
>> + salt.data = ngx_cpymem(p, "\"", 1);
>> + n++;
>> + }
>> + salt.data = ngx_cpymem(p+ n, prefix, len);
>> s->salt.len -= 2;
>> ngx_encode_base64(&salt, &s->salt);
>> s->salt.len += 2;
>> - n = len + salt.len;
>> + n += len + salt.len;
>> + if (quote) {
>> + p[n++] = '"';
>> + }
>> p[n++] = CR; p[n++] = LF;
>> s->out.len = n;
>> - s->out.data = p;
>> + s->out.data = p--;
>> return NGX_OK;
>> }
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_imap_handler.c
>> --- a/src/mail/ngx_mail_imap_handler.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_imap_handler.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -397,7 +397,7 @@
>> }
>> }
>> - if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
>> + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2, 0) == NGX_OK) {
>> s->mail_state = ngx_imap_auth_cram_md5;
>> return NGX_OK;
>> }
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_parse.c
>> --- a/src/mail/ngx_mail_parse.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_parse.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -11,6 +11,7 @@
>> #include <ngx_mail.h>
>> #include <ngx_mail_pop3_module.h>
>> #include <ngx_mail_imap_module.h>
>> +#include <ngx_mail_sieve_module.h>
>> #include <ngx_mail_smtp_module.h>
>> @@ -620,6 +621,364 @@
>> ngx_int_t
>> +ngx_mail_sieve_parse_command(ngx_mail_session_t *s)
>> +{
>> + u_char ch, *p, *c;
>> + ngx_str_t *arg;
>> + enum {
>> + sw_start = 0,
>> + sw_spaces_before_argument,
>> + sw_argument,
>> + sw_backslash,
>> + sw_literal,
>> + sw_no_sync_literal_argument,
>> + sw_start_literal_argument,
>> + sw_literal_argument,
>> + sw_end_literal_argument,
>> + sw_almost_done
>> + } state;
>> +
>> + state = s->state;
>> +
>> + for (p = s->buffer->pos; p < s->buffer->last; p++) {
>> + ch = *p;
>> +
>> + switch (state) {
>> +
>> + /* SIEVE command */
>> + case sw_start:
>> + if (ch == ' ' || ch == CR || ch == LF) {
>> +
>> + c = s->buffer->start;
>> +
>> + switch (p - c) {
>> +
>> + case 4:
>> + if ((c[0] == 'N' || c[0] == 'n')
>> + && (c[1] == 'O'|| c[1] == 'o')
>> + && (c[2] == 'O'|| c[2] == 'o')
>> + && (c[3] == 'P'|| c[3] == 'p'))
>> + {
>> + s->command = NGX_SIEVE_NOOP;
>> +
>> + } else {
>> + goto invalid;
>> + }
>> + break;
>> +
>> + case 6:
>> + if ((c[0] == 'L'|| c[0] == 'l')
>> + && (c[1] == 'O'|| c[1] == 'o')
>> + && (c[2] == 'G'|| c[2] == 'g')
>> + && (c[3] == 'O'|| c[3] == 'o')
>> + && (c[4] == 'U'|| c[4] == 'u')
>> + && (c[5] == 'T'|| c[5] == 't'))
>> + {
>> + s->command = NGX_SIEVE_LOGOUT;
>> +
>> + } else {
>> + goto invalid;
>> + }
>> + break;
>> +
>> +#if (NGX_MAIL_SSL)
>> + case 8:
>> + if ((c[0] == 'S'|| c[0] == 's')
>> + && (c[1] == 'T'|| c[1] == 't')
>> + && (c[2] == 'A'|| c[2] == 'a')
>> + && (c[3] == 'R'|| c[3] == 'r')
>> + && (c[4] == 'T'|| c[4] == 't')
>> + && (c[5] == 'T'|| c[5] == 't')
>> + && (c[6] == 'L'|| c[6] == 'l')
>> + && (c[7] == 'S'|| c[7] == 's'))
>> + {
>> + s->command = NGX_SIEVE_STARTTLS;
>> +
>> + } else {
>> + goto invalid;
>> + }
>> + break;
>> +#endif
>> +
>> + case 10:
>> + if ((c[0] == 'C'|| c[0] == 'c')
>> + && (c[1] == 'A'|| c[1] == 'a')
>> + && (c[2] == 'P'|| c[2] == 'p')
>> + && (c[3] == 'A'|| c[3] == 'a')
>> + && (c[4] == 'B'|| c[4] == 'b')
>> + && (c[5] == 'I'|| c[5] == 'i')
>> + && (c[6] == 'L'|| c[6] == 'l')
>> + && (c[7] == 'I'|| c[7] == 'i')
>> + && (c[8] == 'T'|| c[8] == 't')
>> + && (c[9] == 'Y'|| c[9] == 'y'))
>> + {
>> + s->command = NGX_SIEVE_CAPABILITY;
>> +
>> + } else {
>> + goto invalid;
>> + }
>> + break;
>> +
>> + case 12:
>> + if ((c[0] == 'A'|| c[0] == 'a')
>> + && (c[1] == 'U'|| c[1] == 'u')
>> + && (c[2] == 'T'|| c[2] == 't')
>> + && (c[3] == 'H'|| c[3] == 'h')
>> + && (c[4] == 'E'|| c[4] == 'e')
>> + && (c[5] == 'N'|| c[5] == 'n')
>> + && (c[6] == 'T'|| c[6] == 't')
>> + && (c[7] == 'I'|| c[7] == 'i')
>> + && (c[8] == 'C'|| c[8] == 'c')
>> + && (c[9] == 'A'|| c[9] == 'a')
>> + && (c[10] == 'T'|| c[10] == 't')
>> + && (c[11] == 'E'|| c[11] == 'e'))
>> + {
>> + s->command = NGX_SIEVE_AUTHENTICATE;
>> +
>> + } else {
>> + goto invalid;
>> + }
>> + break;
>> +
>> + default:
>> + goto invalid;
>> + }
>> +
>> + switch (ch) {
>> + case ' ':
>> + state = sw_spaces_before_argument;
>> + break;
>> + case CR:
>> + state = sw_almost_done;
>> + break;
>> + case LF:
>> + goto done;
>> + }
>> + break;
>> + }
>> +
>> + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
>> + goto invalid;
>> + }
>> +
>> + break;
>> +
>> + case sw_spaces_before_argument:
>> + switch (ch) {
>> + case ' ':
>> + break;
>> + case CR:
>> + state = sw_almost_done;
>> + s->arg_end = p;
>> + break;
>> + case LF:
>> + s->arg_end = p;
>> + goto done;
>> + case '"':
>> + if (s->args.nelts <= 2) {
>> + s->quoted = 1;
>> + s->arg_start = p + 1;
>> + state = sw_argument;
>> + break;
>> + }
>> + goto invalid;
>> + case '{':
>> + if (s->args.nelts <= 2) {
>> + state = sw_literal;
>> + break;
>> + }
>> + goto invalid;
>> + default:
>> + if (s->args.nelts <= 2) {
>> + s->arg_start = p;
>> + state = sw_argument;
>> + break;
>> + }
>> + goto invalid;
>> + }
>> + break;
>> +
>> + case sw_argument:
>> + if (ch == ' ' && s->quoted) {
>> + break;
>> + }
>> +
>> + switch (ch) {
>> + case '"':
>> + if (!s->quoted) {
>> + break;
>> + }
>> + s->quoted = 0;
>> + /* fall through */
>> + case ' ':
>> + case CR:
>> + case LF:
>> + arg = ngx_array_push(&s->args);
>> + if (arg == NULL) {
>> + return NGX_ERROR;
>> + }
>> + arg->len = p - s->arg_start;
>> + arg->data = s->arg_start;
>> + s->arg_start = NULL;
>> +
>> + switch (ch) {
>> + case '"':
>> + case ' ':
>> + state = sw_spaces_before_argument;
>> + break;
>> + case CR:
>> + state = sw_almost_done;
>> + break;
>> + case LF:
>> + goto done;
>> + }
>> + break;
>> + case '\\':
>> + if (s->quoted) {
>> + s->backslash = 1;
>> + state = sw_backslash;
>> + }
>> + break;
>> + }
>> + break;
>> +
>> + case sw_backslash:
>> + switch (ch) {
>> + case CR:
>> + case LF:
>> + goto invalid;
>> + default:
>> + state = sw_argument;
>> + }
>> + break;
>> +
>> + case sw_literal:
>> + if (ch >= '0' && ch <= '9') {
>> + s->literal_len = s->literal_len * 10 + (ch - '0');
>> + break;
>> + }
>> + if (ch == '}') {
>> + state = sw_start_literal_argument;
>> + break;
>> + }
>> + if (ch == '+') {
>> + state = sw_no_sync_literal_argument;
>> + break;
>> + }
>> + goto invalid;
>> +
>> + case sw_no_sync_literal_argument:
>> + if (ch == '}') {
>> + s->no_sync_literal = 1;
>> + state = sw_start_literal_argument;
>> + break;
>> + }
>> + goto invalid;
>> +
>> + case sw_start_literal_argument:
>> + switch (ch) {
>> + case CR:
>> + break;
>> + case LF:
>> + s->buffer->pos = p + 1;
>> + s->arg_start = p + 1;
>> + if (s->no_sync_literal == 0) {
>> + s->state = sw_literal_argument;
>> + return NGX_SIEVE_NEXT;
>> + }
>> + state = sw_literal_argument;
>> + s->no_sync_literal = 0;
>> + break;
>> + default:
>> + goto invalid;
>> + }
>> + break;
>> +
>> + case sw_literal_argument:
>> + if (s->literal_len && --s->literal_len) {
>> + break;
>> + }
>> +
>> + arg = ngx_array_push(&s->args);
>> + if (arg == NULL) {
>> + return NGX_ERROR;
>> + }
>> + arg->len = p + 1 - s->arg_start;
>> + arg->data = s->arg_start;
>> + s->arg_start = NULL;
>> + state = sw_end_literal_argument;
>> +
>> + break;
>> +
>> + case sw_end_literal_argument:
>> + switch (ch) {
>> + case '{':
>> + if (s->args.nelts <= 2) {
>> + state = sw_literal;
>> + break;
>> + }
>> + goto invalid;
>> + case CR:
>> + state = sw_almost_done;
>> + break;
>> + case LF:
>> + goto done;
>> + default:
>> + state = sw_spaces_before_argument;
>> + break;
>> + }
>> + break;
>> +
>> + case sw_almost_done:
>> + switch (ch) {
>> + case LF:
>> + goto done;
>> + default:
>> + goto invalid;
>> + }
>> + }
>> + }
>> +
>> + s->buffer->pos = p;
>> + s->state = state;
>> +
>> + return NGX_AGAIN;
>> +
>> +done:
>> +
>> + s->buffer->pos = p + 1;
>> +
>> + if (s->arg_start) {
>> + arg = ngx_array_push(&s->args);
>> + if (arg == NULL) {
>> + return NGX_ERROR;
>> + }
>> + arg->len = s->arg_end - s->arg_start;
>> + arg->data = s->arg_start;
>> +
>> + s->arg_start = NULL;
>> + s->cmd_start = NULL;
>> + s->quoted = 0;
>> + s->no_sync_literal = 0;
>> + s->literal_len = 0;
>> + }
>> +
>> + s->state = (s->command != NGX_SIEVE_AUTHENTICATE) ? sw_start : 
>> sw_spaces_before_argument;
>> +
>> + return NGX_OK;
>> +
>> +invalid:
>> +
>> + s->state = sw_start;
>> + s->quoted = 0;
>> + s->no_sync_literal = 0;
>> + s->literal_len = 0;
>> +
>> + return NGX_MAIL_PARSE_INVALID_COMMAND;
>> +}
>> +
>> +
>> +ngx_int_t
>> ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
>> {
>> u_char ch, *p, *c, c0, c1, c2, c3;
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_pop3_handler.c
>> --- a/src/mail/ngx_mail_pop3_handler.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_pop3_handler.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -492,7 +492,7 @@
>> return NGX_MAIL_PARSE_INVALID_COMMAND;
>> }
>> - if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
>> + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2, 0) == NGX_OK) {
>> s->mail_state = ngx_pop3_auth_cram_md5;
>> return NGX_OK;
>> }
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_proxy_module.c
>> --- a/src/mail/ngx_mail_proxy_module.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_proxy_module.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -24,6 +24,7 @@
>> static void ngx_mail_proxy_block_read(ngx_event_t *rev);
>> static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev);
>> static void ngx_mail_proxy_imap_handler(ngx_event_t *rev);
>> +static void ngx_mail_proxy_sieve_handler(ngx_event_t *rev);
>> static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev);
>> static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev);
>> static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s,
>> @@ -173,6 +174,11 @@
>> s->mail_state = ngx_imap_start;
>> break;
>> + case NGX_MAIL_SIEVE_PROTOCOL:
>> + p->upstream.connection->read->handler = ngx_mail_proxy_sieve_handler;
>> + s->mail_state = ngx_sieve_start;
>> + break;
>> +
>> default: /* NGX_MAIL_SMTP_PROTOCOL */
>> p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler;
>> s->mail_state = ngx_smtp_start;
>> @@ -446,6 +452,144 @@
>> static void
>> +ngx_mail_proxy_sieve_handler(ngx_event_t *rev)
>> +{
>> + u_char *p;
>> + ngx_int_t rc;
>> + ngx_str_t line;
>> + ngx_str_t userpass;
>> + ngx_str_t b64_userpass;
>> + ngx_connection_t *c;
>> + ngx_mail_session_t *s;
>> + ngx_mail_proxy_conf_t *pcf;
>> +
>> + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
>> + "mail proxy sieve auth handler");
>> +
>> + c = rev->data;
>> + s = c->data;
>> +
>> + if (rev->timedout) {
>> + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
>> + "upstream timed out");
>> + c->timedout = 1;
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> +
>> + rc = ngx_mail_proxy_read_response(s, s->mail_state);
>> +
>> + if (rc == NGX_AGAIN) {
>> + return;
>> + }
>> +
>> + if (rc == NGX_ERROR) {
>> + ngx_mail_proxy_upstream_error(s);
>> + return;
>> + }
>> +
>> + switch (s->mail_state) {
>> +
>> + case ngx_sieve_start:
>> + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
>> + "mail proxy send login");
>> +
>> + s->connection->log->action = "sending LOGIN command to upstream";
>> +
>> + line.len = s->tag.len + sizeof("AUTHENTICATE ") - 1
>> + + 1 + NGX_SIZE_T_LEN + 1 + 2;
>> + line.data = ngx_pnalloc(c->pool, line.len);
>> + if (line.data == NULL) {
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> +
>> + userpass.len = s->login.len + s->passwd.len + 2;
>> + userpass.data = ngx_pnalloc(c->pool, userpass.len);
>> + if (userpass.data == NULL) {
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> + b64_userpass.len = ngx_base64_encoded_length(userpass.len) + 2;
>> + b64_userpass.data = ngx_pnalloc(c->pool, b64_userpass.len);
>> + if (b64_userpass.data == NULL) {
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> +
>> + p = userpass.data;
>> + *p++ = '\0';
>> + p = ngx_cpymem(p, s->login.data, s->login.len);
>> + *p++ = '\0';
>> + p = ngx_cpymem(p, s->passwd.data, s->passwd.len);
>> +
>> + ngx_encode_base64(&b64_userpass, &userpass);
>> + line.len = ngx_sprintf(line.data, "AUTHENTICATE \"PLAIN\" \"%V\"" 
>> CRLF,
>> + &b64_userpass)
>> + - line.data;
>> +
>> + s->mail_state = ngx_sieve_login;
>> + break;
>> +
>> + case ngx_sieve_login:
>> + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
>> + "mail proxy send capabilities");
>> +
>> + s->connection->log->action = "sending CAPABILITY command to upstream";
>> +
>> + line.len = s->tag.len + sizeof("AUTHENTICATE ") - 1
>> + + 1 + NGX_SIZE_T_LEN + 1 + 2;
>> + line.data = ngx_pnalloc(c->pool, line.len);
>> + if (line.data == NULL) {
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> +
>> + line.len = ngx_sprintf(line.data, "CAPABILITY" CRLF)
>> + - line.data;
>> +
>> + s->mail_state = ngx_sieve_login_capabilities;
>> + break;
>> +
>> + case ngx_sieve_login_capabilities:
>> + s->connection->read->handler = ngx_mail_proxy_handler;
>> + s->connection->write->handler = ngx_mail_proxy_handler;
>> + rev->handler = ngx_mail_proxy_handler;
>> + c->write->handler = ngx_mail_proxy_handler;
>> +
>> + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
>> + ngx_add_timer(s->connection->read, pcf->timeout);
>> + ngx_del_timer(c->read);
>> +
>> + c->log->action = NULL;
>> + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
>> +
>> + ngx_mail_proxy_handler(s->connection->write);
>> +
>> + return;
>> +
>> + default:
>> +#if (NGX_SUPPRESS_WARN)
>> + ngx_str_null(&line);
>> +#endif
>> + break;
>> + }
>> +
>> + if (c->send(c, line.data, line.len) < (ssize_t) line.len) {
>> + /*
>> + * we treat the incomplete sending as NGX_ERROR
>> + * because it is very strange here
>> + */
>> + ngx_mail_proxy_internal_server_error(s);
>> + return;
>> + }
>> +
>> + s->proxy->buffer->pos = s->proxy->buffer->start;
>> + s->proxy->buffer->last = s->proxy->buffer->start;
>> +}
>> +
>> +
>> +static void
>> ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
>> {
>> u_char *p;
>> @@ -793,6 +937,42 @@
>> break;
>> + case NGX_MAIL_SIEVE_PROTOCOL:
>> + if (p[0] == '"') {
>> + m = b->last - (sizeof(CRLF "OK" CRLF) - 1);
>> +
>> + while (m > p) {
>> + if (m[0] == CR && m[1] == LF) {
>> + break;
>> + }
>> + m--;
>> + }
>> +
>> + if (m <= p || m[0] == '"') {
>> + return NGX_AGAIN;
>> + }
>> + p = m + 2;
>> + }
>> +
>> + switch (state) {
>> +
>> + case ngx_sieve_start:
>> + case ngx_sieve_login:
>> + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "1 upstream 
>> sent: \"%s\"", p);
>> + if (p[0] == 'O' && p[1] == 'K') {
>> + return NGX_OK;
>> + }
>> + break;
>> + case ngx_sieve_login_capabilities:
>> + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "2 upstream 
>> sent: \"%s\"", p);
>> + if (p[0] == 'O' && p[1] == 'K') {
>> + return NGX_OK;
>> + }
>> + break;
>> + }
>> +
>> + break;
>> +
>> default: /* NGX_MAIL_SMTP_PROTOCOL */
>> if (p[3] == '-') {
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/mail/ngx_mail_smtp_handler.c
>> --- a/src/mail/ngx_mail_smtp_handler.c Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/mail/ngx_mail_smtp_handler.c Wed Apr 08 20:17:11 2020 +0200
>> @@ -693,7 +693,7 @@
>> }
>> }
>> - if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) {
>> + if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4, 0) == NGX_OK) {
>> s->mail_state = ngx_smtp_auth_cram_md5;
>> return NGX_OK;
>> }
>> diff -r 0cb942c1c1aa -r f1dffaf61968 src/misc/ngx_cpp_test_module.cpp
>> --- a/src/misc/ngx_cpp_test_module.cpp Fri Mar 13 02:12:10 2020 +0300
>> +++ b/src/misc/ngx_cpp_test_module.cpp Wed Apr 08 20:17:11 2020 +0200
>> @@ -13,6 +13,7 @@
>> #include <ngx_mail.h>
>> #include <ngx_mail_pop3_module.h>
>> #include <ngx_mail_imap_module.h>
>> + #include <ngx_mail_sieve_module.h>
>> #include <ngx_mail_smtp_module.h>
>> }
>>
>>
>> _______________________________________________
>> nginx-devel mailing list
>> nginx-devel at nginx.org
>> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>


More information about the nginx-devel mailing list