Mercurial > hg > nginx-vendor-0-6
diff src/imap/ngx_imap_handler.c @ 252:644510700914 NGINX_0_4_11
nginx 0.4.11
*) Feature: the POP3 proxy supports the AUTH LOGIN PLAIN and CRAM-MD5.
*) Feature: the ngx_http_perl_module supports the $r->allow_ranges
method.
*) Bugfix: if the APOP was enabled in the POP3 proxy, then the
USER/PASS commands might not work; bug appeared in 0.4.10.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 25 Oct 2006 00:00:00 +0400 |
parents | fbf2b2f66c9f |
children | 6ae1357b7b7c |
line wrap: on
line diff
--- a/src/imap/ngx_imap_handler.c +++ b/src/imap/ngx_imap_handler.c @@ -32,6 +32,9 @@ static ngx_str_t internal_server_errors }; static u_char pop3_ok[] = "+OK" CRLF; +static u_char pop3_next[] = "+ " CRLF; +static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; +static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; static u_char imap_star[] = "* "; @@ -547,11 +550,9 @@ ngx_imap_auth_state(ngx_event_t *rev) ngx_imap_auth_http_init(s); return; - - } else { - rc = NGX_IMAP_PARSE_INVALID_COMMAND; } + rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; case NGX_IMAP_CAPABILITY: @@ -666,10 +667,10 @@ ngx_imap_auth_state(ngx_event_t *rev) void ngx_pop3_auth_state(ngx_event_t *rev) { - u_char *text; + u_char *text, *p, *last; ssize_t size; ngx_int_t rc; - ngx_str_t *arg; + ngx_str_t *arg, salt, plain; ngx_connection_t *c; ngx_imap_session_t *s; ngx_imap_core_srv_conf_t *cscf; @@ -730,10 +731,10 @@ ngx_pop3_auth_state(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "pop3 login: \"%V\"", &s->login); - } else { - rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; } + rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; case NGX_POP3_CAPA: @@ -799,11 +800,74 @@ ngx_pop3_auth_state(ngx_event_t *rev) ngx_imap_auth_http_init(s); return; + } - } else { + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + + case NGX_POP3_AUTH: + cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); + + if (s->args.nelts == 0) { + size = cscf->pop3_auth_capability.len; + text = cscf->pop3_auth_capability.data; + s->state = 0; + break; + } + + if (s->args.nelts != 1) { rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; } + arg = s->args.elts; + + if (arg[0].len == 5) { + + if (ngx_strncasecmp(arg[0].data, "LOGIN", 5) == 0) { + s->imap_state = ngx_pop3_auth_login_username; + + size = sizeof(pop3_username) - 1; + text = pop3_username; + + break; + + } else if (ngx_strncasecmp(arg[0].data, "PLAIN", 5) == 0) { + s->imap_state = ngx_pop3_auth_plain; + + size = sizeof(pop3_next) - 1; + text = pop3_next; + + break; + } + + } else if (arg[0].len == 8 + && ngx_strncasecmp(arg[0].data, "CRAM-MD5", 8) == 0) + { + s->imap_state = ngx_pop3_auth_cram_md5; + + text = ngx_palloc(c->pool, + sizeof("+ " CRLF) - 1 + + ngx_base64_encoded_length(s->salt.len)); + if (text == NULL) { + ngx_imap_session_internal_server_error(s); + return; + } + + text[0] = '+'; text[1]= ' '; + salt.data = &text[2]; + s->salt.len -= 2; + + ngx_encode_base64(&salt, &s->salt); + + s->salt.len += 2; + size = 2 + salt.len; + text[size++] = CR; text[size++] = LF; + + break; + } + + rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; case NGX_POP3_QUIT: @@ -869,11 +933,9 @@ ngx_pop3_auth_state(ngx_event_t *rev) ngx_imap_auth_http_init(s); return; - - } else { - rc = NGX_IMAP_PARSE_INVALID_COMMAND; } + rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; case NGX_POP3_CAPA: @@ -900,10 +962,212 @@ ngx_pop3_auth_state(ngx_event_t *rev) /* suppress warinings */ case ngx_pop3_passwd: break; + + case ngx_pop3_auth_login_username: + arg = s->args.elts; + s->imap_state = ngx_pop3_auth_login_password; + + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth login username: \"%V\"", &arg[0]); + + s->login.data = ngx_palloc(c->pool, + ngx_base64_decoded_length(arg[0].len)); + if (s->login.data == NULL){ + ngx_imap_session_internal_server_error(s); + return; + } + + if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding " + "in AUTH LOGIN command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth login username: \"%V\"", &s->login); + + size = sizeof(pop3_password) - 1; + text = pop3_password; + + break; + + case ngx_pop3_auth_login_password: + arg = s->args.elts; + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth login password: \"%V\"", &arg[0]); +#endif + + s->passwd.data = ngx_palloc(c->pool, + ngx_base64_decoded_length(arg[0].len)); + if (s->passwd.data == NULL){ + ngx_imap_session_internal_server_error(s); + return; + } + + if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding " + "in AUTH LOGIN command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth login password: \"%V\"", &s->passwd); +#endif + + s->args.nelts = 0; + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + if (rev->timer_set) { + ngx_del_timer(rev); + } + + ngx_imap_auth_http_init(s); + + return; + + case ngx_pop3_auth_plain: + arg = s->args.elts; + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth plain: \"%V\"", &arg[0]); +#endif + + plain.data = ngx_palloc(c->pool, + ngx_base64_decoded_length(arg[0].len)); + if (plain.data == NULL){ + ngx_imap_session_internal_server_error(s); + return; + } + + if (ngx_decode_base64(&plain, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding " + "in AUTH PLAIN command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + p = plain.data; + last = p + plain.len; + + while (p < last && *p++) { /* void */ } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid login " + "in AUTH PLAIN command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + s->login.data = p; + + while (p < last && *p) { p++; } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid password " + "in AUTH PLAIN command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + s->login.len = p++ - s->login.data; + + s->passwd.len = last - p; + s->passwd.data = p; + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth plain: \"%V\" \"%V\"", + &s->login, &s->passwd); +#endif + + s->args.nelts = 0; + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + if (rev->timer_set) { + ngx_del_timer(rev); + } + + ngx_imap_auth_http_init(s); + + return; + + case ngx_pop3_auth_cram_md5: + arg = s->args.elts; + + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth cram-md5: \"%V\"", &arg[0]); + + s->login.data = ngx_palloc(c->pool, + ngx_base64_decoded_length(arg[0].len)); + if (s->login.data == NULL){ + ngx_imap_session_internal_server_error(s); + return; + } + + if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid base64 encoding " + "in AUTH CRAM-MD5 command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + p = s->login.data; + last = p + s->login.len; + + while (p < last) { + if (*p++ == ' ') { + s->login.len = p - s->login.data - 1; + s->passwd.len = last - p; + s->passwd.data = p; + break; + } + } + + if (s->passwd.len != 32) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid CRAM-MD5 hash " + "in AUTH CRAM-MD5 command"); + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + + ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, + "pop3 auth cram-md5: \"%V\" \"%V\"", + &s->login, &s->passwd); + + s->auth_method = NGX_IMAP_AUTH_CRAM_MD5; + + s->args.nelts = 0; + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + + if (rev->timer_set) { + ngx_del_timer(rev); + } + + ngx_imap_auth_http_init(s); + + return; } } if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) { + s->imap_state = ngx_pop3_start; + s->state = 0; text = pop3_invalid_command; size = sizeof(pop3_invalid_command) - 1; } @@ -912,6 +1176,10 @@ ngx_pop3_auth_state(ngx_event_t *rev) s->buffer->pos = s->buffer->start; s->buffer->last = s->buffer->start; + if (s->state) { + s->arg_start = s->buffer->start; + } + s->out.data = text; s->out.len = size;