IMAP AUTHENTICATE
patch by Maxim Dounin
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
index 080e0e3..a00f306 100644
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -100,6 +100,7 @@
ngx_str_t smtp_greeting;
ngx_uint_t pop3_auth_methods;
+ ngx_uint_t imap_auth_methods;
ngx_uint_t smtp_auth_methods;
ngx_array_t pop3_capabilities;
@@ -134,6 +135,10 @@
typedef enum {
ngx_imap_start = 0,
+ ngx_imap_auth_login_username,
+ ngx_imap_auth_login_password,
+ ngx_imap_auth_plain,
+ ngx_imap_auth_cram_md5,
ngx_imap_login,
ngx_imap_user,
ngx_imap_passwd
@@ -216,45 +221,47 @@
} ngx_mail_log_ctx_t;
-#define NGX_POP3_USER 1
-#define NGX_POP3_PASS 2
-#define NGX_POP3_CAPA 3
-#define NGX_POP3_QUIT 4
-#define NGX_POP3_NOOP 5
-#define NGX_POP3_STLS 6
-#define NGX_POP3_APOP 7
-#define NGX_POP3_AUTH 8
-#define NGX_POP3_STAT 9
-#define NGX_POP3_LIST 10
-#define NGX_POP3_RETR 11
-#define NGX_POP3_DELE 12
-#define NGX_POP3_RSET 13
-#define NGX_POP3_TOP 14
-#define NGX_POP3_UIDL 15
+#define NGX_POP3_USER 1
+#define NGX_POP3_PASS 2
+#define NGX_POP3_CAPA 3
+#define NGX_POP3_QUIT 4
+#define NGX_POP3_NOOP 5
+#define NGX_POP3_STLS 6
+#define NGX_POP3_APOP 7
+#define NGX_POP3_AUTH 8
+#define NGX_POP3_STAT 9
+#define NGX_POP3_LIST 10
+#define NGX_POP3_RETR 11
+#define NGX_POP3_DELE 12
+#define NGX_POP3_RSET 13
+#define NGX_POP3_TOP 14
+#define NGX_POP3_UIDL 15
-#define NGX_IMAP_LOGIN 1
-#define NGX_IMAP_LOGOUT 2
-#define NGX_IMAP_CAPABILITY 3
-#define NGX_IMAP_NOOP 4
-#define NGX_IMAP_STARTTLS 5
+#define NGX_IMAP_LOGIN 1
+#define NGX_IMAP_LOGOUT 2
+#define NGX_IMAP_CAPABILITY 3
+#define NGX_IMAP_NOOP 4
+#define NGX_IMAP_STARTTLS 5
-#define NGX_IMAP_NEXT 6
+#define NGX_IMAP_NEXT 6
+
+#define NGX_IMAP_AUTHENTICATE 7
-#define NGX_SMTP_HELO 1
-#define NGX_SMTP_EHLO 2
-#define NGX_SMTP_AUTH 3
-#define NGX_SMTP_QUIT 4
-#define NGX_SMTP_NOOP 5
-#define NGX_SMTP_MAIL 6
-#define NGX_SMTP_RSET 7
-#define NGX_SMTP_RCPT 8
-#define NGX_SMTP_DATA 9
-#define NGX_SMTP_VRFY 10
-#define NGX_SMTP_EXPN 11
-#define NGX_SMTP_HELP 12
-#define NGX_SMTP_STARTTLS 13
+#define NGX_SMTP_HELO 1
+#define NGX_SMTP_EHLO 2
+#define NGX_SMTP_AUTH 3
+#define NGX_SMTP_QUIT 4
+#define NGX_SMTP_NOOP 5
+#define NGX_SMTP_MAIL 6
+#define NGX_SMTP_RSET 7
+#define NGX_SMTP_RCPT 8
+#define NGX_SMTP_DATA 9
+#define NGX_SMTP_VRFY 10
+#define NGX_SMTP_EXPN 11
+#define NGX_SMTP_HELP 12
+#define NGX_SMTP_STARTTLS 13
#define NGX_MAIL_AUTH_PLAIN 0
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index bf9e5c1..9b9e20f 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -54,6 +54,14 @@
};
+static ngx_conf_bitmask_t ngx_imap_auth_methods[] = {
+ { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
+ { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
+ { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED },
+ { ngx_null_string, 0 }
+};
+
+
static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = {
{ ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED },
{ ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED },
@@ -62,6 +70,14 @@
};
+static ngx_str_t ngx_imap_auth_methods_names[] = {
+ ngx_string("AUTH=PLAIN"),
+ ngx_string("AUTH=LOGIN"),
+ ngx_null_string, /* APOP */
+ ngx_string("AUTH=CRAM-MD5")
+};
+
+
static ngx_str_t ngx_smtp_auth_methods_names[] = {
ngx_string("PLAIN"),
ngx_string("LOGIN"),
@@ -172,6 +188,13 @@
offsetof(ngx_mail_core_srv_conf_t, pop3_auth_methods),
&ngx_pop3_auth_methods },
+ { ngx_string("imap_auth"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_core_srv_conf_t, imap_auth_methods),
+ &ngx_imap_auth_methods },
+
{ ngx_string("smtp_auth"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
ngx_conf_set_bitmask_slot,
@@ -297,6 +320,11 @@
(NGX_CONF_BITMASK_SET
|NGX_MAIL_AUTH_PLAIN_ENABLED));
+ ngx_conf_merge_bitmask_value(conf->imap_auth_methods,
+ prev->imap_auth_methods,
+ (NGX_CONF_BITMASK_SET
+ |NGX_MAIL_AUTH_PLAIN_ENABLED));
+
ngx_conf_merge_bitmask_value(conf->smtp_auth_methods,
prev->smtp_auth_methods,
(NGX_CONF_BITMASK_SET
@@ -463,6 +491,15 @@
size += 1 + c[i].len;
}
+ for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
+ m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
+ m <<= 1, i++)
+ {
+ if (m & conf->imap_auth_methods) {
+ size += 1 + ngx_imap_auth_methods_names[i].len;
+ }
+ }
+
p = ngx_palloc(cf->pool, size);
if (p == NULL) {
return NGX_CONF_ERROR;
@@ -478,6 +515,19 @@
p = ngx_cpymem(p, c[i].data, c[i].len);
}
+ auth = p;
+
+ for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0;
+ m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED;
+ m <<= 1, i++)
+ {
+ if (m & conf->imap_auth_methods) {
+ *p++ = ' ';
+ p = ngx_cpymem(p, ngx_imap_auth_methods_names[i].data,
+ ngx_imap_auth_methods_names[i].len);
+ }
+ }
+
*p++ = CR; *p = LF;
@@ -497,7 +547,8 @@
*p++ = CR; *p = LF;
- size += sizeof(" LOGINDISABLED") - 1;
+ size = (auth - conf->imap_capability.data) + sizeof(CRLF) - 1
+ + sizeof(" STARTTLS LOGINDISABLED") - 1;
p = ngx_palloc(cf->pool, size);
if (p == NULL) {
@@ -507,9 +558,10 @@
conf->imap_starttls_only_capability.len = size;
conf->imap_starttls_only_capability.data = p;
- p = ngx_cpymem(p, conf->imap_starttls_capability.data,
- conf->imap_starttls_capability.len - (sizeof(CRLF) - 1));
- p = ngx_cpymem(p, " LOGINDISABLED", sizeof(" LOGINDISABLED") - 1);
+ p = ngx_cpymem(p, conf->imap_capability.data,
+ auth - conf->imap_capability.data);
+ p = ngx_cpymem(p, " STARTTLS LOGINDISABLED",
+ sizeof(" STARTTLS LOGINDISABLED") - 1);
*p++ = CR; *p = LF;
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 0ae9c44..73bfbd2 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -280,6 +280,9 @@
&& (cscf->pop3_auth_methods
& (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED)))
+ || (s->protocol == NGX_MAIL_IMAP_PROTOCOL
+ && (cscf->imap_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED))
+
|| (s->protocol == NGX_MAIL_SMTP_PROTOCOL
&& (cscf->smtp_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)))
{
@@ -985,7 +988,7 @@
{
u_char *p, *last, *text, *dst, *src, *end;
ssize_t text_len, last_len;
- ngx_str_t *arg;
+ ngx_str_t *arg, salt;
ngx_int_t rc;
ngx_uint_t tag, i;
ngx_connection_t *c;
@@ -1055,113 +1058,342 @@
s->backslash = 0;
}
- switch (s->command) {
+ switch (s->mail_state) {
- case NGX_IMAP_LOGIN:
+ case ngx_imap_start:
+
+ switch (s->command) {
+
+ case NGX_IMAP_LOGIN:
#if (NGX_MAIL_SSL)
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+ }
+#endif
+
+ arg = s->args.elts;
+
+ if (s->args.nelts == 2 && arg[0].len) {
+
+ s->login.len = arg[0].len;
+ s->login.data = ngx_palloc(c->pool, s->login.len);
+ if (s->login.data == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ ngx_memcpy(s->login.data, arg[0].data, s->login.len);
+
+ s->passwd.len = arg[1].len;
+ s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
+ if (s->passwd.data == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
+
+#if (NGX_DEBUG_MAIL_PASSWD)
+ ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap login:\"%V\" passwd:\"%V\"",
+ &s->login, &s->passwd);
+#else
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap login:\"%V\"", &s->login);
+#endif
+
+ ngx_mail_do_auth(s);
+ return;
+ }
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+
+ case NGX_IMAP_AUTHENTICATE:
+
+#if (NGX_MAIL_SSL)
+
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+ }
+#endif
+
+ if (s->args.nelts != 1) {
rc = NGX_MAIL_PARSE_INVALID_COMMAND;
break;
}
- }
+
+ arg = s->args.elts;
+
+ if (arg[0].len == 5) {
+
+ if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5)
+ == 0)
+ {
+
+ s->mail_state = ngx_imap_auth_login_username;
+
+ last_len = sizeof(pop3_username) - 1;
+ last = pop3_username;
+ tag = 0;
+
+ break;
+
+ } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN",
+ 5)
+ == 0)
+ {
+
+ s->mail_state = ngx_imap_auth_plain;
+
+ last_len = sizeof(pop3_next) - 1;
+ last = pop3_next;
+ tag = 0;
+
+ break;
+ }
+
+ } else if (arg[0].len == 8
+ && ngx_strncasecmp(arg[0].data,
+ (u_char *) "CRAM-MD5", 8)
+ == 0)
+ {
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ if (!(cscf->imap_auth_methods
+ & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)
+ || s->args.nelts != 1)
+ {
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ s->mail_state = ngx_imap_auth_cram_md5;
+
+ last = ngx_palloc(c->pool,
+ sizeof("+ " CRLF) - 1
+ + ngx_base64_encoded_length(s->salt.len));
+ if (last == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ last[0] = '+'; last[1]= ' ';
+ salt.data = &last[2];
+ s->salt.len -= 2;
+
+ ngx_encode_base64(&salt, &s->salt);
+
+ s->salt.len += 2;
+ last_len = 2 + salt.len;
+ last[last_len++] = CR; last[last_len++] = LF;
+ tag = 0;
+
+ break;
+ }
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+
+ case NGX_IMAP_CAPABILITY:
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+#if (NGX_MAIL_SSL)
+
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
+ text_len = cscf->imap_starttls_capability.len;
+ text = cscf->imap_starttls_capability.data;
+ break;
+ }
+
+ if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+ text_len = cscf->imap_starttls_only_capability.len;
+ text = cscf->imap_starttls_only_capability.data;
+ break;
+ }
+ }
#endif
+ text_len = cscf->imap_capability.len;
+ text = cscf->imap_capability.data;
+ break;
+
+ case NGX_IMAP_LOGOUT:
+ s->quit = 1;
+ text = imap_bye;
+ text_len = sizeof(imap_bye) - 1;
+ break;
+
+ case NGX_IMAP_NOOP:
+ break;
+
+#if (NGX_MAIL_SSL)
+
+ case NGX_IMAP_STARTTLS:
+ if (c->ssl == NULL) {
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (sslcf->starttls) {
+ c->read->handler = ngx_mail_starttls_handler;
+ break;
+ }
+ }
+
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+#endif
+
+ default:
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ break;
+
+ case ngx_imap_auth_login_username:
+ arg = s->args.elts;
+ s->mail_state = ngx_imap_auth_login_password;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login username: \"%V\"", &arg[0]);
+
+ s->login.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->login.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH LOGIN command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login username: \"%V\"", &s->login);
+
+ last_len = sizeof(pop3_password) - 1;
+ last = pop3_password;
+ tag = 0;
+
+ break;
+
+ case ngx_imap_auth_login_password:
arg = s->args.elts;
- if (s->args.nelts == 2 && arg[0].len) {
-
- s->login.len = arg[0].len;
- s->login.data = ngx_palloc(c->pool, s->login.len);
- if (s->login.data == NULL) {
- ngx_mail_session_internal_server_error(s);
- return;
- }
-
- ngx_memcpy(s->login.data, arg[0].data, s->login.len);
-
- s->passwd.len = arg[1].len;
- s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
- if (s->passwd.data == NULL) {
- ngx_mail_session_internal_server_error(s);
- return;
- }
-
- ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
-
#if (NGX_DEBUG_MAIL_PASSWD)
- ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
- "imap login:\"%V\" passwd:\"%V\"",
- &s->login, &s->passwd);
-#else
- ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
- "imap login:\"%V\"", &s->login);
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login password: \"%V\"", &arg[0]);
#endif
+ s->passwd.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->passwd.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
+
+ if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH LOGIN command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+#if (NGX_DEBUG_MAIL_PASSWD)
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth login password: \"%V\"", &s->passwd);
+#endif
+
+ ngx_mail_do_auth(s);
+ return;
+
+ case ngx_imap_auth_plain:
+ arg = s->args.elts;
+
+ rc = ngx_mail_decode_auth_plain(s, &arg[0]);
+
+ if (rc == NGX_OK) {
ngx_mail_do_auth(s);
return;
}
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
- break;
-
- case NGX_IMAP_CAPABILITY:
- cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
-
-#if (NGX_MAIL_SSL)
-
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
- text_len = cscf->imap_starttls_capability.len;
- text = cscf->imap_starttls_capability.data;
- break;
- }
-
- if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
- text_len = cscf->imap_starttls_only_capability.len;
- text = cscf->imap_starttls_only_capability.data;
- break;
- }
+ if (rc == NGX_ERROR) {
+ ngx_mail_session_internal_server_error(s);
+ return;
}
-#endif
- text_len = cscf->imap_capability.len;
- text = cscf->imap_capability.data;
+ /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */
+
break;
- case NGX_IMAP_LOGOUT:
- s->quit = 1;
- text = imap_bye;
- text_len = sizeof(imap_bye) - 1;
- break;
+ case ngx_imap_auth_cram_md5:
+ arg = s->args.elts;
- case NGX_IMAP_NOOP:
- break;
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth cram-md5: \"%V\"", &arg[0]);
-#if (NGX_MAIL_SSL)
+ s->login.data = ngx_palloc(c->pool,
+ ngx_base64_decoded_length(arg[0].len));
+ if (s->login.data == NULL){
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
- case NGX_IMAP_STARTTLS:
- if (c->ssl == NULL) {
- sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
- if (sslcf->starttls) {
- c->read->handler = ngx_mail_starttls_handler;
+ if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid base64 encoding "
+ "in AUTH CRAM-MD5 command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
+
+ p = s->login.data;
+ last = p + s->login.len;
+
+ while (p < last) {
+ if (*p++ == ' ') {
+ s->login.len = p - s->login.data - 1;
+ s->passwd.len = last - p;
+ s->passwd.data = p;
break;
}
}
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
- break;
-#endif
+ if (s->passwd.len != 32) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent invalid CRAM-MD5 hash "
+ "in AUTH CRAM-MD5 command");
+ rc = NGX_MAIL_PARSE_INVALID_COMMAND;
+ break;
+ }
- default:
- rc = NGX_MAIL_PARSE_INVALID_COMMAND;
- break;
+ ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "imap auth cram-md5: \"%V\" \"%V\"",
+ &s->login, &s->passwd);
+
+ s->auth_method = NGX_MAIL_AUTH_CRAM_MD5;
+
+ ngx_mail_do_auth(s);
+ return;
}
} else if (rc == NGX_IMAP_NEXT) {
@@ -1171,6 +1403,8 @@
}
if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) {
+ s->mail_state = ngx_imap_start;
+ s->state = 0;
last = imap_invalid_command;
last_len = sizeof(imap_invalid_command) - 1;
}
@@ -1209,9 +1443,18 @@
if (rc != NGX_IMAP_NEXT) {
s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
- s->tag.len = 0;
+
+ if (s->state) {
+ /* preserve tag */
+ s->arg_start = s->buffer->start + s->tag.len;
+ s->buffer->pos = s->arg_start;
+ s->buffer->last = s->arg_start;
+
+ } else {
+ s->buffer->pos = s->buffer->start;
+ s->buffer->last = s->buffer->start;
+ s->tag.len = 0;
+ }
}
ngx_mail_send(c->write);
diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c
index 7c4a3b5..fa0fda3 100644
--- a/src/mail/ngx_mail_parse.c
+++ b/src/mail/ngx_mail_parse.c
@@ -354,6 +354,27 @@
}
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_IMAP_AUTHENTICATE;
+
+ } else {
+ goto invalid;
+ }
+ break;
+
default:
goto invalid;
}
@@ -573,7 +594,7 @@
s->literal_len = 0;
}
- s->state = sw_start;
+ s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
return NGX_OK;