Changeset: 3e5561b96555 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3e5561b96555
Modified Files:
clients/mapilib/CMakeLists.txt
clients/mapilib/connect_openssl.c
Branch: monetdburl
Log Message:
Perform the SSL handshake
diffs (181 lines):
diff --git a/clients/mapilib/CMakeLists.txt b/clients/mapilib/CMakeLists.txt
--- a/clients/mapilib/CMakeLists.txt
+++ b/clients/mapilib/CMakeLists.txt
@@ -43,6 +43,7 @@ target_link_libraries(mapi
moptions
mcrypt
stream
+ $<$<BOOL:${OPENSSL_FOUND}>:OpenSSL::SSL>
$<$<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
@@ -1,20 +1,159 @@
#include "monetdb_config.h"
+
#include "stream.h" /* include before mapi.h */
#include "stream_socket.h"
#include "mapi.h"
-#include "mapi_prompt.h"
-#include "mcrypt.h"
-#include "matomic.h"
-#include "mstring.h"
+#include "mapi_intern.h"
+
+#include <stdarg.h>
+#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
+croak(Mapi mid, const char *action, const char *fmt, ...)
+{
+ va_list ap;
+ char buffer[800];
+ va_start(ap, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ va_end(ap);
+
+ unsigned long err = ERR_get_error();
+ const char *errmsg =
+ ERR_SYSTEM_ERROR(err)
+ ? strerror(ERR_GET_REASON(err))
+ : ERR_reason_error_string(err);
+ if (errmsg)
+ return mapi_printError(mid, action, MERROR, "TLS error: %s:
%s", buffer, errmsg);
+ else
+ return mapi_printError(mid, action, MERROR, "TLS error: %s:
failed with error %lu (0x%lx)", buffer, err, err);
+}
+
+static MapiMsg
+perform_handshake(Mapi mid, ssl_state *state, SOCKET sock)
+{
+ // Based on the example on the OpenSSL wiki:
+ // https://wiki.openssl.org/index.php/SSL/TLS_Client
+ const msettings *settings = mid->settings;
-#include "mapi_intern.h"
+ // Clear any earlier errrors
+ do {} while (ERR_get_error() != 0);
+
+ /////////////////////////////////////////////////////////////////////
+ // Set up the context
+
+ const SSL_METHOD *method = TLS_method();
+ if (!method)
+ return croak(mid, __func__, "TLS_method");
+ SSL_CTX *ctx = state->ctx = SSL_CTX_new(method);
+ if (!ctx)
+ return croak(mid, __func__, "SSL_CTX_new");
+
+ 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)) {
+ 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))
+ return croak(mid, __func__,
"SSL_CTX_load_verify_file: %s", cert);
+ break;
+ case verify_system:
+ if (1 != SSL_CTX_set_default_verify_paths(ctx))
+ return croak(mid, __func__,
"SSL_CTX_set_default_verify_paths");
+ break;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ // Create the SSL connection
+
+ SSL *ssl = state->ssl = SSL_new(ctx);
+ if (ssl == NULL) {
+ return croak(mid, __func__, "SSL_new");
+ }
+
+ BIO *bio = BIO_new_socket(sock, BIO_NOCLOSE);
+ if (bio == NULL)
+ return croak(mid, __func__, "BIO_new_socket");
+ if (!BIO_up_ref(bio)) {
+ BIO_free_all(bio);
+ 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'.
+
+ const char *hostname = msettings_connect_tcp(settings);
+ if (!SSL_set_tlsext_host_name(ssl, hostname))
+ 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)
{
- closesocket(sock);
- return mapi_setError(mid, "It's a work in progress", __func__, MERROR);
+ ssl_state *state = create_ssl_state();
+ if (!state) {
+ mapi_setError(mid, "malloc failed", __func__, MERROR);
+ goto bailout;
+ }
+
+ if (perform_handshake(mid, state, sock) != MOK)
+ goto bailout;
+
+
+ return mapi_setError(mid, "it's still a work in progress", __func__,
MERROR);
+
+bailout:
+ assert(mid->error != MOK);
+ destroy_ssl_state(state);
+ return mid->error;
}
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]