diff --git a/CMakeLists.txt b/CMakeLists.txt index 34cc64753..b92585976 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 75e6e5867..30865659c 100644 --- a/src/common.h +++ b/src/common.h @@ -22,6 +22,9 @@ #ifdef GIT_GNUTLS # include +#elif defined(GIT_OPENSSL) +# include +# include #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 f2b504a00..67a361ea9 100644 --- a/src/netops.c +++ b/src/netops.c @@ -22,8 +22,11 @@ # include # include # include +#elif defined(GIT_OPENSSL) +# include #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 9401ac2a9..8591a8e94 100644 --- a/src/netops.h +++ b/src/netops.h @@ -9,16 +9,14 @@ #include "posix.h" #include "transport.h" -#ifdef GIT_GNUTLS -# include -#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 0c348cc2d..0257ccea5 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 4f8e03163..6746f68b4 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;