# HG changeset patch # User Roman Arutyunyan # Date 1590168905 -10800 # Node ID 7cffd81015e701cc310f6f54e6a6a6185b4f7859 # Parent 6ca8e15caf1f9bf869289c6750ad27152079fd61 OCSP stapling: iterate over all responder addresses. Previously only the first responder address was used per each stapling update. Now, in case of a network or parsing error, next address is used. This also fixes the issue with unsupported responder address families (ticket #1330). diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -22,6 +22,7 @@ typedef struct { ngx_msec_t resolver_timeout; ngx_addr_t *addrs; + ngx_uint_t naddrs; ngx_str_t host; ngx_str_t uri; in_port_t port; @@ -57,6 +58,7 @@ struct ngx_ssl_ocsp_ctx_s { u_char *name; ngx_uint_t naddrs; + ngx_uint_t naddr; ngx_addr_t *addrs; ngx_str_t host; @@ -114,6 +116,7 @@ static void ngx_ssl_stapling_cleanup(voi static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void); static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx); +static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx); static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx); static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve); static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx); @@ -469,6 +472,7 @@ ngx_ssl_stapling_responder(ngx_conf_t *c } staple->addrs = u.addrs; + staple->naddrs = u.naddrs; staple->host = u.host; staple->uri = u.uri; staple->port = u.port; @@ -579,6 +583,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY); ctx->addrs = staple->addrs; + ctx->naddrs = staple->naddrs; ctx->host = staple->host; ctx->uri = staple->uri; ctx->port = staple->port; @@ -769,6 +774,36 @@ ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *c static void +ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx) +{ + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, + "ssl ocsp next"); + + if (++ctx->naddr >= ctx->naddrs) { + ngx_ssl_ocsp_error(ctx); + return; + } + + ctx->request->pos = ctx->request->start; + + if (ctx->response) { + ctx->response->last = ctx->response->pos; + } + + if (ctx->peer.connection) { + ngx_close_connection(ctx->peer.connection); + ctx->peer.connection = NULL; + } + + ctx->state = 0; + ctx->count = 0; + ctx->done = 0; + + ngx_ssl_ocsp_connect(ctx); +} + + +static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx) { ngx_resolver_ctx_t *resolve, temp; @@ -906,16 +941,17 @@ failed: static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx) { - ngx_int_t rc; + ngx_int_t rc; + ngx_addr_t *addr; - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, - "ssl ocsp connect"); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, + "ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs); - /* TODO: use all ip addresses */ + addr = &ctx->addrs[ctx->naddr]; - ctx->peer.sockaddr = ctx->addrs[0].sockaddr; - ctx->peer.socklen = ctx->addrs[0].socklen; - ctx->peer.name = &ctx->addrs[0].name; + ctx->peer.sockaddr = addr->sockaddr; + ctx->peer.socklen = addr->socklen; + ctx->peer.name = &addr->name; ctx->peer.get = ngx_event_get_peer; ctx->peer.log = ctx->log; ctx->peer.log_error = NGX_ERROR_ERR; @@ -925,11 +961,16 @@ ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp connect peer done"); - if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { + if (rc == NGX_ERROR) { ngx_ssl_ocsp_error(ctx); return; } + if (rc == NGX_BUSY || rc == NGX_DECLINED) { + ngx_ssl_ocsp_next(ctx); + return; + } + ctx->peer.connection->data = ctx; ctx->peer.connection->pool = ctx->pool; @@ -964,7 +1005,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t * if (wev->timedout) { ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, "OCSP responder timed out"); - ngx_ssl_ocsp_error(ctx); + ngx_ssl_ocsp_next(ctx); return; } @@ -973,7 +1014,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t * n = ngx_send(c, ctx->request->pos, size); if (n == NGX_ERROR) { - ngx_ssl_ocsp_error(ctx); + ngx_ssl_ocsp_next(ctx); return; } @@ -1018,7 +1059,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *r if (rev->timedout) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, "OCSP responder timed out"); - ngx_ssl_ocsp_error(ctx); + ngx_ssl_ocsp_next(ctx); return; } @@ -1042,7 +1083,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *r rc = ctx->process(ctx); if (rc == NGX_ERROR) { - ngx_ssl_ocsp_error(ctx); + ngx_ssl_ocsp_next(ctx); return; } @@ -1073,7 +1114,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *r ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "OCSP responder prematurely closed connection"); - ngx_ssl_ocsp_error(ctx); + ngx_ssl_ocsp_next(ctx); }