Mercurial > hg > nginx
changeset 1487:f69493e8faab
ngx_mail_pop3_module, ngx_mail_imap_module, and ngx_mail_smtp_module
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 15 Sep 2007 16:51:16 +0000 |
parents | 0e7074ef7303 |
children | 0e66eabd18b5 |
files | auto/modules auto/options auto/sources src/mail/ngx_mail.c src/mail/ngx_mail.h src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_core_module.c src/mail/ngx_mail_handler.c src/mail/ngx_mail_imap_handler.c src/mail/ngx_mail_imap_module.c src/mail/ngx_mail_imap_module.h src/mail/ngx_mail_pop3_handler.c src/mail/ngx_mail_pop3_module.c src/mail/ngx_mail_pop3_module.h src/mail/ngx_mail_proxy_module.c src/mail/ngx_mail_smtp_handler.c src/mail/ngx_mail_smtp_module.c src/mail/ngx_mail_smtp_module.h src/mail/ngx_mail_ssl_module.c |
diffstat | 19 files changed, 1188 insertions(+), 723 deletions(-) [+] |
line wrap: on
line diff
--- a/auto/modules Fri Sep 14 15:04:45 2007 +0000 +++ b/auto/modules Sat Sep 15 16:51:16 2007 +0000 @@ -308,8 +308,6 @@ if [ $MAIL_SSL = YES ]; then - MAIL_DEPS="$MAIL_DEPS $MAIL_SSL_DEPS" - MAIL_SRCS="$MAIL_SRCS $MAIL_SSL_SRCS" have=NGX_MAIL_SSL . auto/have USE_OPENSSL=YES fi @@ -341,6 +339,26 @@ if [ $MAIL_SSL = YES ]; then modules="$modules $MAIL_SSL_MODULE" + MAIL_DEPS="$MAIL_DEPS $MAIL_SSL_DEPS" + MAIL_SRCS="$MAIL_SRCS $MAIL_SSL_SRCS" + fi + + if [ $MAIL_POP3 = YES ]; then + modules="$modules $MAIL_POP3_MODULE" + MAIL_DEPS="$MAIL_DEPS $MAIL_POP3_DEPS" + MAIL_SRCS="$MAIL_SRCS $MAIL_POP3_SRCS" + fi + + if [ $MAIL_IMAP = YES ]; then + modules="$modules $MAIL_IMAP_MODULE" + MAIL_DEPS="$MAIL_DEPS $MAIL_IMAP_DEPS" + MAIL_SRCS="$MAIL_SRCS $MAIL_IMAP_SRCS" + fi + + if [ $MAIL_SMTP = YES ]; then + modules="$modules $MAIL_SMTP_MODULE" + MAIL_DEPS="$MAIL_DEPS $MAIL_SMTP_DEPS" + MAIL_SRCS="$MAIL_SRCS $MAIL_SMTP_SRCS" fi modules="$modules $MAIL_AUTH_HTTP_MODULE"
--- a/auto/options Fri Sep 14 15:04:45 2007 +0000 +++ b/auto/options Sat Sep 15 16:51:16 2007 +0000 @@ -81,6 +81,9 @@ MAIL=NO MAIL_SSL=NO +MAIL_POP3=YES +MAIL_IMAP=YES +MAIL_SMTP=YES NGX_ADDONS= @@ -190,6 +193,9 @@ # STUB --with-imap) MAIL=YES ;; --with-imap_ssl_module) MAIL_SSL=YES ;; + --without-mail_pop3_module) MAIL_POP3=NO ;; + --without-mail_imap_module) MAIL_IMAP=NO ;; + --without-mail_smtp_module) MAIL_SMTP=NO ;; --add-module=*) NGX_ADDONS="$NGX_ADDONS $value" ;;
--- a/auto/sources Fri Sep 14 15:04:45 2007 +0000 +++ b/auto/sources Sat Sep 15 16:51:16 2007 +0000 @@ -423,11 +423,23 @@ MAIL_SRCS="src/mail/ngx_mail.c \ src/mail/ngx_mail_core_module.c \ src/mail/ngx_mail_handler.c \ - src/mail/ngx_mail_pop3_handler.c \ - src/mail/ngx_mail_imap_handler.c \ - src/mail/ngx_mail_smtp_handler.c \ src/mail/ngx_mail_parse.c" +MAIL_POP3_MODULE="ngx_mail_pop3_module" +MAIL_POP3_DEPS="src/mail/ngx_mail_pop3_module.h" +MAIL_POP3_SRCS="src/mail/ngx_mail_pop3_module.c \ + src/mail/ngx_mail_pop3_handler.c" + +MAIL_IMAP_MODULE="ngx_mail_imap_module" +MAIL_IMAP_DEPS="src/mail/ngx_mail_imap_module.h" +MAIL_IMAP_SRCS="src/mail/ngx_mail_imap_module.c \ + src/mail/ngx_mail_imap_handler.c" + +MAIL_SMTP_MODULE="ngx_mail_smtp_module" +MAIL_SMTP_DEPS="src/mail/ngx_mail_smtp_module.h" +MAIL_SMTP_SRCS="src/mail/ngx_mail_smtp_module.c \ + src/mail/ngx_mail_smtp_handler.c" + MAIL_SSL_MODULE="ngx_mail_ssl_module" MAIL_SSL_DEPS="src/mail/ngx_mail_ssl_module.h" MAIL_SSL_SRCS="src/mail/ngx_mail_ssl_module.c"
--- a/src/mail/ngx_mail.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail.c Sat Sep 15 16:51:16 2007 +0000 @@ -185,6 +185,8 @@ /* init mail{} main_conf's */ + cf->ctx = ctx; + if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { @@ -197,6 +199,8 @@ /* merge the server{}s' srv_conf's */ + cf->ctx = cscfp[s]->ctx; + if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], @@ -209,8 +213,6 @@ } } - /* mail{}'s cf->ctx was needed while the configuration merging */ - *cf = pcf;
--- a/src/mail/ngx_mail.h Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail.h Sat Sep 15 16:51:16 2007 +0000 @@ -73,57 +73,27 @@ #define NGX_MAIL_IMAP_PROTOCOL 1 #define NGX_MAIL_SMTP_PROTOCOL 2 -typedef struct { - ngx_msec_t timeout; - ngx_msec_t smtp_greeting_delay; + +typedef struct ngx_mail_protocol_s ngx_mail_protocol_t; + - size_t imap_client_buffer_size; - size_t smtp_client_buffer_size; +typedef struct { + ngx_mail_protocol_t *protocol; - ngx_uint_t protocol; + ngx_msec_t timeout; ngx_flag_t so_keepalive; - ngx_str_t pop3_capability; - ngx_str_t pop3_starttls_capability; - ngx_str_t pop3_starttls_only_capability; - ngx_str_t pop3_auth_capability; - - ngx_str_t imap_capability; - ngx_str_t imap_starttls_capability; - ngx_str_t imap_starttls_only_capability; + ngx_str_t server_name; - ngx_str_t smtp_capability; - ngx_str_t smtp_starttls_capability; - ngx_str_t smtp_starttls_only_capability; - - ngx_str_t server_name; - ngx_str_t smtp_server_name; - 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; - ngx_array_t imap_capabilities; - ngx_array_t smtp_capabilities; + u_char *file_name; + ngx_int_t line; /* server ctx */ ngx_mail_conf_ctx_t *ctx; } ngx_mail_core_srv_conf_t; -typedef struct { - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, - void *conf); -} ngx_mail_module_t; - - typedef enum { ngx_pop3_start = 0, ngx_pop3_user, @@ -181,9 +151,9 @@ ngx_uint_t mail_state; + unsigned protocol:3; unsigned blocked:1; unsigned quit:1; - unsigned protocol:2; unsigned quoted:1; unsigned backslash:1; unsigned no_sync_literal:1; @@ -208,7 +178,7 @@ ngx_uint_t login_attempt; - /* used to parse IMAP/POP3/SMTP command */ + /* used to parse POP3/IMAP/SMTP command */ ngx_uint_t state; u_char *cmd_start; @@ -282,10 +252,43 @@ #define NGX_MAIL_PARSE_INVALID_COMMAND 20 -#define NGX_MAIL_MODULE 0x4C49414D /* "MAIL" */ +typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, + ngx_connection_t *c); +typedef void (*ngx_mail_init_protocol_pt)(ngx_event_t *rev); +typedef void (*ngx_mail_auth_state_pt)(ngx_event_t *rev); +typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s); + + +struct ngx_mail_protocol_s { + ngx_str_t name; + in_port_t port[4]; + ngx_uint_t type; + + ngx_mail_init_session_pt init_session; + ngx_mail_init_protocol_pt init_protocol; + ngx_mail_parse_command_pt parse_command; + ngx_mail_auth_state_pt auth_state; -#define NGX_MAIL_MAIN_CONF 0x02000000 -#define NGX_MAIL_SRV_CONF 0x04000000 + ngx_str_t internal_server_error; +}; + + +typedef struct { + ngx_mail_protocol_t *protocol; + + void *(*create_main_conf)(ngx_conf_t *cf); + char *(*init_main_conf)(ngx_conf_t *cf, void *conf); + + void *(*create_srv_conf)(ngx_conf_t *cf); + char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, + void *conf); +} ngx_mail_module_t; + + +#define NGX_MAIL_MODULE 0x4C49414D /* "MAIL" */ + +#define NGX_MAIL_MAIN_CONF 0x02000000 +#define NGX_MAIL_SRV_CONF 0x04000000 #define NGX_MAIL_MAIN_CONF_OFFSET offsetof(ngx_mail_conf_ctx_t, main_conf) @@ -306,12 +309,6 @@ #define ngx_mail_conf_get_module_srv_conf(cf, module) \ ((ngx_mail_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index] -typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, - ngx_connection_t *c); -typedef void (*ngx_mail_init_protocol_pt)(ngx_event_t *rev); -typedef void (*ngx_mail_auth_state_pt)(ngx_event_t *rev); -typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s); - #if (NGX_MAIL_SSL) void ngx_mail_starttls_handler(ngx_event_t *rev); @@ -321,10 +318,6 @@ void ngx_mail_init_connection(ngx_connection_t *c); -void ngx_mail_pop3_auth_state(ngx_event_t *rev); -void ngx_mail_imap_auth_state(ngx_event_t *rev); -void ngx_mail_smtp_auth_state(ngx_event_t *rev); - ngx_int_t ngx_mail_salt(ngx_mail_session_t *s, ngx_connection_t *c, ngx_mail_core_srv_conf_t *cscf); ngx_int_t ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, @@ -336,6 +329,7 @@ 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); +ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c); void ngx_mail_send(ngx_event_t *wev); ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c); @@ -345,18 +339,7 @@ u_char *ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len); -void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c); -void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c); -void ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c); - -void ngx_mail_pop3_init_protocol(ngx_event_t *rev); -void ngx_mail_imap_init_protocol(ngx_event_t *rev); -void ngx_mail_smtp_init_protocol(ngx_event_t *rev); - -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); +char *ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); /* STUB */
--- a/src/mail/ngx_mail_auth_http_module.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_auth_http_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -111,6 +111,8 @@ static ngx_mail_module_t ngx_mail_auth_http_module_ctx = { + NULL, /* protocol */ + NULL, /* create main configuration */ NULL, /* init main configuration */ @@ -135,7 +137,6 @@ }; -static char *ngx_mail_auth_http_protocol[] = { "pop3", "imap", "smtp" }; static ngx_str_t ngx_mail_auth_http_method[] = { ngx_string("plain"), ngx_string("plain"), @@ -145,18 +146,6 @@ static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0"); -static ngx_uint_t ngx_mail_start_states[] = { - ngx_pop3_start, - ngx_imap_start, - ngx_smtp_start -}; - -static ngx_mail_auth_state_pt ngx_mail_auth_states[] = { - ngx_mail_pop3_auth_state, - ngx_mail_imap_auth_state, - ngx_mail_smtp_auth_state -}; - void ngx_mail_auth_http_init(ngx_mail_session_t *s) @@ -762,7 +751,8 @@ return; } - if (s->passwd.data == NULL && s->protocol != NGX_MAIL_SMTP_PROTOCOL) + 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", @@ -881,9 +871,11 @@ return; } - s->mail_state = ngx_mail_start_states[s->protocol]; - rev->handler = ngx_mail_auth_states[s->protocol]; + 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"; @@ -894,8 +886,6 @@ return; } - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - ngx_add_timer(rev, cscf->timeout); if (rev->ready) { @@ -1145,9 +1135,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, ngx_mail_auth_http_conf_t *ahcf) { - size_t len; - ngx_buf_t *b; - ngx_str_t login, passwd; + size_t len; + ngx_buf_t *b; + ngx_str_t login, passwd; + ngx_mail_core_srv_conf_t *cscf; if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { return NULL; @@ -1157,6 +1148,8 @@ return NULL; } + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 + sizeof("Auth-Method: ") - 1 @@ -1165,7 +1158,8 @@ + sizeof("Auth-User: ") - 1 + login.len + sizeof(CRLF) - 1 + sizeof("Auth-Pass: ") - 1 + passwd.len + sizeof(CRLF) - 1 + sizeof("Auth-Salt: ") - 1 + s->salt.len - + sizeof("Auth-Protocol: imap" CRLF) - 1 + + sizeof("Auth-Protocol: ") - 1 + cscf->protocol->name.len + + sizeof(CRLF) - 1 + sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN + sizeof(CRLF) - 1 + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len @@ -1212,8 +1206,8 @@ b->last = ngx_cpymem(b->last, "Auth-Protocol: ", sizeof("Auth-Protocol: ") - 1); - b->last = ngx_cpymem(b->last, ngx_mail_auth_http_protocol[s->protocol], - sizeof("imap") - 1); + b->last = ngx_cpymem(b->last, cscf->protocol->name.data, + cscf->protocol->name.len); *b->last++ = CR; *b->last++ = LF; b->last = ngx_sprintf(b->last, "Auth-Login-Attempt: %ui" CRLF,
--- a/src/mail/ngx_mail_core_module.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_core_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -18,90 +18,10 @@ void *conf); static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_mail_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, +static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_conf_enum_t ngx_mail_core_procotol[] = { - { ngx_string("pop3"), NGX_MAIL_POP3_PROTOCOL }, - { ngx_string("imap"), NGX_MAIL_IMAP_PROTOCOL }, - { ngx_string("smtp"), NGX_MAIL_SMTP_PROTOCOL }, - { ngx_null_string, 0 } -}; - - -static ngx_str_t ngx_pop3_default_capabilities[] = { - ngx_string("TOP"), - ngx_string("USER"), - ngx_string("UIDL"), - ngx_null_string -}; - - -static ngx_str_t ngx_imap_default_capabilities[] = { - ngx_string("IMAP4"), - ngx_string("IMAP4rev1"), - ngx_string("UIDPLUS"), - ngx_null_string -}; - - -static ngx_conf_bitmask_t ngx_pop3_auth_methods[] = { - { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, - { ngx_string("apop"), NGX_MAIL_AUTH_APOP_ENABLED }, - { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, - { ngx_null_string, 0 } -}; - - -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 }, - { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, - { ngx_null_string, 0 } -}; - - -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"), - ngx_null_string, /* APOP */ - ngx_string("CRAM-MD5") -}; - - -static ngx_str_t ngx_pop3_auth_plain_capability = - ngx_string("+OK methods supported:" CRLF - "LOGIN" CRLF - "PLAIN" CRLF - "." CRLF); - - -static ngx_str_t ngx_pop3_auth_cram_md5_capability = - ngx_string("+OK methods supported:" CRLF - "LOGIN" CRLF - "PLAIN" CRLF - "CRAM-MD5" CRLF - "." CRLF); - - - static ngx_command_t ngx_mail_core_commands[] = { { ngx_string("server"), @@ -114,36 +34,15 @@ { ngx_string("listen"), NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12, ngx_mail_core_listen, - 0, + NGX_MAIL_SRV_CONF_OFFSET, 0, NULL }, { ngx_string("protocol"), NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, protocol), - &ngx_mail_core_procotol }, - - { ngx_string("imap_client_buffer"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, + ngx_mail_core_protocol, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, imap_client_buffer_size), - NULL }, - - { ngx_string("smtp_client_buffer"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, smtp_client_buffer_size), - NULL }, - - { ngx_string("smtp_greeting_delay"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, smtp_greeting_delay), + 0, NULL }, { ngx_string("so_keepalive"), @@ -160,27 +59,6 @@ offsetof(ngx_mail_core_srv_conf_t, timeout), NULL }, - { ngx_string("pop3_capabilities"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, - ngx_mail_core_capability, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, pop3_capabilities), - NULL }, - - { ngx_string("imap_capabilities"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, - ngx_mail_core_capability, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, imap_capabilities), - NULL }, - - { ngx_string("smtp_capabilities"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, - ngx_mail_core_capability, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, smtp_capabilities), - NULL }, - { ngx_string("server_name"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -188,39 +66,13 @@ offsetof(ngx_mail_core_srv_conf_t, server_name), NULL }, - { ngx_string("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, pop3_auth_methods), - &ngx_pop3_auth_methods }, - - { ngx_string("pop3_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, 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, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_core_srv_conf_t, smtp_auth_methods), - &ngx_smtp_auth_methods }, - ngx_null_command }; static ngx_mail_module_t ngx_mail_core_module_ctx = { + NULL, /* protocol */ + ngx_mail_core_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ @@ -282,30 +134,14 @@ return NULL; } - cscf->imap_client_buffer_size = NGX_CONF_UNSET_SIZE; - cscf->smtp_client_buffer_size = NGX_CONF_UNSET_SIZE; - cscf->protocol = NGX_CONF_UNSET_UINT; - cscf->timeout = NGX_CONF_UNSET_MSEC; - cscf->smtp_greeting_delay = NGX_CONF_UNSET_MSEC; - cscf->so_keepalive = NGX_CONF_UNSET; + /* + * set by ngx_pcalloc(): + * + * cscf->protocol = NULL; + */ - if (ngx_array_init(&cscf->pop3_capabilities, cf->pool, 4, sizeof(ngx_str_t)) - != NGX_OK) - { - return NULL; - } - - if (ngx_array_init(&cscf->imap_capabilities, cf->pool, 4, sizeof(ngx_str_t)) - != NGX_OK) - { - return NULL; - } - - if (ngx_array_init(&cscf->smtp_capabilities, cf->pool, 4, sizeof(ngx_str_t)) - != NGX_OK) - { - return NULL; - } + cscf->timeout = NGX_CONF_UNSET_MSEC; + cscf->so_keepalive = NGX_CONF_UNSET; return cscf; } @@ -317,42 +153,10 @@ ngx_mail_core_srv_conf_t *prev = parent; ngx_mail_core_srv_conf_t *conf = child; - u_char *p, *auth; - size_t size, stls_only_size; - ngx_str_t *c, *d; - ngx_uint_t i, m; - - ngx_conf_merge_size_value(conf->imap_client_buffer_size, - prev->imap_client_buffer_size, - (size_t) ngx_pagesize); - ngx_conf_merge_size_value(conf->smtp_client_buffer_size, - prev->smtp_client_buffer_size, - (size_t) ngx_pagesize); - ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); - ngx_conf_merge_msec_value(conf->smtp_greeting_delay, - prev->smtp_greeting_delay, 0); - ngx_conf_merge_uint_value(conf->protocol, prev->protocol, - NGX_MAIL_IMAP_PROTOCOL); ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); - ngx_conf_merge_bitmask_value(conf->pop3_auth_methods, - prev->pop3_auth_methods, - (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 - |NGX_MAIL_AUTH_PLAIN_ENABLED - |NGX_MAIL_AUTH_LOGIN_ENABLED)); - ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); @@ -365,351 +169,21 @@ if (gethostname((char *) conf->server_name.data, NGX_MAXHOSTNAMELEN) == -1) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, - "gethostname() failed"); + ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, + "gethostname() failed"); return NGX_CONF_ERROR; } conf->server_name.len = ngx_strlen(conf->server_name.data); } - - if (conf->pop3_capabilities.nelts == 0) { - conf->pop3_capabilities = prev->pop3_capabilities; - } - - if (conf->pop3_capabilities.nelts == 0) { - - for (d = ngx_pop3_default_capabilities; d->len; d++) { - c = ngx_array_push(&conf->pop3_capabilities); - if (c == NULL) { - return NGX_CONF_ERROR; - } - - *c = *d; - } - } - - size = sizeof("+OK Capability list follows" CRLF) - 1 - + sizeof("." CRLF) - 1; - - stls_only_size = size + sizeof("STLS" CRLF) - 1; - - c = conf->pop3_capabilities.elts; - for (i = 0; i < conf->pop3_capabilities.nelts; i++) { - size += c[i].len + sizeof(CRLF) - 1; - - if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { - continue; - } - - stls_only_size += c[i].len + sizeof(CRLF) - 1; - } - - if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { - size += sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1; - - } else { - size += sizeof("SASL LOGIN PLAIN" CRLF) - 1; - } - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->pop3_capability.len = size; - conf->pop3_capability.data = p; - - p = ngx_cpymem(p, "+OK Capability list follows" CRLF, - sizeof("+OK Capability list follows" CRLF) - 1); - - for (i = 0; i < conf->pop3_capabilities.nelts; i++) { - p = ngx_cpymem(p, c[i].data, c[i].len); - *p++ = CR; *p++ = LF; - } - - if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { - p = ngx_cpymem(p, "SASL LOGIN PLAIN CRAM-MD5" CRLF, - sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1); - - } else { - p = ngx_cpymem(p, "SASL LOGIN PLAIN" CRLF, - sizeof("SASL LOGIN PLAIN" CRLF) - 1); - } - - *p++ = '.'; *p++ = CR; *p = LF; - - - size += sizeof("STLS" CRLF) - 1; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->pop3_starttls_capability.len = size; - conf->pop3_starttls_capability.data = p; - - p = ngx_cpymem(p, conf->pop3_capability.data, - conf->pop3_capability.len - (sizeof("." CRLF) - 1)); - - p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); - *p++ = '.'; *p++ = CR; *p = LF; - - - if (conf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { - conf->pop3_auth_capability = ngx_pop3_auth_cram_md5_capability; - - } else { - conf->pop3_auth_capability = ngx_pop3_auth_plain_capability; - } - - - p = ngx_palloc(cf->pool, stls_only_size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->pop3_starttls_only_capability.len = stls_only_size; - conf->pop3_starttls_only_capability.data = p; - - p = ngx_cpymem(p, "+OK Capability list follows" CRLF, - sizeof("+OK Capability list follows" CRLF) - 1); - - for (i = 0; i < conf->pop3_capabilities.nelts; i++) { - if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { - continue; - } - - p = ngx_cpymem(p, c[i].data, c[i].len); - *p++ = CR; *p++ = LF; - } - - p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); - *p++ = '.'; *p++ = CR; *p = LF; - - - if (conf->imap_capabilities.nelts == 0) { - conf->imap_capabilities = prev->imap_capabilities; - } - - if (conf->imap_capabilities.nelts == 0) { - - for (d = ngx_imap_default_capabilities; d->len; d++) { - c = ngx_array_push(&conf->imap_capabilities); - if (c == NULL) { - return NGX_CONF_ERROR; - } - - *c = *d; - } - } - - size = sizeof("* CAPABILITY" CRLF) - 1; - - c = conf->imap_capabilities.elts; - for (i = 0; i < conf->imap_capabilities.nelts; i++) { - 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) { + if (conf->protocol == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown mail protocol for server in %s:%ui", + conf->file_name, conf->line); return NGX_CONF_ERROR; } - conf->imap_capability.len = size; - conf->imap_capability.data = p; - - p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); - - for (i = 0; i < conf->imap_capabilities.nelts; i++) { - *p++ = ' '; - 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; - - - size += sizeof(" STARTTLS") - 1; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->imap_starttls_capability.len = size; - conf->imap_starttls_capability.data = p; - - p = ngx_cpymem(p, conf->imap_capability.data, - conf->imap_capability.len - (sizeof(CRLF) - 1)); - p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); - *p++ = CR; *p = LF; - - - size = (auth - conf->imap_capability.data) + sizeof(CRLF) - 1 - + sizeof(" STARTTLS LOGINDISABLED") - 1; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->imap_starttls_only_capability.len = size; - conf->imap_starttls_only_capability.data = p; - - 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; - - - size = sizeof("220 ESMTP ready" CRLF) - 1 + conf->server_name.len; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->smtp_greeting.len = size; - conf->smtp_greeting.data = p; - - *p++ = '2'; *p++ = '2'; *p++ = '0'; *p++ = ' '; - p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); - ngx_memcpy(p, " ESMTP ready" CRLF, sizeof(" ESMTP ready" CRLF) - 1); - - - size = sizeof("250 " CRLF) - 1 + conf->server_name.len; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->smtp_server_name.len = size; - conf->smtp_server_name.data = p; - - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; - p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); - *p++ = CR; *p = LF; - - - if (conf->smtp_capabilities.nelts == 0) { - conf->smtp_capabilities = prev->smtp_capabilities; - } - - size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1 - + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; - - c = conf->smtp_capabilities.elts; - for (i = 0; i < conf->smtp_capabilities.nelts; i++) { - size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; - } - - for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; - m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; - m <<= 1, i++) - { - if (m & conf->smtp_auth_methods) { - size += 1 + ngx_smtp_auth_methods_names[i].len; - } - } - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->smtp_capability.len = size; - conf->smtp_capability.data = p; - - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; - p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); - *p++ = CR; *p++ = LF; - - for (i = 0; i < conf->smtp_capabilities.nelts; i++) { - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; - p = ngx_cpymem(p, c[i].data, c[i].len); - *p++ = CR; *p++ = LF; - } - - auth = p; - - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; - *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; - - for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; - m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; - m <<= 1, i++) - { - if (m & conf->smtp_auth_methods) { - *p++ = ' '; - p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, - ngx_smtp_auth_methods_names[i].len); - } - } - - *p++ = CR; *p = LF; - - size += sizeof("250 STARTTLS" CRLF) - 1; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->smtp_starttls_capability.len = size; - conf->smtp_starttls_capability.data = p; - - p = ngx_cpymem(p, conf->smtp_capability.data, - conf->smtp_capability.len); - - p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); - *p++ = CR; *p = LF; - - p = conf->smtp_starttls_capability.data - + (auth - conf->smtp_capability.data) + 3; - *p = '-'; - - size = (auth - conf->smtp_capability.data) - + sizeof("250 STARTTLS" CRLF) - 1; - - p = ngx_palloc(cf->pool, size); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - conf->smtp_starttls_only_capability.len = size; - conf->smtp_starttls_only_capability.data = p; - - p = ngx_cpymem(p, conf->smtp_capability.data, - auth - conf->smtp_capability.data); - - ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); - return NGX_CONF_OK; } @@ -726,7 +200,6 @@ ngx_mail_core_srv_conf_t *cscf, **cscfp; ngx_mail_core_main_conf_t *cmcf; - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; @@ -764,6 +237,9 @@ cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; cscf->ctx = ctx; + cscf->file_name = cf->conf_file->file.name.data; + cscf->line = cf->conf_file->line; + cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); @@ -793,10 +269,13 @@ static char * ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + ngx_mail_core_srv_conf_t *cscf = conf; + ngx_str_t *value; ngx_url_t u; - ngx_uint_t i; + ngx_uint_t i, m; ngx_mail_listen_t *imls; + ngx_mail_module_t *module; ngx_mail_core_main_conf_t *cmcf; value = cf->args->elts; @@ -843,6 +322,25 @@ imls->family = AF_INET; imls->ctx = cf->ctx; + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->protocol == NULL) { + continue; + } + + for (i = 0; module->protocol->port[i]; i++) { + if (module->protocol->port[i] == u.port) { + cscf->protocol = module->protocol; + break; + } + } + } + if (cf->args->nelts == 2) { return NGX_CONF_OK; } @@ -859,7 +357,40 @@ static char * -ngx_mail_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_mail_core_srv_conf_t *cscf = conf; + + ngx_str_t *value; + ngx_uint_t m; + ngx_mail_module_t *module; + + value = cf->args->elts; + + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->protocol + && ngx_strcmp(module->protocol->name.data, value[1].data) == 0) + { + cscf->protocol = module->protocol; + + return NGX_CONF_OK; + } + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown protocol \"%V\"", &value[1]); + return NGX_CONF_ERROR; +} + + +char * +ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf;
--- a/src/mail/ngx_mail_handler.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_handler.c Sat Sep 15 16:51:16 2007 +0000 @@ -18,34 +18,6 @@ #endif -static ngx_mail_init_session_pt ngx_mail_init_sessions[] = { - ngx_mail_pop3_init_session, - ngx_mail_imap_init_session, - ngx_mail_smtp_init_session -}; - - -static ngx_mail_init_protocol_pt ngx_mail_init_protocols[] = { - ngx_mail_pop3_init_protocol, - ngx_mail_imap_init_protocol, - ngx_mail_smtp_init_protocol -}; - - -static ngx_mail_parse_command_pt ngx_mail_parse_commands[] = { - ngx_mail_pop3_parse_command, - ngx_mail_imap_parse_command, - ngx_mail_smtp_parse_command -}; - - -static ngx_str_t internal_server_errors[] = { - ngx_string("-ERR internal server error" CRLF), - ngx_string("* BAD internal server error" CRLF), - ngx_string("451 4.3.2 Internal server error" CRLF), -}; - - void ngx_mail_init_connection(ngx_connection_t *c) { @@ -210,17 +182,20 @@ static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c) { - ngx_mail_session_t *s; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; if (c->ssl->handshaked) { s = c->data; if (s->starttls) { - c->read->handler = ngx_mail_init_protocols[s->protocol]; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + c->read->handler = cscf->protocol->init_protocol; c->write->handler = ngx_mail_send; - ngx_mail_init_protocols[s->protocol](c->read); + cscf->protocol->init_protocol(c->read); return; } @@ -245,7 +220,7 @@ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - s->protocol = cscf->protocol; + s->protocol = cscf->protocol->type; s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module); if (s->ctx == NULL) { @@ -255,7 +230,7 @@ c->write->handler = ngx_mail_send; - ngx_mail_init_sessions[s->protocol](s, c); + cscf->protocol->init_session(s, c); } @@ -567,9 +542,10 @@ ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) { - ssize_t n; - ngx_int_t rc; - ngx_str_t l; + ssize_t n; + ngx_int_t rc; + ngx_str_t l; + ngx_mail_core_srv_conf_t *cscf; n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); @@ -591,7 +567,9 @@ return NGX_AGAIN; } - rc = ngx_mail_parse_commands[s->protocol](s); + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + rc = cscf->protocol->parse_command(s); if (rc == NGX_AGAIN) { @@ -644,7 +622,11 @@ void ngx_mail_session_internal_server_error(ngx_mail_session_t *s) { - s->out = internal_server_errors[s->protocol]; + 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);
--- a/src/mail/ngx_mail_imap_handler.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_imap_handler.c Sat Sep 15 16:51:16 2007 +0000 @@ -8,6 +8,7 @@ #include <ngx_core.h> #include <ngx_event.h> #include <ngx_mail.h> +#include <ngx_mail_imap_module.h> static ngx_int_t ngx_mail_imap_login(ngx_mail_session_t *s, @@ -58,7 +59,7 @@ { ngx_connection_t *c; ngx_mail_session_t *s; - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_imap_srv_conf_t *iscf; c = rev->data; @@ -81,9 +82,9 @@ return; } - 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->buffer = ngx_create_temp_buf(c->pool, cscf->imap_client_buffer_size); + s->buffer = ngx_create_temp_buf(c->pool, iscf->client_buffer_size); if (s->buffer == NULL) { ngx_mail_session_internal_server_error(s); return; @@ -349,6 +350,7 @@ { ngx_int_t rc; ngx_mail_core_srv_conf_t *cscf; + ngx_mail_imap_srv_conf_t *iscf; #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { @@ -378,13 +380,15 @@ case NGX_MAIL_AUTH_CRAM_MD5: - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); - if (!(cscf->imap_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } if (s->salt.data == NULL) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + if (ngx_mail_salt(s, c, cscf) != NGX_OK) { return NGX_ERROR; } @@ -405,12 +409,12 @@ static ngx_int_t ngx_mail_imap_capability(ngx_mail_session_t *s, ngx_connection_t *c) { - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_imap_srv_conf_t *iscf; #if (NGX_MAIL_SSL) ngx_mail_ssl_conf_t *sslcf; #endif - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); #if (NGX_MAIL_SSL) @@ -418,18 +422,18 @@ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { - s->text = cscf->imap_starttls_capability; + s->text = iscf->starttls_capability; return NGX_OK; } if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - s->text = cscf->imap_starttls_only_capability; + s->text = iscf->starttls_only_capability; return NGX_OK; } } #endif - s->text = cscf->imap_capability; + s->text = iscf->capability; return NGX_OK; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_imap_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,251 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> +#include <ngx_mail.h> +#include <ngx_mail_imap_module.h> + + +static void *ngx_mail_imap_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_imap_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_str_t ngx_mail_imap_default_capabilities[] = { + ngx_string("IMAP4"), + ngx_string("IMAP4rev1"), + ngx_string("UIDPLUS"), + ngx_null_string +}; + + +static ngx_conf_bitmask_t ngx_mail_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_str_t ngx_mail_imap_auth_methods_names[] = { + ngx_string("AUTH=PLAIN"), + ngx_string("AUTH=LOGIN"), + ngx_null_string, /* APOP */ + ngx_string("AUTH=CRAM-MD5") +}; + + +static ngx_mail_protocol_t ngx_mail_imap_protocol = { + ngx_string("imap"), + { 143, 993, 0, 0 }, + NGX_MAIL_IMAP_PROTOCOL, + + ngx_mail_imap_init_session, + ngx_mail_imap_init_protocol, + ngx_mail_imap_parse_command, + ngx_mail_imap_auth_state, + + ngx_string("* BAD internal server error" CRLF) +}; + + +static ngx_command_t ngx_mail_imap_commands[] = { + + { ngx_string("imap_client_buffer"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_imap_srv_conf_t, client_buffer_size), + NULL }, + + { ngx_string("imap_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_imap_srv_conf_t, capabilities), + NULL }, + + { 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_imap_srv_conf_t, auth_methods), + &ngx_mail_imap_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_imap_module_ctx = { + &ngx_mail_imap_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_imap_create_srv_conf, /* create server configuration */ + ngx_mail_imap_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_imap_module = { + NGX_MODULE_V1, + &ngx_mail_imap_module_ctx, /* module context */ + ngx_mail_imap_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_imap_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_imap_srv_conf_t *iscf; + + iscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_imap_srv_conf_t)); + if (iscf == NULL) { + return NULL; + } + + iscf->client_buffer_size = NGX_CONF_UNSET_SIZE; + + if (ngx_array_init(&iscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return iscf; +} + + +static char * +ngx_mail_imap_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_imap_srv_conf_t *prev = parent; + ngx_mail_imap_srv_conf_t *conf = child; + + u_char *p, *auth; + size_t size; + ngx_str_t *c, *d; + ngx_uint_t i, m; + + ngx_conf_merge_size_value(conf->client_buffer_size, + prev->client_buffer_size, + (size_t) ngx_pagesize); + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED)); + + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + if (conf->capabilities.nelts == 0) { + + for (d = ngx_mail_imap_default_capabilities; d->len; d++) { + c = ngx_array_push(&conf->capabilities); + if (c == NULL) { + return NGX_CONF_ERROR; + } + + *c = *d; + } + } + + size = sizeof("* CAPABILITY" CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + 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->auth_methods) { + size += 1 + ngx_mail_imap_auth_methods_names[i].len; + } + } + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + *p++ = ' '; + 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->auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_mail_imap_auth_methods_names[i].data, + ngx_mail_imap_auth_methods_names[i].len); + } + } + + *p++ = CR; *p = LF; + + + size += sizeof(" STARTTLS") - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + conf->capability.len - (sizeof(CRLF) - 1)); + p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); + *p++ = CR; *p = LF; + + + size = (auth - conf->capability.data) + sizeof(CRLF) - 1 + + sizeof(" STARTTLS LOGINDISABLED") - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + auth - conf->capability.data); + p = ngx_cpymem(p, " STARTTLS LOGINDISABLED", + sizeof(" STARTTLS LOGINDISABLED") - 1); + *p++ = CR; *p = LF; + + return NGX_CONF_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_imap_module.h Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,38 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ +#define _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_mail.h> + + +typedef struct { + size_t client_buffer_size; + + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_imap_srv_conf_t; + + +void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_imap_init_protocol(ngx_event_t *rev); +void ngx_mail_imap_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_imap_module; + + +#endif /* _NGX_MAIL_IMAP_MODULE_H_INCLUDED_ */
--- a/src/mail/ngx_mail_pop3_handler.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_pop3_handler.c Sat Sep 15 16:51:16 2007 +0000 @@ -8,6 +8,7 @@ #include <ngx_core.h> #include <ngx_event.h> #include <ngx_mail.h> +#include <ngx_mail_pop3_module.h> static ngx_int_t ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c); @@ -32,10 +33,12 @@ { 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 (cscf->pop3_auth_methods + if (pscf->auth_methods & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { if (ngx_mail_salt(s, c, cscf) != NGX_OK) { @@ -340,12 +343,12 @@ static ngx_int_t ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, ngx_int_t stls) { - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_pop3_srv_conf_t *pscf; #if (NGX_MAIL_SSL) ngx_mail_ssl_conf_t *sslcf; #endif - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); #if (NGX_MAIL_SSL) @@ -353,19 +356,19 @@ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { - s->out = cscf->pop3_starttls_capability; + s->out = pscf->starttls_capability; return NGX_OK; } if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - s->out = cscf->pop3_starttls_only_capability; + s->out = pscf->starttls_only_capability; return NGX_OK; } } #endif - s->out = cscf->pop3_capability; + s->out = pscf->capability; return NGX_OK; } @@ -394,7 +397,7 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_str_t *arg; - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_pop3_srv_conf_t *pscf; #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { @@ -406,9 +409,9 @@ return NGX_MAIL_PARSE_INVALID_COMMAND; } - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); - if (!(cscf->pop3_auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) { + if (!(pscf->auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } @@ -443,7 +446,7 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_int_t rc; - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_pop3_srv_conf_t *pscf; #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { @@ -451,10 +454,10 @@ } #endif - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); if (s->args.nelts == 0) { - s->out = cscf->pop3_auth_capability; + s->out = pscf->auth_capability; s->state = 0; return NGX_OK; @@ -482,7 +485,7 @@ case NGX_MAIL_AUTH_CRAM_MD5: - if (!(cscf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + if (!(pscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_pop3_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,263 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> +#include <ngx_mail.h> +#include <ngx_mail_pop3_module.h> + + +static void *ngx_mail_pop3_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_str_t ngx_mail_pop3_default_capabilities[] = { + ngx_string("TOP"), + ngx_string("USER"), + ngx_string("UIDL"), + ngx_null_string +}; + + +static ngx_conf_bitmask_t ngx_mail_pop3_auth_methods[] = { + { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, + { ngx_string("apop"), NGX_MAIL_AUTH_APOP_ENABLED }, + { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_null_string, 0 } +}; + + +static ngx_str_t ngx_mail_pop3_auth_plain_capability = + ngx_string("+OK methods supported:" CRLF + "LOGIN" CRLF + "PLAIN" CRLF + "." CRLF); + + +static ngx_str_t ngx_mail_pop3_auth_cram_md5_capability = + ngx_string("+OK methods supported:" CRLF + "LOGIN" CRLF + "PLAIN" CRLF + "CRAM-MD5" CRLF + "." CRLF); + + +static ngx_mail_protocol_t ngx_mail_pop3_protocol = { + ngx_string("pop3"), + { 110, 995, 0, 0 }, + NGX_MAIL_POP3_PROTOCOL, + + ngx_mail_pop3_init_session, + ngx_mail_pop3_init_protocol, + ngx_mail_pop3_parse_command, + ngx_mail_pop3_auth_state, + + ngx_string("-ERR internal server error" CRLF) +}; + + +static ngx_command_t ngx_mail_pop3_commands[] = { + + { ngx_string("pop3_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_pop3_srv_conf_t, capabilities), + NULL }, + + { ngx_string("pop3_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_pop3_srv_conf_t, auth_methods), + &ngx_mail_pop3_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_pop3_module_ctx = { + &ngx_mail_pop3_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_pop3_create_srv_conf, /* create server configuration */ + ngx_mail_pop3_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_pop3_module = { + NGX_MODULE_V1, + &ngx_mail_pop3_module_ctx, /* module context */ + ngx_mail_pop3_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_pop3_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_pop3_srv_conf_t *pscf; + + pscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_pop3_srv_conf_t)); + if (pscf == NULL) { + return NULL; + } + + if (ngx_array_init(&pscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return pscf; +} + + +static char * +ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_pop3_srv_conf_t *prev = parent; + ngx_mail_pop3_srv_conf_t *conf = child; + + u_char *p; + size_t size, stls_only_size; + ngx_str_t *c, *d; + ngx_uint_t i; + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED)); + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + if (conf->capabilities.nelts == 0) { + + for (d = ngx_mail_pop3_default_capabilities; d->len; d++) { + c = ngx_array_push(&conf->capabilities); + if (c == NULL) { + return NGX_CONF_ERROR; + } + + *c = *d; + } + } + + size = sizeof("+OK Capability list follows" CRLF) - 1 + + sizeof("." CRLF) - 1; + + stls_only_size = size + sizeof("STLS" CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + size += c[i].len + sizeof(CRLF) - 1; + + if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { + continue; + } + + stls_only_size += c[i].len + sizeof(CRLF) - 1; + } + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + size += sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1; + + } else { + size += sizeof("SASL LOGIN PLAIN" CRLF) - 1; + } + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + p = ngx_cpymem(p, "+OK Capability list follows" CRLF, + sizeof("+OK Capability list follows" CRLF) - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + p = ngx_cpymem(p, "SASL LOGIN PLAIN CRAM-MD5" CRLF, + sizeof("SASL LOGIN PLAIN CRAM-MD5" CRLF) - 1); + + } else { + p = ngx_cpymem(p, "SASL LOGIN PLAIN" CRLF, + sizeof("SASL LOGIN PLAIN" CRLF) - 1); + } + + *p++ = '.'; *p++ = CR; *p = LF; + + + size += sizeof("STLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + conf->capability.len - (sizeof("." CRLF) - 1)); + + p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); + *p++ = '.'; *p++ = CR; *p = LF; + + + if (conf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) { + conf->auth_capability = ngx_mail_pop3_auth_cram_md5_capability; + + } else { + conf->auth_capability = ngx_mail_pop3_auth_plain_capability; + } + + + p = ngx_palloc(cf->pool, stls_only_size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = stls_only_size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, "+OK Capability list follows" CRLF, + sizeof("+OK Capability list follows" CRLF) - 1); + + for (i = 0; i < conf->capabilities.nelts; i++) { + if (ngx_strcasecmp(c[i].data, (u_char *) "USER") == 0) { + continue; + } + + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); + *p++ = '.'; *p++ = CR; *p = LF; + + return NGX_CONF_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_pop3_module.h Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,37 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_MAIL_POP3_MODULE_H_INCLUDED_ +#define _NGX_MAIL_POP3_MODULE_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_mail.h> + + +typedef struct { + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + ngx_str_t auth_capability; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_pop3_srv_conf_t; + + +void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_pop3_init_protocol(ngx_event_t *rev); +void ngx_mail_pop3_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_pop3_module; + + +#endif /* _NGX_MAIL_POP3_MODULE_H_INCLUDED_ */
--- a/src/mail/ngx_mail_proxy_module.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_proxy_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -78,6 +78,8 @@ static ngx_mail_module_t ngx_mail_proxy_module_ctx = { + NULL, /* protocol */ + NULL, /* create main configuration */ NULL, /* init main configuration */
--- a/src/mail/ngx_mail_smtp_handler.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_smtp_handler.c Sat Sep 15 16:51:16 2007 +0000 @@ -8,6 +8,7 @@ #include <ngx_core.h> #include <ngx_event.h> #include <ngx_mail.h> +#include <ngx_mail_smtp_module.h> static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); @@ -43,25 +44,26 @@ { 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 = cscf->smtp_greeting_delay ? cscf->smtp_greeting_delay: - cscf->timeout; + 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 (cscf->smtp_greeting_delay) { + if (sscf->greeting_delay) { c->read->handler = ngx_mail_smtp_invalid_pipelining; return; } c->read->handler = ngx_mail_smtp_init_protocol; - s->out = cscf->smtp_greeting; + s->out = sscf->greeting; ngx_mail_send(c->write); } @@ -73,6 +75,7 @@ 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; @@ -96,7 +99,9 @@ return; } - s->out = cscf->smtp_greeting; + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + + s->out = sscf->greeting; } else { @@ -158,16 +163,16 @@ static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c) { - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) { ngx_mail_session_internal_server_error(s); return NGX_ERROR; } - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); - s->buffer = ngx_create_temp_buf(c->pool, cscf->smtp_client_buffer_size); + s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size); if (s->buffer == NULL) { ngx_mail_session_internal_server_error(s); return NGX_ERROR; @@ -313,13 +318,11 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_str_t *arg; - ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; #if (NGX_MAIL_SSL) ngx_mail_ssl_conf_t *sslcf; #endif - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - if (s->args.nelts != 1) { s->out.len = sizeof(smtp_invalid_argument) - 1; s->out.data = smtp_invalid_argument; @@ -338,8 +341,10 @@ ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + if (s->command == NGX_SMTP_HELO) { - s->out = cscf->smtp_server_name; + s->out = sscf->server_name; } else { s->esmtp = 1; @@ -350,18 +355,18 @@ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { - s->out = cscf->smtp_starttls_capability; + s->out = sscf->starttls_capability; return NGX_OK; } if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - s->out = cscf->smtp_starttls_only_capability; + s->out = sscf->starttls_only_capability; return NGX_OK; } } #endif - s->out = cscf->smtp_capability; + s->out = sscf->capability; } return NGX_OK; @@ -373,6 +378,7 @@ { ngx_int_t rc; ngx_mail_core_srv_conf_t *cscf; + ngx_mail_smtp_srv_conf_t *sscf; #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { @@ -409,13 +415,15 @@ case NGX_MAIL_AUTH_CRAM_MD5: - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); - if (!(cscf->smtp_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { + if (!(sscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } if (s->salt.data == NULL) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + if (ngx_mail_salt(s, c, cscf) != NGX_OK) { return NGX_ERROR; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_smtp_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,285 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> +#include <ngx_mail.h> +#include <ngx_mail_smtp_module.h> + + +static void *ngx_mail_smtp_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); + + +static ngx_conf_bitmask_t ngx_mail_smtp_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_str_t ngx_mail_smtp_auth_methods_names[] = { + ngx_string("PLAIN"), + ngx_string("LOGIN"), + ngx_null_string, /* APOP */ + ngx_string("CRAM-MD5") +}; + + +static ngx_mail_protocol_t ngx_mail_smtp_protocol = { + ngx_string("smtp"), + { 25, 465, 587, 0 }, + NGX_MAIL_SMTP_PROTOCOL, + + ngx_mail_smtp_init_session, + ngx_mail_smtp_init_protocol, + ngx_mail_smtp_parse_command, + ngx_mail_smtp_auth_state, + + ngx_string("451 4.3.2 Internal server error" CRLF) +}; + + +static ngx_command_t ngx_mail_smtp_commands[] = { + + { ngx_string("smtp_client_buffer"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, client_buffer_size), + NULL }, + + { ngx_string("smtp_greeting_delay"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, greeting_delay), + NULL }, + + { ngx_string("smtp_capabilities"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE, + ngx_mail_capabilities, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_smtp_srv_conf_t, capabilities), + NULL }, + + { ngx_string("smtp_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_smtp_srv_conf_t, auth_methods), + &ngx_mail_smtp_auth_methods }, + + ngx_null_command +}; + + +static ngx_mail_module_t ngx_mail_smtp_module_ctx = { + &ngx_mail_smtp_protocol, /* protocol */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_mail_smtp_create_srv_conf, /* create server configuration */ + ngx_mail_smtp_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_mail_smtp_module = { + NGX_MODULE_V1, + &ngx_mail_smtp_module_ctx, /* module context */ + ngx_mail_smtp_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void * +ngx_mail_smtp_create_srv_conf(ngx_conf_t *cf) +{ + ngx_mail_smtp_srv_conf_t *sscf; + + sscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_smtp_srv_conf_t)); + if (sscf == NULL) { + return NULL; + } + + sscf->client_buffer_size = NGX_CONF_UNSET_SIZE; + sscf->greeting_delay = NGX_CONF_UNSET_MSEC; + + if (ngx_array_init(&sscf->capabilities, cf->pool, 4, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + + return sscf; +} + + +static char * +ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_mail_smtp_srv_conf_t *prev = parent; + ngx_mail_smtp_srv_conf_t *conf = child; + + u_char *p, *auth; + size_t size; + ngx_str_t *c; + ngx_uint_t i, m; + ngx_mail_core_srv_conf_t *cscf; + + ngx_conf_merge_size_value(conf->client_buffer_size, + prev->client_buffer_size, + (size_t) ngx_pagesize); + + ngx_conf_merge_msec_value(conf->greeting_delay, + prev->greeting_delay, 0); + + ngx_conf_merge_bitmask_value(conf->auth_methods, + prev->auth_methods, + (NGX_CONF_BITMASK_SET + |NGX_MAIL_AUTH_PLAIN_ENABLED + |NGX_MAIL_AUTH_LOGIN_ENABLED)); + + + cscf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_core_module); + + size = sizeof("220 ESMTP ready" CRLF) - 1 + cscf->server_name.len; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->greeting.len = size; + conf->greeting.data = p; + + *p++ = '2'; *p++ = '2'; *p++ = '0'; *p++ = ' '; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + ngx_memcpy(p, " ESMTP ready" CRLF, sizeof(" ESMTP ready" CRLF) - 1); + + + size = sizeof("250 " CRLF) - 1 + cscf->server_name.len; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->server_name.len = size; + conf->server_name.data = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + *p++ = CR; *p = LF; + + + if (conf->capabilities.nelts == 0) { + conf->capabilities = prev->capabilities; + } + + size = sizeof("250-") - 1 + cscf->server_name.len + sizeof(CRLF) - 1 + + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + + c = conf->capabilities.elts; + for (i = 0; i < conf->capabilities.nelts; i++) { + size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; + } + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + size += 1 + ngx_mail_smtp_auth_methods_names[i].len; + } + } + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->capability.len = size; + conf->capability.data = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; + p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); + *p++ = CR; *p++ = LF; + + for (i = 0; i < conf->capabilities.nelts; i++) { + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + auth = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; + + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_mail_smtp_auth_methods_names[i].data, + ngx_mail_smtp_auth_methods_names[i].len); + } + } + + *p++ = CR; *p = LF; + + size += sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_capability.len = size; + conf->starttls_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + conf->capability.len); + + p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + *p++ = CR; *p = LF; + + p = conf->starttls_capability.data + + (auth - conf->capability.data) + 3; + *p = '-'; + + size = (auth - conf->capability.data) + + sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->starttls_only_capability.len = size; + conf->starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->capability.data, + auth - conf->capability.data); + + ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + + return NGX_CONF_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_smtp_module.h Sat Sep 15 16:51:16 2007 +0000 @@ -0,0 +1,44 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ +#define _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_mail.h> +#include <ngx_mail_smtp_module.h> + + +typedef struct { + ngx_msec_t greeting_delay; + + size_t client_buffer_size; + + ngx_str_t capability; + ngx_str_t starttls_capability; + ngx_str_t starttls_only_capability; + + ngx_str_t server_name; + ngx_str_t greeting; + + ngx_uint_t auth_methods; + + ngx_array_t capabilities; +} ngx_mail_smtp_srv_conf_t; + + +void ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_smtp_init_protocol(ngx_event_t *rev); +void ngx_mail_smtp_auth_state(ngx_event_t *rev); +ngx_int_t ngx_mail_smtp_parse_command(ngx_mail_session_t *s); + + +extern ngx_module_t ngx_mail_smtp_module; + + +#endif /* _NGX_MAIL_SMTP_MODULE_H_INCLUDED_ */
--- a/src/mail/ngx_mail_ssl_module.c Fri Sep 14 15:04:45 2007 +0000 +++ b/src/mail/ngx_mail_ssl_module.c Sat Sep 15 16:51:16 2007 +0000 @@ -120,6 +120,8 @@ static ngx_mail_module_t ngx_mail_ssl_module_ctx = { + NULL, /* protocol */ + NULL, /* create main configuration */ NULL, /* init main configuration */