mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 18:11:43 +00:00
1722 lines
52 KiB
Diff
1722 lines
52 KiB
Diff
From ca3b2234dc7f1bd0d0f81488d3e29980b47a85b4 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:13:56 +0200
|
||
Subject: [PATCH 01/15] mbedtls: initial support
|
||
|
||
---
|
||
cmake/Modules/FindmbedTLS.cmake | 93 +++++++++++
|
||
src/CMakeLists.txt | 13 ++
|
||
src/features.h.in | 1 +
|
||
src/settings.c | 11 ++
|
||
src/streams/mbedtls.c | 344 ++++++++++++++++++++++++++++++++++++++++
|
||
src/streams/mbedtls.h | 18 +++
|
||
src/streams/tls.c | 3 +
|
||
7 files changed, 483 insertions(+)
|
||
create mode 100644 cmake/Modules/FindmbedTLS.cmake
|
||
create mode 100644 src/streams/mbedtls.c
|
||
create mode 100644 src/streams/mbedtls.h
|
||
|
||
diff --git a/cmake/Modules/FindmbedTLS.cmake b/cmake/Modules/FindmbedTLS.cmake
|
||
new file mode 100644
|
||
index 0000000000..93297555e8
|
||
--- /dev/null
|
||
+++ b/cmake/Modules/FindmbedTLS.cmake
|
||
@@ -0,0 +1,93 @@
|
||
+# - Try to find mbedTLS
|
||
+# Once done this will define
|
||
+#
|
||
+# Read-Only variables
|
||
+# MBEDTLS_FOUND - system has mbedTLS
|
||
+# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory
|
||
+# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory
|
||
+# MBEDTLS_LIBRARIES - Link these to use mbedTLS
|
||
+# MBEDTLS_LIBRARY - path to mbedTLS library
|
||
+# MBEDX509_LIBRARY - path to mbedTLS X.509 library
|
||
+# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library
|
||
+#
|
||
+# Hint
|
||
+# MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation.
|
||
+
|
||
+SET(_MBEDTLS_ROOT_HINTS
|
||
+ ${MBEDTLS_ROOT_DIR}
|
||
+ ENV MBEDTLS_ROOT_DIR
|
||
+)
|
||
+
|
||
+SET(_MBEDTLS_ROOT_HINTS_AND_PATHS
|
||
+ HINTS ${_MBEDTLS_ROOT_HINTS}
|
||
+ PATHS ${_MBEDTLS_ROOT_PATHS}
|
||
+)
|
||
+
|
||
+FIND_PATH(MBEDTLS_INCLUDE_DIR
|
||
+ NAMES mbedtls/version.h
|
||
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||
+ PATH_SUFFIXES include
|
||
+)
|
||
+
|
||
+IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES)
|
||
+ # Already in cache, be silent
|
||
+ SET(MBEDTLS_FIND_QUIETLY TRUE)
|
||
+ENDIF()
|
||
+
|
||
+FIND_LIBRARY(MBEDTLS_LIBRARY
|
||
+ NAMES mbedtls libmbedtls
|
||
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||
+ PATH_SUFFIXES library
|
||
+)
|
||
+FIND_LIBRARY(MBEDX509_LIBRARY
|
||
+ NAMES mbedx509 libmbedx509
|
||
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||
+ PATH_SUFFIXES library
|
||
+)
|
||
+FIND_LIBRARY(MBEDCRYPTO_LIBRARY
|
||
+ NAMES mbedcrypto libmbedcrypto
|
||
+ ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||
+ PATH_SUFFIXES library
|
||
+)
|
||
+
|
||
+IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
|
||
+ SET(MBEDTLS_FOUND TRUE)
|
||
+ENDIF()
|
||
+
|
||
+IF(MBEDTLS_FOUND)
|
||
+ # split mbedTLS into -L and -l linker options, so we can set them for pkg-config
|
||
+ GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH)
|
||
+ GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE)
|
||
+ GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE)
|
||
+ GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE)
|
||
+ STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
|
||
+ STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
|
||
+ STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
|
||
+ SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
|
||
+
|
||
+ IF(NOT MBEDTLS_FIND_QUIETLY)
|
||
+ MESSAGE(STATUS "Found mbedTLS:")
|
||
+ FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT)
|
||
+ STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT})
|
||
+ IF (MBEDTLSMATCH)
|
||
+ STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH})
|
||
+ MESSAGE(STATUS " version ${MBEDTLS_VERSION}")
|
||
+ ENDIF(MBEDTLSMATCH)
|
||
+ MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}")
|
||
+ MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}")
|
||
+ MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}")
|
||
+ ENDIF(NOT MBEDTLS_FIND_QUIETLY)
|
||
+ELSE(MBEDTLS_FOUND)
|
||
+ IF(MBEDTLS_FIND_REQUIRED)
|
||
+ MESSAGE(FATAL_ERROR "Could not find mbedTLS")
|
||
+ ENDIF(MBEDTLS_FIND_REQUIRED)
|
||
+ENDIF(MBEDTLS_FOUND)
|
||
+
|
||
+MARK_AS_ADVANCED(
|
||
+ MBEDTLS_INCLUDE_DIR
|
||
+ MBEDTLS_LIBRARY_DIR
|
||
+ MBEDTLS_LIBRARIES
|
||
+ MBEDTLS_LIBRARY
|
||
+ MBEDX509_LIBRARY
|
||
+ MBEDCRYPTO_LIBRARY
|
||
+)
|
||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||
index b03b96af93..cc6f5c961e 100644
|
||
--- a/src/CMakeLists.txt
|
||
+++ b/src/CMakeLists.txt
|
||
@@ -133,6 +133,7 @@ ELSE ()
|
||
ENDIF()
|
||
|
||
IF (USE_HTTPS)
|
||
+ FIND_PACKAGE(mbedTLS)
|
||
IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||
FIND_PACKAGE(Security)
|
||
FIND_PACKAGE(CoreFoundation)
|
||
@@ -149,6 +150,8 @@ IF (USE_HTTPS)
|
||
ENDIF()
|
||
ELSEIF (WINHTTP)
|
||
SET(HTTPS_BACKEND "WinHTTP")
|
||
+ ELSEIF(MBEDTLS_FOUND)
|
||
+ SET(HTTPS_BACKEND "mbedTLS")
|
||
ELSE()
|
||
SET(HTTPS_BACKEND "OpenSSL")
|
||
ENDIF()
|
||
@@ -185,6 +188,16 @@ IF (USE_HTTPS)
|
||
LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES})
|
||
LIST(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS})
|
||
LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
|
||
+ ELSEIF(HTTPS_BACKEND STREQUAL "mbedTLS")
|
||
+ IF (NOT MBEDTLS_FOUND)
|
||
+ MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
|
||
+ ENDIF()
|
||
+
|
||
+ SET(GIT_MBEDTLS 1)
|
||
+ LIST(APPEND LIBGIT2_INCLUDES ${MBEDTLS_INCLUDE_DIR})
|
||
+ LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES})
|
||
+ LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LDFLAGS})
|
||
+ LIST(APPEND LIBGIT2_PC_REQUIRES "mbedtls")
|
||
ELSEIF (HTTPS_BACKEND STREQUAL "WinHTTP")
|
||
# WinHTTP setup was handled in the WinHTTP-specific block above
|
||
ELSE()
|
||
diff --git a/src/features.h.in b/src/features.h.in
|
||
index e03b7a2517..f7f162c2a7 100644
|
||
--- a/src/features.h.in
|
||
+++ b/src/features.h.in
|
||
@@ -27,6 +27,7 @@
|
||
#cmakedefine GIT_HTTPS 1
|
||
#cmakedefine GIT_OPENSSL 1
|
||
#cmakedefine GIT_SECURE_TRANSPORT 1
|
||
+#cmakedefine GIT_MBEDTLS 1
|
||
|
||
#cmakedefine GIT_SHA1_COLLISIONDETECT 1
|
||
#cmakedefine GIT_SHA1_WIN32 1
|
||
diff --git a/src/settings.c b/src/settings.c
|
||
index 2a52ffbf63..13ae6d4892 100644
|
||
--- a/src/settings.c
|
||
+++ b/src/settings.c
|
||
@@ -11,6 +11,10 @@
|
||
# include <openssl/err.h>
|
||
#endif
|
||
|
||
+#ifdef GIT_MBEDTLS
|
||
+# include <mbedtls/error.h>
|
||
+#endif
|
||
+
|
||
#include <git2.h>
|
||
#include "sysdir.h"
|
||
#include "cache.h"
|
||
@@ -20,6 +24,7 @@
|
||
#include "refs.h"
|
||
#include "transports/smart.h"
|
||
#include "streams/openssl.h"
|
||
+#include "streams/mbedtls.h"
|
||
|
||
void git_libgit2_version(int *major, int *minor, int *rev)
|
||
{
|
||
@@ -175,6 +180,12 @@ int git_libgit2_opts(int key, ...)
|
||
const char *path = va_arg(ap, const char *);
|
||
error = git_openssl__set_cert_location(file, path);
|
||
}
|
||
+#elif defined(GIT_MBEDTLS)
|
||
+ {
|
||
+ const char *file = va_arg(ap, const char *);
|
||
+ const char *path = va_arg(ap, const char *);
|
||
+ error = git_mbedtls__set_cert_location(file, path);
|
||
+ }
|
||
#else
|
||
giterr_set(GITERR_SSL, "TLS backend doesn't support certificate locations");
|
||
error = -1;
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
new file mode 100644
|
||
index 0000000000..fbef31e81d
|
||
--- /dev/null
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -0,0 +1,344 @@
|
||
+/*
|
||
+ * Copyright (C) the libgit2 contributors. All rights reserved.
|
||
+ *
|
||
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
|
||
+ * a Linking Exception. For full terms see the included COPYING file.
|
||
+ */
|
||
+
|
||
+#include "streams/mbedtls.h"
|
||
+
|
||
+#ifdef GIT_MBEDTLS
|
||
+
|
||
+#include <ctype.h>
|
||
+
|
||
+#include "global.h"
|
||
+#include "stream.h"
|
||
+#include "streams/socket.h"
|
||
+#include "netops.h"
|
||
+#include "git2/transport.h"
|
||
+
|
||
+#ifdef GIT_CURL
|
||
+# include "streams/curl.h"
|
||
+#endif
|
||
+
|
||
+#include <mbedtls/ssl.h>
|
||
+#include <mbedtls/x509.h>
|
||
+#include <mbedtls/x509_crt.h>
|
||
+#include <mbedtls/error.h>
|
||
+
|
||
+mbedtls_ssl_config *git__ssl_conf;
|
||
+
|
||
+static int bio_read(void *b, unsigned char *buf, size_t len)
|
||
+{
|
||
+ git_stream *io = (git_stream *) b;
|
||
+ return (int) git_stream_read(io, buf, len);
|
||
+}
|
||
+
|
||
+static int bio_write(void *b, const unsigned char *buf, size_t len)
|
||
+{
|
||
+ git_stream *io = (git_stream *) b;
|
||
+ return (int) git_stream_write(io, (const char *)buf, len, 0);
|
||
+}
|
||
+
|
||
+static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
|
||
+{
|
||
+ char errbuf[512];
|
||
+ int ret = -1;
|
||
+
|
||
+ assert(error != MBEDTLS_ERR_SSL_WANT_READ);
|
||
+ assert(error != MBEDTLS_ERR_SSL_WANT_WRITE);
|
||
+
|
||
+ if (error != 0)
|
||
+ mbedtls_strerror( error, errbuf, 512 );
|
||
+
|
||
+ switch(error) {
|
||
+ case 0:
|
||
+ giterr_set(GITERR_SSL, "SSL error: unknown error");
|
||
+ break;
|
||
+
|
||
+ case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
|
||
+ giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
|
||
+ ret = GIT_ECERTIFICATE;
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf);
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static int ssl_teardown(mbedtls_ssl_context *ssl)
|
||
+{
|
||
+ int ret = 0;
|
||
+
|
||
+ ret = mbedtls_ssl_close_notify(ssl);
|
||
+ if (ret < 0)
|
||
+ ret = ssl_set_error(ssl, ret);
|
||
+
|
||
+ mbedtls_ssl_free(ssl);
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
|
||
+{
|
||
+ const mbedtls_x509_crt *cert;
|
||
+ int flags;
|
||
+ struct in6_addr addr6;
|
||
+ struct in_addr addr4;
|
||
+ void *addr;
|
||
+
|
||
+ if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 )
|
||
+ {
|
||
+ char vrfy_buf[512];
|
||
+ mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
|
||
+ giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
|
||
+ return GIT_ECERTIFICATE;
|
||
+ }
|
||
+
|
||
+ /* Try to parse the host as an IP address to see if it is */
|
||
+ if (p_inet_pton(AF_INET, host, &addr4)) {
|
||
+ addr = &addr4;
|
||
+ } else {
|
||
+ if(p_inet_pton(AF_INET6, host, &addr6)) {
|
||
+ addr = &addr6;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ cert = mbedtls_ssl_get_peer_cert(ssl);
|
||
+ if (!cert) {
|
||
+ giterr_set(GITERR_SSL, "the server did not provide a certificate");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ /* Check the alternative names */
|
||
+ //TODO: cert->subject_alt_names
|
||
+
|
||
+ /* If no alternative names are available, check the common name */
|
||
+ /*TODO
|
||
+ mbedtls_x509_name peer_name = cert->subject;
|
||
+ if (peer_name == NULL)
|
||
+ goto on_error;
|
||
+ */
|
||
+
|
||
+ return 0;
|
||
+
|
||
+on_error:
|
||
+ return ssl_set_error(ssl, 0);
|
||
+
|
||
+cert_fail_name:
|
||
+ giterr_set(GITERR_SSL, "hostname does not match certificate");
|
||
+ return GIT_ECERTIFICATE;
|
||
+}
|
||
+
|
||
+typedef struct {
|
||
+ git_stream parent;
|
||
+ git_stream *io;
|
||
+ bool connected;
|
||
+ char *host;
|
||
+ mbedtls_ssl_context *ssl;
|
||
+ git_cert_x509 cert_info;
|
||
+} mbedtls_stream;
|
||
+
|
||
+
|
||
+int mbedtls_connect(git_stream *stream)
|
||
+{
|
||
+ int ret;
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+
|
||
+ if ((ret = git_stream_connect(st->io)) < 0)
|
||
+ return ret;
|
||
+
|
||
+ st->connected = true;
|
||
+
|
||
+ mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
|
||
+
|
||
+ /* specify the host in case SNI is needed */
|
||
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||
+ mbedtls_ssl_set_hostname(st->ssl, st->host);
|
||
+#endif
|
||
+
|
||
+ if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
|
||
+ return ssl_set_error(st->ssl, ret);
|
||
+
|
||
+ return verify_server_cert(st->ssl, st->host);
|
||
+}
|
||
+
|
||
+int mbedtls_certificate(git_cert **out, git_stream *stream)
|
||
+{
|
||
+ unsigned char *encoded_cert;
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+
|
||
+ const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(st->ssl);
|
||
+ if (!cert) {
|
||
+ giterr_set(GITERR_SSL, "the server did not provide a certificate");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ /* Retrieve the length of the certificate first */
|
||
+ if (cert->raw.len == 0) {
|
||
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ encoded_cert = git__malloc(cert->raw.len);
|
||
+ GITERR_CHECK_ALLOC(encoded_cert);
|
||
+ memcpy(encoded_cert, cert->raw.p, cert->raw.len);
|
||
+
|
||
+ st->cert_info.parent.cert_type = GIT_CERT_X509;
|
||
+ st->cert_info.data = encoded_cert;
|
||
+ st->cert_info.len = cert->raw.len;
|
||
+
|
||
+ *out = &st->cert_info.parent;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int mbedtls_set_proxy(git_stream *stream, const git_proxy_options *proxy_options)
|
||
+{
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+
|
||
+ return git_stream_set_proxy(st->io, proxy_options);
|
||
+}
|
||
+
|
||
+ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags)
|
||
+{
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+ int ret;
|
||
+
|
||
+ GIT_UNUSED(flags);
|
||
+
|
||
+ if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) {
|
||
+ return ssl_set_error(st->ssl, ret);
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
|
||
+{
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+ int ret;
|
||
+
|
||
+ if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0)
|
||
+ ssl_set_error(st->ssl, ret);
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+int mbedtls_stream_close(git_stream *stream)
|
||
+{
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+ int ret = 0;
|
||
+
|
||
+ if (st->connected && (ret = ssl_teardown(st->ssl)) != 0)
|
||
+ return -1;
|
||
+
|
||
+ st->connected = false;
|
||
+
|
||
+ return git_stream_close(st->io);
|
||
+}
|
||
+
|
||
+void mbedtls_stream_free(git_stream *stream)
|
||
+{
|
||
+ mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
+
|
||
+ git__free(st->host);
|
||
+ git__free(st->cert_info.data);
|
||
+ git_stream_free(st->io);
|
||
+ git__free(st->ssl);
|
||
+ git__free(st);
|
||
+}
|
||
+
|
||
+int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||
+{
|
||
+ int error;
|
||
+ mbedtls_stream *st;
|
||
+
|
||
+ st = git__calloc(1, sizeof(mbedtls_stream));
|
||
+ GITERR_CHECK_ALLOC(st);
|
||
+
|
||
+#ifdef GIT_CURL
|
||
+ error = git_curl_stream_new(&st->io, host, port);
|
||
+#else
|
||
+ error = git_socket_stream_new(&st->io, host, port);
|
||
+#endif
|
||
+
|
||
+ if (error < 0)
|
||
+ goto out_err;
|
||
+
|
||
+ st->ssl = git__malloc(sizeof(mbedtls_ssl_context));
|
||
+ GITERR_CHECK_ALLOC(st->ssl);
|
||
+ mbedtls_ssl_init(st->ssl);
|
||
+ if (mbedtls_ssl_setup(st->ssl, git__ssl_conf)) {
|
||
+ giterr_set(GITERR_SSL, "failed to create ssl object");
|
||
+ error = -1;
|
||
+ goto out_err;
|
||
+ }
|
||
+
|
||
+ st->host = git__strdup(host);
|
||
+ GITERR_CHECK_ALLOC(st->host);
|
||
+
|
||
+ st->parent.version = GIT_STREAM_VERSION;
|
||
+ st->parent.encrypted = 1;
|
||
+ st->parent.proxy_support = git_stream_supports_proxy(st->io);
|
||
+ st->parent.connect = mbedtls_connect;
|
||
+ st->parent.certificate = mbedtls_certificate;
|
||
+ st->parent.set_proxy = mbedtls_set_proxy;
|
||
+ st->parent.read = mbedtls_stream_read;
|
||
+ st->parent.write = mbedtls_stream_write;
|
||
+ st->parent.close = mbedtls_stream_close;
|
||
+ st->parent.free = mbedtls_stream_free;
|
||
+
|
||
+ *out = (git_stream *) st;
|
||
+ return 0;
|
||
+
|
||
+out_err:
|
||
+ mbedtls_ssl_free(st->ssl);
|
||
+ git_stream_free(st->io);
|
||
+ git__free(st);
|
||
+
|
||
+ return error;
|
||
+}
|
||
+
|
||
+int git_mbedtls__set_cert_location(const char *file, const char *path)
|
||
+{
|
||
+ int ret = 0;
|
||
+ char errbuf[512];
|
||
+ if (!file) {
|
||
+ ret = mbedtls_x509_crt_parse_file(git__ssl_conf->ca_chain, file);
|
||
+ } else if (!path) {
|
||
+ ret = mbedtls_x509_crt_parse_path(git__ssl_conf->ca_chain, path);
|
||
+ }
|
||
+ if (ret != 0) {
|
||
+ mbedtls_strerror( ret, errbuf, 512 );
|
||
+ giterr_set(GITERR_NET, "SSL error: %d - %s", ret, errbuf);
|
||
+ return -1;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#else
|
||
+
|
||
+#include "stream.h"
|
||
+
|
||
+int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||
+{
|
||
+ GIT_UNUSED(out);
|
||
+ GIT_UNUSED(host);
|
||
+ GIT_UNUSED(port);
|
||
+
|
||
+ giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+int git_mbedtls__set_cert_location(const char *file, const char *path)
|
||
+{
|
||
+ GIT_UNUSED(file);
|
||
+ GIT_UNUSED(path);
|
||
+
|
||
+ giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+#endif
|
||
diff --git a/src/streams/mbedtls.h b/src/streams/mbedtls.h
|
||
new file mode 100644
|
||
index 0000000000..0572442014
|
||
--- /dev/null
|
||
+++ b/src/streams/mbedtls.h
|
||
@@ -0,0 +1,18 @@
|
||
+/*
|
||
+ * Copyright (C) the libgit2 contributors. All rights reserved.
|
||
+ *
|
||
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
|
||
+ * a Linking Exception. For full terms see the included COPYING file.
|
||
+ */
|
||
+#ifndef INCLUDE_steams_mbedtls_h__
|
||
+#define INCLUDE_steams_mbedtls_h__
|
||
+
|
||
+#include "common.h"
|
||
+
|
||
+#include "git2/sys/stream.h"
|
||
+
|
||
+extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
|
||
+
|
||
+extern int git_mbedtls__set_cert_location(const char *file, const char *path);
|
||
+
|
||
+#endif
|
||
diff --git a/src/streams/tls.c b/src/streams/tls.c
|
||
index d6ca7d40de..1bcb0d9841 100644
|
||
--- a/src/streams/tls.c
|
||
+++ b/src/streams/tls.c
|
||
@@ -9,6 +9,7 @@
|
||
|
||
#include "git2/errors.h"
|
||
|
||
+#include "streams/mbedtls.h"
|
||
#include "streams/openssl.h"
|
||
#include "streams/stransport.h"
|
||
|
||
@@ -31,6 +32,8 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port)
|
||
return git_stransport_stream_new(out, host, port);
|
||
#elif defined(GIT_OPENSSL)
|
||
return git_openssl_stream_new(out, host, port);
|
||
+#elif defined(GIT_MBEDTLS)
|
||
+ return git_mbedtls_stream_new(out, host, port);
|
||
#else
|
||
GIT_UNUSED(out);
|
||
GIT_UNUSED(host);
|
||
|
||
From 1a1875f3227c3edb6ae0d5da3a5ffe4699aae63b Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:13:58 +0200
|
||
Subject: [PATCH 02/15] mbedtls: proper certificate verification
|
||
|
||
---
|
||
src/streams/mbedtls.c | 76 +++++++++++++++++++++++++++++++++------------------
|
||
1 file changed, 50 insertions(+), 26 deletions(-)
|
||
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index fbef31e81d..ecf219412b 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -80,31 +80,33 @@ static int ssl_teardown(mbedtls_ssl_context *ssl)
|
||
return ret;
|
||
}
|
||
|
||
+static int check_host_name(const char *name, const char *host)
|
||
+{
|
||
+ if (!strcasecmp(name, host))
|
||
+ return 0;
|
||
+
|
||
+ if (gitno__match_host(name, host) < 0)
|
||
+ return -1;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
|
||
{
|
||
const mbedtls_x509_crt *cert;
|
||
- int flags;
|
||
- struct in6_addr addr6;
|
||
- struct in_addr addr4;
|
||
- void *addr;
|
||
+ const mbedtls_x509_sequence *alts;
|
||
+ int ret, matched = -1;
|
||
+ size_t sn_size = 512;
|
||
+ char subject_name[sn_size], alt_name[sn_size];
|
||
+
|
||
|
||
- if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 )
|
||
- {
|
||
+ if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
|
||
char vrfy_buf[512];
|
||
- mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
|
||
+ mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret );
|
||
giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
|
||
return GIT_ECERTIFICATE;
|
||
}
|
||
|
||
- /* Try to parse the host as an IP address to see if it is */
|
||
- if (p_inet_pton(AF_INET, host, &addr4)) {
|
||
- addr = &addr4;
|
||
- } else {
|
||
- if(p_inet_pton(AF_INET6, host, &addr6)) {
|
||
- addr = &addr6;
|
||
- }
|
||
- }
|
||
-
|
||
cert = mbedtls_ssl_get_peer_cert(ssl);
|
||
if (!cert) {
|
||
giterr_set(GITERR_SSL, "the server did not provide a certificate");
|
||
@@ -112,14 +114,39 @@ static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
|
||
}
|
||
|
||
/* Check the alternative names */
|
||
- //TODO: cert->subject_alt_names
|
||
+ alts = &cert->subject_alt_names;
|
||
+ while (alts != NULL && matched != 1) {
|
||
+ // Buffer is too small
|
||
+ if( alts->buf.len >= sn_size )
|
||
+ goto on_error;
|
||
+
|
||
+ memcpy(alt_name, alts->buf.p, alts->buf.len);
|
||
+ alt_name[alts->buf.len] = '\0';
|
||
+
|
||
+ if (!memchr(alt_name, '\0', alts->buf.len)) {
|
||
+ if (check_host_name(alt_name, host) < 0)
|
||
+ matched = 0;
|
||
+ else
|
||
+ matched = 1;
|
||
+ }
|
||
+
|
||
+ alts = alts->next;
|
||
+ }
|
||
+ if (matched == 0)
|
||
+ goto cert_fail_name;
|
||
+
|
||
+ if (matched == 1)
|
||
+ return 0;
|
||
|
||
/* If no alternative names are available, check the common name */
|
||
- /*TODO
|
||
- mbedtls_x509_name peer_name = cert->subject;
|
||
- if (peer_name == NULL)
|
||
+ ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
|
||
+ if (ret == 0)
|
||
goto on_error;
|
||
- */
|
||
+ if (memchr(subject_name, '\0', ret))
|
||
+ goto cert_fail_name;
|
||
+
|
||
+ if (check_host_name(subject_name, host) < 0)
|
||
+ goto cert_fail_name;
|
||
|
||
return 0;
|
||
|
||
@@ -151,12 +178,9 @@ int mbedtls_connect(git_stream *stream)
|
||
|
||
st->connected = true;
|
||
|
||
- mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
|
||
-
|
||
- /* specify the host in case SNI is needed */
|
||
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||
mbedtls_ssl_set_hostname(st->ssl, st->host);
|
||
-#endif
|
||
+
|
||
+ mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
|
||
|
||
if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
|
||
return ssl_set_error(st->ssl, ret);
|
||
|
||
From 6c6be3ce6ff23429089c0211870971b17246a992 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:13:59 +0200
|
||
Subject: [PATCH 03/15] mbedtls: use libmbedcrypto for hashing
|
||
|
||
---
|
||
CMakeLists.txt | 2 +-
|
||
src/CMakeLists.txt | 5 +++++
|
||
src/features.h.in | 1 +
|
||
src/hash.h | 2 ++
|
||
src/hash/hash_mbedtls.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||
src/hash/hash_mbedtls.h | 20 ++++++++++++++++++++
|
||
6 files changed, 67 insertions(+), 1 deletion(-)
|
||
create mode 100644 src/hash/hash_mbedtls.c
|
||
create mode 100644 src/hash/hash_mbedtls.h
|
||
|
||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||
index 2ca5354a7f..9176eee04a 100644
|
||
--- a/CMakeLists.txt
|
||
+++ b/CMakeLists.txt
|
||
@@ -48,7 +48,7 @@ OPTION( PROFILE "Generate profiling information" OFF )
|
||
OPTION( ENABLE_TRACE "Enables tracing support" OFF )
|
||
OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF )
|
||
|
||
-SET(SHA1_BACKEND "CollisionDetection" CACHE STRING "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, CollisionDetection. ")
|
||
+SET(SHA1_BACKEND "CollisionDetection" CACHE STRING "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, mbedTLS, CollisionDetection. ")
|
||
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
|
||
OPTION( USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON )
|
||
OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF )
|
||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||
index cc6f5c961e..027e76a324 100644
|
||
--- a/src/CMakeLists.txt
|
||
+++ b/src/CMakeLists.txt
|
||
@@ -243,6 +243,11 @@ ELSEIF(SHA1_BACKEND STREQUAL "Win32")
|
||
ELSEIF(SHA1_BACKEND STREQUAL "CommonCrypto")
|
||
ADD_FEATURE_INFO(SHA ON "using CommonCrypto")
|
||
SET(GIT_SHA1_COMMON_CRYPTO 1)
|
||
+ELSEIF (SHA1_BACKEND STREQUAL "mbedTLS")
|
||
+ ADD_FEATURE_INFO(SHA ON "using mbedTLS")
|
||
+ SET(GIT_SHA1_MBEDTLS 1)
|
||
+ FILE(GLOB SRC_SHA1 src/hash/hash_mbedtls.c)
|
||
+ LIST(APPEND LIBGIT2_PC_REQUIRES "mbedtls")
|
||
ELSE()
|
||
MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend ${SHA1_BACKEND}")
|
||
ENDIF()
|
||
diff --git a/src/features.h.in b/src/features.h.in
|
||
index f7f162c2a7..f414c58433 100644
|
||
--- a/src/features.h.in
|
||
+++ b/src/features.h.in
|
||
@@ -33,5 +33,6 @@
|
||
#cmakedefine GIT_SHA1_WIN32 1
|
||
#cmakedefine GIT_SHA1_COMMON_CRYPTO 1
|
||
#cmakedefine GIT_SHA1_OPENSSL 1
|
||
+#cmakedefine GIT_SHA1_MBEDTLS 1
|
||
|
||
#endif
|
||
diff --git a/src/hash.h b/src/hash.h
|
||
index 31eaf88897..93765adf33 100644
|
||
--- a/src/hash.h
|
||
+++ b/src/hash.h
|
||
@@ -26,6 +26,8 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx);
|
||
# include "hash/hash_openssl.h"
|
||
#elif defined(GIT_SHA1_WIN32)
|
||
# include "hash/hash_win32.h"
|
||
+#elif defined(GIT_SHA1_MBEDTLS)
|
||
+# include "hash/hash_mbedtls.h"
|
||
#else
|
||
# include "hash/hash_generic.h"
|
||
#endif
|
||
diff --git a/src/hash/hash_mbedtls.c b/src/hash/hash_mbedtls.c
|
||
new file mode 100644
|
||
index 0000000000..a19d763082
|
||
--- /dev/null
|
||
+++ b/src/hash/hash_mbedtls.c
|
||
@@ -0,0 +1,38 @@
|
||
+/*
|
||
+ * Copyright (C) the libgit2 contributors. All rights reserved.
|
||
+ *
|
||
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
|
||
+ * a Linking Exception. For full terms see the included COPYING file.
|
||
+ */
|
||
+
|
||
+#include "common.h"
|
||
+#include "hash.h"
|
||
+#include "hash/hash_mbedtls.h"
|
||
+
|
||
+void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||
+{
|
||
+ assert(ctx);
|
||
+ mbedtls_sha1_free(&ctx->c);
|
||
+}
|
||
+
|
||
+int git_hash_init(git_hash_ctx *ctx)
|
||
+{
|
||
+ assert(ctx);
|
||
+ mbedtls_sha1_init(&ctx->c);
|
||
+ mbedtls_sha1_starts(&ctx->c);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||
+{
|
||
+ assert(ctx);
|
||
+ mbedtls_sha1_update(&ctx->c, data, len);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+int git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||
+{
|
||
+ assert(ctx);
|
||
+ mbedtls_sha1_finish(&ctx->c, out->id);
|
||
+ return 0;
|
||
+}
|
||
diff --git a/src/hash/hash_mbedtls.h b/src/hash/hash_mbedtls.h
|
||
new file mode 100644
|
||
index 0000000000..24196c5bff
|
||
--- /dev/null
|
||
+++ b/src/hash/hash_mbedtls.h
|
||
@@ -0,0 +1,20 @@
|
||
+/*
|
||
+ * Copyright (C) the libgit2 contributors. All rights reserved.
|
||
+ *
|
||
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
|
||
+ * a Linking Exception. For full terms see the included COPYING file.
|
||
+ */
|
||
+
|
||
+#ifndef INCLUDE_hash_mbedtld_h__
|
||
+#define INCLUDE_hash_mbedtld_h__
|
||
+
|
||
+#include <mbedtls/sha1.h>
|
||
+
|
||
+struct git_hash_ctx {
|
||
+ mbedtls_sha1_context c;
|
||
+};
|
||
+
|
||
+#define git_hash_global_init() 0
|
||
+#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||
+
|
||
+#endif /* INCLUDE_hash_mbedtld_h__ */
|
||
|
||
From 60e1ad927b7f64ad33681fc162b512e2cf12b5b8 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:01 +0200
|
||
Subject: [PATCH 04/15] mbedtls: add global initialization
|
||
|
||
---
|
||
src/global.c | 4 +-
|
||
src/streams/mbedtls.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++--
|
||
src/streams/mbedtls.h | 2 +
|
||
3 files changed, 102 insertions(+), 4 deletions(-)
|
||
|
||
diff --git a/src/global.c b/src/global.c
|
||
index 2f9b45bcda..02aedf57d1 100644
|
||
--- a/src/global.c
|
||
+++ b/src/global.c
|
||
@@ -12,6 +12,7 @@
|
||
#include "filter.h"
|
||
#include "merge_driver.h"
|
||
#include "streams/curl.h"
|
||
+#include "streams/mbedtls.h"
|
||
#include "streams/openssl.h"
|
||
#include "thread-utils.h"
|
||
#include "git2/global.h"
|
||
@@ -65,7 +66,8 @@ static int init_common(void)
|
||
(ret = git_merge_driver_global_init()) == 0 &&
|
||
(ret = git_transport_ssh_global_init()) == 0 &&
|
||
(ret = git_openssl_stream_global_init()) == 0 &&
|
||
- (ret = git_curl_stream_global_init()) == 0)
|
||
+ (ret = git_curl_stream_global_init()) == 0 &&
|
||
+ (ret = git_mbedtls_stream_global_init()) == 0)
|
||
ret = git_mwindow_global_init();
|
||
|
||
GIT_MEMORY_BARRIER;
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index ecf219412b..ea0989caaf 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -21,10 +21,99 @@
|
||
# include "streams/curl.h"
|
||
#endif
|
||
|
||
+#include <mbedtls/config.h>
|
||
#include <mbedtls/ssl.h>
|
||
-#include <mbedtls/x509.h>
|
||
-#include <mbedtls/x509_crt.h>
|
||
-#include <mbedtls/error.h>
|
||
+#include <mbedtls/entropy.h>
|
||
+#include <mbedtls/ctr_drbg.h>
|
||
+
|
||
+#define CRT_LOC "/etc/ssl/certs"
|
||
+
|
||
+mbedtls_ssl_config *git__ssl_conf;
|
||
+mbedtls_entropy_context *mbedtls_entropy;
|
||
+
|
||
+/**
|
||
+ * This function aims to clean-up the SSL context which
|
||
+ * we allocated.
|
||
+ */
|
||
+static void shutdown_ssl(void)
|
||
+{
|
||
+ if (git__ssl_conf) {
|
||
+ mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
|
||
+ git__free(git__ssl_conf->ca_chain);
|
||
+ mbedtls_ctr_drbg_free(git__ssl_conf->p_rng);
|
||
+ git__free(git__ssl_conf->p_rng);
|
||
+ mbedtls_ssl_config_free(git__ssl_conf);
|
||
+ git__free(git__ssl_conf);
|
||
+ git__ssl_conf = NULL;
|
||
+ }
|
||
+ if (mbedtls_entropy) {
|
||
+ mbedtls_entropy_free(mbedtls_entropy);
|
||
+ git__free(mbedtls_entropy);
|
||
+ mbedtls_entropy = NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+int git_mbedtls_stream_global_init(void)
|
||
+{
|
||
+ int ret;
|
||
+ mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||
+ mbedtls_x509_crt *cacert = NULL;
|
||
+
|
||
+ git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config));
|
||
+ mbedtls_ssl_config_init(git__ssl_conf);
|
||
+ if (mbedtls_ssl_config_defaults(git__ssl_conf,
|
||
+ MBEDTLS_SSL_IS_CLIENT,
|
||
+ MBEDTLS_SSL_TRANSPORT_STREAM,
|
||
+ MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
|
||
+ giterr_set(GITERR_SSL, "failed to initialize mbedTLS");
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ /* configure TLSv1 */
|
||
+ mbedtls_ssl_conf_min_version(git__ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
|
||
+ mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||
+
|
||
+ /* Seeding the random number generator */
|
||
+ mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context));
|
||
+ mbedtls_entropy_init(mbedtls_entropy);
|
||
+
|
||
+ ctr_drbg = git__malloc(sizeof(mbedtls_ctr_drbg_context));
|
||
+ mbedtls_ctr_drbg_init(ctr_drbg);
|
||
+ if (mbedtls_ctr_drbg_seed(ctr_drbg,
|
||
+ mbedtls_entropy_func,
|
||
+ mbedtls_entropy, NULL, 0) != 0) {
|
||
+ giterr_set(GITERR_SSL, "failed to initialize mbedTLS entropy pool");
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
|
||
+
|
||
+ // set root certificates
|
||
+ cacert = git__malloc(sizeof(mbedtls_x509_crt));
|
||
+ mbedtls_x509_crt_init(cacert);
|
||
+ ret = mbedtls_x509_crt_parse_path(cacert, CRT_LOC);
|
||
+ if (ret) {
|
||
+ giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret);
|
||
+ goto cleanup;
|
||
+ }
|
||
+
|
||
+ mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
|
||
+
|
||
+ git__on_shutdown(shutdown_ssl);
|
||
+
|
||
+ return 0;
|
||
+
|
||
+cleanup:
|
||
+ mbedtls_x509_crt_free(cacert);
|
||
+ git__free(cacert);
|
||
+ mbedtls_ctr_drbg_free(ctr_drbg);
|
||
+ git__free(ctr_drbg);
|
||
+ mbedtls_ssl_config_free(git__ssl_conf);
|
||
+ git__free(git__ssl_conf);
|
||
+ git__ssl_conf = NULL;
|
||
+
|
||
+ return -1;
|
||
+}
|
||
|
||
mbedtls_ssl_config *git__ssl_conf;
|
||
|
||
@@ -346,6 +435,11 @@ int git_mbedtls__set_cert_location(const char *file, const char *path)
|
||
|
||
#include "stream.h"
|
||
|
||
+int git_mbedtls_stream_global_init(void)
|
||
+{
|
||
+ return 0;
|
||
+}
|
||
+
|
||
int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||
{
|
||
GIT_UNUSED(out);
|
||
diff --git a/src/streams/mbedtls.h b/src/streams/mbedtls.h
|
||
index 0572442014..8dab2b6c99 100644
|
||
--- a/src/streams/mbedtls.h
|
||
+++ b/src/streams/mbedtls.h
|
||
@@ -11,6 +11,8 @@
|
||
|
||
#include "git2/sys/stream.h"
|
||
|
||
+extern int git_mbedtls_stream_global_init(void);
|
||
+
|
||
extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
|
||
|
||
extern int git_mbedtls__set_cert_location(const char *file, const char *path);
|
||
|
||
From 2419cccd16ae6585e2b58360dc6a53304a3baee8 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:02 +0200
|
||
Subject: [PATCH 05/15] mbedtls: default cipher list support
|
||
|
||
---
|
||
src/settings.c | 2 +-
|
||
src/streams/mbedtls.c | 29 +++++++++++++++++++++++++++++
|
||
2 files changed, 30 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/src/settings.c b/src/settings.c
|
||
index 13ae6d4892..1195075ee9 100644
|
||
--- a/src/settings.c
|
||
+++ b/src/settings.c
|
||
@@ -210,7 +210,7 @@ int git_libgit2_opts(int key, ...)
|
||
break;
|
||
|
||
case GIT_OPT_SET_SSL_CIPHERS:
|
||
-#ifdef GIT_OPENSSL
|
||
+#if (GIT_OPENSSL || GIT_MBEDTLS)
|
||
{
|
||
git__free(git__ssl_ciphers);
|
||
git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index ea0989caaf..42ac8aa174 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -16,6 +16,7 @@
|
||
#include "streams/socket.h"
|
||
#include "netops.h"
|
||
#include "git2/transport.h"
|
||
+#include "util.h"
|
||
|
||
#ifdef GIT_CURL
|
||
# include "streams/curl.h"
|
||
@@ -31,6 +32,9 @@
|
||
mbedtls_ssl_config *git__ssl_conf;
|
||
mbedtls_entropy_context *mbedtls_entropy;
|
||
|
||
+#define GIT_SSL_DEFAULT_CIPHERS "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-DSS-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-DSS-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-128-CBC-SHA256:TLS-DHE-DSS-WITH-AES-256-CBC-SHA256:TLS-DHE-DSS-WITH-AES-128-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-128-GCM-SHA256:TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-128-CBC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-128-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA"
|
||
+#define GIT_SSL_DEFAULT_CIPHERS_COUNT 30
|
||
+
|
||
/**
|
||
* This function aims to clean-up the SSL context which
|
||
* we allocated.
|
||
@@ -57,6 +61,13 @@ int git_mbedtls_stream_global_init(void)
|
||
{
|
||
int ret;
|
||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||
+
|
||
+ int *ciphers_list = NULL;
|
||
+ int ciphers_known = 0;
|
||
+ char *cipher_name = NULL;
|
||
+ char *cipher_string = NULL;
|
||
+ char *cipher_string_tmp = NULL;
|
||
+
|
||
mbedtls_x509_crt *cacert = NULL;
|
||
|
||
git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config));
|
||
@@ -73,6 +84,24 @@ int git_mbedtls_stream_global_init(void)
|
||
mbedtls_ssl_conf_min_version(git__ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
|
||
mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||
|
||
+ /* set the list of allowed ciphersuites */
|
||
+ ciphers_list = calloc(GIT_SSL_DEFAULT_CIPHERS_COUNT, sizeof(int));
|
||
+ ciphers_known = 0;
|
||
+ cipher_string = cipher_string_tmp = git__strdup(GIT_SSL_DEFAULT_CIPHERS);
|
||
+ while ((cipher_name = git__strtok(&cipher_string_tmp, ":")) != NULL) {
|
||
+ int cipherid = mbedtls_ssl_get_ciphersuite_id(cipher_name);
|
||
+ if (cipherid == 0) continue;
|
||
+
|
||
+ ciphers_list[ciphers_known++] = cipherid;
|
||
+ }
|
||
+ git__free(cipher_string);
|
||
+
|
||
+ if (!ciphers_known) {
|
||
+ giterr_set(GITERR_SSL, "no cipher could be enabled");
|
||
+ goto cleanup;
|
||
+ }
|
||
+ mbedtls_ssl_conf_ciphersuites(git__ssl_conf, ciphers_list);
|
||
+
|
||
/* Seeding the random number generator */
|
||
mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context));
|
||
mbedtls_entropy_init(mbedtls_entropy);
|
||
|
||
From ec79b0fdd6236647349a67010f1a8fdcc5edfae7 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:04 +0200
|
||
Subject: [PATCH 06/15] mbedtls: fix libgit2 hanging due to incomplete writes
|
||
|
||
---
|
||
src/streams/mbedtls.c | 14 +++++++++-----
|
||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index 42ac8aa174..fa7d31e71a 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -345,16 +345,20 @@ static int mbedtls_set_proxy(git_stream *stream, const git_proxy_options *proxy_
|
||
|
||
ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags)
|
||
{
|
||
+ size_t read = 0;
|
||
mbedtls_stream *st = (mbedtls_stream *) stream;
|
||
- int ret;
|
||
|
||
GIT_UNUSED(flags);
|
||
|
||
- if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) {
|
||
- return ssl_set_error(st->ssl, ret);
|
||
- }
|
||
+ do {
|
||
+ int error = mbedtls_ssl_write(st->ssl, (const unsigned char *)data + read, len - read);
|
||
+ if (error <= 0) {
|
||
+ return ssl_set_error(st->ssl, error);
|
||
+ }
|
||
+ read += error;
|
||
+ } while (read < len);
|
||
|
||
- return ret;
|
||
+ return read;
|
||
}
|
||
|
||
ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
|
||
|
||
From 262dfcf0bf7416ddac5012737dfa1686e013824f Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:05 +0200
|
||
Subject: [PATCH 07/15] mbedtls: enable Travis CI tests
|
||
|
||
---
|
||
.travis.yml | 10 ++++++++++
|
||
script/install-deps-linux.sh | 13 +++++++++++++
|
||
2 files changed, 23 insertions(+)
|
||
create mode 100755 script/install-deps-linux.sh
|
||
|
||
diff --git a/.travis.yml b/.travis.yml
|
||
index a4c8e91dfb..b5f1c6ff68 100644
|
||
--- a/.travis.yml
|
||
+++ b/.travis.yml
|
||
@@ -55,6 +55,16 @@ matrix:
|
||
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
|
||
os: linux
|
||
dist: trusty
|
||
+ - compiler: gcc
|
||
+ env:
|
||
+ MBEDTLS=1
|
||
+ OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DUSE_HTTPS=mbedTLS -DMBEDTLS_ROOT_DIR=../deps/mbedtls"
|
||
+ os: linux
|
||
+ - compiler: gcc
|
||
+ env:
|
||
+ MBEDTLS=1
|
||
+ OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DUSE_HTTPS=mbedTLS -DMBEDTLS_ROOT_DIR=../deps/mbedtls"
|
||
+ os: linux
|
||
allow_failures:
|
||
- env: COVERITY=1
|
||
|
||
diff --git a/script/install-deps-linux.sh b/script/install-deps-linux.sh
|
||
new file mode 100755
|
||
index 0000000000..c084ca2e7c
|
||
--- /dev/null
|
||
+++ b/script/install-deps-linux.sh
|
||
@@ -0,0 +1,13 @@
|
||
+#!/bin/sh
|
||
+
|
||
+set -x
|
||
+
|
||
+if [ "$MBEDTLS" ]; then
|
||
+ git clone https://github.com/ARMmbed/mbedtls.git ./deps/mbedtls
|
||
+ cd ./deps/mbedtls
|
||
+ git checkout mbedtls-2.6.1
|
||
+ cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF .
|
||
+ cmake --build .
|
||
+
|
||
+ echo "mbedTLS built in `pwd`"
|
||
+fi
|
||
|
||
From 4165bb7f4b767801c2142ec521e275f6560197a5 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:06 +0200
|
||
Subject: [PATCH 08/15] mbedtls: use our own certificate validation
|
||
|
||
Otherwise REQUIRED means that `git_stream_certificate` will always error.
|
||
We're doing the mbedtls check in verify_server_cert though.
|
||
---
|
||
src/streams/mbedtls.c | 6 +++++-
|
||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index fa7d31e71a..b2f02ccd3f 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -82,7 +82,11 @@ int git_mbedtls_stream_global_init(void)
|
||
|
||
/* configure TLSv1 */
|
||
mbedtls_ssl_conf_min_version(git__ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
|
||
- mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||
+
|
||
+ /* verify_server_cert is responsible for making the check.
|
||
+ * OPTIONAL because REQUIRED drops the certificate as soon as the check
|
||
+ * is made, so we can never see the certificate and override it. */
|
||
+ mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||
|
||
/* set the list of allowed ciphersuites */
|
||
ciphers_list = calloc(GIT_SSL_DEFAULT_CIPHERS_COUNT, sizeof(int));
|
||
|
||
From 1edde0bcea160f5629d733b1aae26a1fa8215177 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:08 +0200
|
||
Subject: [PATCH 09/15] mbedtls: use mbedTLS certificate verification
|
||
|
||
Taken from https://github.com/JuliaLang/julia/blob/8d47a314537779c8fb86642c54925613628a91b0/deps/patches/libgit2-mbedtls-verify.patch, with some modifications.
|
||
---
|
||
src/streams/mbedtls.c | 75 +++++----------------------------------------------
|
||
1 file changed, 6 insertions(+), 69 deletions(-)
|
||
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index b2f02ccd3f..ea96ae3de2 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -202,82 +202,19 @@ static int ssl_teardown(mbedtls_ssl_context *ssl)
|
||
return ret;
|
||
}
|
||
|
||
-static int check_host_name(const char *name, const char *host)
|
||
+static int verify_server_cert(mbedtls_ssl_context *ssl)
|
||
{
|
||
- if (!strcasecmp(name, host))
|
||
- return 0;
|
||
-
|
||
- if (gitno__match_host(name, host) < 0)
|
||
- return -1;
|
||
-
|
||
- return 0;
|
||
-}
|
||
-
|
||
-static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
|
||
-{
|
||
- const mbedtls_x509_crt *cert;
|
||
- const mbedtls_x509_sequence *alts;
|
||
- int ret, matched = -1;
|
||
- size_t sn_size = 512;
|
||
- char subject_name[sn_size], alt_name[sn_size];
|
||
-
|
||
+ int ret = -1;
|
||
|
||
if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
|
||
char vrfy_buf[512];
|
||
- mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret );
|
||
- giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
|
||
+ int len = mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "", ret);
|
||
+ if (len >= 1) vrfy_buf[len - 1] = '\0'; /* Remove trailing \n */
|
||
+ giterr_set(GITERR_SSL, "the SSL certificate is invalid: %x - %s", ret, vrfy_buf);
|
||
return GIT_ECERTIFICATE;
|
||
}
|
||
|
||
- cert = mbedtls_ssl_get_peer_cert(ssl);
|
||
- if (!cert) {
|
||
- giterr_set(GITERR_SSL, "the server did not provide a certificate");
|
||
- return -1;
|
||
- }
|
||
-
|
||
- /* Check the alternative names */
|
||
- alts = &cert->subject_alt_names;
|
||
- while (alts != NULL && matched != 1) {
|
||
- // Buffer is too small
|
||
- if( alts->buf.len >= sn_size )
|
||
- goto on_error;
|
||
-
|
||
- memcpy(alt_name, alts->buf.p, alts->buf.len);
|
||
- alt_name[alts->buf.len] = '\0';
|
||
-
|
||
- if (!memchr(alt_name, '\0', alts->buf.len)) {
|
||
- if (check_host_name(alt_name, host) < 0)
|
||
- matched = 0;
|
||
- else
|
||
- matched = 1;
|
||
- }
|
||
-
|
||
- alts = alts->next;
|
||
- }
|
||
- if (matched == 0)
|
||
- goto cert_fail_name;
|
||
-
|
||
- if (matched == 1)
|
||
- return 0;
|
||
-
|
||
- /* If no alternative names are available, check the common name */
|
||
- ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
|
||
- if (ret == 0)
|
||
- goto on_error;
|
||
- if (memchr(subject_name, '\0', ret))
|
||
- goto cert_fail_name;
|
||
-
|
||
- if (check_host_name(subject_name, host) < 0)
|
||
- goto cert_fail_name;
|
||
-
|
||
return 0;
|
||
-
|
||
-on_error:
|
||
- return ssl_set_error(ssl, 0);
|
||
-
|
||
-cert_fail_name:
|
||
- giterr_set(GITERR_SSL, "hostname does not match certificate");
|
||
- return GIT_ECERTIFICATE;
|
||
}
|
||
|
||
typedef struct {
|
||
@@ -307,7 +244,7 @@ int mbedtls_connect(git_stream *stream)
|
||
if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
|
||
return ssl_set_error(st->ssl, ret);
|
||
|
||
- return verify_server_cert(st->ssl, st->host);
|
||
+ return verify_server_cert(st->ssl);
|
||
}
|
||
|
||
int mbedtls_certificate(git_cert **out, git_stream *stream)
|
||
|
||
From 382ed1e873da51cb411bd8842cc160fe4d67a666 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:09 +0200
|
||
Subject: [PATCH 10/15] mbedtls: load default CA certificates
|
||
|
||
---
|
||
src/CMakeLists.txt | 37 +++++++++++++++++++++++++++++++
|
||
src/settings.c | 5 ++++-
|
||
src/streams/mbedtls.c | 60 ++++++++++++++++++++++++++++++++-------------------
|
||
src/streams/mbedtls.h | 2 +-
|
||
4 files changed, 80 insertions(+), 24 deletions(-)
|
||
|
||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||
index 027e76a324..fa86d9fb44 100644
|
||
--- a/src/CMakeLists.txt
|
||
+++ b/src/CMakeLists.txt
|
||
@@ -193,6 +193,43 @@ IF (USE_HTTPS)
|
||
MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
|
||
ENDIF()
|
||
|
||
+ IF(NOT CERT_LOCATION)
|
||
+ MESSAGE("Auto-detecting default certificates location")
|
||
+ IF(CMAKE_SYSTEM_NAME MATCHES Darwin)
|
||
+ # Check for an Homebrew installation
|
||
+ SET(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl")
|
||
+ ELSE()
|
||
+ SET(OPENSSL_CMD "openssl")
|
||
+ ENDIF()
|
||
+ EXECUTE_PROCESS(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||
+ IF(OPENSSL_DIR)
|
||
+ STRING(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR})
|
||
+
|
||
+ SET(OPENSSL_CA_LOCATIONS
|
||
+ "ca-bundle.pem" # OpenSUSE Leap 42.1
|
||
+ "cert.pem" # Ubuntu 14.04, FreeBSD
|
||
+ "certs/ca-certificates.crt" # Ubuntu 16.04
|
||
+ "certs/ca.pem" # Debian 7
|
||
+ )
|
||
+ FOREACH(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS)
|
||
+ SET(LOC "${OPENSSL_DIR}${SUFFIX}")
|
||
+ IF(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}")
|
||
+ SET(CERT_LOCATION ${LOC})
|
||
+ ENDIF()
|
||
+ ENDFOREACH()
|
||
+ ELSE()
|
||
+ MESSAGE("Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION")
|
||
+ ENDIF()
|
||
+ ENDIF()
|
||
+
|
||
+ IF(CERT_LOCATION)
|
||
+ IF(NOT EXISTS ${CERT_LOCATION})
|
||
+ MESSAGE(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist")
|
||
+ ENDIF()
|
||
+ ADD_FEATURE_INFO(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}")
|
||
+ ADD_DEFINITIONS(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}")
|
||
+ ENDIF()
|
||
+
|
||
SET(GIT_MBEDTLS 1)
|
||
LIST(APPEND LIBGIT2_INCLUDES ${MBEDTLS_INCLUDE_DIR})
|
||
LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES})
|
||
diff --git a/src/settings.c b/src/settings.c
|
||
index 1195075ee9..f6bc5b270a 100644
|
||
--- a/src/settings.c
|
||
+++ b/src/settings.c
|
||
@@ -184,7 +184,10 @@ int git_libgit2_opts(int key, ...)
|
||
{
|
||
const char *file = va_arg(ap, const char *);
|
||
const char *path = va_arg(ap, const char *);
|
||
- error = git_mbedtls__set_cert_location(file, path);
|
||
+ if (file)
|
||
+ error = git_mbedtls__set_cert_location(file, 0);
|
||
+ if (error && path)
|
||
+ error = git_mbedtls__set_cert_location(path, 1);
|
||
}
|
||
#else
|
||
giterr_set(GITERR_SSL, "TLS backend doesn't support certificate locations");
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index ea96ae3de2..d134e865f6 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -22,13 +22,16 @@
|
||
# include "streams/curl.h"
|
||
#endif
|
||
|
||
+#ifndef GIT_DEFAULT_CERT_LOCATION
|
||
+#define GIT_DEFAULT_CERT_LOCATION NULL
|
||
+#endif
|
||
+
|
||
#include <mbedtls/config.h>
|
||
#include <mbedtls/ssl.h>
|
||
+#include <mbedtls/error.h>
|
||
#include <mbedtls/entropy.h>
|
||
#include <mbedtls/ctr_drbg.h>
|
||
|
||
-#define CRT_LOC "/etc/ssl/certs"
|
||
-
|
||
mbedtls_ssl_config *git__ssl_conf;
|
||
mbedtls_entropy_context *mbedtls_entropy;
|
||
|
||
@@ -57,9 +60,13 @@ static void shutdown_ssl(void)
|
||
}
|
||
}
|
||
|
||
+int git_mbedtls__set_cert_location(const char *path, int is_dir);
|
||
+
|
||
int git_mbedtls_stream_global_init(void)
|
||
{
|
||
- int ret;
|
||
+ int loaded = 0;
|
||
+ char *crtpath = GIT_DEFAULT_CERT_LOCATION;
|
||
+ struct stat statbuf;
|
||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||
|
||
int *ciphers_list = NULL;
|
||
@@ -121,16 +128,11 @@ int git_mbedtls_stream_global_init(void)
|
||
|
||
mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
|
||
|
||
- // set root certificates
|
||
- cacert = git__malloc(sizeof(mbedtls_x509_crt));
|
||
- mbedtls_x509_crt_init(cacert);
|
||
- ret = mbedtls_x509_crt_parse_path(cacert, CRT_LOC);
|
||
- if (ret) {
|
||
- giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret);
|
||
- goto cleanup;
|
||
- }
|
||
-
|
||
- mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
|
||
+ /* load default certificates */
|
||
+ if (crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
|
||
+ loaded = (git_mbedtls__set_cert_location(crtpath, 0) == 0);
|
||
+ if (!loaded && crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
|
||
+ loaded = (git_mbedtls__set_cert_location(crtpath, 1) == 0);
|
||
|
||
git__on_shutdown(shutdown_ssl);
|
||
|
||
@@ -388,20 +390,34 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||
return error;
|
||
}
|
||
|
||
-int git_mbedtls__set_cert_location(const char *file, const char *path)
|
||
+int git_mbedtls__set_cert_location(const char *path, int is_dir)
|
||
{
|
||
int ret = 0;
|
||
char errbuf[512];
|
||
- if (!file) {
|
||
- ret = mbedtls_x509_crt_parse_file(git__ssl_conf->ca_chain, file);
|
||
- } else if (!path) {
|
||
- ret = mbedtls_x509_crt_parse_path(git__ssl_conf->ca_chain, path);
|
||
+ mbedtls_x509_crt *cacert;
|
||
+
|
||
+ assert(path != NULL);
|
||
+
|
||
+ cacert = git__malloc(sizeof(mbedtls_x509_crt));
|
||
+ mbedtls_x509_crt_init(cacert);
|
||
+ if (is_dir) {
|
||
+ ret = mbedtls_x509_crt_parse_path(cacert, path);
|
||
+ } else {
|
||
+ ret = mbedtls_x509_crt_parse_file(cacert, path);
|
||
}
|
||
- if (ret != 0) {
|
||
+ /* mbedtls_x509_crt_parse_path returns the number of invalid certs on success */
|
||
+ if (ret < 0) {
|
||
+ mbedtls_x509_crt_free(cacert);
|
||
+ git__free(cacert);
|
||
mbedtls_strerror( ret, errbuf, 512 );
|
||
- giterr_set(GITERR_NET, "SSL error: %d - %s", ret, errbuf);
|
||
+ giterr_set(GITERR_SSL, "failed to load CA certificates : %s (%d)", errbuf, ret);
|
||
return -1;
|
||
}
|
||
+
|
||
+ mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
|
||
+ git__free(git__ssl_conf->ca_chain);
|
||
+ mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
|
||
+
|
||
return 0;
|
||
}
|
||
|
||
@@ -424,10 +440,10 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||
return -1;
|
||
}
|
||
|
||
-int git_mbedtls__set_cert_location(const char *file, const char *path)
|
||
+int git_mbedtls__set_cert_location(const char *path, int is_dir)
|
||
{
|
||
- GIT_UNUSED(file);
|
||
GIT_UNUSED(path);
|
||
+ GIT_UNUSED(is_dir);
|
||
|
||
giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
|
||
return -1;
|
||
diff --git a/src/streams/mbedtls.h b/src/streams/mbedtls.h
|
||
index 8dab2b6c99..7283698ffa 100644
|
||
--- a/src/streams/mbedtls.h
|
||
+++ b/src/streams/mbedtls.h
|
||
@@ -15,6 +15,6 @@ extern int git_mbedtls_stream_global_init(void);
|
||
|
||
extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
|
||
|
||
-extern int git_mbedtls__set_cert_location(const char *file, const char *path);
|
||
+extern int git_mbedtls__set_cert_location(const char *path, int is_dir);
|
||
|
||
#endif
|
||
|
||
From b3e0280d0b76891cae9f9abb8650938f86b6ef2c Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:11 +0200
|
||
Subject: [PATCH 11/15] mbedtls: display error codes as hex for consistency
|
||
with mbedTLS docs
|
||
|
||
Remaining parts of https://github.com/JuliaLang/julia/blob/8d47a314537779c8fb86642c54925613628a91b0/deps/patches/libgit2-mbedtls-fixup.patch
|
||
---
|
||
src/streams/mbedtls.c | 8 ++++----
|
||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||
|
||
diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
|
||
index d134e865f6..0a49a36a6f 100644
|
||
--- a/src/streams/mbedtls.c
|
||
+++ b/src/streams/mbedtls.c
|
||
@@ -181,12 +181,12 @@ static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
|
||
break;
|
||
|
||
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
|
||
- giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
|
||
+ giterr_set(GITERR_SSL, "SSL error: %#04x [%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
|
||
ret = GIT_ECERTIFICATE;
|
||
break;
|
||
|
||
default:
|
||
- giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf);
|
||
+ giterr_set(GITERR_SSL, "SSL error: %#04x - %s", error, errbuf);
|
||
}
|
||
|
||
return ret;
|
||
@@ -212,7 +212,7 @@ static int verify_server_cert(mbedtls_ssl_context *ssl)
|
||
char vrfy_buf[512];
|
||
int len = mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "", ret);
|
||
if (len >= 1) vrfy_buf[len - 1] = '\0'; /* Remove trailing \n */
|
||
- giterr_set(GITERR_SSL, "the SSL certificate is invalid: %x - %s", ret, vrfy_buf);
|
||
+ giterr_set(GITERR_SSL, "the SSL certificate is invalid: %#04x - %s", ret, vrfy_buf);
|
||
return GIT_ECERTIFICATE;
|
||
}
|
||
|
||
@@ -410,7 +410,7 @@ int git_mbedtls__set_cert_location(const char *path, int is_dir)
|
||
mbedtls_x509_crt_free(cacert);
|
||
git__free(cacert);
|
||
mbedtls_strerror( ret, errbuf, 512 );
|
||
- giterr_set(GITERR_SSL, "failed to load CA certificates : %s (%d)", errbuf, ret);
|
||
+ giterr_set(GITERR_SSL, "failed to load CA certificates: %#04x - %s", ret, errbuf);
|
||
return -1;
|
||
}
|
||
|
||
|
||
From e3d764a46b41886d8700e6d2c70c7dd33b255f96 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:12 +0200
|
||
Subject: [PATCH 12/15] tests: clarify comment
|
||
|
||
---
|
||
tests/core/stream.c | 5 ++---
|
||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||
|
||
diff --git a/tests/core/stream.c b/tests/core/stream.c
|
||
index 9bed4ae278..262888b10d 100644
|
||
--- a/tests/core/stream.c
|
||
+++ b/tests/core/stream.c
|
||
@@ -33,9 +33,8 @@ void test_core_stream__register_tls(void)
|
||
cl_git_pass(git_stream_register_tls(NULL));
|
||
error = git_tls_stream_new(&stream, "localhost", "443");
|
||
|
||
- /* We don't have arbitrary TLS stream support on Windows
|
||
- * or when openssl support is disabled (except on OSX
|
||
- * with Security framework).
|
||
+ /* We don't have TLS support enabled, or we're on Windows,
|
||
+ * which has no arbitrary TLS stream support.
|
||
*/
|
||
#if defined(GIT_WIN32) || !defined(GIT_HTTPS)
|
||
cl_git_fail_with(-1, error);
|
||
|
||
From 54554757c0595f5b3705f15d1212b34984bb35d1 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:14 +0200
|
||
Subject: [PATCH 13/15] cmake: make our preferred backend ordering consistent
|
||
|
||
---
|
||
src/CMakeLists.txt | 9 ++++++---
|
||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||
|
||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||
index fa86d9fb44..0f5d78547b 100644
|
||
--- a/src/CMakeLists.txt
|
||
+++ b/src/CMakeLists.txt
|
||
@@ -133,6 +133,8 @@ ELSE ()
|
||
ENDIF()
|
||
|
||
IF (USE_HTTPS)
|
||
+ # We try to find any packages our backends might use
|
||
+ FIND_PACKAGE(OpenSSL)
|
||
FIND_PACKAGE(mbedTLS)
|
||
IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||
FIND_PACKAGE(Security)
|
||
@@ -150,10 +152,13 @@ IF (USE_HTTPS)
|
||
ENDIF()
|
||
ELSEIF (WINHTTP)
|
||
SET(HTTPS_BACKEND "WinHTTP")
|
||
+ ELSEIF(OPENSSL_FOUND)
|
||
+ SET(HTTPS_BACKEND "OpenSSL")
|
||
ELSEIF(MBEDTLS_FOUND)
|
||
SET(HTTPS_BACKEND "mbedTLS")
|
||
ELSE()
|
||
- SET(HTTPS_BACKEND "OpenSSL")
|
||
+ MESSAGE(FATAL_ERROR "Unable to autodetect a usable HTTPS backend."
|
||
+ "Please pass the backend name explicitly (-DUSE_HTTPS=backend)")
|
||
ENDIF()
|
||
ELSE()
|
||
# Backend was explicitly set
|
||
@@ -177,8 +182,6 @@ IF (USE_HTTPS)
|
||
LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LIBRARIES} ${SECURITY_LIBRARIES})
|
||
LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
|
||
ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
|
||
- FIND_PACKAGE(OpenSSL)
|
||
-
|
||
IF (NOT OPENSSL_FOUND)
|
||
MESSAGE(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found")
|
||
ENDIF()
|
||
|
||
From 10aff3d5236c390155d247c9c366a9e4ff133825 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:15 +0200
|
||
Subject: [PATCH 14/15] travis: just grab what we need from mbedtls
|
||
|
||
---
|
||
script/install-deps-linux.sh | 3 +--
|
||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||
|
||
diff --git a/script/install-deps-linux.sh b/script/install-deps-linux.sh
|
||
index c084ca2e7c..68b3cc2756 100755
|
||
--- a/script/install-deps-linux.sh
|
||
+++ b/script/install-deps-linux.sh
|
||
@@ -3,9 +3,8 @@
|
||
set -x
|
||
|
||
if [ "$MBEDTLS" ]; then
|
||
- git clone https://github.com/ARMmbed/mbedtls.git ./deps/mbedtls
|
||
+ git clone --depth 10 --single-branch --branch mbedtls-2.6.1 https://github.com/ARMmbed/mbedtls.git ./deps/mbedtls
|
||
cd ./deps/mbedtls
|
||
- git checkout mbedtls-2.6.1
|
||
cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF .
|
||
cmake --build .
|
||
|
||
|
||
From cb2da47e56159faaaf143943c74ffb8f60a988b1 Mon Sep 17 00:00:00 2001
|
||
From: Etienne Samson <samson.etienne@gmail.com>
|
||
Date: Thu, 29 Mar 2018 22:14:17 +0200
|
||
Subject: [PATCH 15/15] travis: pass -fPIC when configuring mbedtls
|
||
|
||
---
|
||
script/install-deps-linux.sh | 3 ++-
|
||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/script/install-deps-linux.sh b/script/install-deps-linux.sh
|
||
index 68b3cc2756..99cbde4e0a 100755
|
||
--- a/script/install-deps-linux.sh
|
||
+++ b/script/install-deps-linux.sh
|
||
@@ -5,7 +5,8 @@ set -x
|
||
if [ "$MBEDTLS" ]; then
|
||
git clone --depth 10 --single-branch --branch mbedtls-2.6.1 https://github.com/ARMmbed/mbedtls.git ./deps/mbedtls
|
||
cd ./deps/mbedtls
|
||
- cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF .
|
||
+ # We pass -fPIC explicitely because we'll include it in libgit2.so
|
||
+ CFLAGS=-fPIC cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON .
|
||
cmake --build .
|
||
|
||
echo "mbedTLS built in `pwd`"
|