static void ngx_mail_zmauth_wait_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_zmauth_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, ev->log, 0, "mail zmauth wait handler"); c = ev->data; s = c->data; ctx = ngx_mail_get_module_ctx(s, ngx_mail_zmauth_module); if (ev->timedout) { /* we need to close the connection immediately */ ngx_destroy_pool(ctx->pool); ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module); s->quit = 1; ngx_mail_send(c->write); return; } if (ev->active) { if (ngx_handle_read_event(ev, 0) != NGX_OK) { ngx_mail_close_connection(c); } } }
static void ngx_mail_zmauth_cleanup (void * data) { ngx_mail_session_t * s; ngx_mail_zmauth_ctx_t * ctx; s = (ngx_mail_session_t *)data; ctx = ngx_mail_get_module_ctx(s, ngx_mail_zmauth_module); if (ctx != NULL) { ngx_zm_lookup_finalize(ctx->work); ngx_destroy_pool(ctx->pool); ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module); } }
void ngx_mail_auth_http_init(ngx_mail_session_t *s) { ngx_int_t rc; ngx_pool_t *pool; ngx_mail_auth_http_ctx_t *ctx; ngx_mail_auth_http_conf_t *ahcf; s->connection->log->action = "in http auth state"; pool = ngx_create_pool(2048, s->connection->log); if (pool == NULL) { ngx_mail_session_internal_server_error(s); return; } ctx = ngx_pcalloc(pool, sizeof(ngx_mail_auth_http_ctx_t)); if (ctx == NULL) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } ctx->pool = pool; ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module); ctx->request = ngx_mail_auth_http_create_request(s, pool, ahcf); if (ctx->request == NULL) { ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ngx_mail_set_ctx(s, ctx, ngx_mail_auth_http_module); ctx->peer.sockaddr = ahcf->peer->sockaddr; ctx->peer.socklen = ahcf->peer->socklen; ctx->peer.name = &ahcf->peer->name; ctx->peer.get = ngx_event_get_peer; ctx->peer.log = s->connection->log; ctx->peer.log_error = NGX_ERROR_ERR; rc = ngx_event_connect_peer(&ctx->peer); if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { if (ctx->peer.connection) { ngx_close_connection(ctx->peer.connection); } ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ctx->peer.connection->data = s; ctx->peer.connection->pool = s->connection->pool; s->connection->read->handler = ngx_mail_auth_http_block_read; ctx->peer.connection->read->handler = ngx_mail_auth_http_read_handler; ctx->peer.connection->write->handler = ngx_mail_auth_http_write_handler; ctx->handler = ngx_mail_auth_http_ignore_status_line; ngx_add_timer(ctx->peer.connection->read, ahcf->timeout); ngx_add_timer(ctx->peer.connection->write, ahcf->timeout); if (rc == NGX_OK) { ngx_mail_auth_http_write_handler(ctx->peer.connection->write); return; } }
void ngx_mail_zmauth_init(ngx_mail_session_t *s) { ngx_pool_t *pool; ngx_mail_zmauth_ctx_t *ctx; ngx_zm_lookup_work_t *work; ngx_str_t escaped_login, escaped_account_name; ngx_mail_cleanup_t *cln; ngx_flag_t proxy_ssl; s->connection->log->action = "in mail zmauth state"; /* create pool and module context */ pool = ngx_create_pool(2048, s->connection->log); if (pool == NULL) { ngx_mail_session_internal_server_error(s); return; } ctx = ngx_pcalloc(pool, sizeof(ngx_mail_zmauth_ctx_t)); if (ctx == NULL) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } ctx->pool = pool; ngx_mail_set_ctx(s, ctx, ngx_mail_zmauth_module); /* init clean up */ cln = ngx_mail_cleanup_add(s, 0); cln->data = s; cln->handler = ngx_mail_zmauth_cleanup; /* init wait event */ ctx->wait_ev = ngx_palloc(pool, sizeof(ngx_event_t)); if (ctx->wait_ev == NULL) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } ngx_memzero (ctx->wait_ev, sizeof (ngx_event_t)); ctx->wait_ev->handler = ngx_mail_zmauth_wait_handler; ctx->wait_ev->log = s->connection->log; ctx->wait_ev->data = s->connection; work = ngx_pcalloc(pool, sizeof(ngx_zm_lookup_work_t)); if (work == NULL) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } if (s->auth_method == NGX_MAIL_AUTH_PASSWD || s->auth_method == NGX_MAIL_AUTH_PLAIN || s->auth_method == NGX_MAIL_AUTH_PLAIN_IR || s->auth_method == NGX_MAIL_AUTH_LOGIN || s->auth_method == NGX_MAIL_AUTH_LOGIN_USERNAME) { work->auth_method = ZM_AUTHMETH_USERNAME; } else if (s->auth_method == NGX_MAIL_AUTH_GSSAPI || s->auth_method == NGX_MAIL_AUTH_GSSAPI_IR) { work->auth_method = ZM_AUTHMETH_GSSAPI; work->auth_id = s->authid; } else { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "unsupported auth method %V", &ngx_mail_zmauth_method[s->auth_method]); ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } proxy_ssl = ngx_mail_get_proxy_ssl(s); switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: work->protocol = proxy_ssl?ZM_PROTO_POP3S:ZM_PROTO_POP3; break; case NGX_MAIL_IMAP_PROTOCOL: work->protocol = proxy_ssl?ZM_PROTO_IMAPS:ZM_PROTO_IMAP; break; default: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "unsupported auth protocol %V", &ngx_mail_zmauth_proto[s->protocol]); ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } if (ngx_mail_zmauth_escape(pool, &s->login, &escaped_login) != NGX_OK) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } work->username = escaped_login; work->connection = s->connection; work->login_attempts = s->login_attempt; work->log = s->connection->log; work->pool = s->connection->pool; work->data = s; work->on_success = ngx_mail_zmauth_lookup_result_handler; work->on_failure = ngx_mail_zmauth_lookup_result_handler; switch (s->vlogin) { case 0: work->alias_check_stat = ZM_ALIAS_NOT_CHECKED; break; case 1: work->alias_check_stat = ZM_ALIAS_NOT_FOUND; work->account_name = work->username; work->alias_key = s->key_alias; break; case 2: work->alias_check_stat = ZM_ALIAS_FOUND; if (ngx_mail_zmauth_escape(pool, &s->qlogin, &escaped_account_name) != NGX_OK) { ngx_destroy_pool(pool); ngx_mail_session_internal_server_error(s); return; } work->account_name = escaped_account_name; work->alias_key = s->key_alias; break; default: ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "Should never reach here"); return; } ctx->work = work; s->connection->read->handler = ngx_mail_zmauth_block_read; ngx_zm_lookup(work); }
static void ngx_mail_zmauth_lookup_result_handler(ngx_zm_lookup_work_t * work) { ngx_mail_session_t *s; ngx_mail_zmauth_ctx_t *ctx; size_t size; u_char *p; ngx_addr_t *peer; ngx_str_t errmsg; s = (ngx_mail_session_t *) work->data; ctx = (ngx_mail_zmauth_ctx_t *)ngx_mail_get_module_ctx(s, ngx_mail_zmauth_module); if (work->result == ZM_LOOKUP_SUCCESS) { ngx_mail_zmauth_unescape(&work->account_name); /* copy the lookup result from zmauth pool to s->connection pool */ s->qlogin = *(ngx_pstrcpy(s->connection->pool, &work->account_name)); s->key_alias = *(ngx_pstrcpy(s->connection->pool, &work->alias_key)); s->key_route = *(ngx_pstrcpy(s->connection->pool, &work->route_key)); if (s->auth_method == NGX_MAIL_AUTH_GSSAPI || s->auth_method == NGX_MAIL_AUTH_GSSAPI_IR) { s->dusr = *(ngx_pstrcpy(s->connection->pool, &work->auth_id)); s->dpasswd = *(ngx_pstrcpy(s->connection->pool, &work->zm_auth_token)); } peer = ngx_palloc(s->connection->pool, sizeof(ngx_addr_t)); peer->name = *(ngx_pstrcpy(s->connection->pool, &work->route->name)); peer->socklen = work->route->socklen; peer->sockaddr = ngx_palloc(s->connection->pool, peer->socklen); if(peer->sockaddr == NULL) { return; /* NO MEM */ } ngx_memcpy(peer->sockaddr, work->route->sockaddr, peer->socklen); switch (work->alias_check_stat) { case ZM_ALIAS_NOT_FOUND: s->vlogin = 1; break; case ZM_ALIAS_FOUND: s->vlogin = 2; break; default: break; /* do nothing */ } ngx_destroy_pool(ctx->pool); ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module); ngx_mail_proxy_init(s, peer); return; } else { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "An error occurred in mail zmauth: %V", &work->err); /* construct error msg */ if (work->result != ZM_LOOKUP_LOGIN_FAILED) { /* zmauth clean up will destroy the ctx->pool */ ngx_mail_session_internal_server_error(s); return; } errmsg = LOGIN_FAILED; /* should we return the real err msg to user? */ switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: size = sizeof("-ERR ") - 1 + errmsg.len + sizeof(CRLF) - 1; if (s->command == NGX_POP3_AUTH) { size += AUTHENTICATION_FAILED.len; } break; case NGX_MAIL_IMAP_PROTOCOL: if (s->command == NGX_IMAP_AUTHENTICATE) { errmsg = AUTHENTICATE_FAILED; } size = s->tag.len + 1 /*for space*/+ sizeof("NO ") - 1 + errmsg.len + sizeof(CRLF) - 1; break; default: /* NGX_MAIL_SMTP_PROTOCOL */ ngx_log_error(NGX_LOG_CRIT, s->connection->log, 0, "smtp is not supported!!"); return; } p = ngx_pnalloc(s->connection->pool, size); if (p == NULL) { ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } ctx->errmsg.data = p; switch (s->protocol) { case NGX_MAIL_POP3_PROTOCOL: *p++ = '-'; *p++ = 'E'; *p++ = 'R'; *p++ = 'R'; *p++ = ' '; if (s->command == NGX_POP3_AUTH) { p = ngx_cpymem(p, AUTHENTICATION_FAILED.data, AUTHENTICATION_FAILED.len); } break; case NGX_MAIL_IMAP_PROTOCOL: p = ngx_cpymem(p, s->tag.data, s->tag.len); *p++ = ' '; *p++ = 'N'; *p++ = 'O'; *p++ = ' '; break; default: /* NGX_MAIL_SMTP_PROTOCOL */ break; } p = ngx_cpymem(p, errmsg.data, errmsg.len); *p++ = CR; *p++ = LF; ctx->errmsg.len = p - ctx->errmsg.data; s->out = ctx->errmsg; if (work->result == ZM_LOOKUP_LOGIN_FAILED && work->wait_time > 0) { ngx_add_timer(ctx->wait_ev, (ngx_msec_t) (work->wait_time * 1000)); s->connection->read->handler = ngx_mail_zmauth_block_read; } else { s->quit = 1; ngx_mail_send(s->connection->write); ngx_mail_set_ctx(s, NULL, ngx_mail_zmauth_module); ngx_destroy_pool(ctx->pool); } return; } }