Changeset: 2137305889ba for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2137305889ba
Modified Files:
        clients/Tests/exports.stable.out
Branch: default
Log Message:

Merge 'monetdburl' into 'default'


diffs (truncated from 628 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -730,9 +730,10 @@ msettings_error msetting_set_named(msett
 const char *msetting_string(const msettings *mp, mparm parm);
 long msettings_connect_binary(const msettings *mp);
 const char *msettings_connect_certhash_digits(const msettings *mp);
+const char *msettings_connect_clientcert(const msettings *mp);
+const char *msettings_connect_clientkey(const msettings *mp);
 long msettings_connect_port(const msettings *mp);
 bool msettings_connect_scan(const msettings *mp);
-const char *msettings_connect_sockdir(const msettings *mp);
 const char *msettings_connect_tcp(const msettings *mp);
 enum msetting_tls_verify msettings_connect_tls_verify(const msettings *mp);
 const char *msettings_connect_unix(const msettings *mp);
diff --git a/clients/examples/C/testsfile.c b/clients/examples/C/testsfile.c
--- a/clients/examples/C/testsfile.c
+++ b/clients/examples/C/testsfile.c
@@ -235,6 +235,10 @@ handle_expect_command(const char *locati
                return expect_string(location, MP_UNKNOWN, 
msettings_connect_certhash_digits, value);
        if (strcmp("connect_binary", key) == 0)
                return expect_long(location, MP_UNKNOWN, 
msettings_connect_binary, value);
+       if (strcmp("connect_clientkey", key) == 0)
+               return expect_string(location, MP_UNKNOWN, 
msettings_connect_clientkey, value);
+       if (strcmp("connect_clientcert", key) == 0)
+               return expect_string(location, MP_UNKNOWN, 
msettings_connect_clientcert, value);
 
        const mparm parm = mparm_parse(key);
        if (parm == MP_UNKNOWN) {
diff --git a/clients/mapilib/Tests/systemcertificates.py 
b/clients/mapilib/Tests/systemcertificates.py
--- a/clients/mapilib/Tests/systemcertificates.py
+++ b/clients/mapilib/Tests/systemcertificates.py
@@ -25,13 +25,20 @@ HOST = 'python.org'
 # Run mclient
 cmd = ['mclient', '-L-', '-d', f"monetdbs://{HOST}:443/demo"]
 proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
-assert proc.returncode == 2, f"mclient is supposed to exit with status 2, not 
{proc.returncode}"
+if proc.returncode != 2:
+    msg = str(proc.stderr, 'utf-8')
+    print(f"mclient is supposed to exit with status 2, not 
{proc.returncode}.\n--- stderr ---\n{msg}\n---end stderr ---", file=sys.stderr)
+    exit(1)
 
-# We expect the server to send something like 'HTTP/1.1 400 Bad Request'
-# libmapi will interpret the first two bytes as a block header.
+# After the TLS handshake succeeds we expect the server to send something like
+# 'HTTP/1.1 400 Bad Request' because we're sending \x00\x00 instead of an HTTP
+# request. libmapi will interpret the first two bytes 'H' and 'T' as an invalid
+# block header.
 #
-# In ASCII, 'H' + 256 * 'T' is 21576.
-if b'21576' not in proc.stderr:
+# In ASCII,  'H' + 256 * 'T'  ==  72 + 256 * 84  ==  21576.
+tls_works_but_mapi_fails = b'21576' in proc.stderr
+
+if not tls_works_but_mapi_fails:
     msg = str(proc.stderr, 'utf-8')
     print(f"Expected mclient to print an error message containing the number 
21576, got:\n--- stderr ---\n{msg}\n---end stderr ---", file=sys.stderr)
     exit(1)
diff --git a/clients/mapilib/Tests/tests.md b/clients/mapilib/Tests/tests.md
--- a/clients/mapilib/Tests/tests.md
+++ b/clients/mapilib/Tests/tests.md
@@ -258,6 +258,7 @@ EXPECT port=-1
 EXPECT database=
 EXPECT tableschema=
 EXPECT table=
+EXPECT binary=on
 ```
 
 ### sock
@@ -272,6 +273,15 @@ ACCEPT monetdb:///?sock=C:\TEMP\sock
 EXPECT sock=C:\TEMP\sock
 ```
 
+### sockdir
+
+```test
+EXPECT sockdir=/tmp
+ACCEPT monetdb:///demo?sockdir=/tmp/nonstandard
+EXPECT sockdir=/tmp/nonstandard
+EXPECT connect_unix=/tmp/nonstandard/.s.monetdb.50000
+```
+
 ### cert
 
 ```test
@@ -321,15 +331,40 @@ REJECT monetdbs:///?certhash={sha99}X
 
 ```test
 EXPECT clientkey=
+EXPECT clientcert=
 ACCEPT monetdbs:///?clientkey=/tmp/clientkey.pem
 EXPECT clientkey=/tmp/clientkey.pem
 ACCEPT monetdbs:///?clientkey=C:\TEMP\clientkey.pem
 EXPECT clientkey=C:\TEMP\clientkey.pem
 ```
 
-### clientcert
+```test
+EXPECT connect_clientkey=
+EXPECT connect_clientcert=
+```
+
+```test
+SET clientkey=/tmp/key.pem
+SET clientcert=/tmp/cert.pem
+EXPECT valid=true
+EXPECT connect_clientkey=/tmp/key.pem
+EXPECT connect_clientcert=/tmp/cert.pem
+```
 
 ```test
+SET clientkey=/tmp/key.pem
+EXPECT valid=true
+EXPECT connect_clientkey=/tmp/key.pem
+EXPECT connect_clientcert=/tmp/key.pem
+```
+
+```test
+SET clientcert=/tmp/cert.pem
+EXPECT valid=false
+```
+
+```test
+SET clientkey=dummy
 EXPECT clientcert=
 ACCEPT monetdbs:///?clientcert=/tmp/clientcert.pem
 EXPECT clientcert=/tmp/clientcert.pem
@@ -471,14 +506,8 @@ ACCEPT monetdb:///?binary=0100
 EXPECT connect_binary=100
 ```
 
-We take empty to be 'on'
-
 ```test
-ACCEPT monetdb:///?binary=
-EXPECT connect_binary=65535
-```
-
-```test
+REJECT monetdb:///?binary=
 REJECT monetdb:///?binary=-1
 REJECT monetdb:///?binary=1.0
 REJECT monetdb:///?binary=banana
@@ -1129,6 +1158,21 @@ EXPECT connect_tcp=not.localhost
 REJECT monetdbs://not.localhost/?sock=/a/path
 ```
 
+### sock and sockdir
+
+Sockdir only applies to implicit Unix domain sockets,
+not to ones that are given explicitly
+
+```test
+EXPECT sockdir=/tmp
+EXPECT port=-1
+EXPECT host=
+EXPECT connect_unix=/tmp/.s.monetdb.50000
+SET sockdir=/somewhere/else
+EXPECT connect_unix=/somewhere/else/.s.monetdb.50000
+SET port=12345
+EXPECT connect_unix=/somewhere/else/.s.monetdb.12345
+```
 
 ## Legacy URL's
 
diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -75,7 +75,10 @@ def attempt(experiment: str, portname: s
     logging.debug(f"cmd={cmd}")
     proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
     logging.debug(f"mclient exited with code {proc.returncode}, 
err={proc.stderr}")
-    assert proc.returncode == 2, f"mclient is supposed to exit with status 2, 
not {proc.returncode}"
+    if proc.returncode != 2:
+        msg = str(proc.stderr, 'utf-8')
+        print(f"mclient is supposed to exit with status 2, not 
{proc.returncode}.\n--- stderr ---\n{msg}\n---end stderr ---", file=sys.stderr)
+        assert proc.returncode == 2, f"mclient is supposed to exit with status 
2, not {proc.returncode}"
     output = str(proc.stderr, 'utf-8').rstrip()
     actual_error = None if 'Sorry, this is not' in output else output
 
diff --git a/clients/mapilib/Tests/tlstester.py 
b/clients/mapilib/Tests/tlstester.py
--- a/clients/mapilib/Tests/tlstester.py
+++ b/clients/mapilib/Tests/tlstester.py
@@ -26,6 +26,8 @@ from threading import Thread
 import threading
 from typing import Any, Callable, Dict, List, Optional, Tuple, Union
 
+# Our TLS implementation never uses anything less than TLSv1.3.
+assert ssl.HAS_TLSv1_3
 
 import warnings
 with warnings.catch_warnings():
@@ -434,10 +436,14 @@ def make_context(allowtlsv12 = False):
 
     if hasattr(context, 'minimum_version'):
         context.maximum_version = ssl.TLSVersion.TLSv1_3
-        if allowtlsv12:
-            context.minimum_version = ssl.TLSVersion.TLSv1_2
-        else:
-            context.minimum_version = ssl.TLSVersion.TLSv1_3
+        try:
+            if allowtlsv12:
+                context.minimum_version = ssl.TLSVersion.TLSv1_2
+            else:
+                context.minimum_version = ssl.TLSVersion.TLSv1_3
+        except ValueError as e:
+            log.error(f"Setting context.minimum_version caused ValueError. 
Python version {sys.version!r}, linked to OpenSSL {ssl.OPENSSL_VERSION} 
({ssl.OPENSSL_VERSION_NUMBER:#x})")
+            raise e
 
     return context
 
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
@@ -24,6 +24,7 @@
 #include <stdarg.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#include <openssl/x509v3.h>
 
 MapiMsg
 croak_openssl(Mapi mid, const char *action, const char *fmt, ...)
@@ -121,7 +122,7 @@ make_ssl_context(Mapi mid, SSL_CTX **ctx
 }
 
 static MapiMsg
-verify_server_certificate_hash(Mapi mid, SSL *ssl, const char *required_prefix)
+verify_server_certificate_hash(Mapi mid, X509 *x509, const char 
*required_prefix)
 {
        mapi_log_record(mid, "CONN", "verifying certificate hash against prefix 
'%s'", required_prefix);
 
@@ -129,19 +130,13 @@ verify_server_certificate_hash(Mapi mid,
        if (prefix_len > 2 * SHA256_DIGEST_LENGTH)
                return mapi_setError(mid, "value of certhash= is longer than a 
sha256 digest", __func__, MERROR);
 
-       X509 *x509 = SSL_get_peer_certificate(ssl);
-       if (x509 == NULL)
-               return mapi_printError(mid, __func__, MERROR, "Server did not 
send a TLS certificate");
-
        // Convert to DER
        unsigned char *buf = NULL;
        int buflen = i2d_X509(x509, &buf);
        if (buflen <= 0) {
-               X509_free(x509);
                return croak_openssl(mid, __func__, "could not convert server 
certificate to DER");
        }
        assert(buf);
-       X509_free(x509);
 
        // Compute the has of the DER using the deprecated API so we stay
        // compatible with OpenSSL 1.1.1.
@@ -175,8 +170,6 @@ verify_server_certificate_hash(Mapi mid,
        mapi_log_record(mid, "CONN", "server certificate matches certhash");
        return MOK;
 }
-
-
 MapiMsg
 wrap_tls(Mapi mid, SOCKET sock)
 {
@@ -193,10 +186,8 @@ wrap_tls(Mapi mid, SOCKET sock)
        size_t hostlen = strlen(host);
        size_t hostportlen = hostlen + 1 + 20;
 
-       const char *clientkey = msetting_string(settings, MP_CLIENTKEY);
-       const char *clientcert = msetting_string(settings, MP_CLIENTCERT);
-       if (!clientcert[0])
-               clientcert = clientkey;  // this logic should be virtual 
parameters in the spec!
+       const char *clientkey = msettings_connect_clientkey(settings);
+       const char *clientcert = msettings_connect_clientcert(settings);
        enum msetting_tls_verify verify_method = 
msettings_connect_tls_verify(settings);
 
        // Clear any earlier errrors
@@ -266,6 +257,17 @@ wrap_tls(Mapi mid, SOCKET sock)
                return croak_openssl(mid, __func__, "SSL_set_tlsext_host_name");
        }
 
+       X509_VERIFY_PARAM *param = SSL_get0_param(ssl);
+       if (param == NULL) {
+               BIO_free_all(bio);
+               return croak_openssl(mid, __func__, "SSL_get0_param");
+       }
+       X509_VERIFY_PARAM_set_hostflags(param, 
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+       if (1 != X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
+               BIO_free_all(bio);
+               return croak_openssl(mid, __func__, 
"X509_VERIFY_PARAM_set1_host");
+       }
+
        // Temporarily disable the ALPN header.
        // TODO re-enable it when test systemcertificates.py no longer relies
        // on connecting to an HTTPS server. (Which is an ugly hack in the 
first place!)
@@ -291,19 +293,35 @@ wrap_tls(Mapi mid, SOCKET sock)
                }
        }
 
-       // handshake
+       // Handshake.
        if (1 != SSL_connect(ssl)) {
                BIO_free_all(bio);
                return croak_openssl(mid, __func__, "SSL_connect handshake");
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to