Remove ssl->verify_result.
Having two copies of this is confusing. This field is inherently tied to
the certificate chain, which lives on SSL_SESSION, so this should live
there too. This also wasn't getting reset correctly on SSL_clear, but
this is now resolved.
Change-Id: I22b1734a93320bb0bf0dc31faa74d77a8e1de906
Reviewed-on: https://boringssl-review.googlesource.com/10283
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 10a0423..f1c25ef 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3669,9 +3669,9 @@
* |peer|, but when a server it does not. */
STACK_OF(X509) *cert_chain;
- /* when app_verify_callback accepts a session where the peer's certificate is
- * not ok, we must remember the error for session reuse: */
- long verify_result; /* only for servers */
+ /* verify_result is the result of certificate verification in the case of
+ * non-fatal certificate errors. */
+ long verify_result;
long timeout;
long time;
@@ -4131,7 +4131,6 @@
SSL_CTX *ctx;
/* extra application data */
- long verify_result;
CRYPTO_EX_DATA ex_data;
/* for server side, keep the list of CA_dn we can use */
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index d7b1a2c..237f452 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -1101,11 +1101,11 @@
}
static int ssl3_verify_server_cert(SSL *ssl) {
- if (!ssl_verify_cert_chain(ssl, ssl->s3->new_session->cert_chain)) {
+ if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
+ ssl->s3->new_session->cert_chain)) {
return -1;
}
- ssl->s3->new_session->verify_result = ssl->verify_result;
return 1;
}
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index f5bf0da..1d7c7ee 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -712,7 +712,6 @@
/* Use the old session. */
ssl->session = session;
session = NULL;
- ssl->verify_result = ssl->session->verify_result;
ssl->s3->session_reused = 1;
} else {
SSL_set_session(ssl, NULL);
@@ -813,7 +812,6 @@
if (!ssl->s3->tmp.cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->verify_result = X509_V_OK;
ssl->s3->new_session->verify_result = X509_V_OK;
}
}
@@ -1261,7 +1259,6 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->verify_result = X509_V_OK;
ssl->s3->new_session->verify_result = X509_V_OK;
ssl->s3->tmp.reuse_message = 1;
return 1;
@@ -1312,21 +1309,21 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->verify_result = X509_V_OK;
+ ssl->s3->new_session->verify_result = X509_V_OK;
} else {
/* The hash would have been filled in. */
if (ssl->ctx->retain_only_sha256_of_client_certs) {
ssl->s3->new_session->peer_sha256_valid = 1;
}
- if (!ssl_verify_cert_chain(ssl, chain)) {
+ if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
+ chain)) {
goto err;
}
}
X509_free(ssl->s3->new_session->peer);
ssl->s3->new_session->peer = sk_X509_shift(chain);
- ssl->s3->new_session->verify_result = ssl->verify_result;
sk_X509_pop_free(ssl->s3->new_session->cert_chain, X509_free);
ssl->s3->new_session->cert_chain = chain;
diff --git a/ssl/internal.h b/ssl/internal.h
index 4f13459..6e3a744 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1301,7 +1301,8 @@
void ssl_cert_set_cert_cb(CERT *cert,
int (*cb)(SSL *ssl, void *arg), void *arg);
-int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
+int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
+ STACK_OF(X509) * cert_chain);
void ssl_update_cache(SSL *ssl, int mode);
/* ssl_get_compatible_server_ciphers determines the key exchange and
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index c35834e..3cfcd8d 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -285,7 +285,8 @@
c->cert_cb_arg = arg;
}
-int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) {
+int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
+ STACK_OF(X509) *cert_chain) {
if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
return 0;
}
@@ -326,17 +327,15 @@
verify_ret = X509_verify_cert(&ctx);
}
- ssl->verify_result = ctx.error;
-
/* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL,
- ssl_verify_alarm_type(ssl->verify_result));
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, ssl_verify_alarm_type(ctx.error));
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
ERR_clear_error();
+ *out_verify_result = ctx.error;
ret = 1;
err:
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index da66263..9be76be 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -441,7 +441,6 @@
ssl->alpn_client_proto_list_len = ssl->ctx->alpn_client_proto_list_len;
}
- ssl->verify_result = X509_V_ERR_INVALID_CALL;
ssl->method = ctx->method;
if (!ssl->method->ssl_new(ssl)) {
@@ -2316,7 +2315,13 @@
}
}
-long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; }
+long SSL_get_verify_result(const SSL *ssl) {
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL) {
+ return X509_V_ERR_INVALID_CALL;
+ }
+ return session->verify_result;
+}
int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index e26866b..a9eb5bd 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -801,7 +801,6 @@
ssl->session = session;
if (session != NULL) {
SSL_SESSION_up_ref(session);
- ssl->verify_result = session->verify_result;
}
return 1;
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 8400c60..bccc09b 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -184,7 +184,6 @@
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->verify_result = X509_V_OK;
ssl->s3->new_session->verify_result = X509_V_OK;
/* No certificate, so nothing more to do. */
@@ -194,12 +193,11 @@
ssl->s3->new_session->peer_sha256_valid = retain_sha256;
- if (!ssl_verify_cert_chain(ssl, chain)) {
+ if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
+ chain)) {
goto err;
}
- ssl->s3->new_session->verify_result = ssl->verify_result;
-
X509_free(ssl->s3->new_session->peer);
X509 *leaf = sk_X509_value(chain, 0);
X509_up_ref(leaf);
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index eb11738..5bb52f2 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -165,7 +165,6 @@
return ssl_hs_error;
}
ssl->s3->session_reused = 1;
- ssl->verify_result = session->verify_result;
SSL_SESSION_free(session);
}
@@ -492,7 +491,6 @@
if (!ssl->s3->tmp.cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
- ssl->verify_result = X509_V_OK;
ssl->s3->new_session->verify_result = X509_V_OK;
/* Skip this state. */