mirror of
https://github.com/nginx/nginx.git
synced 2024-12-01 21:19:12 -06:00
AUTH PLAIN LOGIN CRAM-MD5
This commit is contained in:
parent
df6f57afeb
commit
50cca1cb4b
@ -83,6 +83,8 @@ typedef struct {
|
||||
|
||||
ngx_str_t pop3_capability;
|
||||
ngx_str_t pop3_starttls_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;
|
||||
@ -120,7 +122,11 @@ typedef enum {
|
||||
typedef enum {
|
||||
ngx_pop3_start = 0,
|
||||
ngx_pop3_user,
|
||||
ngx_pop3_passwd
|
||||
ngx_pop3_passwd,
|
||||
ngx_pop3_auth_login_username,
|
||||
ngx_pop3_auth_login_password,
|
||||
ngx_pop3_auth_plain,
|
||||
ngx_pop3_auth_cram_md5
|
||||
} ngx_po3_state_e;
|
||||
|
||||
|
||||
@ -153,7 +159,7 @@ typedef struct {
|
||||
unsigned backslash:1;
|
||||
unsigned no_sync_literal:1;
|
||||
unsigned starttls:1;
|
||||
unsigned auth_method:1;
|
||||
unsigned auth_method:2;
|
||||
|
||||
ngx_str_t login;
|
||||
ngx_str_t passwd;
|
||||
@ -192,13 +198,14 @@ typedef struct {
|
||||
#define NGX_POP3_NOOP 5
|
||||
#define NGX_POP3_STLS 6
|
||||
#define NGX_POP3_APOP 7
|
||||
#define NGX_POP3_STAT 8
|
||||
#define NGX_POP3_LIST 9
|
||||
#define NGX_POP3_RETR 10
|
||||
#define NGX_POP3_DELE 11
|
||||
#define NGX_POP3_RSET 12
|
||||
#define NGX_POP3_TOP 13
|
||||
#define NGX_POP3_UIDL 14
|
||||
#define NGX_POP3_AUTH 8
|
||||
#define NGX_POP3_STAT 9
|
||||
#define NGX_POP3_LIST 10
|
||||
#define NGX_POP3_RETR 11
|
||||
#define NGX_POP3_DELE 12
|
||||
#define NGX_POP3_RSET 13
|
||||
#define NGX_POP3_TOP 14
|
||||
#define NGX_POP3_UIDL 15
|
||||
|
||||
|
||||
#define NGX_IMAP_LOGIN 1
|
||||
@ -210,12 +217,14 @@ typedef struct {
|
||||
#define NGX_IMAP_NEXT 6
|
||||
|
||||
|
||||
#define NGX_IMAP_AUTH_PLAIN 0
|
||||
#define NGX_IMAP_AUTH_APOP 1
|
||||
#define NGX_IMAP_AUTH_PLAIN 0
|
||||
#define NGX_IMAP_AUTH_APOP 1
|
||||
#define NGX_IMAP_AUTH_CRAM_MD5 2
|
||||
|
||||
|
||||
#define NGX_IMAP_AUTH_PLAIN_ENABLED 0x0002
|
||||
#define NGX_IMAP_AUTH_APOP_ENABLED 0x0004
|
||||
#define NGX_IMAP_AUTH_PLAIN_ENABLED 0x0002
|
||||
#define NGX_IMAP_AUTH_APOP_ENABLED 0x0004
|
||||
#define NGX_IMAP_AUTH_CRAM_MD5_ENABLED 0x0008
|
||||
|
||||
|
||||
#define NGX_IMAP_PARSE_INVALID_COMMAND 20
|
||||
|
@ -133,7 +133,9 @@ ngx_module_t ngx_imap_auth_http_module = {
|
||||
|
||||
static char *ngx_imap_auth_http_protocol[] = { "pop3", "imap" };
|
||||
static ngx_str_t ngx_imap_auth_http_method[] = {
|
||||
ngx_string("plain"), ngx_string("apop")
|
||||
ngx_string("plain"),
|
||||
ngx_string("apop"),
|
||||
ngx_string("cram-md5")
|
||||
};
|
||||
|
||||
|
||||
@ -1078,7 +1080,7 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool,
|
||||
b->last = ngx_copy(b->last, passwd.data, passwd.len);
|
||||
*b->last++ = CR; *b->last++ = LF;
|
||||
|
||||
if (s->salt.len) {
|
||||
if (s->auth_method != NGX_IMAP_AUTH_PLAIN && s->salt.len) {
|
||||
b->last = ngx_cpymem(b->last, "Auth-Salt: ", sizeof("Auth-Salt: ") - 1);
|
||||
b->last = ngx_copy(b->last, s->salt.data, s->salt.len);
|
||||
|
||||
|
@ -48,10 +48,27 @@ static ngx_str_t ngx_imap_default_capabilities[] = {
|
||||
static ngx_conf_bitmask_t ngx_imap_auth_methods[] = {
|
||||
{ ngx_string("plain"), NGX_IMAP_AUTH_PLAIN_ENABLED },
|
||||
{ ngx_string("apop"), NGX_IMAP_AUTH_APOP_ENABLED },
|
||||
{ ngx_string("cram-md5"), NGX_IMAP_AUTH_CRAM_MD5_ENABLED },
|
||||
{ ngx_null_string, 0 }
|
||||
};
|
||||
|
||||
|
||||
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_imap_core_commands[] = {
|
||||
|
||||
{ ngx_string("server"),
|
||||
@ -279,6 +296,13 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
size += c[i].len + sizeof(CRLF) - 1;
|
||||
}
|
||||
|
||||
if (conf->auth_methods & NGX_IMAP_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;
|
||||
@ -295,6 +319,15 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
*p++ = CR; *p++ = LF;
|
||||
}
|
||||
|
||||
if (conf->auth_methods & NGX_IMAP_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;
|
||||
|
||||
|
||||
@ -315,6 +348,14 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
*p++ = '.'; *p++ = CR; *p = LF;
|
||||
|
||||
|
||||
if (conf->auth_methods & NGX_IMAP_AUTH_CRAM_MD5_ENABLED) {
|
||||
conf->pop3_auth_capability = ngx_pop3_auth_cram_md5_capability;
|
||||
|
||||
} else {
|
||||
conf->pop3_auth_capability = ngx_pop3_auth_plain_capability;
|
||||
}
|
||||
|
||||
|
||||
if (conf->imap_capabilities.nelts == 0) {
|
||||
conf->imap_capabilities = prev->imap_capabilities;
|
||||
}
|
||||
|
@ -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,78 @@ 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_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;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->args.nelts != 1) {
|
||||
rc = NGX_IMAP_PARSE_INVALID_COMMAND;
|
||||
break;
|
||||
}
|
||||
|
||||
arg = s->args.elts;
|
||||
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
s->arg_start = s->buffer->start;
|
||||
|
||||
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 +937,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,6 +966,189 @@ 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;
|
||||
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
s->arg_start = s->buffer->start;
|
||||
|
||||
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");
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
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");
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
#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");
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
p = plain.data;
|
||||
last = p + plain.len;
|
||||
|
||||
while (p < last && *p++) { /* void */ }
|
||||
|
||||
s->login.data = p;
|
||||
|
||||
while (p < last && *p) { p++; }
|
||||
|
||||
s->login.len = p++ - s->login.data;
|
||||
s->passwd.data = p;
|
||||
|
||||
while (p < last && *p) { p++; }
|
||||
|
||||
s->passwd.len = p - s->passwd.data;
|
||||
|
||||
#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 LOGIN command");
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,6 +441,10 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s)
|
||||
{
|
||||
s->command = NGX_POP3_CAPA;
|
||||
|
||||
} else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H')
|
||||
{
|
||||
s->command = NGX_POP3_AUTH;
|
||||
|
||||
} else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P')
|
||||
{
|
||||
s->command = NGX_POP3_NOOP;
|
||||
@ -571,8 +575,7 @@ done:
|
||||
s->arg_start = NULL;
|
||||
}
|
||||
|
||||
s->state = sw_start;
|
||||
|
||||
s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument;
|
||||
return NGX_OK;
|
||||
|
||||
invalid:
|
||||
|
Loading…
Reference in New Issue
Block a user