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)