Mercurial > hg > nginx
comparison src/event/ngx_event_openssl_stapling.c @ 7667:1ece2ac2555a
OCSP: fixed use-after-free on error.
When validating second and further certificates, ssl callback could be called
twice to report the error. After the first call client connection is
terminated and its memory is released. Prior to the second call and in it
released connection memory is accessed.
Errors triggering this behavior:
- failure to create the request
- failure to start resolving OCSP responder name
- failure to start connecting to the OCSP responder
The fix is to rearrange the code to eliminate the second call.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 15 Jun 2020 20:17:16 +0300 |
parents | bd4d1b9db0ee |
children | d752a2c76d49 |
comparison
equal
deleted
inserted
replaced
7666:8cf31489b479 | 7667:1ece2ac2555a |
---|---|
978 for ( ;; ) { | 978 for ( ;; ) { |
979 | 979 |
980 if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) { | 980 if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) { |
981 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 981 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
982 "ssl ocsp validated, certs:%ui", ocsp->ncert); | 982 "ssl ocsp validated, certs:%ui", ocsp->ncert); |
983 rc = NGX_OK; | |
983 goto done; | 984 goto done; |
984 } | 985 } |
985 | 986 |
986 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 987 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
987 "ssl ocsp validate cert:%ui", ocsp->ncert); | 988 "ssl ocsp validate cert:%ui", ocsp->ncert); |
988 | 989 |
989 ctx = ngx_ssl_ocsp_start(c->log); | 990 ctx = ngx_ssl_ocsp_start(c->log); |
990 if (ctx == NULL) { | 991 if (ctx == NULL) { |
991 goto failed; | 992 rc = NGX_ERROR; |
993 goto done; | |
992 } | 994 } |
993 | 995 |
994 ocsp->ctx = ctx; | 996 ocsp->ctx = ctx; |
995 | 997 |
996 ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection); | 998 ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection); |
1010 ctx->naddrs = ocf->naddrs; | 1012 ctx->naddrs = ocf->naddrs; |
1011 ctx->host = ocf->host; | 1013 ctx->host = ocf->host; |
1012 ctx->uri = ocf->uri; | 1014 ctx->uri = ocf->uri; |
1013 ctx->port = ocf->port; | 1015 ctx->port = ocf->port; |
1014 | 1016 |
1015 if (ngx_ssl_ocsp_responder(c, ctx) != NGX_OK) { | 1017 rc = ngx_ssl_ocsp_responder(c, ctx); |
1016 goto failed; | 1018 if (rc != NGX_OK) { |
1019 goto done; | |
1017 } | 1020 } |
1018 | 1021 |
1019 if (ctx->uri.len == 0) { | 1022 if (ctx->uri.len == 0) { |
1020 ngx_str_set(&ctx->uri, "/"); | 1023 ngx_str_set(&ctx->uri, "/"); |
1021 } | 1024 } |
1023 ocsp->ncert++; | 1026 ocsp->ncert++; |
1024 | 1027 |
1025 rc = ngx_ssl_ocsp_cache_lookup(ctx); | 1028 rc = ngx_ssl_ocsp_cache_lookup(ctx); |
1026 | 1029 |
1027 if (rc == NGX_ERROR) { | 1030 if (rc == NGX_ERROR) { |
1028 goto failed; | 1031 goto done; |
1029 } | 1032 } |
1030 | 1033 |
1031 if (rc == NGX_DECLINED) { | 1034 if (rc == NGX_DECLINED) { |
1032 break; | 1035 break; |
1033 } | 1036 } |
1049 ngx_ssl_ocsp_request(ctx); | 1052 ngx_ssl_ocsp_request(ctx); |
1050 return; | 1053 return; |
1051 | 1054 |
1052 done: | 1055 done: |
1053 | 1056 |
1054 ocsp->status = NGX_OK; | 1057 ocsp->status = rc; |
1055 return; | 1058 |
1056 | 1059 if (c->ssl->in_ocsp) { |
1057 failed: | 1060 c->ssl->handshaked = 1; |
1058 | 1061 c->ssl->handler(c); |
1059 ocsp->status = NGX_ERROR; | 1062 } |
1060 } | 1063 } |
1061 | 1064 |
1062 | 1065 |
1063 static void | 1066 static void |
1064 ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) | 1067 ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) |
1071 ocsp = c->ssl->ocsp; | 1074 ocsp = c->ssl->ocsp; |
1072 ocsp->ctx = NULL; | 1075 ocsp->ctx = NULL; |
1073 | 1076 |
1074 rc = ngx_ssl_ocsp_verify(ctx); | 1077 rc = ngx_ssl_ocsp_verify(ctx); |
1075 if (rc != NGX_OK) { | 1078 if (rc != NGX_OK) { |
1076 ocsp->status = rc; | |
1077 ngx_ssl_ocsp_done(ctx); | |
1078 goto done; | 1079 goto done; |
1079 } | 1080 } |
1080 | 1081 |
1081 rc = ngx_ssl_ocsp_cache_store(ctx); | 1082 rc = ngx_ssl_ocsp_cache_store(ctx); |
1082 if (rc != NGX_OK) { | 1083 if (rc != NGX_OK) { |
1083 ocsp->status = rc; | |
1084 ngx_ssl_ocsp_done(ctx); | |
1085 goto done; | 1084 goto done; |
1086 } | 1085 } |
1087 | 1086 |
1088 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) { | 1087 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) { |
1089 ocsp->cert_status = ctx->status; | 1088 ocsp->cert_status = ctx->status; |
1090 ocsp->status = NGX_OK; | |
1091 ngx_ssl_ocsp_done(ctx); | |
1092 goto done; | 1089 goto done; |
1093 } | 1090 } |
1094 | 1091 |
1095 ngx_ssl_ocsp_done(ctx); | 1092 ngx_ssl_ocsp_done(ctx); |
1096 | 1093 |
1097 ngx_ssl_ocsp_validate_next(c); | 1094 ngx_ssl_ocsp_validate_next(c); |
1098 | 1095 |
1096 return; | |
1097 | |
1099 done: | 1098 done: |
1100 | 1099 |
1101 if (ocsp->status == NGX_AGAIN || !c->ssl->in_ocsp) { | 1100 ocsp->status = rc; |
1102 return; | 1101 ngx_ssl_ocsp_done(ctx); |
1103 } | 1102 |
1104 | 1103 if (c->ssl->in_ocsp) { |
1105 c->ssl->handshaked = 1; | 1104 c->ssl->handshaked = 1; |
1106 | 1105 c->ssl->handler(c); |
1107 c->ssl->handler(c); | 1106 } |
1108 } | 1107 } |
1109 | 1108 |
1110 | 1109 |
1111 static ngx_int_t | 1110 static ngx_int_t |
1112 ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx) | 1111 ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx) |