version.c \
virtual_server.c
-TGT_PREREQS := libfreeradius-internal$(L) libfreeradius-util$(L)
+TGT_PREREQS := libfreeradius-internal$(L) libfreeradius-util$(L) libfreeradius-der$(L)
# This lets the linker determine which version of the SSLeay functions to use.
TGT_LDLIBS := $(LIBS) $(OPENSSL_LIBS) $(GPERFTOOLS_LIBS)
extern HIDDEN fr_dict_t const *dict_freeradius;
extern HIDDEN fr_dict_t const *dict_radius;
extern HIDDEN fr_dict_t const *dict_tls;
+extern HIDDEN fr_dict_t const *dict_der;
extern HIDDEN fr_dict_attr_t const *attr_allow_session_resumption;
extern HIDDEN fr_dict_attr_t const *attr_session_resumed;
extern HIDDEN fr_dict_attr_t const *attr_tls_session_resumed;
extern HIDDEN fr_dict_attr_t const *attr_tls_session_ttl;
+extern HIDDEN fr_dict_attr_t const *attr_der_certificate;
+
extern fr_value_box_t const *enum_tls_session_resumed_stateful;
extern fr_value_box_t const *enum_tls_session_resumed_stateless;
fr_dict_t const *dict_freeradius;
fr_dict_t const *dict_radius;
fr_dict_t const *dict_tls;
+fr_dict_t const *dict_der;
extern fr_dict_autoload_t tls_dict[];
fr_dict_autoload_t tls_dict[] = {
{ .out = &dict_freeradius, .proto = "freeradius" },
{ .out = &dict_tls, .proto = "tls" },
+ { .out = &dict_der, .proto = "der" },
{ NULL }
};
fr_dict_attr_t const *attr_tls_session_resumed;
fr_dict_attr_t const *attr_tls_session_ttl;
+fr_dict_attr_t const *attr_der_certificate;
+
extern fr_dict_attr_autoload_t tls_dict_attr[];
fr_dict_attr_autoload_t tls_dict_attr[] = {
{ .out = &attr_allow_session_resumption, .name = "Allow-Session-Resumption", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
{ .out = &attr_tls_session_id, .name = "Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_tls },
{ .out = &attr_tls_session_resumed, .name = "Session-Resumed", .type = FR_TYPE_BOOL, .dict = &dict_tls },
{ .out = &attr_tls_session_ttl, .name = "Session-TTL", .type = FR_TYPE_TIME_DELTA, .dict = &dict_tls },
+
+ { .out = &attr_der_certificate, .name = "Certificate", .type = FR_TYPE_TLV, .dict = &dict_der },
+
{ NULL }
};
bool check_crl; //!< Check certificate revocation lists.
bool allow_expired_crl; //!< Don't error out if CRL is expired.
bool allow_not_yet_valid_crl; //!< Don't error out if CRL is not-yet-valid.
+
+ bool der_decode; //!< Should certificates be passed to the DER decoder.
} fr_tls_verify_conf_t;
/* configured values goes right here */
{ FR_CONF_OFFSET("check_crl", fr_tls_verify_conf_t, check_crl), .dflt = "no" },
{ FR_CONF_OFFSET("allow_expired_crl", fr_tls_verify_conf_t, allow_expired_crl) },
{ FR_CONF_OFFSET("allow_not_yet_valid_crl", fr_tls_verify_conf_t, allow_not_yet_valid_crl) },
+ { FR_CONF_OFFSET("der_decode", fr_tls_verify_conf_t, der_decode) },
CONF_PARSER_TERMINATOR
};
#include <freeradius-devel/util/pair.h>
#include <freeradius-devel/server/request.h>
#include <freeradius-devel/server/pair.h>
+#include <freeradius-devel/der/der.h>
#include "attrs.h"
#include "bio.h"
* @param[in] ctx to allocate attributes in.
* @param[in] request the current request.
* @param[in] cert to validate.
+ * @param[in] der_decode should the certificate be parsed with the DER decoder.
* @return
* - 1 already exists.
* - 0 on success.
* - < 0 on failure.
*/
-int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, request_t *request, X509 *cert)
+int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, request_t *request, X509 *cert,
+#if OPENSSL_VERSION_NUMBER >= 0x30400000L
+ bool der_decode
+#else
+ UNUSED bool der_decode
+#endif
+ )
{
int loc;
char buff[1024];
ssize_t slen;
bool san_found = false, crl_found = false;
+ /*
+ * We require OpenSSL >= 3.4 to call the DER decoder due to the stack size
+ * needed to handle the recursive calls involved in certificate decoding.
+ */
+#if OPENSSL_VERSION_NUMBER >= 0x30400000L
+ if (der_decode) {
+ uint8_t *cert_der;
+ uint8_t *cd;
+ int der_len;
+ fr_der_decode_ctx_t der_ctx;
+
+ der_len = i2d_X509(cert, NULL);
+ if (der_len < 0) {
+ fr_tls_log(request, "Failed retrieving certificate");
+ return -1;
+ }
+ der_ctx.tmp_ctx = talloc_new(ctx);
+ cert_der = cd = talloc_array(der_ctx.tmp_ctx, uint8_t, der_len);
+ i2d_X509(cert, &cd);
+ slen = fr_der_decode_pair_dbuff(request->session_state_ctx, &request->session_state_pairs,
+ attr_der_certificate, &FR_DBUFF_TMP(cert_der, (size_t)der_len), &der_ctx);
+ talloc_free(der_ctx.tmp_ctx);
+ if (slen < 0) {
+ fr_tls_log(request, "Failed decoding certificate");
+ return -1;
+ }
+ }
+#endif
+
/*
* Subject
*/
void fr_tls_session_keylog_cb(const SSL *ssl, const char *line);
int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *ctx,
- request_t *request, X509 *cert) CC_HINT(nonnull);
+ request_t *request, X509 *cert, bool der_decode) CC_HINT(nonnull);
int fr_tls_session_recv(request_t *request, fr_tls_session_t *tls_session);
* and cause validation to fail.
*/
if (fr_tls_session_pairs_from_x509_cert(&container->vp_group, container,
- request, cert) < 0) {
+ request, cert, conf->verify.der_decode) < 0) {
fr_pair_delete_by_da(&request->session_state_pairs, attr_tls_certificate);
my_ok = 0;
goto done;