📄 ngx_mail_auth_http_module.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>#include <ngx_event_connect.h>#include <ngx_mail.h>typedef struct { ngx_peer_addr_t *peer; ngx_msec_t timeout; ngx_str_t host_header; ngx_str_t uri; ngx_str_t header; ngx_array_t *headers; u_char *file; ngx_uint_t line;} ngx_mail_auth_http_conf_t;typedef struct ngx_mail_auth_http_ctx_s ngx_mail_auth_http_ctx_t;typedef void (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx);struct ngx_mail_auth_http_ctx_s { ngx_buf_t *request; ngx_buf_t *response; ngx_peer_connection_t peer; ngx_mail_auth_http_handler_pt handler; ngx_uint_t state; ngx_uint_t hash; /* no needed ? */ u_char *header_name_start; u_char *header_name_end; u_char *header_start; u_char *header_end; ngx_str_t addr; ngx_str_t port; ngx_str_t err; ngx_str_t errmsg; ngx_str_t errcode; time_t sleep; ngx_pool_t *pool;};static void ngx_mail_auth_http_write_handler(ngx_event_t *wev);static void ngx_mail_auth_http_read_handler(ngx_event_t *rev);static void ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx);static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx);static void ngx_mail_auth_sleep_handler(ngx_event_t *rev);static ngx_int_t ngx_mail_auth_http_parse_header_line(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx);static void ngx_mail_auth_http_block_read(ngx_event_t *rev);static void ngx_mail_auth_http_dummy_handler(ngx_event_t *ev);static ngx_buf_t *ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, ngx_mail_auth_http_conf_t *ahcf);static ngx_int_t ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped);static void *ngx_mail_auth_http_create_conf(ngx_conf_t *cf);static char *ngx_mail_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child);static char *ngx_mail_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static char *ngx_mail_auth_http_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static ngx_command_t ngx_mail_auth_http_commands[] = { { ngx_string("auth_http"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_mail_auth_http, NGX_MAIL_SRV_CONF_OFFSET, 0, NULL }, { ngx_string("auth_http_timeout"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, NGX_MAIL_SRV_CONF_OFFSET, offsetof(ngx_mail_auth_http_conf_t, timeout), NULL }, { ngx_string("auth_http_header"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2, ngx_mail_auth_http_header, NGX_MAIL_SRV_CONF_OFFSET, 0, NULL }, ngx_null_command};static ngx_mail_module_t ngx_mail_auth_http_module_ctx = { NULL, /* protocol */ NULL, /* create main configuration */ NULL, /* init main configuration */ ngx_mail_auth_http_create_conf, /* create server configuration */ ngx_mail_auth_http_merge_conf /* merge server configuration */};ngx_module_t ngx_mail_auth_http_module = { NGX_MODULE_V1, &ngx_mail_auth_http_module_ctx, /* module context */ ngx_mail_auth_http_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 ngx_str_t ngx_mail_auth_http_method[] = { ngx_string("plain"), ngx_string("plain"), ngx_string("apop"), ngx_string("cram-md5")};static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0");voidngx_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; }}static voidngx_mail_auth_http_write_handler(ngx_event_t *wev){ ssize_t n, size; ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_auth_http_ctx_t *ctx; ngx_mail_auth_http_conf_t *ahcf; c = wev->data; s = c->data; ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail auth http write handler"); if (wev->timedout) { ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, "auth http server %V timed out", ctx->peer.name); ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } size = ctx->request->last - ctx->request->pos; n = ngx_send(c, ctx->request->pos, size); if (n == NGX_ERROR) { ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } if (n > 0) { ctx->request->pos += n; if (n == size) { wev->handler = ngx_mail_auth_http_dummy_handler; if (wev->timer_set) { ngx_del_timer(wev); } if (ngx_handle_write_event(wev, 0) == NGX_ERROR) { ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); } return; } } if (!wev->timer_set) { ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module); ngx_add_timer(wev, ahcf->timeout); }}static voidngx_mail_auth_http_read_handler(ngx_event_t *rev){ ssize_t n, size; ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_auth_http_ctx_t *ctx; c = rev->data; s = c->data; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail auth http read handler"); ctx = ngx_mail_get_module_ctx(s, ngx_mail_auth_http_module); if (rev->timedout) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, "auth http server %V timed out", ctx->peer.name); ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } if (ctx->response == NULL) { ctx->response = ngx_create_temp_buf(ctx->pool, 1024); if (ctx->response == NULL) { ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } } size = ctx->response->end - ctx->response->last; n = ngx_recv(c, ctx->response->pos, size); if (n > 0) { ctx->response->last += n; ctx->handler(s, ctx); return; } if (n == NGX_AGAIN) { return; } ngx_close_connection(c); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s);}static voidngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx){ u_char *p, ch; enum { sw_start = 0, sw_H, sw_HT, sw_HTT, sw_HTTP, sw_skip, sw_almost_done } state; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http process status line"); state = ctx->state; for (p = ctx->response->pos; p < ctx->response->last; p++) { ch = *p; switch (state) { /* "HTTP/" */ case sw_start: if (ch == 'H') { state = sw_H; break; } goto next; case sw_H: if (ch == 'T') { state = sw_HT; break; } goto next; case sw_HT: if (ch == 'T') { state = sw_HTT; break; } goto next; case sw_HTT: if (ch == 'P') { state = sw_HTTP; break; } goto next; case sw_HTTP: if (ch == '/') { state = sw_skip; break; } goto next; /* any text until end of line */ case sw_skip: switch (ch) { case CR: state = sw_almost_done; break; case LF: goto done; } break; /* end of status line */ case sw_almost_done: if (ch == LF) { goto done; } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "auth http server &V sent invalid response", ctx->peer.name); ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); ngx_mail_session_internal_server_error(s); return; } } ctx->response->pos = p; ctx->state = state; return;next: p = ctx->response->start - 1;done: ctx->response->pos = p + 1; ctx->state = 0; ctx->handler = ngx_mail_auth_http_process_headers; ctx->handler(s, ctx);}static voidngx_mail_auth_http_process_headers(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx){ u_char *p; time_t timer; size_t len, size; ngx_int_t rc, port, n; ngx_peer_addr_t *peer; struct sockaddr_in *sin; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http process headers"); for ( ;; ) { rc = ngx_mail_auth_http_parse_header_line(s, ctx); if (rc == NGX_OK) {#if (NGX_DEBUG) { ngx_str_t key, value; key.len = ctx->header_name_end - ctx->header_name_start;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -