mirror of
https://github.com/nginx/nginx.git
synced 2025-06-28 02:02:50 +08:00
nginx-0.1.44-RELEASE import
*) Feature: the IMAP/POP3 proxy supports SSL. *) Feature: the "proxy_timeout" directive of the ngx_imap_proxy_module. *) Feature: the "userid_mark" directive. *) Feature: the $remote_user variable value is determined independently of authorization use.
This commit is contained in:
parent
5650106a09
commit
ceb992921c
@ -228,6 +228,14 @@ fi
|
||||
if [ $IMAP = YES ]; then
|
||||
modules="$modules $IMAP_MODULES"
|
||||
|
||||
if [ $IMAP_SSL = YES ]; then
|
||||
modules="$modules $IMAP_SSL_MODULE"
|
||||
IMAP_DEPS="$IMAP_DEPS $IMAP_SSL_DEPS"
|
||||
IMAP_SRCS="$IMAP_SRCS $IMAP_SSL_SRCS"
|
||||
have=NGX_IMAP_SSL . auto/have
|
||||
USE_OPENSSL=YES
|
||||
fi
|
||||
|
||||
modules="$modules $IMAP_AUTH_HTTP_MODULE"
|
||||
IMAP_SRCS="$IMAP_SRCS $IMAP_AUTH_HTTP_SRCS"
|
||||
|
||||
|
@ -64,6 +64,7 @@ HTTP_FASTCGI=YES
|
||||
HTTP_STUB_STATUS=NO
|
||||
|
||||
IMAP=NO
|
||||
IMAP_SSL=NO
|
||||
|
||||
NGX_ADDONS=
|
||||
|
||||
@ -141,6 +142,7 @@ do
|
||||
--with-http_stub_status_module) HTTP_STUB_STATUS=YES ;;
|
||||
|
||||
--with-imap) IMAP=YES ;;
|
||||
--with-imap_ssl_module) IMAP_SSL=YES ;;
|
||||
|
||||
--add-module=*) NGX_ADDONS="$NGX_ADDONS $value" ;;
|
||||
|
||||
|
@ -346,6 +346,10 @@ IMAP_SRCS="src/imap/ngx_imap.c \
|
||||
src/imap/ngx_imap_handler.c \
|
||||
src/imap/ngx_imap_parse.c"
|
||||
|
||||
IMAP_SSL_MODULE="ngx_imap_ssl_module"
|
||||
IMAP_SSL_DEPS="src/imap/ngx_imap_ssl_module.h"
|
||||
IMAP_SSL_SRCS="src/imap/ngx_imap_ssl_module.c"
|
||||
|
||||
IMAP_AUTH_HTTP_MODULE="ngx_imap_auth_http_module"
|
||||
IMAP_AUTH_HTTP_SRCS="src/imap/ngx_imap_auth_http_module.c"
|
||||
|
||||
|
@ -9,6 +9,49 @@
|
||||
<title lang="en">nginx changelog</title>
|
||||
|
||||
|
||||
<changes ver="0.1.44" date="06.09.2005">
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
IMAP/POP3 ÐÒÏËÓÉ ÐÏÄÄÅÒÖÉ×ÁÅÔ SSL.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the IMAP/POP3 proxy supports SSL.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
ÄÉÒÅËÔÉ×Á proxy_timeout.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "proxy_timeout" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
ÄÉÒÅËÔÉ×Á userid_mark.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "userid_mark" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
ÚÎÁÞÅÎÉÅ ÐÅÒÅÍÅÎÎÏÊ $remote_user ÏÐÒÅÄÅÌÑÅÔÓÑ ÎÅÚÁ×ÉÓÉÍÏ ÏÔ ÔÏÇÏ,
|
||||
ÉÓÐÏÌØÚÕÅÔÓÑ ÌÉ Á×ÔÏÒÉÚÁÃÉÑ ÉÌÉ ÎÅÔ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the $remote_user variable value is determined independently of
|
||||
authorization use.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="0.1.43" date="30.08.2005">
|
||||
|
||||
<change type="feature">
|
||||
|
@ -236,6 +236,10 @@ main(int argc, char *const *argv)
|
||||
|
||||
#else
|
||||
|
||||
if (ngx_init_signals(cycle->log) == NGX_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!ngx_inherited && ccf->daemon) {
|
||||
if (ngx_daemon(cycle->log) == NGX_ERROR) {
|
||||
return 1;
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define NGINX_VER "nginx/0.1.43"
|
||||
#define NGINX_VER "nginx/0.1.44"
|
||||
|
||||
#define NGINX_VAR "NGINX"
|
||||
#define NGX_NEWPID_EXT ".newbin"
|
||||
|
@ -92,6 +92,7 @@ struct ngx_connection_s {
|
||||
ngx_socket_t fd;
|
||||
|
||||
ngx_recv_pt recv;
|
||||
ngx_send_pt send;
|
||||
ngx_send_chain_pt send_chain;
|
||||
|
||||
ngx_listening_t *listening;
|
||||
|
@ -256,6 +256,7 @@ ngx_event_accept(ngx_event_t *ev)
|
||||
c->servers = ls->servers;
|
||||
|
||||
c->recv = ngx_recv;
|
||||
c->send = ngx_send;
|
||||
c->send_chain = ngx_send_chain;
|
||||
|
||||
c->log = log;
|
||||
|
@ -151,6 +151,7 @@ int ngx_event_post_acceptex(ngx_listening_t *ls, int n)
|
||||
c->servers = ls->servers;
|
||||
|
||||
c->recv = ngx_recv;
|
||||
c->send = ngx_send;
|
||||
c->send_chain = ngx_send_chain;
|
||||
|
||||
c->pool = ngx_create_pool(ls->pool_size, ls->log);
|
||||
|
@ -229,6 +229,10 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
|
||||
c->write = wev;
|
||||
wev->write = 1;
|
||||
|
||||
c->recv = ngx_recv;
|
||||
c->send = ngx_send;
|
||||
c->send_chain = ngx_send_chain;
|
||||
|
||||
c->log = pc->log;
|
||||
rev->log = pc->log;
|
||||
wev->log = pc->log;
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
|
||||
static void ngx_ssl_write_handler(ngx_event_t *wev);
|
||||
static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
|
||||
static void ngx_ssl_read_handler(ngx_event_t *rev);
|
||||
|
||||
|
||||
@ -209,8 +208,10 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
|
||||
}
|
||||
|
||||
if (sslerr == SSL_ERROR_WANT_WRITE) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, err,
|
||||
"SSL wants to write%s", handshake);
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, err,
|
||||
"client does SSL %shandshake",
|
||||
SSL_is_init_finished(c->ssl->ssl) ? "re" : "");
|
||||
|
||||
c->write->ready = 0;
|
||||
|
||||
@ -391,12 +392,11 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
ssize_t
|
||||
ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
|
||||
{
|
||||
int n, sslerr;
|
||||
ngx_err_t err;
|
||||
char *handshake;
|
||||
int n, sslerr;
|
||||
ngx_err_t err;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
|
||||
|
||||
@ -405,6 +405,47 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
|
||||
|
||||
if (n > 0) {
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
|
||||
if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->ssl)) {
|
||||
char buf[129], *s, *d;
|
||||
SSL_CIPHER *cipher;
|
||||
|
||||
c->ssl->handshaked = 1;
|
||||
|
||||
cipher = SSL_get_current_cipher(c->ssl->ssl);
|
||||
|
||||
if (cipher) {
|
||||
SSL_CIPHER_description(cipher, &buf[1], 128);
|
||||
|
||||
for (s = &buf[1], d = buf; *s; s++) {
|
||||
if (*s == ' ' && *d == ' ') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*s == LF || *s == CR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*++d = *s;
|
||||
}
|
||||
|
||||
if (*d != ' ') {
|
||||
d++;
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"SSL cipher: \"%s\"", &buf[1]);
|
||||
} else {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"SSL no shared ciphers");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (c->ssl->saved_read_handler) {
|
||||
|
||||
c->read->handler = c->ssl->saved_read_handler;
|
||||
@ -440,15 +481,9 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
|
||||
|
||||
if (sslerr == SSL_ERROR_WANT_READ) {
|
||||
|
||||
if (!SSL_is_init_finished(c->ssl->ssl)) {
|
||||
handshake = " in SSL handshake";
|
||||
|
||||
} else {
|
||||
handshake = "";
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, err,
|
||||
"SSL wants to read%s", handshake);
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, err,
|
||||
"client does SSL %shandshake",
|
||||
SSL_is_init_finished(c->ssl->ssl) ? "re" : "");
|
||||
|
||||
c->read->ready = 0;
|
||||
|
||||
|
@ -49,6 +49,7 @@ ngx_int_t ngx_ssl_create_session(ngx_ssl_ctx_t *ctx, ngx_connection_t *c,
|
||||
#define ngx_ssl_handshake(c) NGX_OK
|
||||
|
||||
ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
|
||||
ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||
off_t limit);
|
||||
ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c);
|
||||
|
@ -90,8 +90,9 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
||||
off_t offset;
|
||||
ssize_t n;
|
||||
ngx_fd_t fd;
|
||||
ngx_str_t auth, encoded, pwd;
|
||||
ngx_uint_t i, login, len, left, passwd;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t pwd;
|
||||
ngx_uint_t i, login, left, passwd;
|
||||
ngx_file_t file;
|
||||
ngx_http_auth_basic_ctx_t *ctx;
|
||||
ngx_http_auth_basic_loc_conf_t *alcf;
|
||||
@ -115,57 +116,16 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
||||
&alcf->realm);
|
||||
}
|
||||
|
||||
if (r->headers_in.authorization == NULL) {
|
||||
rc = ngx_http_auth_basic_user(r);
|
||||
|
||||
if (rc == NGX_DECLINED) {
|
||||
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
|
||||
}
|
||||
|
||||
encoded = r->headers_in.authorization->value;
|
||||
|
||||
if (encoded.len < sizeof("Basic ") - 1
|
||||
|| ngx_strncasecmp(encoded.data, "Basic ", sizeof("Basic ") - 1) != 0)
|
||||
{
|
||||
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
|
||||
}
|
||||
|
||||
encoded.len -= sizeof("Basic ") - 1;
|
||||
encoded.data += sizeof("Basic ") - 1;
|
||||
|
||||
while (encoded.len && encoded.data[0] == ' ') {
|
||||
encoded.len--;
|
||||
encoded.data++;
|
||||
}
|
||||
|
||||
if (encoded.len == 0) {
|
||||
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
|
||||
}
|
||||
|
||||
auth.len = ngx_base64_decoded_length(encoded.len);
|
||||
auth.data = ngx_palloc(r->pool, auth.len + 1);
|
||||
if (auth.data == NULL) {
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
|
||||
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
|
||||
}
|
||||
|
||||
auth.data[auth.len] = '\0';
|
||||
|
||||
for (len = 0; len < auth.len; len++) {
|
||||
if (auth.data[len] == ':') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == auth.len) {
|
||||
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
|
||||
}
|
||||
|
||||
r->headers_in.user.len = len;
|
||||
r->headers_in.user.data = auth.data;
|
||||
r->headers_in.passwd.len = auth.len - len - 1;
|
||||
r->headers_in.passwd.data = &auth.data[len + 1];
|
||||
|
||||
fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
|
||||
if (fd == NGX_INVALID_FILE) {
|
||||
@ -208,12 +168,12 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf[i] != auth.data[login]) {
|
||||
if (buf[i] != r->headers_in.user.data[login]) {
|
||||
state = sw_skip;
|
||||
break;
|
||||
}
|
||||
|
||||
if (login == len) {
|
||||
if (login == r->headers_in.user.len) {
|
||||
state = sw_passwd;
|
||||
passwd = i + 1;
|
||||
}
|
||||
|
@ -424,10 +424,10 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
|
||||
escape = 0;
|
||||
|
||||
loc_len = r->valid_location ? u->conf->location->len : 1;
|
||||
loc_len = r->valid_location ? u->conf->location->len - 1 : 0;
|
||||
|
||||
if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
|
||||
len += r->unparsed_uri.len - 1;
|
||||
len += r->unparsed_uri.len;
|
||||
|
||||
} else {
|
||||
if (r->quoted_uri) {
|
||||
@ -508,11 +508,11 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
r->method_name.len + 1);
|
||||
}
|
||||
|
||||
b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len);
|
||||
b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len - 1);
|
||||
|
||||
if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
|
||||
b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1,
|
||||
r->unparsed_uri.len - 1);
|
||||
b->last = ngx_cpymem(b->last, r->unparsed_uri.data,
|
||||
r->unparsed_uri.len);
|
||||
} else {
|
||||
if (escape) {
|
||||
ngx_escape_uri(b->last, r->uri.data + loc_len,
|
||||
|
@ -26,18 +26,22 @@ typedef struct {
|
||||
ngx_str_t name;
|
||||
ngx_str_t domain;
|
||||
ngx_str_t path;
|
||||
time_t expires;
|
||||
ngx_str_t p3p;
|
||||
|
||||
time_t expires;
|
||||
|
||||
u_char mark;
|
||||
} ngx_http_userid_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t uid_got[4];
|
||||
uint32_t uid_set[4];
|
||||
ngx_str_t cookie;
|
||||
} ngx_http_userid_ctx_t;
|
||||
|
||||
|
||||
static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
|
||||
static void ngx_http_userid_get_uid(ngx_http_request_t *r,
|
||||
ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
|
||||
static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
|
||||
ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
|
||||
@ -61,6 +65,9 @@ static char *ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data);
|
||||
static char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data);
|
||||
static char *ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
||||
|
||||
static uint32_t sequencer_v1 = 1;
|
||||
@ -84,7 +91,6 @@ static ngx_conf_enum_t ngx_http_userid_state[] = {
|
||||
|
||||
static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
|
||||
ngx_http_userid_domain;
|
||||
|
||||
static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
|
||||
static ngx_conf_post_handler_pt ngx_http_userid_p3p_p = ngx_http_userid_p3p;
|
||||
|
||||
@ -99,28 +105,28 @@ static ngx_command_t ngx_http_userid_commands[] = {
|
||||
ngx_http_userid_state },
|
||||
|
||||
{ ngx_string("userid_service"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_userid_conf_t, service),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("userid_name"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_userid_conf_t, name),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("userid_domain"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_userid_conf_t, domain),
|
||||
&ngx_http_userid_domain_p },
|
||||
|
||||
{ ngx_string("userid_path"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_userid_conf_t, path),
|
||||
@ -140,6 +146,13 @@ static ngx_command_t ngx_http_userid_commands[] = {
|
||||
offsetof(ngx_http_userid_conf_t, p3p),
|
||||
&ngx_http_userid_p3p_p },
|
||||
|
||||
{ ngx_string("userid_mark"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_http_userid_mark,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
@ -205,15 +218,24 @@ ngx_http_userid_filter(ngx_http_request_t *r)
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module);
|
||||
|
||||
ngx_http_userid_get_uid(r, ctx, conf);
|
||||
|
||||
rc = ngx_http_userid_get_uid(r, ctx, conf);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
if (conf->enable == NGX_HTTP_USERID_LOG) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
if (conf->enable == NGX_HTTP_USERID_LOG || ctx->uid_got[3] != 0) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
if (ctx->uid_got[3] != 0) {
|
||||
if (conf->mark == '\0') {
|
||||
return ngx_http_next_header_filter(r);
|
||||
|
||||
} else {
|
||||
if (ctx->cookie.len > 23
|
||||
&& ctx->cookie.data[22] == conf->mark
|
||||
&& ctx->cookie.data[23] == '=')
|
||||
{
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = ngx_http_userid_set_uid(r, ctx, conf);
|
||||
@ -226,7 +248,7 @@ ngx_http_userid_filter(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
static void
|
||||
ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
ngx_http_userid_conf_t *conf)
|
||||
{
|
||||
@ -235,23 +257,29 @@ ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
ngx_table_elt_t **cookies;
|
||||
|
||||
n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name,
|
||||
&src);
|
||||
&ctx->cookie);
|
||||
if (n == NGX_DECLINED) {
|
||||
return NGX_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (src.len < 22) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"uid cookie: \"%V\"", &ctx->cookie);
|
||||
|
||||
if (ctx->cookie.len < 22) {
|
||||
cookies = r->headers_in.cookies.elts;
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent too short userid cookie \"%V\"",
|
||||
&cookies[n]->value);
|
||||
return NGX_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
src = ctx->cookie;
|
||||
|
||||
/*
|
||||
* we have to limit encoded string to 22 characters
|
||||
* because there are already the millions cookies with a garbage
|
||||
* instead of the correct base64 trail "=="
|
||||
* we have to limit the encoded string to 22 characters because
|
||||
* 1) cookie may be marked by "userid_mark",
|
||||
* 2) and there are already the millions cookies with a garbage
|
||||
* instead of the correct base64 trail "=="
|
||||
*/
|
||||
|
||||
src.len = 22;
|
||||
@ -263,15 +291,13 @@ ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent invalid userid cookie \"%V\"",
|
||||
&cookies[n]->value);
|
||||
return NGX_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"uid: %08XD%08XD%08XD%08XD",
|
||||
ctx->uid_got[0], ctx->uid_got[1],
|
||||
ctx->uid_got[2], ctx->uid_got[3]);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -286,47 +312,58 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
ngx_str_t src, dst;
|
||||
ngx_table_elt_t *set_cookie, *p3p;
|
||||
|
||||
/* TODO: mutex for sequencers */
|
||||
/*
|
||||
* TODO: in the threaded mode the sequencers should be in TLS and their
|
||||
* ranges should be divided between threads
|
||||
*/
|
||||
|
||||
if (ctx->uid_got[3] == 0) {
|
||||
|
||||
if (conf->enable == NGX_HTTP_USERID_V1) {
|
||||
if (conf->service == NGX_CONF_UNSET) {
|
||||
ctx->uid_set[0] = 0;
|
||||
} else {
|
||||
ctx->uid_set[0] = conf->service;
|
||||
}
|
||||
ctx->uid_set[1] = ngx_time();
|
||||
ctx->uid_set[2] = ngx_pid;
|
||||
ctx->uid_set[3] = sequencer_v1;
|
||||
sequencer_v1 += 0x100;
|
||||
|
||||
if (conf->enable == NGX_HTTP_USERID_V1) {
|
||||
if (conf->service == NGX_CONF_UNSET) {
|
||||
ctx->uid_set[0] = 0;
|
||||
} else {
|
||||
ctx->uid_set[0] = htonl(conf->service);
|
||||
}
|
||||
if (conf->service == NGX_CONF_UNSET) {
|
||||
if (r->in_addr == 0) {
|
||||
slen = sizeof(struct sockaddr_in);
|
||||
if (getsockname(r->connection->fd,
|
||||
(struct sockaddr *) &sin, &slen) == -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log,
|
||||
ngx_socket_errno, "getsockname() failed");
|
||||
}
|
||||
|
||||
ctx->uid_set[1] = ngx_time();
|
||||
ctx->uid_set[2] = ngx_pid;
|
||||
ctx->uid_set[3] = sequencer_v1;
|
||||
sequencer_v1 += 0x100;
|
||||
|
||||
} else {
|
||||
if (conf->service == NGX_CONF_UNSET) {
|
||||
if (r->in_addr == 0) {
|
||||
slen = sizeof(struct sockaddr_in);
|
||||
if (getsockname(r->connection->fd,
|
||||
(struct sockaddr *) &sin, &slen) == -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log,
|
||||
ngx_socket_errno, "getsockname() failed");
|
||||
r->in_addr = sin.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
r->in_addr = sin.sin_addr.s_addr;
|
||||
ctx->uid_set[0] = htonl(r->in_addr);
|
||||
|
||||
} else {
|
||||
ctx->uid_set[0] = htonl(conf->service);
|
||||
}
|
||||
|
||||
ctx->uid_set[0] = htonl(r->in_addr);
|
||||
|
||||
} else {
|
||||
ctx->uid_set[0] = htonl(conf->service);
|
||||
ctx->uid_set[1] = htonl(ngx_time());
|
||||
ctx->uid_set[2] = htonl(ngx_pid);
|
||||
ctx->uid_set[3] = htonl(sequencer_v2);
|
||||
sequencer_v2 += 0x100;
|
||||
if (sequencer_v2 < 0x03030302) {
|
||||
sequencer_v2 = 0x03030302;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->uid_set[1] = htonl(ngx_time());
|
||||
ctx->uid_set[2] = htonl(ngx_pid);
|
||||
ctx->uid_set[3] = htonl(sequencer_v2);
|
||||
sequencer_v2 += 0x100;
|
||||
if (sequencer_v2 < 0x03030302) {
|
||||
sequencer_v2 = 0x03030302;
|
||||
}
|
||||
} else {
|
||||
ctx->uid_set[0] = ctx->uid_got[0];
|
||||
ctx->uid_set[1] = ctx->uid_got[1];
|
||||
ctx->uid_set[2] = ctx->uid_got[2];
|
||||
ctx->uid_set[3] = ctx->uid_got[3];
|
||||
}
|
||||
|
||||
len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
|
||||
@ -347,13 +384,24 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
p = ngx_cpymem(cookie, conf->name.data, conf->name.len);
|
||||
*p++ = '=';
|
||||
|
||||
src.len = 16;
|
||||
src.data = (u_char *) ctx->uid_set;
|
||||
dst.data = p;
|
||||
if (ctx->uid_got[3] == 0) {
|
||||
src.len = 16;
|
||||
src.data = (u_char *) ctx->uid_set;
|
||||
dst.data = p;
|
||||
|
||||
ngx_encode_base64(&dst, &src);
|
||||
ngx_encode_base64(&dst, &src);
|
||||
|
||||
p += dst.len;
|
||||
p += dst.len;
|
||||
|
||||
if (conf->mark) {
|
||||
*(p - 2) = conf->mark;
|
||||
}
|
||||
|
||||
} else {
|
||||
p = ngx_cpymem(p, ctx->cookie.data, 22);
|
||||
*p++ = conf->mark;
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
|
||||
p = ngx_cpymem(p, expires, sizeof(expires) - 1);
|
||||
@ -545,6 +593,7 @@ ngx_http_userid_create_conf(ngx_conf_t *cf)
|
||||
conf->enable = NGX_CONF_UNSET_UINT;
|
||||
conf->service = NGX_CONF_UNSET;
|
||||
conf->expires = NGX_CONF_UNSET;
|
||||
conf->mark = (u_char) '\xFF';
|
||||
|
||||
return conf;
|
||||
}
|
||||
@ -567,6 +616,14 @@ ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET);
|
||||
ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
|
||||
|
||||
if (conf->mark == (u_char) '\xFF') {
|
||||
if (prev->mark == (u_char) '\xFF') {
|
||||
conf->mark = '\0';
|
||||
} else {
|
||||
conf->mark = prev->mark;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
@ -627,7 +684,7 @@ ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_userid_conf_t *ucf = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_str_t *value;
|
||||
|
||||
if (ucf->expires != NGX_CONF_UNSET) {
|
||||
return "is duplicate";
|
||||
@ -670,3 +727,36 @@ ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data)
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_userid_conf_t *ucf = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
|
||||
if (ucf->mark != (u_char) '\xFF') {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
ucf->mark = '\0';
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
if (value[1].len != 1
|
||||
|| !((value[1].data[0] >= '0' && value[1].data[0] <= '9')
|
||||
|| (value[1].data[0] >= 'A' && value[1].data[0] <= 'Z')
|
||||
|| (value[1].data[0] >= 'a' && value[1].data[0] <= 'z')
|
||||
|| value[1].data[0] == '='))
|
||||
{
|
||||
return "value must be \"off\" or a single letter, digit or \"=\"";
|
||||
}
|
||||
|
||||
ucf->mark = value[1].data[0];
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -930,6 +930,76 @@ ngx_http_set_exten(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_auth_basic_user(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_str_t auth, encoded;
|
||||
ngx_uint_t len;
|
||||
|
||||
if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (r->headers_in.authorization == NULL) {
|
||||
r->headers_in.user.data = (u_char *) "";
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
encoded = r->headers_in.authorization->value;
|
||||
|
||||
if (encoded.len < sizeof("Basic ") - 1
|
||||
|| ngx_strncasecmp(encoded.data, "Basic ", sizeof("Basic ") - 1) != 0)
|
||||
{
|
||||
r->headers_in.user.data = (u_char *) "";
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
encoded.len -= sizeof("Basic ") - 1;
|
||||
encoded.data += sizeof("Basic ") - 1;
|
||||
|
||||
while (encoded.len && encoded.data[0] == ' ') {
|
||||
encoded.len--;
|
||||
encoded.data++;
|
||||
}
|
||||
|
||||
if (encoded.len == 0) {
|
||||
r->headers_in.user.data = (u_char *) "";
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
auth.len = ngx_base64_decoded_length(encoded.len);
|
||||
auth.data = ngx_palloc(r->pool, auth.len + 1);
|
||||
if (auth.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
|
||||
r->headers_in.user.data = (u_char *) "";
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
auth.data[auth.len] = '\0';
|
||||
|
||||
for (len = 0; len < auth.len; len++) {
|
||||
if (auth.data[len] == ':') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == auth.len) {
|
||||
r->headers_in.user.data = (u_char *) "";
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
r->headers_in.user.len = len;
|
||||
r->headers_in.user.data = auth.data;
|
||||
r->headers_in.passwd.len = auth.len - len - 1;
|
||||
r->headers_in.passwd.data = &auth.data[len + 1];
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_subrequest(ngx_http_request_t *r,
|
||||
ngx_str_t *uri, ngx_str_t *args)
|
||||
|
@ -252,6 +252,7 @@ ngx_int_t ngx_http_find_location_config(ngx_http_request_t *r);
|
||||
|
||||
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
|
||||
ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
|
||||
ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
|
||||
|
||||
ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,
|
||||
ngx_str_t *uri, ngx_str_t *args);
|
||||
|
@ -11,9 +11,6 @@
|
||||
|
||||
|
||||
static void ngx_http_init_request(ngx_event_t *ev);
|
||||
#if (NGX_HTTP_SSL)
|
||||
static void ngx_http_ssl_handshake(ngx_event_t *rev);
|
||||
#endif
|
||||
static void ngx_http_process_request_line(ngx_event_t *rev);
|
||||
static void ngx_http_process_request_headers(ngx_event_t *rev);
|
||||
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
|
||||
@ -50,6 +47,11 @@ static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||
static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf,
|
||||
size_t len);
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
static void ngx_http_ssl_handshake(ngx_event_t *rev);
|
||||
static void ngx_http_ssl_close_handler(ngx_event_t *ev);
|
||||
#endif
|
||||
|
||||
|
||||
static char *ngx_http_client_errors[] = {
|
||||
|
||||
@ -490,6 +492,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
|
||||
"https ssl handshake: 0x%02Xd", buf[0]);
|
||||
|
||||
c->recv = ngx_ssl_recv;
|
||||
c->send = ngx_ssl_write;
|
||||
c->send_chain = ngx_ssl_send_chain;
|
||||
|
||||
rc = ngx_ssl_handshake(c);
|
||||
@ -2412,27 +2415,6 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
static void
|
||||
ngx_http_ssl_close_handler(ngx_event_t *ev)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ev->data;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http ssl close handler");
|
||||
|
||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_close_connection(c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_close_connection(ngx_connection_t *c)
|
||||
{
|
||||
@ -2441,7 +2423,7 @@ ngx_http_close_connection(ngx_connection_t *c)
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"close http connection: %d", c->fd);
|
||||
|
||||
#if (NGX_OPENSSL)
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
if (c->ssl) {
|
||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||
@ -2465,6 +2447,27 @@ ngx_http_close_connection(ngx_connection_t *c)
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
static void
|
||||
ngx_http_ssl_close_handler(ngx_event_t *ev)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ev->data;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http ssl close handler");
|
||||
|
||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_close_connection(c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
||||
{
|
||||
|
@ -292,6 +292,8 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
|
||||
|
||||
r->err_ctx = r->ctx;
|
||||
|
||||
r->method = NGX_HTTP_GET;
|
||||
|
||||
return ngx_http_internal_redirect(r, &err_page[i].uri, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ static ngx_http_variable_value_t *
|
||||
ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data);
|
||||
static ngx_http_variable_value_t *
|
||||
ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data);
|
||||
static ngx_http_variable_value_t *
|
||||
ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data);
|
||||
|
||||
|
||||
/*
|
||||
@ -108,8 +110,7 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
||||
{ ngx_string("request_method"), ngx_http_variable_request,
|
||||
offsetof(ngx_http_request_t, method_name), 0, 0 },
|
||||
|
||||
{ ngx_string("remote_user"), ngx_http_variable_request,
|
||||
offsetof(ngx_http_request_t, headers_in.user), 0, 0 },
|
||||
{ ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
|
||||
|
||||
{ ngx_null_string, NULL, 0, 0, 0 }
|
||||
};
|
||||
@ -657,6 +658,34 @@ ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data)
|
||||
}
|
||||
|
||||
|
||||
static ngx_http_variable_value_t *
|
||||
ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_variable_value_t *vv;
|
||||
|
||||
rc = ngx_http_auth_basic_user(r);
|
||||
|
||||
if (rc == NGX_DECLINED) {
|
||||
return NGX_HTTP_VAR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
|
||||
if (vv == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vv->value = 0;
|
||||
vv->text = r->headers_in.user;
|
||||
|
||||
return vv;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
|
||||
{
|
||||
|
@ -13,6 +13,11 @@
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_connect.h>
|
||||
|
||||
#if (NGX_IMAP_SSL)
|
||||
#include <ngx_imap_ssl_module.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
void **main_conf;
|
||||
@ -32,7 +37,6 @@ typedef struct {
|
||||
ngx_msec_t timeout;
|
||||
|
||||
size_t imap_client_buffer_size;
|
||||
size_t proxy_buffer_size;
|
||||
|
||||
ngx_uint_t protocol;
|
||||
|
||||
@ -82,8 +86,8 @@ typedef struct {
|
||||
|
||||
ngx_connection_t *connection;
|
||||
|
||||
ngx_buf_t *buffer;
|
||||
ngx_str_t out;
|
||||
ngx_buf_t *buffer;
|
||||
|
||||
void **ctx;
|
||||
void **main_conf;
|
||||
@ -93,6 +97,8 @@ typedef struct {
|
||||
|
||||
ngx_uint_t imap_state;
|
||||
|
||||
unsigned blocked:1;
|
||||
unsigned quit:1;
|
||||
unsigned protocol:1;
|
||||
unsigned quoted:1;
|
||||
|
||||
@ -100,6 +106,7 @@ typedef struct {
|
||||
ngx_str_t passwd;
|
||||
|
||||
ngx_str_t tag;
|
||||
ngx_str_t tagged_line;
|
||||
|
||||
ngx_uint_t command;
|
||||
ngx_array_t args;
|
||||
@ -167,6 +174,7 @@ typedef struct {
|
||||
|
||||
|
||||
void ngx_imap_init_connection(ngx_connection_t *c);
|
||||
void ngx_imap_send(ngx_event_t *wev);
|
||||
void ngx_imap_auth_state(ngx_event_t *rev);
|
||||
void ngx_pop3_auth_state(ngx_event_t *rev);
|
||||
void ngx_imap_close_connection(ngx_connection_t *c);
|
||||
|
@ -516,13 +516,14 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s,
|
||||
ngx_close_connection(ctx->peer.connection);
|
||||
|
||||
if (ctx->err.len) {
|
||||
(void) ngx_send(s->connection, ctx->err.data, ctx->err.len);
|
||||
s->out = ctx->err;
|
||||
|
||||
if (ctx->sleep == 0) {
|
||||
ngx_imap_close_connection(s->connection);
|
||||
return;
|
||||
s->quit = 1;
|
||||
}
|
||||
|
||||
ngx_imap_send(s->connection->write);
|
||||
|
||||
ngx_add_timer(s->connection->read, ctx->sleep * 1000);
|
||||
|
||||
s->connection->read->handler = ngx_imap_auth_sleep_handler;
|
||||
|
@ -75,13 +75,6 @@ static ngx_command_t ngx_imap_core_commands[] = {
|
||||
offsetof(ngx_imap_core_srv_conf_t, imap_client_buffer_size),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_buffer"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_size_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_core_srv_conf_t, proxy_buffer_size),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("timeout"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_msec_slot,
|
||||
@ -157,7 +150,6 @@ ngx_imap_core_create_srv_conf(ngx_conf_t *cf)
|
||||
}
|
||||
|
||||
cscf->imap_client_buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
cscf->proxy_buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
cscf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
cscf->protocol = NGX_CONF_UNSET_UINT;
|
||||
|
||||
@ -191,8 +183,6 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_conf_merge_size_value(conf->imap_client_buffer_size,
|
||||
prev->imap_client_buffer_size,
|
||||
(size_t) ngx_pagesize);
|
||||
ngx_conf_merge_size_value(conf->proxy_buffer_size, prev->proxy_buffer_size,
|
||||
(size_t) ngx_pagesize);
|
||||
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
|
||||
ngx_conf_merge_unsigned_value(conf->protocol, prev->protocol,
|
||||
NGX_IMAP_IMAP_PROTOCOL);
|
||||
|
@ -13,6 +13,10 @@
|
||||
static void ngx_imap_init_session(ngx_event_t *rev);
|
||||
static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s);
|
||||
|
||||
#if (NGX_IMAP_SSL)
|
||||
static void ngx_imap_ssl_close_handler(ngx_event_t *ev);
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_str_t greetings[] = {
|
||||
ngx_string("+OK POP3 ready" CRLF),
|
||||
@ -36,8 +40,12 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF;
|
||||
void
|
||||
ngx_imap_init_connection(ngx_connection_t *c)
|
||||
{
|
||||
ssize_t size;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_conf_ctx_t *ctx;
|
||||
#if (NGX_IMAP_SSL)
|
||||
ngx_int_t rc;
|
||||
ngx_imap_ssl_conf_t *sslcf;
|
||||
#endif
|
||||
ngx_imap_core_srv_conf_t *cscf;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap init connection");
|
||||
@ -45,26 +53,123 @@ ngx_imap_init_connection(ngx_connection_t *c)
|
||||
c->log_error = NGX_ERROR_INFO;
|
||||
|
||||
ctx = c->ctx;
|
||||
cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module);
|
||||
|
||||
size = greetings[cscf->protocol].len;
|
||||
#if (NGX_IMAP_SSL)
|
||||
|
||||
if (ngx_send(c, greetings[cscf->protocol].data, size) < size) {
|
||||
/*
|
||||
* we treat the incomplete sending as NGX_ERROR
|
||||
* because it is very strange here
|
||||
*/
|
||||
sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module);
|
||||
|
||||
if (sslcf->enable) {
|
||||
|
||||
if (ngx_ssl_create_session(sslcf->ssl_ctx, c, NGX_SSL_BUFFER)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ngx_ssl_handshake(c);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
c->recv = ngx_ssl_recv;
|
||||
c->send = ngx_ssl_write;
|
||||
c->send_chain = ngx_ssl_send_chain;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
|
||||
if (s == NULL) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
c->read->handler = ngx_imap_init_session;
|
||||
c->data = s;
|
||||
s->connection = c;
|
||||
|
||||
cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module);
|
||||
s->protocol = cscf->protocol;
|
||||
|
||||
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module);
|
||||
if (s->ctx == NULL) {
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
s->main_conf = ctx->main_conf;
|
||||
s->srv_conf = ctx->srv_conf;
|
||||
|
||||
s->out = greetings[s->protocol];
|
||||
|
||||
c->read->handler = ngx_imap_init_session;
|
||||
c->write->handler = ngx_imap_send;
|
||||
|
||||
ngx_add_timer(c->write, cscf->timeout);
|
||||
ngx_add_timer(c->read, cscf->timeout);
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
|
||||
ngx_imap_close_connection(c);
|
||||
}
|
||||
|
||||
ngx_imap_send(c->write);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_imap_send(ngx_event_t *wev)
|
||||
{
|
||||
ngx_int_t n;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
|
||||
c = wev->data;
|
||||
s = c->data;
|
||||
|
||||
if (wev->timedout) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->out.len == 0) {
|
||||
if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
|
||||
ngx_imap_close_connection(c);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
n = c->send(c, s->out.data, s->out.len);
|
||||
|
||||
if (n > 0) {
|
||||
s->out.len -= n;
|
||||
|
||||
if (s->quit) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->blocked) {
|
||||
c->read->handler(c->read);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* n == NGX_AGAIN */
|
||||
|
||||
if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +179,6 @@ ngx_imap_init_session(ngx_event_t *rev)
|
||||
size_t size;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_conf_ctx_t *ctx;
|
||||
ngx_imap_core_srv_conf_t *cscf;
|
||||
|
||||
c = rev->data;
|
||||
@ -85,40 +189,20 @@ ngx_imap_init_session(ngx_event_t *rev)
|
||||
return;
|
||||
}
|
||||
|
||||
s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
|
||||
if (s == NULL) {
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
c->data = s;
|
||||
s->connection = c;
|
||||
|
||||
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module);
|
||||
if (s->ctx == NULL) {
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = c->ctx;
|
||||
s->main_conf = ctx->main_conf;
|
||||
s->srv_conf = ctx->srv_conf;
|
||||
s = c->data;
|
||||
|
||||
if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
|
||||
ngx_imap_session_internal_server_error(s);
|
||||
return;
|
||||
}
|
||||
|
||||
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||
|
||||
s->protocol = cscf->protocol;
|
||||
|
||||
if (cscf->protocol == NGX_IMAP_POP3_PROTOCOL) {
|
||||
if (s->protocol == NGX_IMAP_POP3_PROTOCOL) {
|
||||
size = 128;
|
||||
s->imap_state = ngx_pop3_start;
|
||||
c->read->handler = ngx_pop3_auth_state;
|
||||
|
||||
} else {
|
||||
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||
size = cscf->imap_client_buffer_size;
|
||||
s->imap_state = ngx_imap_start;
|
||||
c->read->handler = ngx_imap_auth_state;
|
||||
@ -137,11 +221,11 @@ ngx_imap_init_session(ngx_event_t *rev)
|
||||
void
|
||||
ngx_imap_auth_state(ngx_event_t *rev)
|
||||
{
|
||||
u_char *text, *last, *out, *p;
|
||||
ssize_t size, text_len, last_len;
|
||||
u_char *text, *last, *p;
|
||||
ssize_t text_len, last_len;
|
||||
ngx_str_t *arg;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t quit, tag;
|
||||
ngx_uint_t tag;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_core_srv_conf_t *cscf;
|
||||
@ -157,6 +241,14 @@ ngx_imap_auth_state(ngx_event_t *rev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->out.len) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap send handler busy");
|
||||
s->blocked = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
s->blocked = 0;
|
||||
|
||||
rc = ngx_imap_read_command(s);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth: %i", rc);
|
||||
@ -165,7 +257,6 @@ ngx_imap_auth_state(ngx_event_t *rev)
|
||||
return;
|
||||
}
|
||||
|
||||
quit = 0;
|
||||
tag = 1;
|
||||
|
||||
text = NULL;
|
||||
@ -235,9 +326,9 @@ ngx_imap_auth_state(ngx_event_t *rev)
|
||||
break;
|
||||
|
||||
case NGX_IMAP_LOGOUT:
|
||||
s->quit = 1;
|
||||
text = imap_bye;
|
||||
text_len = sizeof(imap_bye) - 1;
|
||||
quit = 1;
|
||||
break;
|
||||
|
||||
case NGX_IMAP_NOOP:
|
||||
@ -260,18 +351,19 @@ ngx_imap_auth_state(ngx_event_t *rev)
|
||||
}
|
||||
|
||||
if (tag) {
|
||||
if (s->out.len < text_len + s->tag.len + last_len) {
|
||||
|
||||
s->out.len = text_len + s->tag.len + last_len;
|
||||
s->out.data = ngx_palloc(c->pool, s->out.len);
|
||||
if (s->out.data == NULL) {
|
||||
if (s->tagged_line.len < s->tag.len + text_len + last_len) {
|
||||
s->tagged_line.len = s->tag.len + text_len + last_len;
|
||||
s->tagged_line.data = ngx_palloc(c->pool, s->tagged_line.len);
|
||||
if (s->tagged_line.data == NULL) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out = s->out.data;
|
||||
p = out;
|
||||
s->out.data = s->tagged_line.data;
|
||||
s->out.len = s->tag.len + text_len + last_len;
|
||||
|
||||
p = s->out.data;
|
||||
|
||||
if (text) {
|
||||
p = ngx_cpymem(p, text, text_len);
|
||||
@ -279,35 +371,20 @@ ngx_imap_auth_state(ngx_event_t *rev)
|
||||
p = ngx_cpymem(p, s->tag.data, s->tag.len);
|
||||
ngx_memcpy(p, last, last_len);
|
||||
|
||||
size = text_len + s->tag.len + last_len;
|
||||
|
||||
} else {
|
||||
out = last;
|
||||
size = last_len;
|
||||
s->out.data = last;
|
||||
s->out.len = last_len;
|
||||
}
|
||||
|
||||
if (ngx_send(c, out, size) < size) {
|
||||
/*
|
||||
* we treat the incomplete sending as NGX_ERROR
|
||||
* because it is very strange here
|
||||
*/
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
if (rc != NGX_IMAP_NEXT) {
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
s->tag.len = 0;
|
||||
}
|
||||
|
||||
if (rc == NGX_IMAP_NEXT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (quit) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
s->tag.len = 0;
|
||||
ngx_imap_send(c->write);
|
||||
}
|
||||
|
||||
|
||||
@ -317,7 +394,6 @@ ngx_pop3_auth_state(ngx_event_t *rev)
|
||||
u_char *text;
|
||||
ssize_t size;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t quit;
|
||||
ngx_str_t *arg;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
@ -334,13 +410,20 @@ ngx_pop3_auth_state(ngx_event_t *rev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->out.len) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap send handler busy");
|
||||
s->blocked = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
s->blocked = 0;
|
||||
|
||||
rc = ngx_imap_read_command(s);
|
||||
|
||||
if (rc == NGX_AGAIN || rc == NGX_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
quit = 0;
|
||||
text = pop3_ok;
|
||||
size = sizeof(pop3_ok) - 1;
|
||||
|
||||
@ -381,7 +464,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
|
||||
break;
|
||||
|
||||
case NGX_POP3_QUIT:
|
||||
quit = 1;
|
||||
s->quit = 1;
|
||||
break;
|
||||
|
||||
case NGX_POP3_NOOP:
|
||||
@ -441,7 +524,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
|
||||
break;
|
||||
|
||||
case NGX_POP3_QUIT:
|
||||
quit = 1;
|
||||
s->quit = 1;
|
||||
break;
|
||||
|
||||
case NGX_POP3_NOOP:
|
||||
@ -466,23 +549,14 @@ ngx_pop3_auth_state(ngx_event_t *rev)
|
||||
size = sizeof(pop3_invalid_command) - 1;
|
||||
}
|
||||
|
||||
if (ngx_send(c, text, size) < size) {
|
||||
/*
|
||||
* we treat the incomplete sending as NGX_ERROR
|
||||
* because it is very strange here
|
||||
*/
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quit) {
|
||||
ngx_imap_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
|
||||
s->out.data = text;
|
||||
s->out.len = size;
|
||||
|
||||
ngx_imap_send(c->write);
|
||||
}
|
||||
|
||||
|
||||
@ -492,8 +566,8 @@ ngx_imap_read_command(ngx_imap_session_t *s)
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
|
||||
n = ngx_recv(s->connection, s->buffer->last,
|
||||
s->buffer->end - s->buffer->last);
|
||||
n = s->connection->recv(s->connection, s->buffer->last,
|
||||
s->buffer->end - s->buffer->last);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
ngx_imap_close_connection(s->connection);
|
||||
@ -538,10 +612,10 @@ ngx_imap_read_command(ngx_imap_session_t *s)
|
||||
void
|
||||
ngx_imap_session_internal_server_error(ngx_imap_session_t *s)
|
||||
{
|
||||
(void) ngx_send(s->connection, internal_server_errors[s->protocol].data,
|
||||
internal_server_errors[s->protocol].len);
|
||||
s->out = internal_server_errors[s->protocol];
|
||||
s->quit = 1;
|
||||
|
||||
ngx_imap_close_connection(s->connection);
|
||||
ngx_imap_send(s->connection->write);
|
||||
}
|
||||
|
||||
|
||||
@ -553,9 +627,42 @@ ngx_imap_close_connection(ngx_connection_t *c)
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0,
|
||||
"close imap connection: %d", c->fd);
|
||||
|
||||
#if (NGX_IMAP_SSL)
|
||||
|
||||
if (c->ssl) {
|
||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||
c->read->handler = ngx_imap_ssl_close_handler;
|
||||
c->write->handler = ngx_imap_ssl_close_handler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pool = c->pool;
|
||||
|
||||
ngx_close_connection(c);
|
||||
|
||||
ngx_destroy_pool(pool);
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_IMAP_SSL)
|
||||
|
||||
static void
|
||||
ngx_imap_ssl_close_handler(ngx_event_t *ev)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ev->data;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, "http ssl close handler");
|
||||
|
||||
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_imap_close_connection(c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
typedef struct {
|
||||
ngx_flag_t enable;
|
||||
size_t buffer_size;
|
||||
ngx_msec_t timeout;
|
||||
} ngx_imap_proxy_conf_t;
|
||||
|
||||
|
||||
@ -35,6 +37,7 @@ static char *ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent,
|
||||
|
||||
|
||||
static ngx_command_t ngx_imap_proxy_commands[] = {
|
||||
|
||||
{ ngx_string("proxy"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
@ -42,6 +45,20 @@ static ngx_command_t ngx_imap_proxy_commands[] = {
|
||||
offsetof(ngx_imap_proxy_conf_t, enable),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_buffer"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_size_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_proxy_conf_t, buffer_size),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_timeout"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_msec_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_proxy_conf_t, timeout),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
@ -131,12 +148,12 @@ ngx_imap_proxy_block_read(ngx_event_t *rev)
|
||||
static void
|
||||
ngx_imap_proxy_imap_handler(ngx_event_t *rev)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t line;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_core_srv_conf_t *cscf;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t line;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_proxy_conf_t *pcf;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0,
|
||||
"imap proxy imap auth handler");
|
||||
@ -152,10 +169,9 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev)
|
||||
}
|
||||
|
||||
if (s->proxy->buffer == NULL) {
|
||||
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||
pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
|
||||
|
||||
s->proxy->buffer = ngx_create_temp_buf(c->pool,
|
||||
cscf->proxy_buffer_size);
|
||||
s->proxy->buffer = ngx_create_temp_buf(c->pool, pcf->buffer_size);
|
||||
if (s->proxy->buffer == NULL) {
|
||||
ngx_imap_proxy_internal_server_error(s);
|
||||
return;
|
||||
@ -247,7 +263,7 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) {
|
||||
if (c->send(c, line.data, line.len) < (ssize_t) line.len) {
|
||||
/*
|
||||
* we treat the incomplete sending as NGX_ERROR
|
||||
* because it is very strange here
|
||||
@ -265,6 +281,8 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev)
|
||||
rev->handler = ngx_imap_proxy_handler;
|
||||
c->write->handler = ngx_imap_proxy_handler;
|
||||
|
||||
pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
|
||||
ngx_add_timer(s->connection->read, pcf->timeout);
|
||||
ngx_del_timer(c->read);
|
||||
}
|
||||
}
|
||||
@ -273,12 +291,12 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev)
|
||||
static void
|
||||
ngx_imap_proxy_pop3_handler(ngx_event_t *rev)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t line;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_core_srv_conf_t *cscf;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t line;
|
||||
ngx_connection_t *c;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_proxy_conf_t *pcf;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0,
|
||||
"imap proxy pop3 auth handler");
|
||||
@ -294,10 +312,9 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev)
|
||||
}
|
||||
|
||||
if (s->proxy->buffer == NULL) {
|
||||
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||
pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
|
||||
|
||||
s->proxy->buffer = ngx_create_temp_buf(c->pool,
|
||||
cscf->proxy_buffer_size);
|
||||
s->proxy->buffer = ngx_create_temp_buf(c->pool, pcf->buffer_size);
|
||||
if (s->proxy->buffer == NULL) {
|
||||
ngx_imap_proxy_internal_server_error(s);
|
||||
return;
|
||||
@ -369,7 +386,7 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) {
|
||||
if (c->send(c, line.data, line.len) < (ssize_t) line.len) {
|
||||
/*
|
||||
* we treat the incomplete sending as NGX_ERROR
|
||||
* because it is very strange here
|
||||
@ -387,6 +404,8 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev)
|
||||
rev->handler = ngx_imap_proxy_handler;
|
||||
c->write->handler = ngx_imap_proxy_handler;
|
||||
|
||||
pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
|
||||
ngx_add_timer(s->connection->read, pcf->timeout);
|
||||
ngx_del_timer(c->read);
|
||||
}
|
||||
}
|
||||
@ -408,7 +427,8 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what)
|
||||
|
||||
b = s->proxy->buffer;
|
||||
|
||||
n = ngx_recv(s->proxy->upstream.connection, b->last, b->end - b->last);
|
||||
n = s->proxy->upstream.connection->recv(s->proxy->upstream.connection,
|
||||
b->last, b->end - b->last);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
return NGX_ERROR;
|
||||
@ -475,12 +495,13 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what)
|
||||
static void
|
||||
ngx_imap_proxy_handler(ngx_event_t *ev)
|
||||
{
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_buf_t *b;
|
||||
ngx_uint_t again, do_write;
|
||||
ngx_connection_t *c, *src, *dst;
|
||||
ngx_imap_session_t *s;
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_buf_t *b;
|
||||
ngx_uint_t again, do_write;
|
||||
ngx_connection_t *c, *src, *dst;
|
||||
ngx_imap_session_t *s;
|
||||
ngx_imap_proxy_conf_t *pcf;
|
||||
|
||||
c = ev->data;
|
||||
s = c->data;
|
||||
@ -537,7 +558,7 @@ ngx_imap_proxy_handler(ngx_event_t *ev)
|
||||
size = b->last - b->pos;
|
||||
|
||||
if (size && dst->write->ready) {
|
||||
n = ngx_send(dst, b->pos, size);
|
||||
n = dst->send(dst, b->pos, size);
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
ngx_imap_proxy_close_session(s);
|
||||
@ -568,7 +589,7 @@ ngx_imap_proxy_handler(ngx_event_t *ev)
|
||||
size = b->end - b->last;
|
||||
|
||||
if (size && src->read->ready) {
|
||||
n = ngx_recv(src, b->last, size);
|
||||
n = src->recv(src, b->last, size);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
ngx_imap_proxy_close_session(s);
|
||||
@ -587,6 +608,11 @@ ngx_imap_proxy_handler(ngx_event_t *ev)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == s->connection) {
|
||||
pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
|
||||
ngx_add_timer(c->read, pcf->timeout);
|
||||
}
|
||||
}
|
||||
|
||||
} while (again);
|
||||
@ -634,6 +660,8 @@ ngx_imap_proxy_create_conf(ngx_conf_t *cf)
|
||||
}
|
||||
|
||||
pcf->enable = NGX_CONF_UNSET;
|
||||
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
pcf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
|
||||
return pcf;
|
||||
}
|
||||
@ -645,7 +673,10 @@ ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_imap_proxy_conf_t *prev = parent;
|
||||
ngx_imap_proxy_conf_t *conf = child;
|
||||
|
||||
ngx_conf_merge_msec_value(conf->enable, prev->enable, 0);
|
||||
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
||||
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
|
||||
(size_t) ngx_pagesize);
|
||||
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
174
src/imap/ngx_imap_ssl_module.c
Normal file
174
src/imap/ngx_imap_ssl_module.c
Normal file
@ -0,0 +1,174 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_imap.h>
|
||||
|
||||
|
||||
#define NGX_DEFLAUT_CERTIFICATE "cert.pem"
|
||||
#define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem"
|
||||
|
||||
|
||||
static void *ngx_imap_ssl_create_conf(ngx_conf_t *cf);
|
||||
static char *ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child);
|
||||
|
||||
|
||||
static ngx_command_t ngx_imap_ssl_commands[] = {
|
||||
|
||||
{ ngx_string("ssl"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_ssl_conf_t, enable),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("ssl_certificate"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_ssl_conf_t, certificate),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("ssl_certificate_key"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_ssl_conf_t, certificate_key),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("ssl_ciphers"),
|
||||
NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_IMAP_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_imap_ssl_conf_t, ciphers),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_imap_module_t ngx_imap_ssl_module_ctx = {
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
ngx_imap_ssl_create_conf, /* create server configuration */
|
||||
ngx_imap_ssl_merge_conf /* merge server configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_imap_ssl_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_imap_ssl_module_ctx, /* module context */
|
||||
ngx_imap_ssl_commands, /* module directives */
|
||||
NGX_IMAP_MODULE, /* module type */
|
||||
NULL, /* init module */
|
||||
NULL /* init process */
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
ngx_imap_ssl_create_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_imap_ssl_conf_t *scf;
|
||||
|
||||
scf = ngx_pcalloc(cf->pool, sizeof(ngx_imap_ssl_conf_t));
|
||||
if (scf == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* scf->certificate.len = 0;
|
||||
* scf->certificate.data = NULL;
|
||||
* scf->certificate_key.len = 0;
|
||||
* scf->certificate_key.data = NULL;
|
||||
* scf->ciphers.len = 0;
|
||||
* scf->ciphers.data = NULL;
|
||||
*/
|
||||
|
||||
scf->enable = NGX_CONF_UNSET;
|
||||
|
||||
return scf;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
{
|
||||
ngx_imap_ssl_conf_t *prev = parent;
|
||||
ngx_imap_ssl_conf_t *conf = child;
|
||||
|
||||
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
||||
|
||||
if (conf->enable == 0) {
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
ngx_conf_merge_str_value(conf->certificate, prev->certificate,
|
||||
NGX_DEFLAUT_CERTIFICATE);
|
||||
|
||||
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
|
||||
NGX_DEFLAUT_CERTIFICATE_KEY);
|
||||
|
||||
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, "");
|
||||
|
||||
|
||||
/* TODO: configure methods */
|
||||
|
||||
conf->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
|
||||
if (conf->ssl_ctx == NULL) {
|
||||
ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_new() failed");
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, conf->ssl_ctx)
|
||||
== NULL)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL);
|
||||
SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3);
|
||||
SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_SINGLE_DH_USE);
|
||||
#endif
|
||||
|
||||
if (conf->ciphers.len) {
|
||||
if (SSL_CTX_set_cipher_list(conf->ssl_ctx,
|
||||
(const char *) conf->ciphers.data) == 0)
|
||||
{
|
||||
ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"SSL_CTX_set_cipher_list(\"%V\") failed",
|
||||
&conf->ciphers);
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(conf->ssl_ctx,
|
||||
(char *) conf->certificate.data) == 0)
|
||||
{
|
||||
ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"SSL_CTX_use_certificate_chain_file(\"%s\") failed",
|
||||
conf->certificate.data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(conf->ssl_ctx,
|
||||
(char *) conf->certificate_key.data,
|
||||
SSL_FILETYPE_PEM) == 0)
|
||||
{
|
||||
ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"SSL_CTX_use_PrivateKey_file(\"%s\") failed",
|
||||
conf->certificate_key.data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
30
src/imap/ngx_imap_ssl_module.h
Normal file
30
src/imap/ngx_imap_ssl_module.h
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_IMAP_SSL_H_INCLUDED_
|
||||
#define _NGX_IMAP_SSL_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_imap.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_flag_t enable;
|
||||
ngx_str_t certificate;
|
||||
ngx_str_t certificate_key;
|
||||
|
||||
ngx_str_t ciphers;
|
||||
|
||||
ngx_ssl_ctx_t *ssl_ctx;
|
||||
} ngx_imap_ssl_conf_t;
|
||||
|
||||
|
||||
extern ngx_module_t ngx_imap_ssl_module;
|
||||
|
||||
|
||||
#endif /* _NGX_IMAP_SSL_H_INCLUDED_ */
|
@ -99,5 +99,7 @@ pid_t rfork_thread(int flags, void *stack, int (*func)(void *arg), void *arg);
|
||||
|
||||
extern char *malloc_options;
|
||||
|
||||
#define NGX_HAVE_OS_SPECIFIC_INIT 1
|
||||
|
||||
|
||||
#endif /* _NGX_FREEBSD_CONFIG_H_INCLUDED_ */
|
||||
|
@ -27,7 +27,7 @@ ngx_uint_t ngx_freebsd_sendfile_nbytes_bug;
|
||||
ngx_uint_t ngx_freebsd_use_tcp_nopush;
|
||||
|
||||
|
||||
ngx_os_io_t ngx_os_io = {
|
||||
static ngx_os_io_t ngx_freebsd_io = {
|
||||
ngx_unix_recv,
|
||||
ngx_readv_chain,
|
||||
ngx_unix_send,
|
||||
@ -74,7 +74,8 @@ sysctl_t sysctls[] = {
|
||||
};
|
||||
|
||||
|
||||
void ngx_debug_init()
|
||||
void
|
||||
ngx_debug_init()
|
||||
{
|
||||
#if (NGX_DEBUG && !NGX_NO_DEBUG_MALLOC)
|
||||
|
||||
@ -88,7 +89,8 @@ void ngx_debug_init()
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
ngx_int_t
|
||||
ngx_os_specific_init(ngx_log_t *log)
|
||||
{
|
||||
int version, somaxconn;
|
||||
size_t size;
|
||||
@ -223,12 +225,14 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
|
||||
ngx_tcp_nodelay_and_tcp_nopush = 1;
|
||||
|
||||
ngx_os_io = ngx_freebsd_io;
|
||||
|
||||
return ngx_posix_init(log);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void ngx_os_status(ngx_log_t *log)
|
||||
void
|
||||
ngx_os_specific_status(ngx_log_t *log)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
|
||||
@ -251,7 +255,4 @@ void ngx_os_status(ngx_log_t *log)
|
||||
sysctls[i].name, *sysctls[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngx_posix_status(log);
|
||||
}
|
||||
|
@ -56,7 +56,11 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
|
||||
#if (NGX_HAVE_KQUEUE)
|
||||
|
||||
if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
|
||||
if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
|
||||
&& wev->pending_eof
|
||||
/* FreeBSD 6.0 may erroneously report ETIMEDOUT */
|
||||
&& wev->kq_errno != NGX_ETIMEDOUT)
|
||||
{
|
||||
(void) ngx_connection_error(c, wev->kq_errno,
|
||||
"kevent() reported about an closed connection");
|
||||
wev->error = 1;
|
||||
|
@ -103,4 +103,7 @@ extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size);
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_HAVE_OS_SPECIFIC_INIT 1
|
||||
|
||||
|
||||
#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */
|
||||
|
@ -14,7 +14,7 @@ char ngx_linux_kern_osrelease[20];
|
||||
int ngx_linux_rtsig_max;
|
||||
|
||||
|
||||
ngx_os_io_t ngx_os_io = {
|
||||
static ngx_os_io_t ngx_linux_io = {
|
||||
ngx_unix_recv,
|
||||
ngx_readv_chain,
|
||||
ngx_unix_send,
|
||||
@ -29,7 +29,7 @@ ngx_os_io_t ngx_os_io = {
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_os_init(ngx_log_t *log)
|
||||
ngx_os_specific_init(ngx_log_t *log)
|
||||
{
|
||||
int name[2];
|
||||
size_t len;
|
||||
@ -74,19 +74,18 @@ ngx_os_init(ngx_log_t *log)
|
||||
}
|
||||
|
||||
|
||||
return ngx_posix_init(log);
|
||||
ngx_os_io = ngx_linux_io;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_os_status(ngx_log_t *log)
|
||||
ngx_os_specific_status(ngx_log_t *log)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
|
||||
ngx_linux_kern_ostype, ngx_linux_kern_osrelease);
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "sysctl(KERN_RTSIGMAX): %d",
|
||||
ngx_linux_rtsig_max);
|
||||
|
||||
|
||||
ngx_posix_status(log);
|
||||
}
|
||||
|
@ -34,10 +34,9 @@ typedef struct {
|
||||
void ngx_debug_init(void);
|
||||
ngx_int_t ngx_os_init(ngx_log_t *log);
|
||||
void ngx_os_status(ngx_log_t *log);
|
||||
ngx_int_t ngx_os_specific_init(ngx_log_t *log);
|
||||
void ngx_os_specific_status(ngx_log_t *log);
|
||||
ngx_int_t ngx_daemon(ngx_log_t *log);
|
||||
ngx_int_t ngx_posix_init(ngx_log_t *log);
|
||||
void ngx_posix_status(ngx_log_t *log);
|
||||
ngx_int_t ngx_posix_post_conf_init(ngx_log_t *log);
|
||||
|
||||
|
||||
ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
|
@ -102,7 +102,4 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_POSIX_IO 1
|
||||
|
||||
|
||||
#endif /* _NGX_POSIX_CONFIG_H_INCLUDED_ */
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
ngx_int_t ngx_ncpu;
|
||||
@ -17,8 +18,6 @@ ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush;
|
||||
struct rlimit rlmt;
|
||||
|
||||
|
||||
#if (NGX_POSIX_IO)
|
||||
|
||||
ngx_os_io_t ngx_os_io = {
|
||||
ngx_unix_recv,
|
||||
ngx_readv_chain,
|
||||
@ -28,75 +27,17 @@ ngx_os_io_t ngx_os_io = {
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
ngx_int_t
|
||||
ngx_os_init(ngx_log_t *log)
|
||||
{
|
||||
return ngx_posix_init(log);
|
||||
}
|
||||
|
||||
|
||||
void ngx_os_status(ngx_log_t *log)
|
||||
{
|
||||
ngx_posix_status(log);
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, NGINX_VER);
|
||||
|
||||
#if (NGX_HAVE_OS_SPECIFIC_INIT)
|
||||
if (ngx_os_specific_init(log) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ngx_signal_handler(int signo);
|
||||
|
||||
|
||||
typedef struct {
|
||||
int signo;
|
||||
char *signame;
|
||||
void (*handler)(int signo);
|
||||
} ngx_signal_t;
|
||||
|
||||
|
||||
ngx_signal_t signals[] = {
|
||||
{ ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
|
||||
"SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_REOPEN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_REOPEN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_NOACCEPT_SIGNAL),
|
||||
"SIG" ngx_value(NGX_NOACCEPT_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_TERMINATE_SIGNAL),
|
||||
"SIG" ngx_value(NGX_TERMINATE_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ SIGALRM, "SIGALRM", ngx_signal_handler },
|
||||
|
||||
{ SIGINT, "SIGINT", ngx_signal_handler },
|
||||
|
||||
{ SIGIO, "SIGIO", ngx_signal_handler },
|
||||
|
||||
{ SIGCHLD, "SIGCHLD", ngx_signal_handler },
|
||||
|
||||
{ SIGPIPE, "SIGPIPE, SIG_IGN", SIG_IGN },
|
||||
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t ngx_posix_init(ngx_log_t *log)
|
||||
{
|
||||
ngx_signal_t *sig;
|
||||
struct sigaction sa;
|
||||
|
||||
ngx_init_setproctitle(log);
|
||||
|
||||
ngx_pagesize = getpagesize();
|
||||
@ -105,17 +46,6 @@ ngx_int_t ngx_posix_init(ngx_log_t *log)
|
||||
ngx_ncpu = 1;
|
||||
}
|
||||
|
||||
for (sig = signals; sig->signo != 0; sig++) {
|
||||
ngx_memzero(&sa, sizeof(struct sigaction));
|
||||
sa.sa_handler = sig->handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(sig->signo, &sa, NULL) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"sigaction(%s) failed", sig->signame);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, errno,
|
||||
"getrlimit(RLIMIT_NOFILE) failed)");
|
||||
@ -134,157 +64,21 @@ ngx_int_t ngx_posix_init(ngx_log_t *log)
|
||||
}
|
||||
|
||||
|
||||
void ngx_posix_status(ngx_log_t *log)
|
||||
void
|
||||
ngx_os_status(ngx_log_t *log)
|
||||
{
|
||||
#if (NGX_HAVE_OS_SPECIFIC_INIT)
|
||||
ngx_os_specific_status(log);
|
||||
#endif
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0,
|
||||
"getrlimit(RLIMIT_NOFILE): %r:%r",
|
||||
rlmt.rlim_cur, rlmt.rlim_max);
|
||||
}
|
||||
|
||||
|
||||
void ngx_signal_handler(int signo)
|
||||
{
|
||||
char *action;
|
||||
struct timeval tv;
|
||||
ngx_int_t ignore;
|
||||
ngx_err_t err;
|
||||
ngx_signal_t *sig;
|
||||
|
||||
ignore = 0;
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
for (sig = signals; sig->signo != 0; sig++) {
|
||||
if (sig->signo == signo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_gettimeofday(&tv);
|
||||
ngx_time_update(tv.tv_sec);
|
||||
|
||||
action = "";
|
||||
|
||||
switch (ngx_process) {
|
||||
|
||||
case NGX_PROCESS_MASTER:
|
||||
case NGX_PROCESS_SINGLE:
|
||||
switch (signo) {
|
||||
|
||||
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
||||
ngx_quit = 1;
|
||||
action = ", shutting down";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
||||
case SIGINT:
|
||||
ngx_terminate = 1;
|
||||
action = ", exiting";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
||||
ngx_noaccept = 1;
|
||||
action = ", stop accepting connections";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
||||
ngx_reconfigure = 1;
|
||||
action = ", reconfiguring";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
||||
ngx_reopen = 1;
|
||||
action = ", reopening logs";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
||||
if (getppid() > 1 || ngx_new_binary > 0) {
|
||||
|
||||
/*
|
||||
* Ignore the signal in the new binary if its parent is
|
||||
* not the init process, i.e. the old binary's process
|
||||
* is still running. Or ingore the signal in the old binary's
|
||||
* process if the new binary's process is already running.
|
||||
*/
|
||||
|
||||
action = ", ignoring";
|
||||
ignore = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_change_binary = 1;
|
||||
action = ", changing binary";
|
||||
break;
|
||||
|
||||
case SIGALRM:
|
||||
if (!ngx_terminate) {
|
||||
ngx_timer = 1;
|
||||
action = ", shutting down old worker processes";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SIGIO:
|
||||
ngx_sigio = 1;
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
ngx_reap = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NGX_PROCESS_WORKER:
|
||||
switch (signo) {
|
||||
|
||||
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
||||
ngx_debug_quit = 1;
|
||||
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
||||
ngx_quit = 1;
|
||||
action = ", shutting down";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
||||
case SIGINT:
|
||||
ngx_terminate = 1;
|
||||
action = ", exiting";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
||||
ngx_reopen = 1;
|
||||
action = ", reopening logs";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
||||
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
||||
case SIGIO:
|
||||
action = ", ignoring";
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
|
||||
"signal %d (%s) received%s", signo, sig->signame, action);
|
||||
|
||||
if (ignore) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0,
|
||||
"the changing binary signal is ignored: "
|
||||
"you should shutdown or terminate "
|
||||
"before either old or new binary's process");
|
||||
}
|
||||
|
||||
if (signo == SIGCHLD) {
|
||||
ngx_process_get_status();
|
||||
}
|
||||
|
||||
ngx_set_errno(err);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_posix_post_conf_init(ngx_log_t *log)
|
||||
ngx_int_t
|
||||
ngx_posix_post_conf_init(ngx_log_t *log)
|
||||
{
|
||||
ngx_fd_t pp[2];
|
||||
|
||||
|
@ -10,7 +10,17 @@
|
||||
#include <ngx_channel.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
int signo;
|
||||
char *signame;
|
||||
void (*handler)(int signo);
|
||||
} ngx_signal_t;
|
||||
|
||||
|
||||
|
||||
static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
|
||||
static void ngx_signal_handler(int signo);
|
||||
static void ngx_process_get_status(void);
|
||||
|
||||
|
||||
int ngx_argc;
|
||||
@ -23,6 +33,45 @@ ngx_int_t ngx_last_process;
|
||||
ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
|
||||
|
||||
|
||||
ngx_signal_t signals[] = {
|
||||
{ ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
|
||||
"SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_REOPEN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_REOPEN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_NOACCEPT_SIGNAL),
|
||||
"SIG" ngx_value(NGX_NOACCEPT_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_TERMINATE_SIGNAL),
|
||||
"SIG" ngx_value(NGX_TERMINATE_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
|
||||
"SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
|
||||
ngx_signal_handler },
|
||||
|
||||
{ SIGALRM, "SIGALRM", ngx_signal_handler },
|
||||
|
||||
{ SIGINT, "SIGINT", ngx_signal_handler },
|
||||
|
||||
{ SIGIO, "SIGIO", ngx_signal_handler },
|
||||
|
||||
{ SIGCHLD, "SIGCHLD", ngx_signal_handler },
|
||||
|
||||
{ SIGPIPE, "SIGPIPE, SIG_IGN", SIG_IGN },
|
||||
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
ngx_pid_t
|
||||
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
|
||||
char *name, ngx_int_t respawn)
|
||||
@ -208,7 +257,171 @@ ngx_execute_proc(ngx_cycle_t *cycle, void *data)
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_init_signals(ngx_log_t *log)
|
||||
{
|
||||
ngx_signal_t *sig;
|
||||
struct sigaction sa;
|
||||
|
||||
for (sig = signals; sig->signo != 0; sig++) {
|
||||
ngx_memzero(&sa, sizeof(struct sigaction));
|
||||
sa.sa_handler = sig->handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(sig->signo, &sa, NULL) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"sigaction(%s) failed", sig->signame);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_signal_handler(int signo)
|
||||
{
|
||||
char *action;
|
||||
struct timeval tv;
|
||||
ngx_int_t ignore;
|
||||
ngx_err_t err;
|
||||
ngx_signal_t *sig;
|
||||
|
||||
ignore = 0;
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
for (sig = signals; sig->signo != 0; sig++) {
|
||||
if (sig->signo == signo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_gettimeofday(&tv);
|
||||
ngx_time_update(tv.tv_sec);
|
||||
|
||||
action = "";
|
||||
|
||||
switch (ngx_process) {
|
||||
|
||||
case NGX_PROCESS_MASTER:
|
||||
case NGX_PROCESS_SINGLE:
|
||||
switch (signo) {
|
||||
|
||||
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
||||
ngx_quit = 1;
|
||||
action = ", shutting down";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
||||
case SIGINT:
|
||||
ngx_terminate = 1;
|
||||
action = ", exiting";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
||||
ngx_noaccept = 1;
|
||||
action = ", stop accepting connections";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
||||
ngx_reconfigure = 1;
|
||||
action = ", reconfiguring";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
||||
ngx_reopen = 1;
|
||||
action = ", reopening logs";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
||||
if (getppid() > 1 || ngx_new_binary > 0) {
|
||||
|
||||
/*
|
||||
* Ignore the signal in the new binary if its parent is
|
||||
* not the init process, i.e. the old binary's process
|
||||
* is still running. Or ingore the signal in the old binary's
|
||||
* process if the new binary's process is already running.
|
||||
*/
|
||||
|
||||
action = ", ignoring";
|
||||
ignore = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_change_binary = 1;
|
||||
action = ", changing binary";
|
||||
break;
|
||||
|
||||
case SIGALRM:
|
||||
if (!ngx_terminate) {
|
||||
ngx_timer = 1;
|
||||
action = ", shutting down old worker processes";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SIGIO:
|
||||
ngx_sigio = 1;
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
ngx_reap = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NGX_PROCESS_WORKER:
|
||||
switch (signo) {
|
||||
|
||||
case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
|
||||
ngx_debug_quit = 1;
|
||||
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
|
||||
ngx_quit = 1;
|
||||
action = ", shutting down";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_TERMINATE_SIGNAL):
|
||||
case SIGINT:
|
||||
ngx_terminate = 1;
|
||||
action = ", exiting";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_REOPEN_SIGNAL):
|
||||
ngx_reopen = 1;
|
||||
action = ", reopening logs";
|
||||
break;
|
||||
|
||||
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
|
||||
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
|
||||
case SIGIO:
|
||||
action = ", ignoring";
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
|
||||
"signal %d (%s) received%s", signo, sig->signame, action);
|
||||
|
||||
if (ignore) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0,
|
||||
"the changing binary signal is ignored: "
|
||||
"you should shutdown or terminate "
|
||||
"before either old or new binary's process");
|
||||
}
|
||||
|
||||
if (signo == SIGCHLD) {
|
||||
ngx_process_get_status();
|
||||
}
|
||||
|
||||
ngx_set_errno(err);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_process_get_status(void)
|
||||
{
|
||||
int status;
|
||||
|
@ -54,7 +54,7 @@ typedef struct {
|
||||
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
|
||||
ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn);
|
||||
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
|
||||
void ngx_process_get_status(void);
|
||||
ngx_int_t ngx_init_signals(ngx_log_t *log);
|
||||
void ngx_debug_point(void);
|
||||
|
||||
|
||||
|
@ -83,4 +83,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_HAVE_OS_SPECIFIC_INIT 1
|
||||
|
||||
|
||||
#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */
|
||||
|
@ -13,7 +13,7 @@ char ngx_solaris_release[10];
|
||||
char ngx_solaris_version[50];
|
||||
|
||||
|
||||
ngx_os_io_t ngx_os_io = {
|
||||
static ngx_os_io_t ngx_solaris_io = {
|
||||
ngx_unix_recv,
|
||||
ngx_readv_chain,
|
||||
ngx_unix_send,
|
||||
@ -27,10 +27,11 @@ ngx_os_io_t ngx_os_io = {
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
ngx_int_t
|
||||
ngx_os_specific_init(ngx_log_t *log)
|
||||
{
|
||||
if (sysinfo(SI_SYSNAME, ngx_solaris_sysname, sizeof(ngx_solaris_sysname))
|
||||
== -1)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"sysinfo(SI_SYSNAME) failed");
|
||||
@ -38,7 +39,7 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
}
|
||||
|
||||
if (sysinfo(SI_RELEASE, ngx_solaris_release, sizeof(ngx_solaris_release))
|
||||
== -1)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"sysinfo(SI_RELEASE) failed");
|
||||
@ -46,7 +47,7 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
}
|
||||
|
||||
if (sysinfo(SI_VERSION, ngx_solaris_version, sizeof(ngx_solaris_version))
|
||||
== -1)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"sysinfo(SI_SYSNAME) failed");
|
||||
@ -54,11 +55,14 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
|
||||
}
|
||||
|
||||
|
||||
return ngx_posix_init(log);
|
||||
ngx_os_io = ngx_solaris_io;
|
||||
|
||||
return NGX_OK;;
|
||||
}
|
||||
|
||||
|
||||
void ngx_os_status(ngx_log_t *log)
|
||||
void
|
||||
ngx_os_specific_status(ngx_log_t *log)
|
||||
{
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
|
||||
@ -66,6 +70,4 @@ void ngx_os_status(ngx_log_t *log)
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "version: %s",
|
||||
ngx_solaris_version);
|
||||
|
||||
ngx_posix_status(log);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user