Mercurial > hg > nginx
view src/mail/ngx_mail_pop3_module.c @ 5396:42f874c0b970
Mail: added session close on smtp_greeting_delay violation.
A server MUST send greeting before other replies, while before this
change in case of smtp_greeting_delay violation the 220 greeting was
sent after several 503 replies to commands received before greeting,
resulting in protocol synchronization loss. Moreover, further commands
were accepted after the greeting.
While closing a connection isn't strictly RFC compliant (RFC 5321
requires servers to wait for a QUIT before closing a connection), it's
probably good enough for practial uses.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 30 Sep 2013 22:09:50 +0400 |
parents | d620f497c50f |
children | ec01b1d1fff1 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #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_pnalloc(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_pnalloc(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_pnalloc(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; }