Commit 250b95b24b1a079be5825f862e42f4b99a4c3587

Carlos Martín Nieto 2012-05-26T21:17:08

ssl: allow skipping the server certificate check Sometimes it's useful not to perform the check. Allow it to be configurable.

diff --git a/include/git2/remote.h b/include/git2/remote.h
index 865dfef..1f36f78 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -229,6 +229,15 @@ GIT_EXTERN(int) git_remote_list(git_strarray *remotes_list, git_repository *repo
  */
 GIT_EXTERN(int) git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url);
 
+/**
+ * Choose whether to check the server's certificate (applies to HTTPS only)
+ *
+ * @param remote the remote to configure
+ * @param check whether to check the server's certificate (defaults to yes)
+ */
+
+GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/netops.c b/src/netops.c
index bd76d30..706e092 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -358,7 +358,7 @@ static int ssl_setup(git_transport *t, const char *host)
 	if ((ret = SSL_connect(t->ssl.ssl)) <= 0)
 		return ssl_set_error(&t->ssl, ret);
 
-	if (verify_server_cert(t, host) < 0)
+	if (t->check_cert && verify_server_cert(t, host) < 0)
 		return -1;
 
 	return 0;
diff --git a/src/remote.c b/src/remote.c
index 9740344..8e280c4 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -66,6 +66,7 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con
 
 	memset(remote, 0x0, sizeof(git_remote));
 	remote->repo = repo;
+	remote->check_cert = 1;
 
 	if (git_vector_init(&remote->refs, 32, NULL) < 0)
 		return -1;
@@ -108,6 +109,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
 	GITERR_CHECK_ALLOC(remote);
 
 	memset(remote, 0x0, sizeof(git_remote));
+	remote->check_cert = 1;
 	remote->name = git__strdup(name);
 	GITERR_CHECK_ALLOC(remote->name);
 
@@ -287,6 +289,7 @@ int git_remote_connect(git_remote *remote, int direction)
 	if (git_transport_new(&t, remote->url) < 0)
 		return -1;
 
+	t->check_cert = remote->check_cert;
 	if (t->connect(t, direction) < 0) {
 		goto on_error;
 	}
@@ -508,3 +511,10 @@ on_error:
 	git_remote_free(*out);
 	return -1;
 }
+
+void git_remote_check_cert(git_remote *remote, int check)
+{
+	assert(remote);
+
+	remote->check_cert = check;
+}
diff --git a/src/remote.h b/src/remote.h
index 5a1625d..0949ad4 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -19,7 +19,8 @@ struct git_remote {
 	struct git_refspec push;
 	git_transport *transport;
 	git_repository *repo;
-	unsigned int need_pack:1;
+	unsigned int need_pack:1,
+		check_cert;
 };
 
 #endif
diff --git a/src/transport.h b/src/transport.h
index 00c140b..68b92f7 100644
--- a/src/transport.h
+++ b/src/transport.h
@@ -69,6 +69,7 @@ struct git_transport {
 	 */
 	int direction : 1, /* 0 fetch, 1 push */
 		connected : 1,
+		check_cert: 1,
 		encrypt : 1;
 #ifdef GIT_SSL
 	struct gitno_ssl ssl;
diff --git a/src/transports/http.c b/src/transports/http.c
index 36cc66c..afbf5ed 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -692,6 +692,7 @@ int git_transport_https(git_transport **out)
 		return -1;
 
 	t->parent.encrypt = 1;
+	t->parent.check_cert = 1;
 	*out = (git_transport *) t;
 
 	return 0;