From 9942ebe7bae4365e5119f6eeef9ce0214984e594 Mon Sep 17 00:00:00 2001 From: davidepianca98 Date: Wed, 22 Mar 2023 15:00:45 +0100 Subject: [PATCH] Fix POSIX client certificate authentication --- .../kotlin/socket.tls/TLSServerContext.kt | 2 + .../kotlin/socket/tls/TLSServerContext.kt | 2 + .../kotlin/socket/tls/TLSServerContext.kt | 2 + .../linuxArm64Main/kotlin/TLSClientEngine.kt | 43 +++++++++++++----- .../linuxX64Main/kotlin/TLSClientEngine.kt | 43 +++++++++++++----- .../mingwX64Main/kotlin/TLSClientEngine.kt | 44 +++++++++++++------ 6 files changed, 99 insertions(+), 37 deletions(-) diff --git a/kmqtt-broker/src/linuxArm64Main/kotlin/socket.tls/TLSServerContext.kt b/kmqtt-broker/src/linuxArm64Main/kotlin/socket.tls/TLSServerContext.kt index 345634d..30a688d 100644 --- a/kmqtt-broker/src/linuxArm64Main/kotlin/socket.tls/TLSServerContext.kt +++ b/kmqtt-broker/src/linuxArm64Main/kotlin/socket.tls/TLSServerContext.kt @@ -17,6 +17,8 @@ actual class TLSServerContext actual constructor(private val tlsSettings: TLSSet if (tlsSettings.requireClientCertificate) { SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER or SSL_VERIFY_FAIL_IF_NO_PEER_CERT, null) + } else { + SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, null) } val pkcs12File = diff --git a/kmqtt-broker/src/linuxX64Main/kotlin/socket/tls/TLSServerContext.kt b/kmqtt-broker/src/linuxX64Main/kotlin/socket/tls/TLSServerContext.kt index 1d0169c..d11c6b4 100644 --- a/kmqtt-broker/src/linuxX64Main/kotlin/socket/tls/TLSServerContext.kt +++ b/kmqtt-broker/src/linuxX64Main/kotlin/socket/tls/TLSServerContext.kt @@ -19,6 +19,8 @@ actual class TLSServerContext actual constructor(private val tlsSettings: TLSSet if (tlsSettings.requireClientCertificate) { SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER or SSL_VERIFY_FAIL_IF_NO_PEER_CERT, null) + } else { + SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, null) } val pkcs12File = diff --git a/kmqtt-broker/src/mingwX64Main/kotlin/socket/tls/TLSServerContext.kt b/kmqtt-broker/src/mingwX64Main/kotlin/socket/tls/TLSServerContext.kt index 1d0169c..d11c6b4 100644 --- a/kmqtt-broker/src/mingwX64Main/kotlin/socket/tls/TLSServerContext.kt +++ b/kmqtt-broker/src/mingwX64Main/kotlin/socket/tls/TLSServerContext.kt @@ -19,6 +19,8 @@ actual class TLSServerContext actual constructor(private val tlsSettings: TLSSet if (tlsSettings.requireClientCertificate) { SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER or SSL_VERIFY_FAIL_IF_NO_PEER_CERT, null) + } else { + SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, null) } val pkcs12File = diff --git a/kmqtt-client/src/linuxArm64Main/kotlin/TLSClientEngine.kt b/kmqtt-client/src/linuxArm64Main/kotlin/TLSClientEngine.kt index aa49da3..feb0343 100644 --- a/kmqtt-client/src/linuxArm64Main/kotlin/TLSClientEngine.kt +++ b/kmqtt-client/src/linuxArm64Main/kotlin/TLSClientEngine.kt @@ -1,8 +1,8 @@ -import kotlinx.cinterop.ByteVar -import kotlinx.cinterop.CPointer -import kotlinx.cinterop.toKString +import kotlinx.cinterop.* import openssl.* import platform.posix.getenv +import platform.posix.strcpy +import platform.posix.strlen import socket.IOException import socket.tls.TLSEngine @@ -24,15 +24,6 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) val method = TLS_client_method() val sslContext = SSL_CTX_new(method)!! - val clientContext = SSL_new(sslContext) - if (clientContext == null) { - BIO_free(readBio) - BIO_free(writeBio) - throw IOException("Failed allocating read BIO") - } - - SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) - if (tlsSettings.serverCertificatePath != null) { if (SSL_CTX_load_verify_locations(sslContext, tlsSettings.serverCertificatePath, null) != 1) { throw Exception("Server certificate path not found") @@ -53,8 +44,36 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) if (SSL_CTX_check_private_key(sslContext) != 1) { throw Exception("Client's certificate and key don't match") } + + if (tlsSettings.clientCertificatePassword != null) { + SSL_CTX_set_default_passwd_cb_userdata(sslContext, tlsSettings.clientCertificatePassword!!.refTo(0)) + SSL_CTX_set_default_passwd_cb( + sslContext, + staticCFunction { buf: CPointer?, size: Int, _: Int, password: COpaquePointer? -> + if (password == null) { + 0 + } else { + val len = strlen(password.reinterpret().toKString()) + if (size < len.toInt() + 1) { + 0 + } else { + strcpy(buf, password.reinterpret().toKString()) + len.toInt() + } + } + }) + } + } + + val clientContext = SSL_new(sslContext) + if (clientContext == null) { + BIO_free(readBio) + BIO_free(writeBio) + throw IOException("Failed allocating read BIO") } + SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) + SSL_set_connect_state(clientContext) SSL_set_bio(clientContext, readBio, writeBio) context = clientContext diff --git a/kmqtt-client/src/linuxX64Main/kotlin/TLSClientEngine.kt b/kmqtt-client/src/linuxX64Main/kotlin/TLSClientEngine.kt index aa49da3..feb0343 100644 --- a/kmqtt-client/src/linuxX64Main/kotlin/TLSClientEngine.kt +++ b/kmqtt-client/src/linuxX64Main/kotlin/TLSClientEngine.kt @@ -1,8 +1,8 @@ -import kotlinx.cinterop.ByteVar -import kotlinx.cinterop.CPointer -import kotlinx.cinterop.toKString +import kotlinx.cinterop.* import openssl.* import platform.posix.getenv +import platform.posix.strcpy +import platform.posix.strlen import socket.IOException import socket.tls.TLSEngine @@ -24,15 +24,6 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) val method = TLS_client_method() val sslContext = SSL_CTX_new(method)!! - val clientContext = SSL_new(sslContext) - if (clientContext == null) { - BIO_free(readBio) - BIO_free(writeBio) - throw IOException("Failed allocating read BIO") - } - - SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) - if (tlsSettings.serverCertificatePath != null) { if (SSL_CTX_load_verify_locations(sslContext, tlsSettings.serverCertificatePath, null) != 1) { throw Exception("Server certificate path not found") @@ -53,8 +44,36 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) if (SSL_CTX_check_private_key(sslContext) != 1) { throw Exception("Client's certificate and key don't match") } + + if (tlsSettings.clientCertificatePassword != null) { + SSL_CTX_set_default_passwd_cb_userdata(sslContext, tlsSettings.clientCertificatePassword!!.refTo(0)) + SSL_CTX_set_default_passwd_cb( + sslContext, + staticCFunction { buf: CPointer?, size: Int, _: Int, password: COpaquePointer? -> + if (password == null) { + 0 + } else { + val len = strlen(password.reinterpret().toKString()) + if (size < len.toInt() + 1) { + 0 + } else { + strcpy(buf, password.reinterpret().toKString()) + len.toInt() + } + } + }) + } + } + + val clientContext = SSL_new(sslContext) + if (clientContext == null) { + BIO_free(readBio) + BIO_free(writeBio) + throw IOException("Failed allocating read BIO") } + SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) + SSL_set_connect_state(clientContext) SSL_set_bio(clientContext, readBio, writeBio) context = clientContext diff --git a/kmqtt-client/src/mingwX64Main/kotlin/TLSClientEngine.kt b/kmqtt-client/src/mingwX64Main/kotlin/TLSClientEngine.kt index eb13d12..feb0343 100644 --- a/kmqtt-client/src/mingwX64Main/kotlin/TLSClientEngine.kt +++ b/kmqtt-client/src/mingwX64Main/kotlin/TLSClientEngine.kt @@ -1,8 +1,8 @@ -import kotlinx.cinterop.ByteVar -import kotlinx.cinterop.CPointer -import kotlinx.cinterop.toKString +import kotlinx.cinterop.* import openssl.* import platform.posix.getenv +import platform.posix.strcpy +import platform.posix.strlen import socket.IOException import socket.tls.TLSEngine @@ -24,15 +24,6 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) val method = TLS_client_method() val sslContext = SSL_CTX_new(method)!! - val clientContext = SSL_new(sslContext) - if (clientContext == null) { - BIO_free(readBio) - BIO_free(writeBio) - throw IOException("Failed allocating read BIO") - } - - SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) - if (tlsSettings.serverCertificatePath != null) { if (SSL_CTX_load_verify_locations(sslContext, tlsSettings.serverCertificatePath, null) != 1) { throw Exception("Server certificate path not found") @@ -50,12 +41,39 @@ actual class TLSClientEngine actual constructor(tlsSettings: TLSClientSettings) if (SSL_CTX_use_PrivateKey_file(sslContext, tlsSettings.clientCertificateKeyPath!!, SSL_FILETYPE_PEM) != 1) { throw Exception("Cannot load client's key file") } - // TODO SSL_CTX_set_default_passwd_cb() if (SSL_CTX_check_private_key(sslContext) != 1) { throw Exception("Client's certificate and key don't match") } + + if (tlsSettings.clientCertificatePassword != null) { + SSL_CTX_set_default_passwd_cb_userdata(sslContext, tlsSettings.clientCertificatePassword!!.refTo(0)) + SSL_CTX_set_default_passwd_cb( + sslContext, + staticCFunction { buf: CPointer?, size: Int, _: Int, password: COpaquePointer? -> + if (password == null) { + 0 + } else { + val len = strlen(password.reinterpret().toKString()) + if (size < len.toInt() + 1) { + 0 + } else { + strcpy(buf, password.reinterpret().toKString()) + len.toInt() + } + } + }) + } + } + + val clientContext = SSL_new(sslContext) + if (clientContext == null) { + BIO_free(readBio) + BIO_free(writeBio) + throw IOException("Failed allocating read BIO") } + SSL_set_verify(clientContext, SSL_VERIFY_PEER, null) + SSL_set_connect_state(clientContext) SSL_set_bio(clientContext, readBio, writeBio) context = clientContext