Commit a6f24a5b3a8dcb9ab7f84679d658e66f374b88d6

Carlos Martín Nieto 2012-05-01T01:50:26

https: make it work with OpenSSL as well Add specific functions that use OpenSSL instead of GnuTLS

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34cc647..b925859 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,7 +26,6 @@ INCLUDE_DIRECTORIES(src include deps/http-parser)
 
 FILE(GLOB SRC_HTTP deps/http-parser/*.c)
 
-FIND_PACKAGE(GnuTLS)
 IF (NOT WIN32)
 	FIND_PACKAGE(ZLIB)
 ELSE()
@@ -87,10 +86,20 @@ IF (NOT CMAKE_BUILD_TYPE)
 	SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
 ENDIF ()
 
-
-IF (GNUTLS_FOUND)
-  INCLUDE_DIRECTORIES(GNUTLS_INCLUDE_DIR)
-  ADD_DEFINITIONS(-DGIT_GNUTLS)
+FIND_PACKAGE(OpenSSL)
+IF (OPENSSL_FOUND)
+  ADD_DEFINITIONS(-DGIT_OPENSSL)
+  ADD_DEFINITIONS(-DGIT_SSL)
+  INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+  SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
+ELSE()
+  FIND_PACKAGE(GnuTLS)
+  IF (GNUTLS_FOUND)
+    INCLUDE_DIRECTORIES(GNUTLS_INCLUDE_DIR)
+    ADD_DEFINITIONS(-DGIT_GNUTLS)
+    ADD_DEFINITIONS(-DGIT_SSL)
+    SET(SSL_LIBRARIES ${GNUTLS_LIBRARIES})
+  ENDIF()
 ENDIF()
 
 IF (THREADSAFE)
@@ -125,7 +134,7 @@ ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
 	TARGET_LINK_LIBRARIES(git2 socket nsl)
 ENDIF ()
 
-TARGET_LINK_LIBRARIES(git2 ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES})
+TARGET_LINK_LIBRARIES(git2 ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES})
 SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
 SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libgit2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc @ONLY)
@@ -161,7 +170,7 @@ IF (BUILD_CLAR)
 		WORKING_DIRECTORY ${CLAR_PATH}
 	)
 	ADD_EXECUTABLE(libgit2_clar ${SRC} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX})
-	TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES})
+	TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES})
 	IF (WIN32)
 		TARGET_LINK_LIBRARIES(libgit2_clar ws2_32)
 	ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
diff --git a/src/common.h b/src/common.h
index 75e6e58..3086565 100644
--- a/src/common.h
+++ b/src/common.h
@@ -22,6 +22,9 @@
 
 #ifdef GIT_GNUTLS
 # include <gnutls/gnutls.h>
+#elif defined(GIT_OPENSSL)
+# include <openssl/ssl.h>
+# include <openssl/err.h>
 #endif
 
 #ifdef GIT_WIN32
@@ -74,6 +77,11 @@ typedef struct gitno_ssl {
 	gnutls_session_t session;
 	gnutls_certificate_credentials_t cred;
 } gitno_ssl;
+#elif defined(GIT_OPENSSL)
+typedef struct gitno_ssl {
+	SSL_CTX *ctx;
+	SSL *ssl;
+} gitno_ssl;
 #endif
 
 #include "util.h"
diff --git a/src/netops.c b/src/netops.c
index f2b504a..67a361e 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -22,8 +22,11 @@
 # include <gnutls/openssl.h>
 # include <gnutls/gnutls.h>
 # include <gnutls/x509.h>
+#elif defined(GIT_OPENSSL)
+# include <openssl/ssl.h>
 #endif
 
+
 #include "git2/errors.h"
 
 #include "common.h"
@@ -57,6 +60,14 @@ static int ssl_set_error(int error)
 	giterr_set(GITERR_NET, "SSL error: (%s) %s", gnutls_strerror_name(error), gnutls_strerror(error));
 	return -1;
 }
+#elif GIT_OPENSSL
+static int ssl_set_error(gitno_ssl *ssl, int error)
+{
+	int err;
+	err = SSL_get_error(ssl->ssl, error);
+	giterr_set(GITERR_NET, "SSL error: %s", ERR_error_string(err, NULL));
+	return -1;
+}
 #endif
 
 void gitno_buffer_setup(git_transport *t, gitno_buffer *buf, char *data, unsigned int len)
@@ -67,12 +78,13 @@ void gitno_buffer_setup(git_transport *t, gitno_buffer *buf, char *data, unsigne
 	buf->len = len;
 	buf->offset = 0;
 	buf->fd = t->socket;
-#ifdef GIT__GNUTLS
+#ifdef GIT_SSL
 	if (t->encrypt)
-		buf->ssl = t->ssl;
+		buf->ssl = &t->ssl;
 #endif
 }
 
+#ifdef GIT_GNUTLS
 static int ssl_recv(gitno_ssl *ssl, void *data, size_t len)
 {
 	int ret;
@@ -88,12 +100,27 @@ static int ssl_recv(gitno_ssl *ssl, void *data, size_t len)
 
 	return ret;
 }
+#elif defined(GIT_OPENSSL)
+static int ssl_recv(gitno_ssl *ssl, void *data, size_t len)
+{
+	int ret;
+
+	do {
+		ret = SSL_read(ssl->ssl, data, len);
+	} while (SSL_get_error(ssl->ssl, ret) == SSL_ERROR_WANT_READ);
+
+	if (ret < 0)
+		return ssl_set_error(ssl, ret);
+
+	return ret;
+}
+#endif
 
 int gitno_recv(gitno_buffer *buf)
 {
 	int ret;
 
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	if (buf->ssl != NULL) {
 		if ((ret = ssl_recv(buf->ssl, buf->data + buf->offset, buf->len - buf->offset)) < 0)
 			return -1;
@@ -174,6 +201,31 @@ on_error:
 	gnutls_deinit(t->ssl.session);
 	return -1;
 }
+#elif defined(GIT_OPENSSL)
+static int ssl_setup(git_transport *t)
+{
+	int ret;
+
+	SSL_library_init();
+	SSL_load_error_strings();
+	t->ssl.ctx = SSL_CTX_new(SSLv23_method());
+	if (t->ssl.ctx == NULL)
+		return ssl_set_error(&t->ssl, 0);
+
+	SSL_CTX_set_mode(t->ssl.ctx, SSL_MODE_AUTO_RETRY);
+
+	t->ssl.ssl = SSL_new(t->ssl.ctx);
+	if (t->ssl.ssl == NULL)
+		return ssl_set_error(&t->ssl, 0);
+
+	if((ret = SSL_set_fd(t->ssl.ssl, t->socket)) == 0)
+		return ssl_set_error(&t->ssl, ret);
+
+	if ((ret = SSL_connect(t->ssl.ssl)) <= 0)
+		return ssl_set_error(&t->ssl, ret);
+
+	return 0;
+}
 #endif
 
 int gitno_connect(git_transport *t, const char *host, const char *port)
@@ -216,7 +268,7 @@ int gitno_connect(git_transport *t, const char *host, const char *port)
 	t->socket = s;
 	freeaddrinfo(info);
 
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	if (t->encrypt && ssl_setup(t) < 0)
 		return -1;
 #endif
@@ -243,6 +295,22 @@ static int send_ssl(gitno_ssl *ssl, const char *msg, size_t len)
 
 	return off;
 }
+#elif defined(GIT_OPENSSL)
+static int send_ssl(gitno_ssl *ssl, const char *msg, size_t len)
+{
+	int ret;
+	size_t off = 0;
+
+	while (off < len) {
+		ret = SSL_write(ssl->ssl, msg + off, len - off);
+		if (ret <= 0)
+			return ssl_set_error(ssl, ret);
+
+		off += ret;
+	}
+
+	return off;
+}
 #endif
 
 int gitno_send(git_transport *t, const char *msg, size_t len, int flags)
@@ -250,7 +318,7 @@ int gitno_send(git_transport *t, const char *msg, size_t len, int flags)
 	int ret;
 	size_t off = 0;
 
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	if (t->encrypt)
 		return send_ssl(&t->ssl, msg, len);
 #endif
diff --git a/src/netops.h b/src/netops.h
index 9401ac2..8591a8e 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -9,16 +9,14 @@
 
 #include "posix.h"
 #include "transport.h"
-#ifdef GIT_GNUTLS
-# include <gnutls/gnutls.h>
-#endif
+#include "common.h"
 
 typedef struct gitno_buffer {
 	char *data;
 	size_t len;
 	size_t offset;
 	GIT_SOCKET fd;
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	struct gitno_ssl *ssl;
 #endif
 } gitno_buffer;
@@ -29,7 +27,7 @@ int gitno_recv(gitno_buffer *buf);
 void gitno_consume(gitno_buffer *buf, const char *ptr);
 void gitno_consume_n(gitno_buffer *buf, size_t cons);
 
-GIT_SOCKET gitno_connect(git_transport *t, const char *host, const char *port);
+int gitno_connect(git_transport *t, const char *host, const char *port);
 int gitno_send(git_transport *t, const char *msg, size_t len, int flags);
 int gitno_close(GIT_SOCKET s);
 int gitno_send_chunk_size(int s, size_t len);
diff --git a/src/transport.h b/src/transport.h
index 0c348cc..0257cce 100644
--- a/src/transport.h
+++ b/src/transport.h
@@ -57,7 +57,7 @@ struct git_transport {
 	int direction : 1, /* 0 fetch, 1 push */
 		connected : 1,
 		encrypt : 1;
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	struct gitno_ssl ssl;
 #endif
 	GIT_SOCKET socket;
diff --git a/src/transports/http.c b/src/transports/http.c
index 4f8e031..6746f68 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -578,7 +578,6 @@ static int http_download_pack(git_transport *transport, git_repository *repo, gi
 
 	gitno_buffer_setup(transport, &buf, buffer, sizeof(buffer));
 
-
 	do {
 		size_t parsed;
 
@@ -684,7 +683,7 @@ int git_transport_http(git_transport **out)
 
 int git_transport_https(git_transport **out)
 {
-#ifdef GIT_GNUTLS
+#ifdef GIT_SSL
 	transport_http *t;
 	if (git_transport_http((git_transport **)&t) < 0)
 		return -1;