changeset 1479:2647950e047f

optimizations
author Igor Sysoev <igor@sysoev.ru>
date Thu, 13 Sep 2007 21:24:27 +0000
parents d0cce8369848
children a231e37a19ab
files src/mail/ngx_mail.h src/mail/ngx_mail_handler.c src/mail/ngx_mail_imap_handler.c src/mail/ngx_mail_parse.c src/mail/ngx_mail_pop3_handler.c src/mail/ngx_mail_smtp_handler.c
diffstat 6 files changed, 187 insertions(+), 219 deletions(-) [+]
line wrap: on
line diff
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -313,6 +313,7 @@ typedef ngx_int_t (*ngx_mail_parse_comma
 
 #if (NGX_MAIL_SSL)
 void ngx_mail_starttls_handler(ngx_event_t *rev);
+ngx_int_t ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c);
 #endif
 
 
@@ -330,6 +331,8 @@ ngx_int_t ngx_mail_auth_login_username(n
     ngx_connection_t *c);
 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_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c);
 
 void ngx_mail_send(ngx_event_t *wev);
@@ -351,6 +354,7 @@ void ngx_mail_smtp_init_protocol(ngx_eve
 ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s);
 ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s);
 ngx_int_t ngx_mail_smtp_parse_command(ngx_mail_session_t *s);
+ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c);
 
 
 /* STUB */
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -285,6 +285,29 @@ ngx_mail_salt(ngx_mail_session_t *s, ngx
 }
 
 
+#if (NGX_MAIL_SSL)
+
+ngx_int_t
+ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c)
+{
+    ngx_mail_ssl_conf_t  *sslcf;
+
+    if (c->ssl) {
+        return 0;
+    }
+
+    sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+    if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
+        return 1;
+    }
+
+    return 0;
+}
+
+#endif
+
+
 ngx_int_t
 ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
 {
@@ -405,6 +428,35 @@ ngx_mail_auth_login_password(ngx_mail_se
 
 
 ngx_int_t
+ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c,
+    char *prefix, size_t len)
+{
+    u_char      *p;
+    ngx_str_t    salt;
+    ngx_uint_t   n;
+
+    p = ngx_palloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2);
+    if (p == NULL) {
+        return NGX_ERROR;
+    }
+
+    salt.data = ngx_cpymem(p, prefix, len);
+    s->salt.len -= 2;
+
+    ngx_encode_base64(&salt, &s->salt);
+
+    s->salt.len += 2;
+    n = len + salt.len;
+    p[n++] = CR; p[n++] = LF;
+
+    s->out.len = n;
+    s->out.data = p;
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     u_char     *p, *last;
--- a/src/mail/ngx_mail_imap_handler.c
+++ b/src/mail/ngx_mail_imap_handler.c
@@ -177,11 +177,7 @@ ngx_mail_imap_auth_state(ngx_event_t *re
 
             case NGX_IMAP_AUTHENTICATE:
                 rc = ngx_mail_imap_authenticate(s, c);
-
-                if (rc == NGX_OK) {
-                    tag = 0;
-                }
-
+                tag = (rc != NGX_OK);
                 break;
 
             case NGX_IMAP_CAPABILITY:
@@ -307,15 +303,10 @@ static ngx_int_t
 ngx_mail_imap_login(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     ngx_str_t            *arg;
+
 #if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t  *sslcf;
-
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
 #endif
 
@@ -357,53 +348,36 @@ ngx_mail_imap_login(ngx_mail_session_t *
 static ngx_int_t
 ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    u_char                    *p;
-    ngx_str_t                 *arg, salt;
-    ngx_uint_t                 n;
+    ngx_int_t                  rc;
     ngx_mail_core_srv_conf_t  *cscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
 
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+#if (NGX_MAIL_SSL)
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
 #endif
 
-    if (s->args.nelts != 1) {
-        return NGX_MAIL_PARSE_INVALID_COMMAND;
-    }
+    rc = ngx_mail_auth_parse(s, c);
 
-    arg = s->args.elts;
-
-    if (arg[0].len == 5) {
+    switch (rc) {
 
-        if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
+    case NGX_MAIL_AUTH_LOGIN:
 
-            s->out.len = sizeof(imap_username) - 1;
-            s->out.data = imap_username;
-            s->mail_state = ngx_imap_auth_login_username;
-
-            return NGX_OK;
+        s->out.len = sizeof(imap_username) - 1;
+        s->out.data = imap_username;
+        s->mail_state = ngx_imap_auth_login_username;
 
-        } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
+        return NGX_OK;
 
-            s->out.len = sizeof(imap_plain_next) - 1;
-            s->out.data = imap_plain_next;
-            s->mail_state = ngx_imap_auth_plain;
+    case NGX_MAIL_AUTH_PLAIN:
 
-            return NGX_OK;
-        }
+        s->out.len = sizeof(imap_plain_next) - 1;
+        s->out.data = imap_plain_next;
+        s->mail_state = ngx_imap_auth_plain;
 
-    } else if (arg[0].len == 8
-               && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0)
-    {
-        if (s->args.nelts != 1) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+        return NGX_OK;
+
+    case NGX_MAIL_AUTH_CRAM_MD5:
 
         cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
 
@@ -411,31 +385,15 @@ ngx_mail_imap_authenticate(ngx_mail_sess
             return NGX_MAIL_PARSE_INVALID_COMMAND;
         }
 
-        p = ngx_palloc(c->pool,
-                       sizeof("+ " CRLF) - 1
-                       + ngx_base64_encoded_length(s->salt.len));
-        if (p == NULL) {
-            return NGX_ERROR;
+        if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
+            s->mail_state = ngx_imap_auth_cram_md5;
+            return NGX_OK;
         }
 
-        p[0] = '+'; p[1]= ' ';
-        salt.data = &p[2];
-        s->salt.len -= 2;
-
-        ngx_encode_base64(&salt, &s->salt);
-
-        s->salt.len += 2;
-        n = 2 + salt.len;
-        p[n++] = CR; p[n++] = LF;
-
-        s->out.len = n;
-        s->out.data = p;
-        s->mail_state = ngx_imap_auth_cram_md5;
-
-        return NGX_OK;
+        return NGX_ERROR;
     }
 
-    return NGX_MAIL_PARSE_INVALID_COMMAND;
+    return rc;
 }
 
 
--- a/src/mail/ngx_mail_parse.c
+++ b/src/mail/ngx_mail_parse.c
@@ -825,3 +825,56 @@ invalid:
 
     return NGX_MAIL_PARSE_INVALID_COMMAND;
 }
+
+
+ngx_int_t
+ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c)
+{
+    ngx_str_t                 *arg;
+
+#if (NGX_MAIL_SSL)
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
+    }
+#endif
+
+    arg = s->args.elts;
+
+    if (arg[0].len == 5) {
+
+        if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
+
+            if (s->args.nelts == 1) {
+                return NGX_MAIL_AUTH_LOGIN;
+            }
+
+            return NGX_MAIL_PARSE_INVALID_COMMAND;
+        }
+
+        if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
+
+            if (s->args.nelts == 1) {
+                return NGX_MAIL_AUTH_PLAIN;
+            }
+
+            if (s->args.nelts == 2) {
+                return ngx_mail_auth_plain(s, c, 1);
+            }
+        }
+
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
+    }
+
+    if (arg[0].len == 8) {
+
+        if (s->args.nelts != 1) {
+            return NGX_MAIL_PARSE_INVALID_COMMAND;
+        }
+
+        if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) {
+            return NGX_MAIL_AUTH_CRAM_MD5;
+        }
+    }
+
+    return NGX_MAIL_PARSE_INVALID_COMMAND;
+}
--- a/src/mail/ngx_mail_pop3_handler.c
+++ b/src/mail/ngx_mail_pop3_handler.c
@@ -275,17 +275,11 @@ static ngx_int_t
 ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     ngx_str_t            *arg;
+
 #if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t  *sslcf;
-
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
-
 #endif
 
     if (s->args.nelts != 1) {
@@ -395,17 +389,11 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s
 {
     ngx_str_t                 *arg;
     ngx_mail_core_srv_conf_t  *cscf;
+
 #if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
-
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
-
 #endif
 
     if (s->args.nelts != 2) {
@@ -448,21 +436,13 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s
 static ngx_int_t
 ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    size_t                     n;
-    u_char                    *p;
-    ngx_str_t                 *arg, salt;
+    ngx_int_t                  rc;
     ngx_mail_core_srv_conf_t  *cscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
 
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+#if (NGX_MAIL_SSL)
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
-
 #endif
 
     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
@@ -474,80 +454,39 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s
         return NGX_OK;
     }
 
-    arg = s->args.elts;
-
-    if (arg[0].len == 5) {
+    rc = ngx_mail_auth_parse(s, c);
 
-        if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
-
-            if (s->args.nelts != 1) {
-                return NGX_MAIL_PARSE_INVALID_COMMAND;
-            }
+    switch (rc) {
 
-            s->out.len = sizeof(pop3_username) - 1;
-            s->out.data = pop3_username;
-            s->mail_state = ngx_pop3_auth_login_username;
+    case NGX_MAIL_AUTH_LOGIN:
 
-            return NGX_OK;
-
-        } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
-
-            if (s->args.nelts == 1) {
+        s->out.len = sizeof(pop3_username) - 1;
+        s->out.data = pop3_username;
+        s->mail_state = ngx_pop3_auth_login_username;
 
-                s->out.len = sizeof(pop3_next) - 1;
-                s->out.data = pop3_next;
-                s->mail_state = ngx_pop3_auth_plain;
+        return NGX_OK;
 
-                return NGX_OK;
-            }
-
-            if (s->args.nelts == 2) {
+    case NGX_MAIL_AUTH_PLAIN:
 
-                /*
-                 * workaround for Eudora for Mac: it sends
-                 *    AUTH PLAIN [base64 encoded]
-                 */
-
-                return ngx_mail_auth_plain(s, c, 1);
-            }
+        s->out.len = sizeof(pop3_next) - 1;
+        s->out.data = pop3_next;
+        s->mail_state = ngx_pop3_auth_plain;
 
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+        return NGX_OK;
 
-    } else if (arg[0].len == 8
-               && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0)
-    {
-        if (s->args.nelts != 1) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+    case NGX_MAIL_AUTH_CRAM_MD5:
 
         if (!(cscf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) {
             return NGX_MAIL_PARSE_INVALID_COMMAND;
         }
 
-        p = ngx_palloc(c->pool,
-                       sizeof("+ " CRLF) - 1
-                       + ngx_base64_encoded_length(s->salt.len));
-        if (p == NULL) {
-            return NGX_ERROR;
+        if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
+            s->mail_state = ngx_pop3_auth_cram_md5;
+            return NGX_OK;
         }
 
-        p[0] = '+'; p[1]= ' ';
-        salt.data = &p[2];
-        s->salt.len -= 2;
-
-        ngx_encode_base64(&salt, &s->salt);
-
-        s->salt.len += 2;
-        n = 2 + salt.len;
-        p[n++] = CR; p[n++] = LF;
-
-        s->out.len = n;
-        s->out.data = p;
-        s->mail_state = ngx_pop3_auth_cram_md5;
-
-        return NGX_OK;
+        return NGX_ERROR;
     }
 
-    return NGX_MAIL_PARSE_INVALID_COMMAND;
+    return rc;
 }
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -284,21 +284,13 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 static ngx_int_t
 ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    u_char                    *p;
-    ngx_str_t                 *arg, salt;
-    ngx_uint_t                 n;
+    ngx_int_t                  rc;
     ngx_mail_core_srv_conf_t  *cscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
 
-    if (c->ssl == NULL) {
-        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
-
-        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+#if (NGX_MAIL_SSL)
+    if (ngx_mail_starttls_only(s, c)) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
     }
-
 #endif
 
     if (s->args.nelts == 0) {
@@ -308,41 +300,27 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s
         return NGX_OK;
     }
 
-    if (s->args.nelts != 1) {
-        return NGX_MAIL_PARSE_INVALID_COMMAND;
-    }
+    rc = ngx_mail_auth_parse(s, c);
 
-    arg = s->args.elts;
-
-    if (arg[0].len == 5) {
+    switch (rc) {
 
-        if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
+    case NGX_MAIL_AUTH_LOGIN:
 
-            if (s->args.nelts != 1) {
-                return NGX_MAIL_PARSE_INVALID_COMMAND;
-            }
-
-            s->out.len = sizeof(smtp_username) - 1;
-            s->out.data = smtp_username;
-            s->mail_state = ngx_smtp_auth_login_username;
+        s->out.len = sizeof(smtp_username) - 1;
+        s->out.data = smtp_username;
+        s->mail_state = ngx_smtp_auth_login_username;
 
-            return NGX_OK;
-
-        } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
+        return NGX_OK;
 
-            s->out.len = sizeof(smtp_next) - 1;
-            s->out.data = smtp_next;
-            s->mail_state = ngx_smtp_auth_plain;
+    case NGX_MAIL_AUTH_PLAIN:
 
-            return NGX_OK;
-        }
+        s->out.len = sizeof(smtp_next) - 1;
+        s->out.data = smtp_next;
+        s->mail_state = ngx_smtp_auth_plain;
 
-    } else if (arg[0].len == 8
-               && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0)
-    {
-        if (s->args.nelts != 1) {
-            return NGX_MAIL_PARSE_INVALID_COMMAND;
-        }
+        return NGX_OK;
+
+    case NGX_MAIL_AUTH_CRAM_MD5:
 
         cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
 
@@ -350,31 +328,15 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s
             return NGX_MAIL_PARSE_INVALID_COMMAND;
         }
 
-        p = ngx_palloc(c->pool,
-                       sizeof("334 " CRLF) - 1
-                       + ngx_base64_encoded_length(s->salt.len));
-        if (p == NULL) {
-            return NGX_ERROR;
+        if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) {
+            s->mail_state = ngx_smtp_auth_cram_md5;
+            return NGX_OK;
         }
 
-        p[0] = '3'; p[1]= '3'; p[2] = '4'; p[3]= ' ';
-        salt.data = &p[4];
-        s->salt.len -= 2;
-
-        ngx_encode_base64(&salt, &s->salt);
-
-        s->salt.len += 2;
-        n = 4 + salt.len;
-        p[n++] = CR; p[n++] = LF;
-
-        s->out.len = n;
-        s->out.data = p;
-        s->mail_state = ngx_smtp_auth_cram_md5;
-
-        return NGX_OK;
+        return NGX_ERROR;
     }
 
-    return NGX_MAIL_PARSE_INVALID_COMMAND;
+    return rc;
 }