From 31fe6abbe1fc70bc052ba671f7388b252fd0da62 Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Sun, 25 Jan 2026 14:54:29 +0000 Subject: [PATCH] Add TLS-Certificate.Serial-Number-And-Issuer The Serial Number and Issuer is a string format defined in RFC4523 called a CertificateExactAssertion that allows a unique instance of an X509 certificate to be identified independently of the contents of the certificate. This interoperates with the SSL_CLIENT_CERT_RFC4523_CEA variable in Apache httpd's mod_ssl. --- src/lib/tls/attrs.h | 1 + src/lib/tls/base.c | 2 ++ src/lib/tls/pairs.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/lib/tls/attrs.h b/src/lib/tls/attrs.h index c9fd1cf3f2a0..32af87ccc14c 100644 --- a/src/lib/tls/attrs.h +++ b/src/lib/tls/attrs.h @@ -39,6 +39,7 @@ extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_serial; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_signature; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_signature_algorithm; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_issuer; +extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_serial_number_and_issuer; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_not_before; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_not_after; extern HIDDEN fr_dict_attr_t const *attr_tls_certificate_subject; diff --git a/src/lib/tls/base.c b/src/lib/tls/base.c index cb5a425ae413..ebf2d309849f 100644 --- a/src/lib/tls/base.c +++ b/src/lib/tls/base.c @@ -99,6 +99,7 @@ fr_dict_attr_t const *attr_tls_certificate_serial; fr_dict_attr_t const *attr_tls_certificate_signature; fr_dict_attr_t const *attr_tls_certificate_signature_algorithm; fr_dict_attr_t const *attr_tls_certificate_issuer; +fr_dict_attr_t const *attr_tls_certificate_serial_number_and_issuer; fr_dict_attr_t const *attr_tls_certificate_not_before; fr_dict_attr_t const *attr_tls_certificate_not_after; fr_dict_attr_t const *attr_tls_certificate_subject; @@ -156,6 +157,7 @@ fr_dict_attr_autoload_t tls_dict_attr[] = { { .out = &attr_tls_certificate_signature, .name = "TLS-Certificate.Signature", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius }, { .out = &attr_tls_certificate_signature_algorithm, .name = "TLS-Certificate.Signature-Algorithm", .type = FR_TYPE_STRING, .dict = &dict_freeradius }, { .out = &attr_tls_certificate_issuer, .name = "TLS-Certificate.Issuer", .type = FR_TYPE_STRING, .dict = &dict_freeradius }, + { .out = &attr_tls_certificate_serial_number_and_issuer, .name = "TLS-Certificate.Serial-Number-And-Issuer", .type = FR_TYPE_STRING, .dict = &dict_freeradius }, { .out = &attr_tls_certificate_not_before, .name = "TLS-Certificate.Not-Before", .type = FR_TYPE_DATE, .dict = &dict_freeradius }, { .out = &attr_tls_certificate_not_after, .name = "TLS-Certificate.Not-After", .type = FR_TYPE_DATE, .dict = &dict_freeradius }, { .out = &attr_tls_certificate_subject, .name = "TLS-Certificate.Subject", .type = FR_TYPE_STRING, .dict = &dict_freeradius }, diff --git a/src/lib/tls/pairs.c b/src/lib/tls/pairs.c index 890af502b250..d18d733ad6d5 100644 --- a/src/lib/tls/pairs.c +++ b/src/lib/tls/pairs.c @@ -172,6 +172,8 @@ int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *c int loc; char buff[1024]; + ASN1_INTEGER const *serial = NULL; + ASN1_TIME const *asn_time; time_t time; @@ -287,7 +289,6 @@ int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *c * Serial number */ { - ASN1_INTEGER const *serial = NULL; unsigned char *der; int len; @@ -303,6 +304,46 @@ int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *c i2d_ASN1_INTEGER(serial, &der); } + /* + * Serial Number and Issuer + */ + { + BIO *bio; + char *decimal; + BIGNUM *bn; + + bio = fr_tls_bio_dbuff_thread_local(vp, 256, 0); + + BIO_puts("{ serialNumber "); + + if (unlikely(!(bn = ASN1_INTEGER_to_BN(serial, NULL)))) { + fr_tls_bio_dbuff_thread_local_clear(); + fr_tls_log(request, "Failed converting certificate serial to big number"); + } + if (unlikely(!(decimal = BN_bn2dec(bn)))) { + BN_free(bn); + fr_tls_bio_dbuff_thread_local_clear(); + fr_tls_log(request, "Failed converting certificate serial to decimal"); + goto error; + } + BN_free(bn); + BIO_puts(decimal); + OPENSSL_free(decimal); + + BIO_puts(", issuer rdnSequence:\""); + + if (unlikely(X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, XN_FLAG_RFC2253) < 0)) { + fr_tls_bio_dbuff_thread_local_clear(); + fr_tls_log(request, "Failed retrieving certificate issuer"); + goto error; + } + + BIO_puts("\" }"); + + MEM(fr_pair_append_by_da(ctx, &vp, pair_list, attr_tls_certificate_serial_number_and_issuer) == 0); + fr_pair_value_bstrdup_buffer_shallow(vp, fr_tls_bio_dbuff_thread_local_finalise_bstr(), true); + } + /* * Not valid before */