コード例 #1
0
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);

    timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
    ngx_add_timer(c->read, timeout);

    if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
        ngx_mail_close_connection(c);
    }

    if (sscf->greeting_delay) {
        c->read->handler = ngx_mail_smtp_invalid_pipelining;
        return;
    }

    c->read->handler = ngx_mail_smtp_init_protocol;

    s->out = sscf->greeting;

    ngx_mail_send(c->write);
}
コード例 #2
0
void
ngx_mail_smtp_init_session(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;

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
    sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);

    timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
    ngx_add_timer(c->read, timeout);

    if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
        ngx_mail_close_connection(c);
    }

    if (sscf->greeting_delay) {
         c->read->handler = ngx_mail_smtp_invalid_pipelining;
         return;
    }

    c->read->handler = ngx_mail_smtp_init_protocol;

    s->out = sscf->greeting;

    ngx_mail_send(c->write);
}
コード例 #3
0
static void
ngx_mail_zmauth_wait_handler(ngx_event_t *ev) {
    ngx_connection_t *c;
    ngx_mail_session_t *s;
    ngx_mail_zmauth_ctx_t *ctx;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, ev->log, 0, "mail zmauth wait handler");

    c = ev->data;
    s = c->data;
    ctx = ngx_mail_get_module_ctx(s, ngx_mail_zmauth_module);

    if (ev->timedout) {
        /* we need to close the connection immediately */

        ngx_destroy_pool(ctx->pool);
        ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module);
        s->quit = 1;
        ngx_mail_send(c->write);

        return;
    }

    if (ev->active) {
        if (ngx_handle_read_event(ev, 0) != NGX_OK) {
            ngx_mail_close_connection(c);
        }
    }
}
コード例 #4
0
static void
ngx_mail_auth_sleep_handler(ngx_event_t *rev)
{
    ngx_connection_t          *c;
    ngx_mail_session_t        *s;
    ngx_mail_core_srv_conf_t  *cscf;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail auth sleep handler");

    c = rev->data;
    s = c->data;

    if (rev->timedout) {

        rev->timedout = 0;

        if (s->auth_wait) {
            s->auth_wait = 0;
            ngx_mail_auth_http_init(s);
            return;
        }

        cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

        rev->handler = cscf->protocol->auth_state;

        s->mail_state = 0;
        s->auth_method = NGX_MAIL_AUTH_PLAIN;

        c->log->action = "in auth state";

        ngx_mail_send(c->write);

        if (c->destroyed) {
            return;
        }

        ngx_add_timer(rev, cscf->timeout);

        if (rev->ready) {
            rev->handler(rev);
            return;
        }

        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
            ngx_mail_close_connection(c);
        }

        return;
    }

    if (rev->active) {
        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
            ngx_mail_close_connection(c);
        }
    }
}
コード例 #5
0
static void
ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev)
{
    ngx_connection_t          *c;
    ngx_mail_session_t        *s;
    ngx_mail_core_srv_conf_t  *cscf;
    ngx_mail_smtp_srv_conf_t  *sscf;

    c = rev->data;
    s = c->data;

    c->log->action = "in delay pipelining state";

    if (rev->timedout) {

        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting");

        rev->timedout = 0;

        cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

        c->read->handler = ngx_mail_smtp_init_protocol;

        ngx_add_timer(c->read, cscf->timeout);

        if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
            ngx_mail_close_connection(c);
            return;
        }

        sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);

        s->out = sscf->greeting;

    } else {

        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining");

        if (s->buffer == NULL) {
            if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
                return;
            }
        }

        if (ngx_mail_smtp_discard_command(s, c,
                                          "client was rejected before greeting: \"%V\"")
                != NGX_OK)
        {
            return;
        }

        s->out.len = sizeof(smtp_invalid_pipelining) - 1;
        s->out.data = smtp_invalid_pipelining;
    }

    ngx_mail_send(c->write);
}
コード例 #6
0
void
ngx_mail_session_internal_server_error(ngx_mail_session_t *s)
{
    ngx_mail_core_srv_conf_t  *cscf;

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    s->out = cscf->protocol->internal_server_error;
    s->quit = 1;

    ngx_mail_send(s->connection->write);
}
コード例 #7
0
void
ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
{
    u_char                    *p;
    ngx_mail_core_srv_conf_t  *cscf;
    ngx_mail_pop3_srv_conf_t  *pscf;

    pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    if (pscf->auth_methods
        & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED))
    {
        if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
            ngx_mail_session_internal_server_error(s);
            return;
        }

        s->out.data = ngx_pnalloc(c->pool, sizeof(pop3_greeting) + s->salt.len);
        if (s->out.data == NULL) {
            ngx_mail_session_internal_server_error(s);
            return;
        }

        p = ngx_cpymem(s->out.data, pop3_greeting, sizeof(pop3_greeting) - 3);
        *p++ = ' ';
        p = ngx_cpymem(p, s->salt.data, s->salt.len);

        s->out.len = p - s->out.data;

    } else {
        ngx_str_set(&s->out, pop3_greeting);
    }

    c->read->handler = ngx_mail_pop3_init_protocol;

    ngx_add_timer(c->read, cscf->timeout);

    if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
        ngx_mail_close_connection(c);
    }

    ngx_mail_send(c->write);
}
コード例 #8
0
ファイル: ngx_mail_proxy_module.c プロジェクト: askfor/nginx
static void
ngx_mail_proxy_upstream_error(ngx_mail_session_t *s)
{
    if (s->proxy->upstream.connection) {
        ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                       "close mail proxy connection: %d",
                       s->proxy->upstream.connection->fd);

        ngx_close_connection(s->proxy->upstream.connection);
    }

    if (s->out.len == 0) {
        ngx_mail_session_internal_server_error(s);
        return;
    }

    s->quit = 1;
    ngx_mail_send(s->connection->write);
}
コード例 #9
0
void
ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
{
    ngx_mail_core_srv_conf_t  *cscf;
    ngx_mail_imap_srv_conf_t  *iscf;
    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
    iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module);

    s->out = iscf->greeting;

    c->read->handler = ngx_mail_imap_init_protocol;

    ngx_add_timer(c->read, cscf->timeout);

    if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
        ngx_mail_close_connection(c);
    }

    ngx_mail_send(c->write);
}
コード例 #10
0
void
ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
{
    ngx_mail_core_srv_conf_t  *cscf;

    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

    s->out.len = sizeof(imap_greeting) - 1;
    s->out.data = imap_greeting;

    c->read->handler = ngx_mail_imap_init_protocol;

    ngx_add_timer(c->read, cscf->timeout);

    if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
        ngx_mail_close_connection(c);
    }

    ngx_mail_send(c->write);
}
コード例 #11
0
static void
ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
    ngx_mail_auth_http_ctx_t *ctx)
{
    u_char              *p;
    time_t               timer;
    size_t               len, size;
    ngx_int_t            rc, port, n;
    ngx_peer_addr_t     *peer;
    struct sockaddr_in  *sin;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                   "mail auth http process headers");

    for ( ;; ) {
        rc = ngx_mail_auth_http_parse_header_line(s, ctx);

        if (rc == NGX_OK) {

#if (NGX_DEBUG)
            {
            ngx_str_t  key, value;

            key.len = ctx->header_name_end - ctx->header_name_start;
            key.data = ctx->header_name_start;
            value.len = ctx->header_end - ctx->header_start;
            value.data = ctx->header_start;

            ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                           "mail auth http header: \"%V: %V\"",
                           &key, &value);
            }
#endif

            len = ctx->header_name_end - ctx->header_name_start;

            if (len == sizeof("Auth-Status") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Status",
                                   sizeof("Auth-Status") - 1)
                   == 0)
            {
                len = ctx->header_end - ctx->header_start;

                if (len == 2
                    && ctx->header_start[0] == 'O'
                    && ctx->header_start[1] == 'K')
                {
                    continue;
                }

                if (len == 4
                    && ctx->header_start[0] == 'W'
                    && ctx->header_start[1] == 'A'
                    && ctx->header_start[2] == 'I'
                    && ctx->header_start[3] == 'T')
                {
                    s->auth_wait = 1;
                    continue;
                }

                ctx->errmsg.len = len;
                ctx->errmsg.data = ctx->header_start;

                switch (s->protocol) {

                case NGX_MAIL_POP3_PROTOCOL:
                    size = sizeof("-ERR ") - 1 + len + sizeof(CRLF) - 1;
                    break;

                case NGX_MAIL_IMAP_PROTOCOL:
                    size = s->tag.len + sizeof("NO ") - 1 + len
                           + sizeof(CRLF) - 1;
                    break;

                default: /* NGX_MAIL_SMTP_PROTOCOL */
                    ctx->err = ctx->errmsg;
                    continue;
                }

                p = ngx_pcalloc(s->connection->pool, size);
                if (p == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ctx->err.data = p;

                switch (s->protocol) {

                case NGX_MAIL_POP3_PROTOCOL:
                    *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' ';
                    break;

                case NGX_MAIL_IMAP_PROTOCOL:
                    p = ngx_cpymem(p, s->tag.data, s->tag.len);
                    *p++ = 'N'; *p++ = 'O'; *p++ = ' ';
                    break;

                default: /* NGX_MAIL_SMTP_PROTOCOL */
                    break;
                }

                p = ngx_cpymem(p, ctx->header_start, len);
                *p++ = CR; *p++ = LF;

                ctx->err.len = p - ctx->err.data;

                continue;
            }

            if (len == sizeof("Auth-Server") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Server",
                                   sizeof("Auth-Server") - 1)
                    == 0)
            {
                ctx->addr.len = ctx->header_end - ctx->header_start;
                ctx->addr.data = ctx->header_start;

                continue;
            }

            if (len == sizeof("Auth-Port") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Port",
                                   sizeof("Auth-Port") - 1)
                   == 0)
            {
                ctx->port.len = ctx->header_end - ctx->header_start;
                ctx->port.data = ctx->header_start;

                continue;
            }

            if (len == sizeof("Auth-User") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-User",
                                   sizeof("Auth-User") - 1)
                   == 0)
            {
                s->login.len = ctx->header_end - ctx->header_start;

                s->login.data = ngx_palloc(s->connection->pool, s->login.len);
                if (s->login.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(s->login.data, ctx->header_start, s->login.len);

                continue;
            }

            if (len == sizeof("Auth-Pass") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Pass",
                                   sizeof("Auth-Pass") - 1)
                   == 0)
            {
                s->passwd.len = ctx->header_end - ctx->header_start;

                s->passwd.data = ngx_palloc(s->connection->pool, s->passwd.len);
                if (s->passwd.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len);

                continue;
            }

            if (len == sizeof("Auth-Wait") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Wait",
                                   sizeof("Auth-Wait") - 1)
                   == 0)
            {
                n = ngx_atoi(ctx->header_start,
                             ctx->header_end - ctx->header_start);

                if (n != NGX_ERROR) {
                    ctx->sleep = n;
                }

                continue;
            }

            if (len == sizeof("Auth-Error-Code") - 1
                && ngx_strncasecmp(ctx->header_name_start,
                                   (u_char *) "Auth-Error-Code",
                                   sizeof("Auth-Error-Code") - 1)
                   == 0)
            {
                ctx->errcode.len = ctx->header_end - ctx->header_start;

                ctx->errcode.data = ngx_palloc(s->connection->pool,
                                               ctx->errcode.len);
                if (ctx->errcode.data == NULL) {
                    ngx_close_connection(ctx->peer.connection);
                    ngx_destroy_pool(ctx->pool);
                    ngx_mail_session_internal_server_error(s);
                    return;
                }

                ngx_memcpy(ctx->errcode.data, ctx->header_start,
                           ctx->errcode.len);

                continue;
            }

            /* ignore other headers */

            continue;
        }

        if (rc == NGX_DONE) {
            ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                           "mail auth http header done");

            ngx_close_connection(ctx->peer.connection);

            if (ctx->err.len) {

                ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
                              "client login failed: \"%V\"", &ctx->errmsg);

                if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) {

                    if (ctx->errcode.len == 0) {
                        ctx->errcode = ngx_mail_smtp_errcode;
                    }

                    ctx->err.len = ctx->errcode.len + ctx->errmsg.len
                                   + sizeof(" " CRLF) - 1;

                    p = ngx_palloc(s->connection->pool, ctx->err.len);
                    if (p == NULL) {
                        ngx_close_connection(ctx->peer.connection);
                        ngx_destroy_pool(ctx->pool);
                        ngx_mail_session_internal_server_error(s);
                        return;
                    }

                    ctx->err.data = p;

                    p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len);
                    *p++ = ' ';
                    p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len);
                    *p++ = CR; *p = LF;
                }

                s->out = ctx->err;
                timer = ctx->sleep;

                ngx_destroy_pool(ctx->pool);

                if (timer == 0) {
                    s->quit = 1;
                    ngx_mail_send(s->connection->write);
                    return;
                }

                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));

                s->connection->read->handler = ngx_mail_auth_sleep_handler;

                return;
            }

            if (s->auth_wait) {
                timer = ctx->sleep;

                ngx_destroy_pool(ctx->pool);

                if (timer == 0) {
                    ngx_mail_auth_http_init(s);
                    return;
                }

                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));

                s->connection->read->handler = ngx_mail_auth_sleep_handler;

                return;
            }

            if (ctx->addr.len == 0 || ctx->port.len == 0) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V did not send server or port",
                              ctx->peer.name);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            if (s->passwd.data == NULL
                && s->protocol != NGX_MAIL_SMTP_PROTOCOL)
            {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V did not send password",
                              ctx->peer.name);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_peer_addr_t));
            if (peer == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in));
            if (sin == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            sin->sin_family = AF_INET;

            port = ngx_atoi(ctx->port.data, ctx->port.len);
            if (port == NGX_ERROR || port < 1 || port > 65536) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V sent invalid server "
                              "port:\"%V\"",
                              ctx->peer.name, &ctx->port);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            sin->sin_port = htons((in_port_t) port);

            ctx->addr.data[ctx->addr.len] = '\0';
            sin->sin_addr.s_addr = inet_addr((char *) ctx->addr.data);
            if (sin->sin_addr.s_addr == INADDR_NONE) {
                ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                              "auth http server %V sent invalid server "
                              "address:\"%V\"",
                              ctx->peer.name, &ctx->addr);
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            peer->sockaddr = (struct sockaddr *) sin;
            peer->socklen = sizeof(struct sockaddr_in);

            len = ctx->addr.len + 1 + ctx->port.len;

            peer->name.len = len;

            peer->name.data = ngx_palloc(s->connection->pool, len);
            if (peer->name.data == NULL) {
                ngx_destroy_pool(ctx->pool);
                ngx_mail_session_internal_server_error(s);
                return;
            }

            len = ctx->addr.len;

            ngx_memcpy(peer->name.data, ctx->addr.data, len);

            peer->name.data[len++] = ':';

            ngx_memcpy(peer->name.data + len, ctx->port.data, ctx->port.len);

            ngx_destroy_pool(ctx->pool);
            ngx_mail_proxy_init(s, peer);

            return;
        }

        if (rc == NGX_AGAIN ) {
            return;
        }

        /* rc == NGX_ERROR */

        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "auth http server %V sent invalid header in response",
                      ctx->peer.name);
        ngx_close_connection(ctx->peer.connection);
        ngx_destroy_pool(ctx->pool);
        ngx_mail_session_internal_server_error(s);

        return;
    }
}
コード例 #12
0
void
ngx_mail_imap_auth_state(ngx_event_t *rev)
{
    u_char              *p, *dst, *src, *end;
    ngx_str_t           *arg;
    ngx_int_t            rc;
    ngx_uint_t           tag, i;
    ngx_connection_t    *c;
    ngx_mail_session_t  *s;

    c = rev->data;
    s = c->data;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth state");

    if (rev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        ngx_mail_end_session(s);    /* send IMAP BYE on timeout */
        return;
    }

    if (s->out.len) {
        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy");
        s->blocked = 1;
        return;
    }

    s->blocked = 0;

    rc = ngx_mail_read_command(s, c);

    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
        return;
    }

    if (rc == NGX_IMAP_NEXT) {
        tag = 0;
        ngx_str_set(&s->out, imap_next);
    } else {
        tag = 1;
        ngx_str_set(&s->out, imap_ok);
        s->text.len = 0;

        ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i",
                       s->command);

        if (s->backslash) {

            arg = s->args.elts;

            for (i = 0; i < s->args.nelts; i++) {
                dst = arg[i].data;
                end = dst + arg[i].len;

                for (src = dst; src < end; dst++) {
                    *dst = *src;
                    if (*src++ == '\\') {
                        *dst = *src++;
                    }
                }

                arg[i].len = dst - arg[i].data;
            }

            s->backslash = 0;
        }

        if (rc == NGX_OK) {
            switch (s->mail_state) {

            case ngx_imap_start:

                switch (s->command) {

                case NGX_IMAP_LOGIN:
                      rc = ngx_mail_imap_login(s, c);
                      break;

                case NGX_IMAP_AUTHENTICATE:
                      rc = ngx_mail_imap_authenticate(s, c);
                      break;

                case NGX_IMAP_CAPABILITY:
                      rc = ngx_mail_imap_capability(s, c);
                      break;

                case NGX_IMAP_LOGOUT:
                    s->quit = 1;
                    ngx_str_set(&s->text, imap_bye);
                    break;

                case NGX_IMAP_NOOP:
                    break;

                case NGX_IMAP_STARTTLS:
                    rc = ngx_mail_imap_starttls(s, c);
                    break;

                case NGX_IMAP_ID:
                    rc = ngx_mail_imap_id(s, c);
                    break;

                default:
                    rc = NGX_MAIL_PARSE_INVALID_COMMAND;
                    break;
                }

                break;

            case ngx_imap_auth_login_username:
                rc = ngx_mail_auth_login_username(s, c, 0);
                if (rc == NGX_MAIL_AUTH_ARGUMENT) {
                    ngx_str_set(&s->out, imap_password);
                    s->mail_state = ngx_imap_auth_login_password;
                }

                break;

            case ngx_imap_auth_login_password:
                rc = ngx_mail_auth_login_password(s, c);
                break;

            case ngx_imap_auth_plain:
                rc = ngx_mail_auth_plain(s, c, 0);
                break;

            case ngx_imap_auth_gssapi:
                {
                    ngx_str_t output;
                    ngx_str_set(&output, "");
                    rc = ngx_mail_auth_gssapi(s, c, &output);
                    if (rc == NGX_MAIL_AUTH_ARGUMENT) {
                        s->mail_state = ngx_imap_auth_gssapi;
                        s->out = output;
                    }
                    break;
                }

            case ngx_imap_auth_cram_md5:
                rc = ngx_mail_auth_cram_md5(s, c);
                break;
            }
        }
    }

    switch (rc) {

    case NGX_DONE:
        ngx_mail_do_auth(s, c);
        return;

    case NGX_OK:
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_MAIL_AUTH_ABORT:
        ngx_str_set(&s->out, imap_authaborted);
        s->mail_state = ngx_imap_start;
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_ERROR:
        ngx_mail_session_internal_server_error(s);
        return;
    case NGX_MAIL_AUTH_FAILED:
        ngx_str_set(&s->out, imap_authenticate_failed);
        s->mail_state = ngx_imap_start;
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_MAIL_LOGIN_FAILED:
        ngx_str_set(&s->out, imap_login_failed);
        s->mail_state = ngx_imap_start;
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_MAIL_PARSE_INVALID_AUTH_MECH:
        ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0,
            "unsupported IMAP auth mechanism");
        ngx_str_set(&s->out, imap_unsupported_mech);
        s->mail_state = ngx_imap_start;
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_MAIL_PARSE_INVALID_COMMAND:
        ngx_str_set(&s->out, imap_invalid_command);
        s->mail_state = ngx_imap_start;
        ngx_mail_set_imap_parse_state_start(s);
        s->arg_start = NULL;
        ngx_mail_reset_parse_buffer(s);
        break;

    case NGX_MAIL_AUTH_ARGUMENT:
        ngx_mail_set_imap_parse_state_argument(s);
        /* preserve tag, since tag's memory is allocated in buffer, need to set the
         * buffer pos after tag */
        s->arg_start = s->buffer->start + s->tag.len;
        s->buffer->pos = s->arg_start;
        s->buffer->last = s->arg_start;
        tag = 0; // just output s->out
        break;

    case NGX_IMAP_NEXT:
        /* do nothing, preserve all the state, including s->state, s->mail_state,
         * , s->buffer, s->arg_start
         */
        break;
    }

    //clear args
    if(rc != NGX_IMAP_NEXT) {
        s->args.nelts = 0;
    }

    // process the output
    if (tag) { //text tag out --> out
        if (s->tag.len == 0) {
            ngx_str_set(&s->tag, imap_star);
        }

        if (s->tagged_line.len < s->tag.len + s->text.len + s->out.len + 1) {
            s->tagged_line.len = s->tag.len + s->text.len + s->out.len + 1;
            s->tagged_line.data = ngx_pnalloc(c->pool, s->tagged_line.len);
            if (s->tagged_line.data == NULL) {
                ngx_mail_close_connection(c);
                return;
            }
        }

        p = s->tagged_line.data;

        if (s->text.len) {
            p = ngx_cpymem(p, s->text.data, s->text.len);
        }

        p = ngx_cpymem(p, s->tag.data, s->tag.len);
        *p++ = ' '; /* the space between tag and out */
        ngx_memcpy(p, s->out.data, s->out.len);

        s->out.len = s->text.len + s->tag.len + 1 /*for space*/+ s->out.len;
        s->out.data = s->tagged_line.data;
    }

    ngx_mail_send(c->write);
}
コード例 #13
0
void
ngx_mail_smtp_auth_state(ngx_event_t *rev)
{
    ngx_int_t            rc;
    ngx_connection_t    *c;
    ngx_mail_session_t  *s;

    c = rev->data;
    s = c->data;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state");

    if (rev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        ngx_mail_close_connection(c);
        return;
    }

    if (s->out.len) {
        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy");
        s->blocked = 1;
        return;
    }

    s->blocked = 0;

    rc = ngx_mail_read_command(s, c);

    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
        return;
    }

    s->out.len = sizeof(smtp_ok) - 1;
    s->out.data = smtp_ok;

    if (rc == NGX_OK) {
        switch (s->mail_state) {

        case ngx_smtp_start:

            switch (s->command) {

            case NGX_SMTP_HELO:
            case NGX_SMTP_EHLO:
                rc = ngx_mail_smtp_helo(s, c);
                break;

            case NGX_SMTP_AUTH:
                rc = ngx_mail_smtp_auth(s, c);
                break;

            case NGX_SMTP_QUIT:
                s->quit = 1;
                s->out.len = sizeof(smtp_bye) - 1;
                s->out.data = smtp_bye;
                break;

            case NGX_SMTP_MAIL:
                rc = ngx_mail_smtp_mail(s, c);
                break;

            case NGX_SMTP_NOOP:
            case NGX_SMTP_RSET:
                break;

            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:
                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
                break;
            }

            break;

        case ngx_smtp_auth_login_username:
            rc = ngx_mail_auth_login_username(s, c, 0);

            s->out.len = sizeof(smtp_password) - 1;
            s->out.data = smtp_password;
            s->mail_state = ngx_smtp_auth_login_password;
            break;

        case ngx_smtp_auth_login_password:
            rc = ngx_mail_auth_login_password(s, c);
            break;

        case ngx_smtp_auth_plain:
            rc = ngx_mail_auth_plain(s, c, 0);
            break;

        case ngx_smtp_auth_cram_md5:
            rc = ngx_mail_auth_cram_md5(s, c);
            break;
        }
    }

    switch (rc) {

    case NGX_DONE:
        ngx_mail_auth(s, c);
        return;

    case NGX_ERROR:
        ngx_mail_session_internal_server_error(s);
        return;

    case NGX_MAIL_PARSE_INVALID_COMMAND:
        s->mail_state = ngx_smtp_start;
        s->state = 0;

        s->out.len = sizeof(smtp_invalid_command) - 1;
        s->out.data = smtp_invalid_command;

    /* fall through */

    case NGX_OK:
        s->args.nelts = 0;
        s->buffer->pos = s->buffer->start;
        s->buffer->last = s->buffer->start;

        if (s->state) {
            s->arg_start = s->buffer->start;
        }

        ngx_mail_send(c->write);
    }
}
コード例 #14
0
void
ngx_mail_imap_auth_state(ngx_event_t *rev)
{
    u_char              *p, *dst, *src, *end;
    ngx_str_t           *arg;
    ngx_int_t            rc;
    ngx_uint_t           tag, i;
    ngx_connection_t    *c;
    ngx_mail_session_t  *s;

    c = rev->data;
    s = c->data;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth state");

    if (rev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        ngx_mail_close_connection(c);
        return;
    }

    if (s->out.len) {
        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy");
        s->blocked = 1;
        return;
    }

    s->blocked = 0;

    rc = ngx_mail_read_command(s, c);

    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
        return;
    }

    tag = 1;
    s->text.len = 0;
    s->out.len = sizeof(imap_ok) - 1;
    s->out.data = imap_ok;

    if (rc == NGX_OK) {

        ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i",
                       s->command);

        if (s->backslash) {

            arg = s->args.elts;

            for (i = 0; i < s->args.nelts; i++) {
                dst = arg[i].data;
                end = dst + arg[i].len;

                for (src = dst; src < end; dst++) {
                    *dst = *src;
                    if (*src++ == '\\') {
                        *dst = *src++;
                    }
                }

                arg[i].len = dst - arg[i].data;
            }

            s->backslash = 0;
        }

        switch (s->mail_state) {

        case ngx_imap_start:

            switch (s->command) {

            case NGX_IMAP_LOGIN:
                rc = ngx_mail_imap_login(s, c);
                break;

            case NGX_IMAP_AUTHENTICATE:
                rc = ngx_mail_imap_authenticate(s, c);
                tag = (rc != NGX_OK);
                break;

            case NGX_IMAP_CAPABILITY:
                rc = ngx_mail_imap_capability(s, c);
                break;

            case NGX_IMAP_LOGOUT:
                s->quit = 1;
                s->text.len = sizeof(imap_bye) - 1;
                s->text.data = imap_bye;
                break;

            case NGX_IMAP_NOOP:
                break;

            case NGX_IMAP_STARTTLS:
                rc = ngx_mail_imap_starttls(s, c);
                break;

            default:
                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
                break;
            }

            break;

        case ngx_imap_auth_login_username:
            rc = ngx_mail_auth_login_username(s, c, 0);

            tag = 0;
            s->out.len = sizeof(imap_password) - 1;
            s->out.data = imap_password;
            s->mail_state = ngx_imap_auth_login_password;

            break;

        case ngx_imap_auth_login_password:
            rc = ngx_mail_auth_login_password(s, c);
            break;

        case ngx_imap_auth_plain:
            rc = ngx_mail_auth_plain(s, c, 0);
            break;

        case ngx_imap_auth_cram_md5:
            rc = ngx_mail_auth_cram_md5(s, c);
            break;
        }

    } else if (rc == NGX_IMAP_NEXT) {
        tag = 0;
        s->out.len = sizeof(imap_next) - 1;
        s->out.data = imap_next;
    }

    switch (rc) {

    case NGX_DONE:
        ngx_mail_auth(s, c);
        return;

    case NGX_ERROR:
        ngx_mail_session_internal_server_error(s);
        return;

    case NGX_MAIL_PARSE_INVALID_COMMAND:
        s->state = 0;
        s->out.len = sizeof(imap_invalid_command) - 1;
        s->out.data = imap_invalid_command;
        s->mail_state = ngx_imap_start;
        break;
    }

    if (tag) {
        if (s->tag.len == 0) {
            s->tag.len = sizeof(imap_star) - 1;
            s->tag.data = (u_char *) imap_star;
        }

        if (s->tagged_line.len < s->tag.len + s->text.len + s->out.len) {
            s->tagged_line.len = s->tag.len + s->text.len + s->out.len;
            s->tagged_line.data = ngx_pnalloc(c->pool, s->tagged_line.len);
            if (s->tagged_line.data == NULL) {
                ngx_mail_close_connection(c);
                return;
            }
        }

        p = s->tagged_line.data;

        if (s->text.len) {
            p = ngx_cpymem(p, s->text.data, s->text.len);
        }

        p = ngx_cpymem(p, s->tag.data, s->tag.len);
        ngx_memcpy(p, s->out.data, s->out.len);

        s->out.len = s->text.len + s->tag.len + s->out.len;
        s->out.data = s->tagged_line.data;
    }

    if (rc != NGX_IMAP_NEXT) {
        s->args.nelts = 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);
}
コード例 #15
0
void
ngx_mail_pop3_auth_state(ngx_event_t *rev)
{
    ngx_int_t            rc;
    ngx_connection_t    *c;
    ngx_mail_session_t  *s;

    c = rev->data;
    s = c->data;

    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 auth state");

    if (rev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        ngx_mail_close_connection(c);
        return;
    }

    if (s->out.len) {
        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy");
        s->blocked = 1;
        return;
    }

    s->blocked = 0;

    rc = ngx_mail_read_command(s, c);

    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
        return;
    }

    ngx_str_set(&s->out, pop3_ok);

    if (rc == NGX_OK) {
        switch (s->mail_state) {

        case ngx_pop3_start:

            switch (s->command) {

            case NGX_POP3_USER:
                rc = ngx_mail_pop3_user(s, c);
                break;

            case NGX_POP3_CAPA:
                rc = ngx_mail_pop3_capa(s, c, 1);
                break;

            case NGX_POP3_APOP:
                rc = ngx_mail_pop3_apop(s, c);
                break;

            case NGX_POP3_AUTH:
                rc = ngx_mail_pop3_auth(s, c);
                break;

            case NGX_POP3_QUIT:
                s->quit = 1;
                break;

            case NGX_POP3_NOOP:
                break;

            case NGX_POP3_STLS:
                rc = ngx_mail_pop3_stls(s, c);
                break;

            default:
                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
                break;
            }

            break;

        case ngx_pop3_user:

            switch (s->command) {

            case NGX_POP3_PASS:
                rc = ngx_mail_pop3_pass(s, c);
                break;

            case NGX_POP3_CAPA:
                rc = ngx_mail_pop3_capa(s, c, 0);
                break;

            case NGX_POP3_QUIT:
                s->quit = 1;
                break;

            case NGX_POP3_NOOP:
                break;

            default:
                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
                break;
            }

            break;

        /* suppress warinings */
        case ngx_pop3_passwd:
            break;

        case ngx_pop3_auth_login_username:
            rc = ngx_mail_auth_login_username(s, c, 0);

            ngx_str_set(&s->out, pop3_password);
            s->mail_state = ngx_pop3_auth_login_password;
            break;

        case ngx_pop3_auth_login_password:
            rc = ngx_mail_auth_login_password(s, c);
            break;

        case ngx_pop3_auth_plain:
            rc = ngx_mail_auth_plain(s, c, 0);
            break;

        case ngx_pop3_auth_cram_md5:
            rc = ngx_mail_auth_cram_md5(s, c);
            break;
        }
    }

    switch (rc) {

    case NGX_DONE:
        ngx_mail_auth(s, c);
        return;

    case NGX_ERROR:
        ngx_mail_session_internal_server_error(s);
        return;

    case NGX_MAIL_PARSE_INVALID_COMMAND:
        s->mail_state = ngx_pop3_start;
        s->state = 0;

        ngx_str_set(&s->out, pop3_invalid_command);

        /* fall through */

    case NGX_OK:

        s->args.nelts = 0;
        s->buffer->pos = s->buffer->start;
        s->buffer->last = s->buffer->start;

        if (s->state) {
            s->arg_start = s->buffer->start;
        }

        ngx_mail_send(c->write);
    }
}
コード例 #16
0
static ngx_int_t
ngx_mail_verify_cert(ngx_mail_session_t *s, ngx_connection_t *c)
{
    long                       rc;
    X509                      *cert;
    ngx_mail_ssl_conf_t       *sslcf;
    ngx_mail_core_srv_conf_t  *cscf;

    sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);

    if (!sslcf->verify) {
        return NGX_OK;
    }

    rc = SSL_get_verify_result(c->ssl->connection);

    if (rc != X509_V_OK
        && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
    {
        ngx_log_error(NGX_LOG_INFO, c->log, 0,
                      "client SSL certificate verify error: (%l:%s)",
                      rc, X509_verify_cert_error_string(rc));

        ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
                                      (SSL_get0_session(c->ssl->connection)));

        cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

        s->out = cscf->protocol->cert_error;
        s->quit = 1;

        c->write->handler = ngx_mail_send;

        ngx_mail_send(s->connection->write);
        return NGX_ERROR;
    }

    if (sslcf->verify == 1) {
        cert = SSL_get_peer_certificate(c->ssl->connection);

        if (cert == NULL) {
            ngx_log_error(NGX_LOG_INFO, c->log, 0,
                          "client sent no required SSL certificate");

            ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
                                       (SSL_get0_session(c->ssl->connection)));

            cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

            s->out = cscf->protocol->no_cert;
            s->quit = 1;

            c->write->handler = ngx_mail_send;

            ngx_mail_send(s->connection->write);
            return NGX_ERROR;
        }

        X509_free(cert);
    }

    return NGX_OK;
}
コード例 #17
0
static void
ngx_mail_zmauth_lookup_result_handler(ngx_zm_lookup_work_t * work) {
    ngx_mail_session_t     *s;
    ngx_mail_zmauth_ctx_t  *ctx;
    size_t                  size;
    u_char                 *p;
    ngx_addr_t             *peer;
    ngx_str_t               errmsg;

    s = (ngx_mail_session_t *) work->data;
    ctx = (ngx_mail_zmauth_ctx_t *)ngx_mail_get_module_ctx(s, ngx_mail_zmauth_module);

    if (work->result == ZM_LOOKUP_SUCCESS) {
        ngx_mail_zmauth_unescape(&work->account_name);

        /* copy the lookup result from zmauth pool to s->connection pool */
        s->qlogin = *(ngx_pstrcpy(s->connection->pool, &work->account_name));
        s->key_alias = *(ngx_pstrcpy(s->connection->pool, &work->alias_key));
        s->key_route = *(ngx_pstrcpy(s->connection->pool, &work->route_key));
        if (s->auth_method == NGX_MAIL_AUTH_GSSAPI ||
            s->auth_method == NGX_MAIL_AUTH_GSSAPI_IR) {
            s->dusr = *(ngx_pstrcpy(s->connection->pool, &work->auth_id));
            s->dpasswd = *(ngx_pstrcpy(s->connection->pool, &work->zm_auth_token));
        }
        peer = ngx_palloc(s->connection->pool, sizeof(ngx_addr_t));

        peer->name = *(ngx_pstrcpy(s->connection->pool, &work->route->name));
        peer->socklen = work->route->socklen;
        peer->sockaddr = ngx_palloc(s->connection->pool, peer->socklen);
        if(peer->sockaddr == NULL) {
            return; /* NO MEM */
        }
        ngx_memcpy(peer->sockaddr, work->route->sockaddr, peer->socklen);

        switch (work->alias_check_stat) {
           case ZM_ALIAS_NOT_FOUND:
               s->vlogin = 1;
               break;
           case ZM_ALIAS_FOUND:
               s->vlogin = 2;
               break;
           default:
               break;
               /* do nothing */
           }

        ngx_destroy_pool(ctx->pool);
        ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module);
        ngx_mail_proxy_init(s, peer);
        return;
    } else {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "An error occurred in mail zmauth: %V",
                       &work->err);

        /* construct error msg */
        if (work->result != ZM_LOOKUP_LOGIN_FAILED) {
            /* zmauth clean up will destroy the ctx->pool */
            ngx_mail_session_internal_server_error(s);
            return;
        }

        errmsg = LOGIN_FAILED; /* should we return the real err msg to user? */

        switch (s->protocol) {

        case NGX_MAIL_POP3_PROTOCOL:
            size = sizeof("-ERR ") - 1 + errmsg.len + sizeof(CRLF) - 1;
            if (s->command == NGX_POP3_AUTH) {
                size +=  AUTHENTICATION_FAILED.len;
            }
            break;

        case NGX_MAIL_IMAP_PROTOCOL:
            if (s->command == NGX_IMAP_AUTHENTICATE) {
                errmsg = AUTHENTICATE_FAILED;
            }
            size = s->tag.len + 1 /*for space*/+ sizeof("NO ") - 1 + errmsg.len
                   + sizeof(CRLF) - 1;
            break;

        default: /* NGX_MAIL_SMTP_PROTOCOL */
            ngx_log_error(NGX_LOG_CRIT, s->connection->log, 0, "smtp is not supported!!");
            return;
        }

        p = ngx_pnalloc(s->connection->pool, size);
        if (p == NULL) {
            ngx_destroy_pool(ctx->pool);
            ngx_mail_session_internal_server_error(s);
            return;
        }

        ctx->errmsg.data = p;

        switch (s->protocol) {

        case NGX_MAIL_POP3_PROTOCOL:
            *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' ';
            if (s->command == NGX_POP3_AUTH) {
                p = ngx_cpymem(p, AUTHENTICATION_FAILED.data, AUTHENTICATION_FAILED.len);
            }
            break;

        case NGX_MAIL_IMAP_PROTOCOL:
            p = ngx_cpymem(p, s->tag.data, s->tag.len);
            *p++ = ' '; *p++ = 'N'; *p++ = 'O'; *p++ = ' ';
            break;

        default: /* NGX_MAIL_SMTP_PROTOCOL */
            break;
        }

        p = ngx_cpymem(p, errmsg.data, errmsg.len);
        *p++ = CR; *p++ = LF;

        ctx->errmsg.len = p - ctx->errmsg.data;
        s->out = ctx->errmsg;

        if (work->result == ZM_LOOKUP_LOGIN_FAILED && work->wait_time > 0) {
            ngx_add_timer(ctx->wait_ev, (ngx_msec_t) (work->wait_time * 1000));

            s->connection->read->handler = ngx_mail_zmauth_block_read;
        } else {
            s->quit = 1;
            ngx_mail_send(s->connection->write);
            ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module);
            ngx_destroy_pool(ctx->pool);
        }
        return;
    }
}