Skip to content

Commit

Permalink
Fix POSIX client certificate authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
davidepianca98 committed Mar 22, 2023
1 parent 7516068 commit 9942ebe
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
43 changes: 31 additions & 12 deletions kmqtt-client/src/linuxArm64Main/kotlin/TLSClientEngine.kt
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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")
Expand All @@ -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<ByteVar>?, size: Int, _: Int, password: COpaquePointer? ->
if (password == null) {
0
} else {
val len = strlen(password.reinterpret<ByteVar>().toKString())
if (size < len.toInt() + 1) {
0
} else {
strcpy(buf, password.reinterpret<ByteVar>().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
Expand Down
43 changes: 31 additions & 12 deletions kmqtt-client/src/linuxX64Main/kotlin/TLSClientEngine.kt
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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")
Expand All @@ -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<ByteVar>?, size: Int, _: Int, password: COpaquePointer? ->
if (password == null) {
0
} else {
val len = strlen(password.reinterpret<ByteVar>().toKString())
if (size < len.toInt() + 1) {
0
} else {
strcpy(buf, password.reinterpret<ByteVar>().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
Expand Down
44 changes: 31 additions & 13 deletions kmqtt-client/src/mingwX64Main/kotlin/TLSClientEngine.kt
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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")
Expand All @@ -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<ByteVar>?, size: Int, _: Int, password: COpaquePointer? ->
if (password == null) {
0
} else {
val len = strlen(password.reinterpret<ByteVar>().toKString())
if (size < len.toInt() + 1) {
0
} else {
strcpy(buf, password.reinterpret<ByteVar>().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
Expand Down

0 comments on commit 9942ebe

Please sign in to comment.