25 RCSID(
"$Id: f2f18ca923f13dc05ce9547fa230fbcc75a60578 $")
29 #define LOG_PREFIX "tls"
31 #include <freeradius-devel/tls/openssl_user_macros.h>
32 #include <freeradius-devel/util/pair.h>
33 #include <freeradius-devel/server/request.h>
34 #include <freeradius-devel/server/pair.h>
43 #include <openssl/x509v3.h>
44 #include <openssl/ssl.h>
64 ASN1_TIME
const *asn_time;
67 STACK_OF(X509_EXTENSION)
const *ext_list = NULL;
76 if (
unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(
vp, 256, 0),
77 X509_get_subject_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
78 fr_tls_bio_dbuff_thread_local_clear();
79 fr_tls_log(request,
"Failed retrieving certificate subject");
91 slen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
92 NID_commonName, NULL, 0);
99 slen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, cn, (
size_t)slen + 1);
101 fr_tls_log(request,
"Failed retrieving certificate common name");
110 ASN1_BIT_STRING
const *sig;
111 X509_ALGOR
const *alg;
113 X509_get0_signature(&sig, &alg, cert);
117 (
uint8_t const *)ASN1_STRING_get0_data(sig),
118 ASN1_STRING_length(sig),
true) == 0);
120 OBJ_obj2txt(
buff,
sizeof(
buff), alg->algorithm, 0);
129 if (
unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(
vp, 256, 0),
130 X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
131 fr_tls_bio_dbuff_thread_local_clear();
132 fr_tls_log(request,
"Failed retrieving certificate issuer");
141 ASN1_INTEGER
const *serial = NULL;
143 serial = X509_get0_serialNumber(cert);
145 fr_tls_log(request,
"Failed retrieving certificate serial");
156 asn_time = X509_get0_notBefore(cert);
159 RPWDEBUG(
"Failed parsing certificate not-before");
169 asn_time = X509_get0_notAfter(cert);
172 RPWDEBUG(
"Failed parsing certificate not-after");
182 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, 0);
184 X509_EXTENSION *ext = NULL;
185 GENERAL_NAMES *
names = NULL;
188 ext = X509_get_ext(cert, loc);
189 if (!ext || !(
names = X509V3_EXT_d2i(ext)))
goto skip_alt;
192 for (i = 0; i < sk_GENERAL_NAME_num(
names); i++) {
193 GENERAL_NAME *
name = sk_GENERAL_NAME_value(
names, i);
195 switch (
name->type) {
201 (
char const *)ASN1_STRING_get0_data(
name->d.rfc822Name),
202 ASN1_STRING_length(
name->d.rfc822Name),
true) == 0);
210 (
char const *)ASN1_STRING_get0_data(
name->d.dNSName),
211 ASN1_STRING_length(
name->d.dNSName),
true) == 0);
217 if (NID_ms_upn != OBJ_obj2nid(
name->d.otherName->type_id))
break;
220 if (
name->d.otherName->value->type == V_ASN1_UTF8STRING) {
224 (
char const *)ASN1_STRING_get0_data(
name->d.otherName->value->value.utf8string),
225 ASN1_STRING_length(
name->d.otherName->value->value.utf8string),
229 RWARN(
"Invalid UPN in Subject Alt Name (should be UTF-8)");
244 ext_list = X509_get0_extensions(cert);
246 RWDEBUG(
"Failed retrieving extensions");
254 if (sk_X509_EXTENSION_num(ext_list) > 0) {
257 fr_tls_bio_dbuff_t *bd;
260 bio = fr_tls_bio_dbuff_alloc(&bd, NULL, NULL, 257, 4097,
true);
261 in = fr_tls_bio_dbuff_in(bd);
262 out = fr_tls_bio_dbuff_out(bd);
264 for (i = 0; i < sk_X509_EXTENSION_num(ext_list); i++) {
270 ext = sk_X509_EXTENSION_value(ext_list, i);
272 obj = X509_EXTENSION_get_object(ext);
273 if (i2a_ASN1_OBJECT(bio, obj) <= 0) {
274 RPWDEBUG(
"Skipping X509 Extension (%i) conversion to attribute. "
275 "Conversion from ASN1 failed...", i);
277 fr_tls_bio_dbuff_reset(bd);
295 RWDEBUG(
"Attribute name too long");
304 RWDEBUG3(
"Skipping attribute \"%pV\": "
305 "Add a dictionary definition if you want to access it",
312 fr_tls_bio_dbuff_reset(bd);
314 X509V3_EXT_print(bio, ext, 0, 0);
325 fr_tls_bio_dbuff_reset(bd);
#define USES_APPLE_DEPRECATED_API
#define DIAG_UNKNOWN_PRAGMAS
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
#define fr_dbuff_end(_dbuff_or_marker)
Return the current 'end' position of a dbuff or marker.
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
bool const fr_dict_attr_allowed_chars[UINT8_MAX+1]
Characters that are allowed in dictionary attribute names.
HIDDEN fr_dict_attr_t const * attr_tls_certificate
Attribute definitions for lib curl.
#define RPWDEBUG3(fmt,...)
#define RPWDEBUG(fmt,...)
#define RWDEBUG3(fmt,...)
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject
HIDDEN fr_dict_attr_t const * attr_tls_certificate_serial
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_dns
HIDDEN fr_dict_attr_t const * attr_tls_certificate_not_after
HIDDEN fr_dict_attr_t const * attr_tls_certificate_not_before
HIDDEN fr_dict_attr_t const * attr_tls_certificate_signature_algorithm
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_upn
HIDDEN fr_dict_attr_t const * attr_tls_certificate_common_name
HIDDEN fr_dict_attr_t const * attr_tls_certificate_issuer
HIDDEN fr_dict_attr_t const * attr_tls_certificate_signature
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_email
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
int fr_pair_value_bstrdup_buffer_shallow(fr_pair_t *vp, char const *src, bool tainted)
Assign a string to a "string" type value pair.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
int fr_pair_value_bstr_alloc(fr_pair_t *vp, char **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "string" type value pair.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
static char buff[sizeof("18446744073709551615")+3]
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
Stores an attribute, a value and various bits of other data.
static const char * names[8]
static fr_unix_time_t fr_unix_time_from_time(time_t time)
Convert a time_t into out internal fr_unix_time_t.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
int fr_tls_utils_asn1time_to_epoch(time_t *out, ASN1_TIME const *asn1)
Convert OpenSSL's ASN1_TIME to an epoch time.
return fr_dbuff_set(dbuff, &our_dbuff)
#define fr_box_strvalue_buffer(_val)
#define fr_box_strvalue_len(_val, _len)
static size_t char ** out