Skip to content

Commit cf70c24

Browse files
tniessendanielleadams
authored andcommitted
src: fix static analysis warning and use smart ptr
Coverity issues a warning about `value_before_reset == ca`, where value_before_reset is a pointer that may not be valid. While comparing the pointer itself should still work, we should really be using smart pointers here so that this particular check can be simplified without running into a memory leak. Refactor SSL_CTX_get_issuer to return a smart pointer and update the call sites accordingly. Note that we might have to change that in the future once we improve error handling throughout crypto/tls. Refs: #37990 PR-URL: #43117 Reviewed-By: Darshan Sen <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
1 parent d5b5a26 commit cf70c24

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

src/crypto/crypto_common.cc

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,18 @@ static constexpr int kX509NameFlagsMultiline =
4848
XN_FLAG_SEP_MULTILINE |
4949
XN_FLAG_FN_SN;
5050

51-
bool SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
51+
X509Pointer SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert) {
5252
X509_STORE* store = SSL_CTX_get_cert_store(ctx);
5353
DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
5454
X509_STORE_CTX_new());
55-
return store_ctx.get() != nullptr &&
56-
X509_STORE_CTX_init(store_ctx.get(), store, nullptr, nullptr) == 1 &&
57-
X509_STORE_CTX_get1_issuer(issuer, store_ctx.get(), cert) == 1;
55+
X509Pointer result;
56+
X509* issuer;
57+
if (store_ctx.get() != nullptr &&
58+
X509_STORE_CTX_init(store_ctx.get(), store, nullptr, nullptr) == 1 &&
59+
X509_STORE_CTX_get1_issuer(&issuer, store_ctx.get(), cert) == 1) {
60+
result.reset(issuer);
61+
}
62+
return result;
5863
}
5964

6065
void LogSecret(
@@ -386,29 +391,27 @@ MaybeLocal<Object> GetLastIssuedCert(
386391
Environment* const env) {
387392
Local<Context> context = env->isolate()->GetCurrentContext();
388393
while (X509_check_issued(cert->get(), cert->get()) != X509_V_OK) {
389-
X509* ca;
390-
if (SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get(), &ca) <= 0)
394+
X509Pointer ca;
395+
if (!(ca = SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get())))
391396
break;
392397

393398
Local<Object> ca_info;
394-
MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
399+
MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca.get());
395400
if (!maybe_ca_info.ToLocal(&ca_info))
396401
return MaybeLocal<Object>();
397402

398403
if (!Set<Object>(context, issuer_chain, env->issuercert_string(), ca_info))
399404
return MaybeLocal<Object>();
400405
issuer_chain = ca_info;
401406

402-
// Take the value of cert->get() before the call to cert->reset()
403-
// in order to compare it to ca after and provide a way to exit this loop
404-
// in case it gets stuck.
405-
X509* value_before_reset = cert->get();
407+
// For self-signed certificates whose keyUsage field does not include
408+
// keyCertSign, X509_check_issued() will return false. Avoid going into an
409+
// infinite loop by checking if SSL_CTX_get_issuer() returned the same
410+
// certificate.
411+
if (cert->get() == ca.get()) break;
406412

407413
// Delete previous cert and continue aggregating issuers.
408-
cert->reset(ca);
409-
410-
if (value_before_reset == ca)
411-
break;
414+
*cert = std::move(ca);
412415
}
413416
return MaybeLocal<Object>(issuer_chain);
414417
}

src/crypto/crypto_common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct StackOfXASN1Deleter {
2525
};
2626
using StackOfASN1 = std::unique_ptr<STACK_OF(ASN1_OBJECT), StackOfXASN1Deleter>;
2727

28-
bool SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer);
28+
X509Pointer SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert);
2929

3030
void LogSecret(
3131
const SSLPointer& ssl,

src/crypto/crypto_context.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,21 +110,21 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
110110
// Try getting issuer from a cert store
111111
if (ret) {
112112
if (issuer == nullptr) {
113-
ret = SSL_CTX_get_issuer(ctx, x.get(), &issuer);
114-
ret = ret < 0 ? 0 : 1;
113+
// TODO(tniessen): SSL_CTX_get_issuer does not allow the caller to
114+
// distinguish between a failed operation and an empty result. Fix that
115+
// and then handle the potential error properly here (set ret to 0).
116+
*issuer_ = SSL_CTX_get_issuer(ctx, x.get());
115117
// NOTE: get_cert_store doesn't increment reference count,
116118
// no need to free `store`
117119
} else {
118120
// Increment issuer reference count
119-
issuer = X509_dup(issuer);
120-
if (issuer == nullptr) {
121+
issuer_->reset(X509_dup(issuer));
122+
if (!*issuer_) {
121123
ret = 0;
122124
}
123125
}
124126
}
125127

126-
issuer_->reset(issuer);
127-
128128
if (ret && x != nullptr) {
129129
cert->reset(X509_dup(x.get()));
130130
if (!*cert)

0 commit comments

Comments
 (0)