diff --git a/include/git2/common.h b/include/git2/common.h index b7cf20b31..400f2f611 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -199,6 +199,7 @@ typedef enum { GIT_OPT_GET_TEMPLATE_PATH, GIT_OPT_SET_TEMPLATE_PATH, GIT_OPT_SET_SSL_CERT_LOCATIONS, + GIT_OPT_ADD_SSL_X509_CERT, GIT_OPT_SET_USER_AGENT, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, @@ -336,6 +337,12 @@ typedef enum { * > certificates, one per file. * > * > Either parameter may be `NULL`, but not both. + * + * * opts(GIT_OPT_ADD_SSL_X509_CERT, const X509 *cert) + * + * > Add a raw X509 certificate into the SSL certs store. + * > + * > - `cert` is the raw X509 cert will be added to cert store. * * * opts(GIT_OPT_SET_USER_AGENT, const char *user_agent) * diff --git a/src/libgit2/settings.c b/src/libgit2/settings.c index 4a41830b8..f4c2453a4 100644 --- a/src/libgit2/settings.c +++ b/src/libgit2/settings.c @@ -222,6 +222,18 @@ int git_libgit2_opts(int key, ...) #endif break; + case GIT_OPT_ADD_SSL_X509_CERT: +#ifdef GIT_OPENSSL + { + X509 *cert = va_arg(ap, X509 *); + error = git_openssl__add_x509_cert(cert); + } +#else + git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support adding of the raw certs"); + error = -1; +#endif + break; + case GIT_OPT_SET_USER_AGENT: { const char *new_agent = va_arg(ap, const char *); diff --git a/src/libgit2/streams/openssl.c b/src/libgit2/streams/openssl.c index 7cb8f7f92..afc43edf3 100644 --- a/src/libgit2/streams/openssl.c +++ b/src/libgit2/streams/openssl.c @@ -722,6 +722,24 @@ int git_openssl__set_cert_location(const char *file, const char *path) return 0; } +int git_openssl__add_x509_cert(X509 *cert) +{ + X509_STORE *cert_store; + + if (openssl_ensure_initialized() < 0) + return -1; + + if (!(cert_store = SSL_CTX_get_cert_store(git__ssl_ctx))) + return -1; + + if (cert && X509_STORE_add_cert(cert_store, cert) == 0) { + git_error_set(GIT_ERROR_SSL, "OpenSSL error: failed to add raw X509 certificate"); + return -1; + } + + return 0; +} + #else #include "stream.h" diff --git a/src/libgit2/streams/openssl.h b/src/libgit2/streams/openssl.h index 89fb60a82..e503cbc6d 100644 --- a/src/libgit2/streams/openssl.h +++ b/src/libgit2/streams/openssl.h @@ -24,6 +24,7 @@ extern int git_openssl_stream_global_init(void); #ifdef GIT_OPENSSL extern int git_openssl__set_cert_location(const char *file, const char *path); +extern int git_openssl__add_x509_cert(X509 *cert); extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port); extern int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host); #endif