Changeset: 07883ebf5747 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/07883ebf5747
Added Files:
common/stream/openssl_stream.c
Modified Files:
clients/mapilib/connect_openssl.c
common/stream/CMakeLists.txt
common/stream/stream.h
Branch: monetdburl
Log Message:
Complete the TLS handshake, openssl_stream not yet implemented
diffs (truncated from 303 to 300 lines):
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,36 +11,6 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
-typedef struct ssl_state {
- SOCKET socket;
- SSL_CTX *ctx;
- SSL *ssl;
-} ssl_state;
-
-static ssl_state*
-create_ssl_state(void)
-{
- ssl_state *st = malloc(sizeof(*st));
- if (st == NULL)
- return NULL;
- *st = (ssl_state) {
- .socket = INVALID_SOCKET,
- };
- return st;
-}
-
-static void
-destroy_ssl_state(struct ssl_state *st)
-{
- if (st) {
- if (st->socket != INVALID_SOCKET)
- closesocket(st->socket);
- if (st->ctx != NULL)
- SSL_CTX_free(st->ctx);
- }
- free(st);
-}
-
static MapiMsg croak(Mapi mid, const char *action, const char *fmt, ...)
__attribute__(( __format__(__printf__, 3, 4) ));
static MapiMsg
@@ -59,101 +29,156 @@ croak(Mapi mid, const char *action, cons
: ERR_reason_error_string(err);
if (errmsg)
return mapi_printError(mid, action, MERROR, "TLS error: %s:
%s", buffer, errmsg);
+ else if (err != 0)
+ return mapi_printError(mid, action, MERROR, "TLS error: %s:
failed with error %lu (0x%lx)", buffer, err, err);
else
- return mapi_printError(mid, action, MERROR, "TLS error: %s:
failed with error %lu (0x%lx)", buffer, err, err);
+ return mapi_printError(mid, action, MERROR, "TLS error: %s",
buffer);
}
static MapiMsg
-perform_handshake(Mapi mid, ssl_state *state, SOCKET sock)
+make_ssl_context(Mapi mid, SSL_CTX **ctx_out)
{
- // Based on the example on the OpenSSL wiki:
- // https://wiki.openssl.org/index.php/SSL/TLS_Client
- const msettings *settings = mid->settings;
+ // Today we just create a new one but if we load the system trust store
+ // the result could be cached for a while.
+ // (What's a reasonable amount of time for a process to pick up changes
to
+ // the system trust store?)
- // Clear any earlier errrors
- do {} while (ERR_get_error() != 0);
-
- /////////////////////////////////////////////////////////////////////
- // Set up the context
+ *ctx_out = NULL;
const SSL_METHOD *method = TLS_method();
if (!method)
return croak(mid, __func__, "TLS_method");
- SSL_CTX *ctx = state->ctx = SSL_CTX_new(method);
+ SSL_CTX *ctx = SSL_CTX_new(method);
if (!ctx)
return croak(mid, __func__, "SSL_CTX_new");
+ // From here on we need to free 'ctx' on failure
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
- // SSL_CTX_set_verify_depth: why change the default?
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
// Because we use at least TLSv1.3 we don't need to mess with
// SSL_CTX_set_cipher_list() and SSL_CTX_set_ciphersuites().
- switch (msettings_connect_tls_verify(settings)) {
+ switch (msettings_connect_tls_verify(mid->settings)) {
case verify_none:
case verify_hash:
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
break;
case verify_cert:
- const char *cert = msetting_string(settings, MP_CERT);
- if (1 != SSL_CTX_load_verify_file(ctx, cert))
+ const char *cert = msetting_string(mid->settings,
MP_CERT);
+ if (1 != SSL_CTX_load_verify_file(ctx, cert)) {
+ SSL_CTX_free(ctx);
return croak(mid, __func__,
"SSL_CTX_load_verify_file: %s", cert);
+ }
break;
case verify_system:
- if (1 != SSL_CTX_set_default_verify_paths(ctx))
+ if (1 != SSL_CTX_set_default_verify_paths(ctx)) {
+ SSL_CTX_free(ctx);
return croak(mid, __func__,
"SSL_CTX_set_default_verify_paths");
+ }
break;
}
+ *ctx_out = ctx;
+ return MOK;
+}
+
+MapiMsg
+wrap_tls(Mapi mid, SOCKET sock)
+{
+ // Based on the example on the OpenSSL wiki:
+ // https://wiki.openssl.org/index.php/SSL/TLS_Client
+
+ // On error: close 'sock'.
+
+ MapiMsg msg = MOK;
+ const msettings *settings = mid->settings;
+
+ // Clear any earlier errrors
+ do {} while (ERR_get_error() != 0);
+
+ SSL_CTX *ctx = NULL;
+ msg = make_ssl_context(mid, &ctx);
+ if (msg != MOK) {
+ closesocket(sock);
+ return msg;
+ }
+ // On error: close 'sock' and free 'ctx'.
+
/////////////////////////////////////////////////////////////////////
// Create the SSL connection
- SSL *ssl = state->ssl = SSL_new(ctx);
+ SSL *ssl = SSL_new(ctx);
if (ssl == NULL) {
+ closesocket(sock);
+ SSL_CTX_free(ctx);
return croak(mid, __func__, "SSL_new");
}
+ // SSL_new has inc'd the refcount of ctx. We can now drop our ref
+ // so we don't have to call SSL_CTX_free all the time
+ SSL_CTX_free(ctx);
+ // On error: close 'sock' and free 'ssl'.
- BIO *bio = BIO_new_socket(sock, BIO_NOCLOSE);
- if (bio == NULL)
+ BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
+ if (bio == NULL) {
+ closesocket(sock);
+ SSL_free(ssl);
return croak(mid, __func__, "BIO_new_socket");
+ }
+ // From here on, 'sock' will be free'd by 'bio'.
+ // On error: free 'bio' and free 'ssl'.
+
if (!BIO_up_ref(bio)) {
BIO_free_all(bio);
+ SSL_free(ssl);
return croak(mid, __func__, "BIO_up_ref");
}
SSL_set0_rbio(ssl, bio); // consumes first ref
SSL_set0_wbio(ssl, bio); // consumes second ref
// from here on 'bio' will be freed through 'ssl'.
+ // On error: free 'ssl'.
const char *hostname = msettings_connect_tcp(settings);
- if (!SSL_set_tlsext_host_name(ssl, hostname))
+ if (!SSL_set_tlsext_host_name(ssl, hostname)) {
+ SSL_free(ssl);
return croak(mid, __func__, "SSL_set_tlsext_host_name");
-
- if (1 != SSL_connect(ssl))
- return croak(mid, __func__, "SSL_connect");
-
+ }
- return mapi_setError(mid, "that's how far we get", __func__, MERROR);
-}
-
-
-MapiMsg
-wrap_tls(Mapi mid, SOCKET sock)
-{
- ssl_state *state = create_ssl_state();
- if (!state) {
- mapi_setError(mid, "malloc failed", __func__, MERROR);
- goto bailout;
+ // handshake
+ if (1 != SSL_connect(ssl)) {
+ SSL_free(ssl);
+ return croak(mid, __func__, "SSL_connect");
}
- if (perform_handshake(mid, state, sock) != MOK)
- goto bailout;
-
-
- return mapi_setError(mid, "it's still a work in progress", __func__,
MERROR);
+ /////////////////////////////////////////////////////////////////////
+ // Attach the connection to 'mid'
-bailout:
- assert(mid->error != MOK);
- destroy_ssl_state(state);
- return mid->error;
+ if (!SSL_up_ref(ssl)) {
+ SSL_free(ssl);
+ return croak(mid, __func__, "SSL_up_ref");
+ }
+ // On error: free 'ssl' twice
+ stream *rstream = openssl_stream(ssl);
+ if (rstream == NULL || mnstr_errnr(rstream) != MNSTR_NO__ERROR) {
+ SSL_free(ssl); // drops first ref
+ SSL_free(ssl); // drops second ref
+ return croak(mid, __func__, "openssl_stream: %s",
mnstr_peek_error(rstream));
+ }
+ // On error: free 'ssl' and close 'rstream'.
+ stream *wstream = openssl_stream(ssl);
+ if (wstream == NULL || mnstr_errnr(wstream) != MNSTR_NO__ERROR) {
+ mnstr_close(rstream);
+ SSL_free(ssl);
+ return croak(mid, __func__, "openssl_stream: %s",
mnstr_peek_error(wstream));
+ }
+ // On error: free 'rstream' and 'wstream'.
+ msg = mapi_set_streams(mid, rstream, wstream);
+ if (msg != MOK) {
+ mnstr_close(rstream);
+ mnstr_close(wstream);
+ return msg;
+ }
+ // 'rstream' and 'wstream' are part of 'mid' now.
+
+ return MOK;
}
diff --git a/common/stream/CMakeLists.txt b/common/stream/CMakeLists.txt
--- a/common/stream/CMakeLists.txt
+++ b/common/stream/CMakeLists.txt
@@ -39,6 +39,7 @@ target_sources(stream
fwf.c
iconv_stream.c
text_stream.c
+ $<$<BOOL:${HAVE_OPENSSL}>:openssl_stream.c>
pump.c
stream.h
stream_internal.h
diff --git a/common/stream/openssl_stream.c b/common/stream/openssl_stream.c
new file mode 100644
--- /dev/null
+++ b/common/stream/openssl_stream.c
@@ -0,0 +1,21 @@
+/*
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 1997 - July 2008 CWI, August 2008 - 2023 MonetDB B.V.
+ */
+
+#include "monetdb_config.h"
+#include "stream.h"
+#include "stream_internal.h"
+
+stream *
+openssl_stream(SSL *ssl)
+{
+ (void)ssl;
+ mnstr_set_open_error(NULL, 0, "not implemented yet");
+ return NULL;
+}
diff --git a/common/stream/stream.h b/common/stream/stream.h
--- a/common/stream/stream.h
+++ b/common/stream/stream.h
@@ -31,6 +31,11 @@
#include <signal.h>
#include <limits.h>
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#endif
+
+
/* avoid using "#ifdef WIN32" so that this file does not need our config.h */
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
# ifndef LIBSTREAM
@@ -272,5 +277,9 @@ stream_export stream *mapi_request_downl
// write-only
stream_export stream *byte_counting_stream(stream *wrapped, uint64_t *counter);
+#ifdef HAVE_OPENSSL
+stream_export stream *openssl_stream(SSL *ssl);
+#endif
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]