Hi,
currently stunnel uses the X509_STORE_get_by_subject () API call to
OpenSSL to retrieve the x509 client certificate in the cert_check ()
method (located in verify.c) to gather the client certificate from the
whitelist by the common name (CN) the client presented during the TLS
handshake. It then proceeds to compare both certificates bit by bit.
This all works rather fine until the very moment you have more than one
client certificate with the same CN. The OpenSSL API call will then
return any of the certificates with the provided CN (according to
internal logic). Other implementations using OpenSSL were aware of this
issue and introduced logic to further iterate over the remaining
certificates, retrieving any further with the same CN. See for example
function X509_STORE_CTX_get1_issuer () and its comment:
http://www.opensource.apple.com/source/OpenSSL/OpenSSL-12/openssl/crypto/x509/x509_lu.c
I patched stunnel 4.53 and adapted the patch to upstream version 5.00 to
behave in similar fashion and can report that with these changes stunnel
then also supports multiple client certificates sharing the same CN.
Feel free to adapt indention as my patches aim for minimal changed
lines.
Best regards,
Leon Winter
diff --git a/src/verify.c b/src/verify.c
index 3519144..066c4ff 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -233,22 +233,32 @@ static int cert_check(CLI *c, X509_STORE_CTX *callback_ctx, int preverify_ok) {
}
}
if(c->opt->verify_level>=3 && depth==0) {
+ int i = -1;
if(X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
- X509_get_subject_name(cert), &obj)!=1) {
+ X509_get_subject_name(cert), &obj)==1) {
+ i = X509_OBJECT_idx_by_subject(callback_ctx->ctx->objs,
+ X509_LU_X509, X509_get_subject_name(cert));
+ }
+ if(i == -1) {
s_log(LOG_WARNING,
"CERT: Certificate not found in local repository");
return 0; /* reject connection */
}
+ for (;i<sk_X509_OBJECT_num(callback_ctx->ctx->objs);i++) {
+ X509_OBJECT *pobj = sk_X509_OBJECT_value(callback_ctx->ctx->objs,i);
#if OPENSSL_VERSION_NUMBER>=0x0090700fL
peer_key=X509_get0_pubkey_bitstr(cert);
- local_key=X509_get0_pubkey_bitstr(obj.data.x509);
+ local_key=X509_get0_pubkey_bitstr(pobj->data.x509);
if(!peer_key || !local_key || peer_key->length!=local_key->length ||
memcmp(peer_key->data, local_key->data, local_key->length)) {
- s_log(LOG_WARNING, "CERT: Public keys do not match");
- return 0; /* reject connection */
+ continue;
}
-#endif
s_log(LOG_INFO, "CERT: Locally installed certificate matched");
+ return 1; /* accept connection */
+#endif
+ }
+ s_log(LOG_WARNING, "CERT: Public keys do not match");
+ return 0; /* reject connection */
}
return 1; /* accept connection */
}
diff --git a/src/verify.c b/src/verify.c
index 3519144..066c4ff 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -233,22 +233,32 @@ NOEXPORT int cert_check(X509_STORE_CTX *callback_ctx, int preverify_ok) {
}
}
if(c->opt->verify_level>=3 && depth==0) {
+ int i = -1;
if(X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
- X509_get_subject_name(cert), &obj)!=1) {
+ X509_get_subject_name(cert), &obj)==1) {
+ i = X509_OBJECT_idx_by_subject(callback_ctx->ctx->objs,
+ X509_LU_X509, X509_get_subject_name(cert));
+ }
+ if(i == -1) {
s_log(LOG_WARNING,
"CERT: Certificate not found in local repository");
return 0; /* fail */
}
+ for (;i<sk_X509_OBJECT_num(callback_ctx->ctx->objs);i++) {
+ X509_OBJECT *pobj = sk_X509_OBJECT_value(callback_ctx->ctx->objs,i);
#if OPENSSL_VERSION_NUMBER>=0x0090700fL
peer_key=X509_get0_pubkey_bitstr(cert);
- local_key=X509_get0_pubkey_bitstr(obj.data.x509);
+ local_key=X509_get0_pubkey_bitstr(pobj->data.x509);
if(!peer_key || !local_key || peer_key->length!=local_key->length ||
memcmp(peer_key->data, local_key->data, local_key->length)) {
- s_log(LOG_WARNING, "CERT: Public keys do not match");
- return 0; /* fail */
+ continue;
}
-#endif
s_log(LOG_INFO, "CERT: Locally installed certificate matched");
+ return 1; /* accept connection */
+#endif
+ }
+ s_log(LOG_WARNING, "CERT: Public keys do not match");
+ return 0; /* reject connection */
}
return 1; /* success */
}
_______________________________________________
stunnel-users mailing list
[email protected]
https://www.stunnel.org/cgi-bin/mailman/listinfo/stunnel-users