Commit f54d8d528a5843075c6c60167d4659e393956fa3

Edward Thomson 2014-10-10T11:28:58

Merge pull request #2574 from csware/hostname-for-certificate_check_cb Provide host name to certificate_check_cb

diff --git a/include/git2/types.h b/include/git2/types.h
index 14b7071..64cdfcd 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -290,9 +290,10 @@ typedef struct {
  * @param len The size of the certificate or host info
  * @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think
  * this certificate is valid
+ * @param host Hostname of the host libgit2 connected to
  * @param payload Payload provided by the caller
  */
-typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, void *payload);
+typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload);
 
 /**
  * Opaque structure representing a submodule.
diff --git a/src/transports/http.c b/src/transports/http.c
index 7ef0b51..bcfeaee 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -581,7 +581,7 @@ static int http_connect(http_subtransport *t)
 		cert_info.cert_type = GIT_CERT_X509;
 		cert_info.data = encoded_cert;
 		cert_info.len = len;
-                error = t->owner->certificate_check_cb((git_cert *) &cert_info, is_valid, t->owner->message_cb_payload);
+		error = t->owner->certificate_check_cb((git_cert *) &cert_info, is_valid, t->connection_data.host, t->owner->message_cb_payload);
 		git__free(encoded_cert);
 
 		if (error < 0) {
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 15a45ca..3868a52 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -504,7 +504,7 @@ static int _git_ssh_setup_conn(
 
 		/* We don't currently trust any hostkeys */
 		giterr_clear();
-                error = t->owner->certificate_check_cb((git_cert *) &cert, 0, t->owner->message_cb_payload);
+		error = t->owner->certificate_check_cb((git_cert *) &cert, 0, host, t->owner->message_cb_payload);
 		if (error < 0) {
 			if (!giterr_last())
 				giterr_set(GITERR_NET, "user cancelled hostkey check");
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 8aef631..5a59daf 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -229,7 +229,7 @@ static int certificate_check(winhttp_stream *s, int valid)
 	cert.cert_type = GIT_CERT_X509;
 	cert.data = cert_ctx->pbCertEncoded;
 	cert.len = cert_ctx->cbCertEncoded;
-	error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->owner->cred_acquire_payload);
+	error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->connection_data.host, t->owner->cred_acquire_payload);
 	CertFreeCertificateContext(cert_ctx);
 
 	if (error < 0 && !giterr_last())
diff --git a/tests/online/clone.c b/tests/online/clone.c
index f7f3aae..13abd39 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -473,7 +473,7 @@ void test_online_clone__ssh_cannot_change_username(void)
 	cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
 }
 
-int ssh_certificate_check(git_cert *cert, int valid, void *payload)
+int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
 {
 	git_cert_hostkey *key;
 	git_oid expected = {{0}}, actual = {{0}};
@@ -504,6 +504,8 @@ int ssh_certificate_check(git_cert *cert, int valid, void *payload)
 
 	cl_assert(!memcmp(&expected, &actual, 20));
 
+	cl_assert_equal_s("localhost", host);
+
 	return GIT_EUSER;
 }
 
@@ -523,10 +525,11 @@ void test_online_clone__url_with_no_path_returns_EINVALIDSPEC(void)
 		GIT_EINVALIDSPEC);
 }
 
-static int fail_certificate_check(git_cert *cert, int valid, void *payload)
+static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
 {
 	GIT_UNUSED(cert);
 	GIT_UNUSED(valid);
+	GIT_UNUSED(host);
 	GIT_UNUSED(payload);
 
 	return GIT_ECERTIFICATE;
@@ -545,12 +548,14 @@ void test_online_clone__certificate_invalid(void)
 #endif
 }
 
-static int succeed_certificate_check(git_cert *cert, int valid, void *payload)
+static int succeed_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
 {
 	GIT_UNUSED(cert);
 	GIT_UNUSED(valid);
 	GIT_UNUSED(payload);
 
+	cl_assert_equal_s("github.com", host);
+
 	return 0;
 }