Mercurial > hg > nginx-ranges
diff src/event/ngx_event_openssl.c @ 358:9121a0a91f47 NGINX_0_6_23
nginx 0.6.23
*) Change: the "off" parameter in the "ssl_session_cache" directive;
now this is default parameter.
*) Change: the "open_file_cache_retest" directive was renamed to the
"open_file_cache_valid".
*) Feature: the "open_file_cache_min_uses" directive.
*) Feature: the ngx_http_gzip_static_module.
*) Feature: the "gzip_disable" directive.
*) Feature: the "memcached_pass" directive may be used inside the "if"
block.
*) Bugfix: a segmentation fault occurred in worker process, if the
"memcached_pass" and "if" directives were used in the same location.
*) Bugfix: if a "satisfy_any on" directive was used and not all access
and auth modules directives were set, then other given access and
auth directives were not tested;
*) Bugfix: regex parameters in a "valid_referers" directive were not
inherited from previous level.
*) Bugfix: a "post_action" directive did run if a request was completed
with 499 status code.
*) Bugfix: optimization of 16K buffer usage in a SSL connection.
Thanks to Ben Maurer.
*) Bugfix: the STARTTLS in SMTP mode did not work.
Thanks to Oleg Motienko.
*) Bugfix: in HTTPS mode requests might fail with the "bad write retry"
error; bug appeared in 0.5.13.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Thu, 27 Dec 2007 00:00:00 +0300 |
parents | b743d290eb3b |
children | 2b41fbc2e39e |
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -22,6 +22,7 @@ static void ngx_ssl_read_handler(ngx_eve static void ngx_ssl_shutdown_handler(ngx_event_t *ev); static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, char *text); +static void ngx_ssl_clear_error(ngx_log_t *log); static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); @@ -186,8 +187,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); } - SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - SSL_CTX_set_read_ahead(ssl->ctx, 1); return NGX_OK; @@ -345,14 +344,7 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl return NGX_ERROR; } - if (flags & NGX_SSL_BUFFER) { - sc->buffer = 1; - - sc->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); - if (sc->buf == NULL) { - return NGX_ERROR; - } - } + sc->buffer = ((flags & NGX_SSL_BUFFER) != 0); sc->connection = SSL_new(ssl->ctx); @@ -404,6 +396,8 @@ ngx_ssl_handshake(ngx_connection_t *c) int n, sslerr; ngx_err_t err; + ngx_ssl_clear_error(c->log); + n = SSL_do_handshake(c->ssl->connection); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); @@ -605,6 +599,8 @@ ngx_ssl_recv(ngx_connection_t *c, u_char bytes = 0; + ngx_ssl_clear_error(c->log); + /* * SSL_read() may return data in parts, so try to read * until SSL_read() would return no data @@ -801,8 +797,28 @@ ngx_ssl_send_chain(ngx_connection_t *c, limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; } - buf = c->ssl->buf; + + if (buf == NULL) { + buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE); + if (buf == NULL) { + return NGX_CHAIN_ERROR; + } + + c->ssl->buf = buf; + } + + if (buf->start == NULL) { + buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE); + if (buf->start == NULL) { + return NGX_CHAIN_ERROR; + } + + buf->pos = buf->start; + buf->last = buf->start; + buf->end = buf->start + NGX_SSL_BUFSIZE; + } + send = 0; flush = (in == NULL) ? 1 : 0; @@ -895,6 +911,8 @@ ngx_ssl_write(ngx_connection_t *c, u_cha int n, sslerr; ngx_err_t err; + ngx_ssl_clear_error(c->log); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); n = SSL_write(c->ssl->connection, data, size); @@ -975,12 +993,20 @@ ngx_ssl_read_handler(ngx_event_t *rev) } +void +ngx_ssl_free_buffer(ngx_connection_t *c) +{ + if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) { + c->ssl->buf->start = NULL; + } +} + + ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { - int n, sslerr, mode; - ngx_err_t err; - ngx_uint_t again; + int n, sslerr, mode; + ngx_err_t err; if (c->timedout) { mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; @@ -999,40 +1025,34 @@ ngx_ssl_shutdown(ngx_connection_t *c) SSL_set_shutdown(c->ssl->connection, mode); - again = 0; + ngx_ssl_clear_error(c->log); + + n = SSL_shutdown(c->ssl->connection); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); + sslerr = 0; - for ( ;; ) { - n = SSL_shutdown(c->ssl->connection); - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); - - if (n == 1 || (n == 0 && c->timedout)) { - SSL_free(c->ssl->connection); - c->ssl = NULL; - - return NGX_OK; - } - - if (n == 0) { - again = 1; - break; - } - - break; - } - - if (!again) { + /* SSL_shutdown() never return -1, on error it return 0 */ + + if (n != 1) { sslerr = SSL_get_error(c->ssl->connection, n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); } - if (again - || sslerr == SSL_ERROR_WANT_READ - || sslerr == SSL_ERROR_WANT_WRITE) + if (n == 1 + || sslerr == SSL_ERROR_ZERO_RETURN + || (sslerr == 0 && c->timedout)) { + SSL_free(c->ssl->connection); + c->ssl = NULL; + + return NGX_OK; + } + + if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) { c->read->handler = ngx_ssl_shutdown_handler; c->write->handler = ngx_ssl_shutdown_handler; @@ -1044,7 +1064,7 @@ ngx_ssl_shutdown(ngx_connection_t *c) return NGX_ERROR; } - if (again || sslerr == SSL_ERROR_WANT_READ) { + if (sslerr == SSL_ERROR_WANT_READ) { ngx_add_timer(c->read, 30000); } @@ -1125,6 +1145,15 @@ ngx_ssl_connection_error(ngx_connection_ } +static void +ngx_ssl_clear_error(ngx_log_t *log) +{ + if (ERR_peek_error()) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error"); + } +} + + void ngx_cdecl ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) { @@ -1167,6 +1196,11 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng { long cache_mode; + if (builtin_session_cache == NGX_SSL_NO_SCACHE) { + SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); + return NGX_OK; + } + cache_mode = SSL_SESS_CACHE_SERVER; if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) { @@ -1210,7 +1244,6 @@ static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) { ngx_slab_pool_t *shpool; - ngx_rbtree_node_t *sentinel; ngx_ssl_session_cache_t *cache; if (data) { @@ -1225,25 +1258,11 @@ ngx_ssl_session_cache_init(ngx_shm_zone_ return NGX_ERROR; } - cache->session_cache_head.prev = NULL; - cache->session_cache_head.next = &cache->session_cache_tail; - - cache->session_cache_tail.prev = &cache->session_cache_head; - cache->session_cache_tail.next = NULL; - - cache->session_rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t)); - if (cache->session_rbtree == NULL) { - return NGX_ERROR; - } - - sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t)); - if (sentinel == NULL) { - return NGX_ERROR; - } - - ngx_rbtree_init(cache->session_rbtree, sentinel, + ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel, ngx_ssl_session_rbtree_insert_value); + ngx_queue_init(&cache->expire_queue); + shm_zone->data = cache; return NGX_OK; @@ -1274,7 +1293,6 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_ u_char *p, *id, *cached_sess; uint32_t hash; SSL_CTX *ssl_ctx; - ngx_time_t *tp; ngx_shm_zone_t *shm_zone; ngx_connection_t *c; ngx_slab_pool_t *shpool; @@ -1350,22 +1368,17 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_ "http ssl new session: %08XD:%d:%d", hash, sess->session_id_length, len); - tp = ngx_timeofday(); - sess_id->node.key = hash; sess_id->node.data = (u_char) sess->session_id_length; sess_id->id = id; sess_id->len = len; sess_id->session = cached_sess; - sess_id->expire = tp->sec + SSL_CTX_get_timeout(ssl_ctx); - - sess_id->next = cache->session_cache_head.next; - sess_id->next->prev = sess_id; - sess_id->prev = &cache->session_cache_head; - cache->session_cache_head.next = sess_id; - - ngx_rbtree_insert(cache->session_rbtree, &sess_id->node); + sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx); + + ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue); + + ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node); ngx_shmtx_unlock(&shpool->mutex); @@ -1400,7 +1413,6 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ u_char *p; uint32_t hash; ngx_int_t rc; - ngx_time_t *tp; ngx_shm_zone_t *shm_zone; ngx_slab_pool_t *shpool; ngx_connection_t *c; @@ -1423,18 +1435,14 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ cache = shm_zone->data; - if (cache->session_rbtree == NULL) { - return NULL; - } - sess = NULL; shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); - node = cache->session_rbtree->root; - sentinel = cache->session_rbtree->sentinel; + node = cache->session_rbtree.root; + sentinel = cache->session_rbtree.sentinel; while (node != sentinel) { @@ -1457,9 +1465,7 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ (size_t) len, (size_t) node->data); if (rc == 0) { - tp = ngx_timeofday(); - - if (sess_id->expire > tp->sec) { + if (sess_id->expire > ngx_time()) { ngx_memcpy(buf, sess_id->session, sess_id->len); ngx_shmtx_unlock(&shpool->mutex); @@ -1470,10 +1476,9 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ return sess; } - sess_id->next->prev = sess_id->prev; - sess_id->prev->next = sess_id->next; - - ngx_rbtree_delete(cache->session_rbtree, node); + ngx_queue_remove(&sess_id->queue); + + ngx_rbtree_delete(&cache->session_rbtree, node); ngx_slab_free_locked(shpool, sess_id->session); #if (NGX_PTR_SIZE == 4) @@ -1530,8 +1535,8 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx ngx_shmtx_lock(&shpool->mutex); - node = cache->session_rbtree->root; - sentinel = cache->session_rbtree->sentinel; + node = cache->session_rbtree.root; + sentinel = cache->session_rbtree.sentinel; while (node != sentinel) { @@ -1553,10 +1558,10 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data); if (rc == 0) { - sess_id->next->prev = sess_id->prev; - sess_id->prev->next = sess_id->next; - - ngx_rbtree_delete(cache->session_rbtree, node); + + ngx_queue_remove(&sess_id->queue); + + ngx_rbtree_delete(&cache->session_rbtree, node); ngx_slab_free_locked(shpool, sess_id->session); #if (NGX_PTR_SIZE == 4) @@ -1584,31 +1589,33 @@ static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, ngx_slab_pool_t *shpool, ngx_uint_t n) { - ngx_time_t *tp; + time_t now; + ngx_queue_t *q; ngx_ssl_sess_id_t *sess_id; - tp = ngx_timeofday(); + now = ngx_time(); while (n < 3) { - sess_id = cache->session_cache_tail.prev; - - if (sess_id == &cache->session_cache_head) { + if (ngx_queue_empty(&cache->expire_queue)) { return; } - if (n++ != 0 && sess_id->expire > tp->sec) { + q = ngx_queue_last(&cache->expire_queue); + + sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue); + + if (n++ != 0 && sess_id->expire > now) { return; } - sess_id->next->prev = sess_id->prev; - sess_id->prev->next = sess_id->next; - - ngx_rbtree_delete(cache->session_rbtree, &sess_id->node); + ngx_queue_remove(q); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "expire session: %08Xi", sess_id->node.key); + ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node); + ngx_slab_free_locked(shpool, sess_id->session); #if (NGX_PTR_SIZE == 4) ngx_slab_free_locked(shpool, sess_id->id);