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]