Merge pull request #4430 from tiennou/fix/openssl-x509-leak Free OpenSSL peer certificate
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 2b24600..9d56607 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -332,7 +332,7 @@ static int check_host_name(const char *name, const char *host)
static int verify_server_cert(SSL *ssl, const char *host)
{
- X509 *cert;
+ X509 *cert = NULL;
X509_NAME *peer_name;
ASN1_STRING *str;
unsigned char *peer_cn = NULL;
@@ -341,7 +341,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
struct in6_addr addr6;
struct in_addr addr4;
void *addr;
- int i = -1,j;
+ int i = -1, j, error = 0;
if (SSL_get_verify_result(ssl) != X509_V_OK) {
giterr_set(GITERR_SSL, "the SSL certificate is invalid");
@@ -362,8 +362,9 @@ static int verify_server_cert(SSL *ssl, const char *host)
cert = SSL_get_peer_certificate(ssl);
if (!cert) {
+ error = -1;
giterr_set(GITERR_SSL, "the server did not provide a certificate");
- return -1;
+ goto cleanup;
}
/* Check the alternative names */
@@ -401,8 +402,9 @@ static int verify_server_cert(SSL *ssl, const char *host)
if (matched == 0)
goto cert_fail_name;
- if (matched == 1)
- return 0;
+ if (matched == 1) {
+ goto cleanup;
+ }
/* If no alternative names are available, check the common name */
peer_name = X509_get_subject_name(cert);
@@ -444,18 +446,21 @@ static int verify_server_cert(SSL *ssl, const char *host)
if (check_host_name((char *)peer_cn, host) < 0)
goto cert_fail_name;
- OPENSSL_free(peer_cn);
+ goto cleanup;
- return 0;
+cert_fail_name:
+ error = GIT_ECERTIFICATE;
+ giterr_set(GITERR_SSL, "hostname does not match certificate");
+ goto cleanup;
on_error:
- OPENSSL_free(peer_cn);
- return ssl_set_error(ssl, 0);
+ error = ssl_set_error(ssl, 0);
+ goto cleanup;
-cert_fail_name:
+cleanup:
+ X509_free(cert);
OPENSSL_free(peer_cn);
- giterr_set(GITERR_SSL, "hostname does not match certificate");
- return GIT_ECERTIFICATE;
+ return error;
}
typedef struct {