Changeset: 652d00b37663 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/652d00b37663
Added Files:
clients/mapilib/openssl_windows.c
Modified Files:
clients/mapilib/CMakeLists.txt
clients/mapilib/connect_openssl.c
clients/mapilib/mapi_intern.h
Branch: monetdburl
Log Message:
Use Windows Crypt API to extract system certificates
diffs (290 lines):
diff --git a/clients/mapilib/CMakeLists.txt b/clients/mapilib/CMakeLists.txt
--- a/clients/mapilib/CMakeLists.txt
+++ b/clients/mapilib/CMakeLists.txt
@@ -25,6 +25,7 @@ target_sources(mapi
parseurl.c
$<$<BOOL:${HAVE_SYS_UN_H}>:connect_unix.c>
$<$<BOOL:${OPENSSL_FOUND}>:connect_openssl.c>
+ $<$<BOOL:${OPENSSL_FOUND}>:$<$<BOOL:${WIN32}>:openssl_windows.c>>
mapi_intern.h
PUBLIC
$<BUILD_INTERFACE:$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/mapi.h>
@@ -46,6 +47,7 @@ target_link_libraries(mapi
stream
mutils
$<$<BOOL:${OPENSSL_FOUND}>:OpenSSL::SSL>
+ $<$<BOOL:${OPENSSL_FOUND}>:$<$<BOOL:${WIN32}>:crypt32>>
$<$<PLATFORM_ID:Windows>:ws2_32>)
target_compile_definitions(mapi
diff --git a/clients/mapilib/connect_openssl.c
b/clients/mapilib/connect_openssl.c
--- a/clients/mapilib/connect_openssl.c
+++ b/clients/mapilib/connect_openssl.c
@@ -11,10 +11,8 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
-static MapiMsg croak(Mapi mid, const char *action, const char *fmt, ...)
- __attribute__(( __format__(__printf__, 3, 4) ));
-static MapiMsg
-croak(Mapi mid, const char *action, const char *fmt, ...)
+MapiMsg
+croak_openssl(Mapi mid, const char *action, const char *fmt, ...)
{
va_list ap;
char buffer[800];
@@ -38,6 +36,16 @@ croak(Mapi mid, const char *action, cons
return mapi_printError(mid, action, MERROR, "TLS error: %s",
buffer);
}
+#ifndef NATIVE_WIN32
+MapiMsg
+add_system_certificates(Mapi mid, SSL_CTX *ctx)
+{
+ (void)mid;
+ (void)ctx;
+ return MOK;
+}
+#endif
+
static MapiMsg
make_ssl_context(Mapi mid, SSL_CTX **ctx_out)
{
@@ -50,10 +58,10 @@ make_ssl_context(Mapi mid, SSL_CTX **ctx
const SSL_METHOD *method = TLS_method();
if (!method)
- return croak(mid, __func__, "TLS_method");
+ return croak_openssl(mid, __func__, "TLS_method");
SSL_CTX *ctx = SSL_CTX_new(method);
if (!ctx)
- return croak(mid, __func__, "SSL_CTX_new");
+ return croak_openssl(mid, __func__, "SSL_CTX_new");
// From here on we need to free 'ctx' on failure
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
@@ -72,13 +80,18 @@ make_ssl_context(Mapi mid, SSL_CTX **ctx
cert = msetting_string(mid->settings, MP_CERT);
if (1 != SSL_CTX_load_verify_locations(ctx, cert,
NULL)) {
SSL_CTX_free(ctx);
- return croak(mid, __func__,
"SSL_CTX_load_verify_file: %s", cert);
+ return croak_openssl(mid, __func__,
"SSL_CTX_load_verify_file: %s", cert);
}
break;
case verify_system:
if (1 != SSL_CTX_set_default_verify_paths(ctx)) {
SSL_CTX_free(ctx);
- return croak(mid, __func__,
"SSL_CTX_set_default_verify_paths");
+ return croak_openssl(mid, __func__,
"SSL_CTX_set_default_verify_paths");
+ }
+ MapiMsg msg = add_system_certificates(mid, ctx);
+ if (msg != MOK) {
+ SSL_CTX_free(ctx);
+ return msg;
}
break;
}
@@ -123,7 +136,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (bio == NULL) {
closesocket(sock);
SSL_CTX_free(ctx);
- return croak(mid, __func__, "BIO_new_ssl");
+ return croak_openssl(mid, __func__, "BIO_new_ssl");
}
// BIO_new_ssl() inc'd the reference count of ctx so we can drop our
// reference here.
@@ -134,7 +147,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (1 != BIO_get_ssl(bio, &ssl)) {
closesocket(sock);
BIO_free(bio);
- return croak(mid, __func__, "BIO_get_ssl");
+ return croak_openssl(mid, __func__, "BIO_get_ssl");
}
// As far as I know the SSL returned by BIO_get_ssl has not had
// its refcount inc'd so we don't need to free it.
@@ -150,7 +163,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (sockbio == NULL) {
closesocket(sock);
BIO_free_all(bio);
- return croak(mid, __func__, "BIO_new_socket");
+ return croak_openssl(mid, __func__, "BIO_new_socket");
}
// From here on, 'sock' will be free'd by 'sockbio'.
// On error: free 'sockbio' and free 'bio'.
@@ -158,7 +171,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (!BIO_up_ref(sockbio)) {
BIO_free_all(sockbio);
BIO_free_all(bio);
- return croak(mid, __func__, "BIO_up_ref sockbio");
+ return croak_openssl(mid, __func__, "BIO_up_ref sockbio");
}
SSL_set0_rbio(ssl, sockbio); // consumes first ref
SSL_set0_wbio(ssl, sockbio); // consumes second ref
@@ -167,13 +180,13 @@ wrap_tls(Mapi mid, SOCKET sock)
if (!SSL_set_tlsext_host_name(ssl, host)) {
BIO_free_all(bio);
- return croak(mid, __func__, "SSL_set_tlsext_host_name");
+ return croak_openssl(mid, __func__, "SSL_set_tlsext_host_name");
}
// handshake
if (1 != SSL_connect(ssl)) {
BIO_free_all(bio);
- return croak(mid, __func__, "SSL_connect");
+ return croak_openssl(mid, __func__, "SSL_connect");
}
/////////////////////////////////////////////////////////////////////
@@ -181,7 +194,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (!BIO_up_ref(bio)) {
BIO_free_all(bio);
- return croak(mid, __func__, "BIO_up_ref bio");
+ return croak_openssl(mid, __func__, "BIO_up_ref bio");
}
// On error: free 'bio' twice
@@ -194,7 +207,7 @@ wrap_tls(Mapi mid, SOCKET sock)
BIO_free_all(bio); // drops first ref
BIO_free_all(bio); // drops second ref
free(hostcolonport);
- return croak(mid, __func__, "openssl_rstream: %s",
mnstr_peek_error(rstream));
+ return croak_openssl(mid, __func__, "openssl_rstream: %s",
mnstr_peek_error(rstream));
}
// On error: free 'bio' and close 'rstream'.
stream *wstream = openssl_wstream(hostcolonport ? hostcolonport : "ssl
wstream", bio);
@@ -202,7 +215,7 @@ wrap_tls(Mapi mid, SOCKET sock)
if (wstream == NULL || mnstr_errnr(wstream) != MNSTR_NO__ERROR) {
BIO_free_all(bio);
mnstr_close(rstream);
- return croak(mid, __func__, "openssl_wstream: %s",
mnstr_peek_error(wstream));
+ return croak_openssl(mid, __func__, "openssl_wstream: %s",
mnstr_peek_error(wstream));
}
// On error: free 'rstream' and 'wstream'.
msg = mapi_wrap_streams(mid, rstream, wstream);
diff --git a/clients/mapilib/mapi_intern.h b/clients/mapilib/mapi_intern.h
--- a/clients/mapilib/mapi_intern.h
+++ b/clients/mapilib/mapi_intern.h
@@ -44,6 +44,11 @@
# include <sys/time.h> /* gettimeofday */
#endif
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#endif
+
+
/* Copied from gdk_posix, but without taking a lock because we don't have
access to
* MT_lock_set/unset here. We just have to hope for the best
*/
@@ -312,3 +317,10 @@ MapiMsg wrap_socket(Mapi mid, SOCKET soc
void close_connection(Mapi mid);
void set_uri(Mapi mid);
+
+#ifdef HAVE_OPENSSL
+MapiMsg croak_openssl(Mapi mid, const char *action, const char *fmt, ...)
+ __attribute__(( __format__(__printf__, 3, 4) ));
+
+MapiMsg add_system_certificates(Mapi mid, SSL_CTX *ctx);
+#endif
diff --git a/clients/mapilib/openssl_windows.c
b/clients/mapilib/openssl_windows.c
new file mode 100644
--- /dev/null
+++ b/clients/mapilib/openssl_windows.c
@@ -0,0 +1,94 @@
+#include "monetdb_config.h"
+
+#include "stream.h"
+#include "mapi.h"
+#include "mapi_intern.h"
+
+#include <wincrypt.h>
+
+MapiMsg
+croak_win32(Mapi mid, const char *action, DWORD error)
+{
+ return mapi_printError(mid, action, MERROR, "System Error #%d", error);
+}
+
+static MapiMsg
+process_sysstore_item(Mapi mid, X509_STORE *x509_store, int nr, const
CERT_CONTEXT *item)
+{
+ DWORD typ = item->dwCertEncodingType;
+ const unsigned char *data = item->pbCertEncoded;
+ size_t size = item->cbCertEncoded;
+
+ bool is_x509 = (typ & X509_ASN_ENCODING);
+ bool is_pkcs7 = (typ & PKCS_7_ASN_ENCODING);
+ mapi_log_record(
+ mid, "CONN", "Processing item #%d of type %lu [%s%s], size %zu",
+ nr,
+ typ, (is_x509 ? "X" : ""), (is_pkcs7 ? "P" : ""),
+ size
+ );
+
+ if (!is_x509)
+ return mapi_printError(mid, __func__, MERROR, "sys store
certificate #%d must be in X509 format", nr);
+
+ X509 *x509 = d2i_X509(NULL, &data, (long)size);
+ if (!x509)
+ return croak_openssl(mid, __func__, "sys store certificate #%d:
d2i_X509");
+
+ MapiMsg msg;
+ if (1 == X509_STORE_add_cert(x509_store, x509)) {
+ msg = MOK;
+ } else {
+ msg = mapi_printError(mid, __func__, MERROR, "sys store
certificate #%d: X509_STORE_add_cert");
+ }
+ X509_free(x509);
+
+ return msg;
+}
+
+MapiMsg
+add_system_certificates(Mapi mid, SSL_CTX *ctx)
+{
+ MapiMsg msg;
+ X509_STORE *x509_store = SSL_CTX_get_cert_store(ctx);
+ HCERTSTORE sysstore = NULL;
+ const CERT_CONTEXT *item = NULL;
+
+ mapi_log_record(mid, "CONN", "Enumerating system certificates");
+
+ sysstore = CertOpenSystemStoreW(0, L"ROOT");
+ if (!sysstore)
+ return croak_win32(mid, __func__, GetLastError());
+
+ int count = 0;
+ while (1) {
+ item = CertEnumCertificatesInStore(sysstore, item);
+ if (item == NULL)
+ break;
+ msg = process_sysstore_item(mid, x509_store, ++count, item);
+ if (msg != MOK) {
+ CertFreeCertificateContext(item);
+ CertCloseStore(sysstore, 0);
+ return msg;
+ }
+ }
+
+ // We get here if CertEnumCertificatesInStore returned NULL.
+ DWORD error = GetLastError();
+ assert(item == NULL);
+ CertCloseStore(sysstore, 0);
+ switch (error) {
+ case 0:
+ case CRYPT_E_NOT_FOUND:
+ case ERROR_NO_MORE_FILES:
+ // Normal exit codes according to the documentation at
+ //
https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certenumcertificatesinstore
+ mapi_log_record(mid, "CONN", "Added %d certificates",
count);
+ return MOK;
+ default:
+ // Anything else is problematic
+ return croak_win32(mid, __func__, error);
+ }
+}
+
+
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]