diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 37 | ||||
-rw-r--r-- | src/settings.c | 5 | ||||
-rw-r--r-- | src/streams/mbedtls.c | 60 | ||||
-rw-r--r-- | src/streams/mbedtls.h | 2 |
4 files changed, 80 insertions, 24 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 027e76a32..fa86d9fb4 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 1195075ee..f6bc5b270 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 ea96ae3de..d134e865f 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 @@ out_err: 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 8dab2b6c9..7283698ff 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 |