diff src/mail/ngx_mail_smtp_handler.c @ 410:cd9cb7a3ff9e

Merge with nginx 0.7.8.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 11 Aug 2008 22:07:06 +0400
parents 52b28d322d76 984bb0b1399b
children e2df123bbbe2
line wrap: on
line diff
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -11,6 +11,9 @@
 #include <ngx_mail_smtp_module.h>
 
 
+static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
     ngx_connection_t *c);
@@ -31,6 +34,7 @@ static void ngx_mail_smtp_log_rejected_c
 
 static u_char  smtp_ok[] = "250 2.0.0 OK" CRLF;
 static u_char  smtp_bye[] = "221 2.0.0 Bye" CRLF;
+static u_char  smtp_starttls[] = "220 2.0.0 Start TLS" CRLF;
 static u_char  smtp_next[] = "334 " CRLF;
 static u_char  smtp_username[] = "334 VXNlcm5hbWU6" CRLF;
 static u_char  smtp_password[] = "334 UGFzc3dvcmQ6" CRLF;
@@ -42,13 +46,182 @@ static u_char  smtp_auth_required[] = "5
 static u_char  smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF;
 
 
+static ngx_str_t  smtp_unavailable = ngx_string("[UNAVAILABLE]");
+static ngx_str_t  smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
+
+
 void
 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
 {
+    struct sockaddr_in        *sin;
+    ngx_resolver_ctx_t        *ctx;
+    ngx_mail_core_srv_conf_t  *cscf;
+
+    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+    if (cscf->resolver == NULL) {
+        s->host = smtp_unavailable;
+        ngx_mail_smtp_greeting(s, c);
+        return;
+    }
+
+    c->log->action = "in resolving client address";
+
+    ctx = ngx_resolve_start(cscf->resolver, NULL);
+    if (ctx == NULL) {
+        ngx_mail_close_connection(c);
+        return;
+    }
+
+    /* AF_INET only */
+
+    sin = (struct sockaddr_in *) c->sockaddr;
+
+    ctx->addr = sin->sin_addr.s_addr;
+    ctx->handler = ngx_mail_smtp_resolve_addr_handler;
+    ctx->data = s;
+    ctx->timeout = cscf->resolver_timeout;
+
+    if (ngx_resolve_addr(ctx) != NGX_OK) {
+        ngx_mail_close_connection(c);
+    }
+}
+
+
+static void
+ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
+{
+    ngx_connection_t          *c;
+    ngx_mail_session_t        *s;
+    ngx_mail_core_srv_conf_t  *cscf;
+
+    s = ctx->data;
+    c = s->connection;
+
+    if (ctx->state) {
+        ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                      "%V could not be resolved (%i: %s)",
+                      &c->addr_text, ctx->state,
+                      ngx_resolver_strerror(ctx->state));
+
+        if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
+            s->host = smtp_unavailable;
+
+        } else {
+            s->host = smtp_tempunavail;
+        }
+
+        ngx_resolve_addr_done(ctx);
+
+        ngx_mail_smtp_greeting(s, s->connection);
+
+        return;
+    }
+
+    c->log->action = "in resolving client hostname";
+
+    s->host.data = ngx_pstrdup(c->pool, &ctx->name);
+    if (s->host.data == NULL) {
+        ngx_resolve_addr_done(ctx);
+        ngx_mail_close_connection(c);
+        return;
+    }
+
+    s->host.len = ctx->name.len;
+
+    ngx_resolve_addr_done(ctx);
+
+    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                   "address resolved: %V", &s->host);
+
+    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+    ctx = ngx_resolve_start(cscf->resolver, NULL);
+    if (ctx == NULL) {
+        ngx_mail_close_connection(c);
+        return;
+    }
+
+    ctx->name = s->host;
+    ctx->type = NGX_RESOLVE_A;
+    ctx->handler = ngx_mail_smtp_resolve_name_handler;
+    ctx->data = s;
+    ctx->timeout = cscf->resolver_timeout;
+
+    if (ngx_resolve_name(ctx) != NGX_OK) {
+        ngx_mail_close_connection(c);
+    }
+}
+
+
+static void
+ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
+{
+    in_addr_t            addr;
+    ngx_uint_t           i;
+    ngx_connection_t    *c;
+    struct sockaddr_in  *sin;
+    ngx_mail_session_t  *s;
+
+    s = ctx->data;
+    c = s->connection;
+
+    if (ctx->state) {
+        ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                      "%V could not be resolved (%i: %s)",
+                      &ctx->name, ctx->state,
+                      ngx_resolver_strerror(ctx->state));
+
+        if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
+            s->host = smtp_unavailable;
+
+        } else {
+            s->host = smtp_tempunavail;
+        }
+
+    } else {
+
+        /* AF_INET only */
+
+        sin = (struct sockaddr_in *) c->sockaddr;
+
+        for (i = 0; i < ctx->naddrs; i++) {
+
+            addr = ctx->addrs[i];
+
+            ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                           "name was resolved to %ud.%ud.%ud.%ud",
+                           (ntohl(addr) >> 24) & 0xff,
+                           (ntohl(addr) >> 16) & 0xff,
+                           (ntohl(addr) >> 8) & 0xff,
+                           ntohl(addr) & 0xff);
+
+            if (addr == sin->sin_addr.s_addr) {
+                goto found;
+            }
+        }
+
+        s->host = smtp_unavailable;
+    }
+
+found:
+
+    ngx_resolve_name_done(ctx);
+
+    ngx_mail_smtp_greeting(s, c);
+}
+
+
+static void
+ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
+{
     ngx_msec_t                 timeout;
     ngx_mail_core_srv_conf_t  *cscf;
     ngx_mail_smtp_srv_conf_t  *sscf;
 
+    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                   "smtp greeting for \"%V\"", &s->host);
+
     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
 
@@ -260,6 +433,8 @@ ngx_mail_smtp_auth_state(ngx_event_t *re
 
             case NGX_SMTP_STARTTLS:
                 rc = ngx_mail_smtp_starttls(s, c);
+                s->out.len = sizeof(smtp_starttls) - 1;
+                s->out.data = smtp_starttls;
                 break;
 
             default:
@@ -329,9 +504,6 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 {
     ngx_str_t                 *arg;
     ngx_mail_smtp_srv_conf_t  *sscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
-#endif
 
     if (s->args.nelts != 1) {
         s->out.len = sizeof(smtp_invalid_argument) - 1;
@@ -344,7 +516,7 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 
     s->smtp_helo.len = arg[0].len;
 
-    s->smtp_helo.data = ngx_palloc(c->pool, arg[0].len);
+    s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len);
     if (s->smtp_helo.data == NULL) {
         return NGX_ERROR;
     }
@@ -367,6 +539,8 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 #if (NGX_MAIL_SSL)
 
         if (c->ssl == NULL) {
+            ngx_mail_ssl_conf_t  *sslcf;
+
             sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
 
             if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {