streams: openssl: fix memleak due to us not free'ing certs When creating a `git_cert` from the OpenSSL X509 certificate of a given stream, we do not call `X509_free()` on the certificate, leading to a memory leak as soon as the certificate is requested e.g. by the certificate check callback. Fix the issue by properly calling `X509_free()`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 5b66352..6a490d1 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -655,15 +655,16 @@ static int openssl_connect(git_stream *stream)
static int openssl_certificate(git_cert **out, git_stream *stream)
{
openssl_stream *st = (openssl_stream *) stream;
- int len;
X509 *cert = SSL_get_peer_certificate(st->ssl);
- unsigned char *guard, *encoded_cert;
+ unsigned char *guard, *encoded_cert = NULL;
+ int error, len;
/* Retrieve the length of the certificate first */
len = i2d_X509(cert, NULL);
if (len < 0) {
git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information");
- return -1;
+ error = -1;
+ goto out;
}
encoded_cert = git__malloc(len);
@@ -673,18 +674,23 @@ static int openssl_certificate(git_cert **out, git_stream *stream)
len = i2d_X509(cert, &guard);
if (len < 0) {
- git__free(encoded_cert);
git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information");
- return -1;
+ error = -1;
+ goto out;
}
st->cert_info.parent.cert_type = GIT_CERT_X509;
st->cert_info.data = encoded_cert;
st->cert_info.len = len;
+ encoded_cert = NULL;
*out = &st->cert_info.parent;
+ error = 0;
- return 0;
+out:
+ git__free(encoded_cert);
+ X509_free(cert);
+ return error;
}
static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)