Skip to content

Commit 382ed1e

Browse files
committed
mbedtls: load default CA certificates
1 parent 1edde0b commit 382ed1e

File tree

4 files changed

+80
-24
lines changed

4 files changed

+80
-24
lines changed

src/CMakeLists.txt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,43 @@ IF (USE_HTTPS)
193193
MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
194194
ENDIF()
195195

196+
IF(NOT CERT_LOCATION)
197+
MESSAGE("Auto-detecting default certificates location")
198+
IF(CMAKE_SYSTEM_NAME MATCHES Darwin)
199+
# Check for an Homebrew installation
200+
SET(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl")
201+
ELSE()
202+
SET(OPENSSL_CMD "openssl")
203+
ENDIF()
204+
EXECUTE_PROCESS(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
205+
IF(OPENSSL_DIR)
206+
STRING(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR})
207+
208+
SET(OPENSSL_CA_LOCATIONS
209+
"ca-bundle.pem" # OpenSUSE Leap 42.1
210+
"cert.pem" # Ubuntu 14.04, FreeBSD
211+
"certs/ca-certificates.crt" # Ubuntu 16.04
212+
"certs/ca.pem" # Debian 7
213+
)
214+
FOREACH(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS)
215+
SET(LOC "${OPENSSL_DIR}${SUFFIX}")
216+
IF(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}")
217+
SET(CERT_LOCATION ${LOC})
218+
ENDIF()
219+
ENDFOREACH()
220+
ELSE()
221+
MESSAGE("Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION")
222+
ENDIF()
223+
ENDIF()
224+
225+
IF(CERT_LOCATION)
226+
IF(NOT EXISTS ${CERT_LOCATION})
227+
MESSAGE(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist")
228+
ENDIF()
229+
ADD_FEATURE_INFO(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}")
230+
ADD_DEFINITIONS(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}")
231+
ENDIF()
232+
196233
SET(GIT_MBEDTLS 1)
197234
LIST(APPEND LIBGIT2_INCLUDES ${MBEDTLS_INCLUDE_DIR})
198235
LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES})

src/settings.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ int git_libgit2_opts(int key, ...)
184184
{
185185
const char *file = va_arg(ap, const char *);
186186
const char *path = va_arg(ap, const char *);
187-
error = git_mbedtls__set_cert_location(file, path);
187+
if (file)
188+
error = git_mbedtls__set_cert_location(file, 0);
189+
if (error && path)
190+
error = git_mbedtls__set_cert_location(path, 1);
188191
}
189192
#else
190193
giterr_set(GITERR_SSL, "TLS backend doesn't support certificate locations");

src/streams/mbedtls.c

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
# include "streams/curl.h"
2323
#endif
2424

25+
#ifndef GIT_DEFAULT_CERT_LOCATION
26+
#define GIT_DEFAULT_CERT_LOCATION NULL
27+
#endif
28+
2529
#include <mbedtls/config.h>
2630
#include <mbedtls/ssl.h>
31+
#include <mbedtls/error.h>
2732
#include <mbedtls/entropy.h>
2833
#include <mbedtls/ctr_drbg.h>
2934

30-
#define CRT_LOC "/etc/ssl/certs"
31-
3235
mbedtls_ssl_config *git__ssl_conf;
3336
mbedtls_entropy_context *mbedtls_entropy;
3437

@@ -57,9 +60,13 @@ static void shutdown_ssl(void)
5760
}
5861
}
5962

63+
int git_mbedtls__set_cert_location(const char *path, int is_dir);
64+
6065
int git_mbedtls_stream_global_init(void)
6166
{
62-
int ret;
67+
int loaded = 0;
68+
char *crtpath = GIT_DEFAULT_CERT_LOCATION;
69+
struct stat statbuf;
6370
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
6471

6572
int *ciphers_list = NULL;
@@ -121,16 +128,11 @@ int git_mbedtls_stream_global_init(void)
121128

122129
mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
123130

124-
// set root certificates
125-
cacert = git__malloc(sizeof(mbedtls_x509_crt));
126-
mbedtls_x509_crt_init(cacert);
127-
ret = mbedtls_x509_crt_parse_path(cacert, CRT_LOC);
128-
if (ret) {
129-
giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret);
130-
goto cleanup;
131-
}
132-
133-
mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
131+
/* load default certificates */
132+
if (crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
133+
loaded = (git_mbedtls__set_cert_location(crtpath, 0) == 0);
134+
if (!loaded && crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
135+
loaded = (git_mbedtls__set_cert_location(crtpath, 1) == 0);
134136

135137
git__on_shutdown(shutdown_ssl);
136138

@@ -388,20 +390,34 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
388390
return error;
389391
}
390392

391-
int git_mbedtls__set_cert_location(const char *file, const char *path)
393+
int git_mbedtls__set_cert_location(const char *path, int is_dir)
392394
{
393395
int ret = 0;
394396
char errbuf[512];
395-
if (!file) {
396-
ret = mbedtls_x509_crt_parse_file(git__ssl_conf->ca_chain, file);
397-
} else if (!path) {
398-
ret = mbedtls_x509_crt_parse_path(git__ssl_conf->ca_chain, path);
397+
mbedtls_x509_crt *cacert;
398+
399+
assert(path != NULL);
400+
401+
cacert = git__malloc(sizeof(mbedtls_x509_crt));
402+
mbedtls_x509_crt_init(cacert);
403+
if (is_dir) {
404+
ret = mbedtls_x509_crt_parse_path(cacert, path);
405+
} else {
406+
ret = mbedtls_x509_crt_parse_file(cacert, path);
399407
}
400-
if (ret != 0) {
408+
/* mbedtls_x509_crt_parse_path returns the number of invalid certs on success */
409+
if (ret < 0) {
410+
mbedtls_x509_crt_free(cacert);
411+
git__free(cacert);
401412
mbedtls_strerror( ret, errbuf, 512 );
402-
giterr_set(GITERR_NET, "SSL error: %d - %s", ret, errbuf);
413+
giterr_set(GITERR_SSL, "failed to load CA certificates : %s (%d)", errbuf, ret);
403414
return -1;
404415
}
416+
417+
mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
418+
git__free(git__ssl_conf->ca_chain);
419+
mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
420+
405421
return 0;
406422
}
407423

@@ -424,10 +440,10 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
424440
return -1;
425441
}
426442

427-
int git_mbedtls__set_cert_location(const char *file, const char *path)
443+
int git_mbedtls__set_cert_location(const char *path, int is_dir)
428444
{
429-
GIT_UNUSED(file);
430445
GIT_UNUSED(path);
446+
GIT_UNUSED(is_dir);
431447

432448
giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
433449
return -1;

src/streams/mbedtls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ extern int git_mbedtls_stream_global_init(void);
1515

1616
extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
1717

18-
extern int git_mbedtls__set_cert_location(const char *file, const char *path);
18+
extern int git_mbedtls__set_cert_location(const char *path, int is_dir);
1919

2020
#endif

0 commit comments

Comments
 (0)