The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
pairs.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 2ea970c1d43ec8944e213f31d653d3fc676a1306 $
19 *
20 * @file tls/pairs.c
21 * @brief Functions to convert certificate OIDs to attribute pairs
22 *
23 * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 */
25RCSID("$Id: 2ea970c1d43ec8944e213f31d653d3fc676a1306 $")
26USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
27
28#ifdef WITH_TLS
29#define LOG_PREFIX "tls"
30
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>
35#include <freeradius-devel/der/der.h>
36
37#include "attrs.h"
38#include "bio.h"
39#include "log.h"
40#include "session.h"
41#include "utils.h"
42
43#include <openssl/x509v3.h>
44#include <openssl/ssl.h>
45#include <openssl/ocsp.h>
46
47DIAG_OFF_OPTIONAL(used-but-marked-unused) /* fix spurious warnings for sk macros */
48/** Extract session pairs from the Subject Alternate Name extension
49 *
50 */
51static bool tls_session_pairs_from_san(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, request_t *request,
52 FR_OPENSSL_X509_CONST X509_EXTENSION *ext)
53{
54 GENERAL_NAMES *names = NULL;
55 int i;
57
58 if (!(names = X509V3_EXT_d2i(ext))) return false;
59
60 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
61 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
62
63 switch (name->type) {
64#ifdef GEN_EMAIL
65 case GEN_EMAIL:
69 (char const *)ASN1_STRING_get0_data(name->d.rfc822Name),
70 fr_tls_asn1_string_length(name->d.rfc822Name), true) == 0);
71 break;
72#endif /* GEN_EMAIL */
73#ifdef GEN_DNS
74 case GEN_DNS:
78 (char const *)ASN1_STRING_get0_data(name->d.dNSName),
79 fr_tls_asn1_string_length(name->d.dNSName), true) == 0);
80 break;
81#endif /* GEN_DNS */
82#ifdef GEN_OTHERNAME
83 case GEN_OTHERNAME:
84 /* look for a MS UPN */
85 if (NID_ms_upn != OBJ_obj2nid(name->d.otherName->type_id)) break;
86
87 /* we've got a UPN - Must be ASN1-encoded UTF8 string */
88 if (name->d.otherName->value->type == V_ASN1_UTF8STRING) {
92 (char const *)ASN1_STRING_get0_data(name->d.otherName->value->value.utf8string),
93 fr_tls_asn1_string_length(name->d.otherName->value->value.utf8string),
94 true) == 0);
95 break;
96 }
97 RWARN("Invalid UPN in Subject Alt Name (should be UTF-8)");
98 break;
99#endif /* GEN_OTHERNAME */
100 default:
101 /* XXX TODO handle other SAN types */
102 break;
103 }
104 }
105 if (names != NULL) GENERAL_NAMES_free(names);
106
107 return true;
108}
109
110/** Extract session pairs from the X509v3-CRL-Distribution-Points extension
111 *
112 */
113static bool tls_session_pairs_from_crl(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, UNUSED request_t *request,
114 FR_OPENSSL_X509_CONST X509_EXTENSION *ext)
115{
116 ASN1_STRING const *s = X509_EXTENSION_get_data(ext);
117 char unsigned const *data = ASN1_STRING_get0_data(s);
118 STACK_OF(DIST_POINT) *dps;
119 DIST_POINT *dp;
120 STACK_OF(GENERAL_NAME) *names;
121 GENERAL_NAME *name;
122 fr_pair_t *vp;
123 int i, j;
124
125 if (!(dps = d2i_CRL_DIST_POINTS(NULL, &data, fr_tls_asn1_string_length(s)))) return false;
126
127 for (i = 0; i < sk_DIST_POINT_num(dps); i++) {
128 dp = sk_DIST_POINT_value(dps, i);
129
130 /*
131 * RFC 5280 Section 4.2.1.13 says that the distpoint is optional.
132 */
133 if (!dp->distpoint) {
134 CRL_DIST_POINTS_free(dps);
135 return false;
136 }
137
138 names = dp->distpoint->name.fullname;
139
140 /*
141 * We only want CRL distribution points that cover all reasons,
142 * so ignore any where reasons are set.
143 */
144 if (dp->reasons) continue;
145
146 for (j = 0; j < sk_GENERAL_NAME_num(names); j++) {
147 name = sk_GENERAL_NAME_value(names, j);
148
149 if (name->type != GEN_URI) continue;
153 (char const *)ASN1_STRING_get0_data(name->d.uniformResourceIdentifier),
154 fr_tls_asn1_string_length(name->d.uniformResourceIdentifier),
155 true) == 0);
156 }
157 }
158
159 CRL_DIST_POINTS_free(dps);
160
161 return true;
162}
163
164/** Extract session pairs from the Authority Key Identifier extension - specifically OCSP URI
165 *
166 */
167static bool tls_session_pairs_from_aia(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, UNUSED request_t *request,
168 FR_OPENSSL_X509_CONST X509_EXTENSION *ext)
169{
170 ASN1_STRING const *s = X509_EXTENSION_get_data(ext);
171 char unsigned const *data = ASN1_STRING_get0_data(s);
172 fr_pair_t *vp;
173 AUTHORITY_INFO_ACCESS *aia;
174 ACCESS_DESCRIPTION *ad;
175 char *host = NULL, *path = NULL;
176 int i, port, is_https;
177
178 if (!(aia = d2i_AUTHORITY_INFO_ACCESS(NULL, &data, fr_tls_asn1_string_length(s)))) return false;
179
180 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) {
181 char *uri;
182 size_t len;
183
184 ad = sk_ACCESS_DESCRIPTION_value(aia, i);
185 if (OBJ_obj2nid(ad->method) != NID_ad_OCSP) continue;
186 if (ad->location->type != GEN_URI) continue;
187
188 len = fr_tls_asn1_string_length(ad->location->d.uniformResourceIdentifier);
189 MEM(uri = talloc_bstrndup(NULL,
190 (char const *)ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier),
191 len));
192
193 /*
194 * Use OpenSSL URL parsing to check that the URL is valid. It only takes a
195 * C string, so it needs the terminated copy.
196 */
197 if (OSSL_HTTP_parse_url(uri, &is_https, NULL, &host, NULL, &port, &path, NULL, NULL)) {
198 OPENSSL_free(host);
199 OPENSSL_free(path);
202 MEM(fr_pair_value_bstrndup(vp, uri, len, true) == 0);
203 }
204 talloc_free(uri);
205 }
206 AUTHORITY_INFO_ACCESS_free(aia);
207
208 return true;
209}
210
211/** Extract attributes from an X509 certificate
212 *
213 * @param[out] pair_list to copy attributes to.
214 * @param[in] ctx to allocate attributes in.
215 * @param[in] request the current request.
216 * @param[in] cert to validate.
217 * @param[in] issuer of the certificate.
218 * @param[in] der_decode should the certificate be parsed with the DER decoder.
219 * @return
220 * - 1 already exists.
221 * - 0 on success.
222 * - < 0 on failure.
223 */
224int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, request_t *request, X509 *cert,
225 X509 *issuer,
226#if OPENSSL_VERSION_NUMBER >= 0x30400000L
227 bool der_decode
228#else
229 UNUSED bool der_decode
230#endif
231 )
232{
233 int loc;
234 char buff[1024];
235
236 ASN1_TIME const *asn_time;
237 time_t time;
238
239 STACK_OF(X509_EXTENSION) const *ext_list = NULL;
240
241 fr_pair_t *vp = NULL;
242 bool san_found = false, crl_found = false, aia_found = false;
243
244 /*
245 * We require OpenSSL >= 3.4 to call the DER decoder due to the stack size
246 * needed to handle the recursive calls involved in certificate decoding.
247 */
248#if OPENSSL_VERSION_NUMBER >= 0x30400000L
249 if (der_decode) {
250 uint8_t *cert_der;
251 uint8_t *cd;
252 int der_len;
253 fr_der_decode_ctx_t der_ctx;
254 fr_pair_list_t tmp_list;
255 ssize_t slen;
256
257 der_len = i2d_X509(cert, NULL);
258 if (der_len < 0) {
259 fr_tls_log_perror(request, "Failed retrieving certificate");
260 return -1;
261 }
262 der_ctx = (fr_der_decode_ctx_t) {
263 .tmp_ctx = talloc_new(ctx),
264 .root = attr_der_certificate,
265 };
266 cert_der = cd = talloc_array(der_ctx.tmp_ctx, uint8_t, der_len);
267 i2d_X509(cert, &cd);
268 fr_pair_list_init(&tmp_list);
269 slen = fr_der_decode_pair_dbuff(request->session_state_ctx, &tmp_list,
270 attr_der_certificate, &FR_DBUFF_TMP(cert_der, (size_t)der_len), &der_ctx);
271 talloc_free(der_ctx.tmp_ctx);
272 if (slen < 0) {
273 fr_tls_log_perror(request, "Failed decoding certificate");
274 fr_pair_list_free(&tmp_list);
275 return -1;
276 }
277 /*
278 * Certificates are decoded in CA .. intermediate .. client sequence
279 * so, prepend each decoded one to get the client cert first.
280 */
281 fr_pair_list_prepend(&request->session_state_pairs, &tmp_list);
282 }
283#endif
284
285 /*
286 * Subject
287 */
289 if (unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(vp, 256, 0),
290 X509_get_subject_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
291 fr_tls_bio_dbuff_thread_local_clear();
292 fr_tls_log_perror(request, "Failed retrieving certificate subject");
293 error:
295 return -1;
296 }
297 fr_pair_value_bstrdup_buffer_shallow(vp, fr_tls_bio_dbuff_thread_local_finalise_bstr(), true);
298
299 RDEBUG3("(TLS) Creating attributes for \"%pV\":", fr_box_strvalue_buffer(vp->vp_strvalue));
300
301 /*
302 * Common name
303 */
304 loc = X509_NAME_get_index_by_NID(X509_get_subject_name(cert), NID_commonName, -1);
305 if (loc >= 0) {
306 ASN1_STRING const *cn;
307
308 cn = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(X509_get_subject_name(cert), loc));
309 if (cn && (fr_tls_asn1_string_length(cn) > 0)) {
311 MEM(fr_pair_value_bstrndup(vp, (char const *)ASN1_STRING_get0_data(cn),
312 fr_tls_asn1_string_length(cn), true) == 0);
313 }
314 }
315
316 /*
317 * Signature
318 */
319 {
320 ASN1_BIT_STRING const *sig;
321 X509_ALGOR const *alg;
322
323 X509_get0_signature(&sig, &alg, cert);
324
327 (uint8_t const *)ASN1_STRING_get0_data(sig),
328 fr_tls_asn1_string_length(sig), true) == 0);
329
330 OBJ_obj2txt(buff, sizeof(buff), alg->algorithm, 0);
333 }
334
335 /*
336 * Issuer
337 */
339 if (unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(vp, 256, 0),
340 X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
341 fr_tls_bio_dbuff_thread_local_clear();
342 fr_tls_log_perror(request, "Failed retrieving certificate issuer");
343 goto error;
344 }
345 fr_pair_value_bstrdup_buffer_shallow(vp, fr_tls_bio_dbuff_thread_local_finalise_bstr(), true);
346
347 /*
348 * Serial number
349 */
350 {
351 ASN1_INTEGER const *serial = NULL;
352 unsigned char *der;
353 int len;
354
355 serial = X509_get0_serialNumber(cert);
356 if (!serial) {
357 fr_tls_log_perror(request, "Failed retrieving certificate serial");
358 goto error;
359 }
360
361 len = i2d_ASN1_INTEGER(serial, NULL); /* get length */
363 MEM(fr_pair_value_mem_alloc(vp, &der, len, false) == 0);
364 i2d_ASN1_INTEGER(serial, &der);
365 }
366
367 /*
368 * Not valid before
369 */
370 asn_time = X509_get0_notBefore(cert);
371
372 if (fr_tls_utils_asn1time_to_epoch(&time, asn_time) < 0) {
373 RPWDEBUG("(TLS) Failed parsing certificate not-before");
374 goto error;
375 }
376
378 vp->vp_date = fr_unix_time_from_time(time);
379
380 /*
381 * Not valid after
382 */
383 asn_time = X509_get0_notAfter(cert);
384
385 if (fr_tls_utils_asn1time_to_epoch(&time, asn_time) < 0) {
386 RPWDEBUG("(TLS) Failed parsing certificate not-after");
387 goto error;
388 }
389
391 vp->vp_date = fr_unix_time_from_time(time);
392
393 /*
394 * Get the RFC822 Subject Alternative Name
395 */
396 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, 0);
397 if (loc >= 0) {
398 FR_OPENSSL_X509_CONST X509_EXTENSION *ext = X509_get_ext(cert, loc);
399 if (ext) san_found = tls_session_pairs_from_san(pair_list, ctx, request, ext);
400 }
401
402 loc = X509_get_ext_by_NID(cert, NID_crl_distribution_points, 0);
403 if (loc >= 0) {
404 FR_OPENSSL_X509_CONST X509_EXTENSION *ext = X509_get_ext(cert, loc);
405 if (ext) crl_found = tls_session_pairs_from_crl(pair_list, ctx, request, ext);
406 }
407
408 if (issuer) {
409 OCSP_CERTID *certid;
410 int len;
411 uint8_t *ocsp_certid = NULL;
412
413 certid = OCSP_cert_to_id(NULL, cert, issuer);
414 if (unlikely(!certid)) goto error;
415 len = i2d_OCSP_CERTID(certid, &ocsp_certid);
416 if (len < 0) goto error;
417 if (ocsp_certid != NULL) {
419 fr_value_box_memdup(vp, &vp->data, NULL, ocsp_certid, len, false);
420 OPENSSL_free(ocsp_certid);
421 }
422 OCSP_CERTID_free(certid);
423 }
424
425 /*
426 * Only add extensions for the actual client certificate
427 */
428 ext_list = X509_get0_extensions(cert);
429 if (unlikely(!ext_list)) {
430 RWDEBUG("(TLS) Failed retrieving extensions");
431 goto done;
432 }
433
434 /*
435 * Grab the X509 extensions, and create attributes out of them.
436 * For laziness, we reuse the OpenSSL names
437 */
438 if (sk_X509_EXTENSION_num(ext_list) > 0) {
439 int i;
440 BIO *bio;
441 fr_tls_bio_dbuff_t *bd;
442 fr_dbuff_t *in, *out;
443
444 bio = fr_tls_bio_dbuff_alloc(&bd, NULL, NULL, 257, 4097, true);
445 in = fr_tls_bio_dbuff_in(bd);
446 out = fr_tls_bio_dbuff_out(bd);
447
448 for (i = 0; i < sk_X509_EXTENSION_num(ext_list); i++) {
449 ASN1_OBJECT const *obj;
450 X509_EXTENSION *ext;
451 fr_dict_attr_t const *da;
452 char *p;
453
454 ext = sk_X509_EXTENSION_value(ext_list, i);
455
456 obj = X509_EXTENSION_get_object(ext);
457
458 /*
459 * If this is extension is Subject Alternate Name have we already
460 * handled it? If not, do that now.
461 *
462 * Some certificate encodings have been observed where the SAN extension
463 * was not found by X509_get_ext_by_NID() but then seen when the list
464 * of extensions is handled here.
465 */
466 if (OBJ_obj2nid(obj) == NID_subject_alt_name) {
467 if (!san_found) san_found = tls_session_pairs_from_san(pair_list, ctx, request, ext);
468 goto again;
469 }
470
471 if (OBJ_obj2nid(obj) == NID_crl_distribution_points) {
472 if (!crl_found) crl_found = tls_session_pairs_from_crl(pair_list, ctx, request, ext);
473 goto again;
474 }
475
476 if (OBJ_obj2nid(obj) == NID_info_access) {
477 if (!aia_found) aia_found = tls_session_pairs_from_aia(pair_list, ctx, request, ext);
478 goto again;
479 }
480
481 if (i2a_ASN1_OBJECT(bio, obj) <= 0) {
482 RPWDEBUG("(TLS) Skipping X509 Extension (%i) conversion to attribute. "
483 "Conversion from ASN1 failed...", i);
484 again:
485 fr_tls_bio_dbuff_reset(bd);
486 continue;
487 }
488
489 if (fr_dbuff_remaining(out) == 0) goto again; /* Nothing written ? */
490
491 /*
492 * All disallowed chars get mashed to '-'
493 */
494 for (p = (char *)fr_dbuff_current(out);
495 p < (char *)fr_dbuff_end(out);
496 p++) if (!fr_dict_attr_allowed_chars[(uint8_t)*p]) *p = '-';
497
498 /*
499 * Terminate the buffer (after char replacement,
500 * so we do don't replace the \0)
501 */
502 if (unlikely(fr_dbuff_in_bytes(in, (uint8_t)'\0') <= 0)) {
503 RWDEBUG("(TLS) Attribute name too long");
504 goto again;
505 }
506
508
509 fr_dbuff_set(in, fr_dbuff_current(in) - 1); /* Ensure the \0 isn't counted in remaining */
510
511 if (!da) {
512 RWDEBUG3("(TLS) Skipping attribute \"%pV\": "
513 "Add a dictionary definition if you want to access it",
516 fr_strerror_clear(); /* Don't leave spurious errors from failed resolution */
517 goto again;
518 }
519
520 fr_tls_bio_dbuff_reset(bd); /* 'free' any data used */
521
522 if (X509V3_EXT_print(bio, ext, X509V3_EXT_PARSE_UNKNOWN, 0) != 1) {
523 REDEBUG("(TLS) Failed extracting data for \"%s\"", da->name);
524 goto again;
525 }
526
527 MEM(vp = fr_pair_afrom_da(ctx, da));
529 NULL, true) < 0) {
530 RPWDEBUG3("Skipping: %s += \"%pV\"",
531 da->name, fr_box_strvalue_len((char *)fr_dbuff_current(out),
534 goto again;
535 }
536 fr_tls_bio_dbuff_reset(bd); /* 'free' any data used */
537
539 }
540 talloc_free(bd);
541 }
542
543done:
544 return 0;
545}
546
547/** Extract values from ClientHello extensions into pairs
548 *
549 * @param request being processed.
550 * @param container List to put pairs in.
551 * @param extension data to parse.
552 * @param hlen Length of "length" header in extension.
553 * @param dlen Length of each data entry in extension.
554 * @param total_len of extension.
555 * @param da Attribute to create using extension values.
556 * @return
557 * - 0 on success
558 * - -1 on failure
559 */
560static int fr_tls_extension_decode(request_t *request, fr_pair_t *container, uint8_t const *extension,
561 size_t hlen, size_t dlen, size_t total_len, fr_dict_attr_t const *da)
562{
563 size_t i,extension_len;
564 uint8_t const *data;
565
566 fr_assert((hlen == 1) || (hlen == 2));
567 fr_assert((dlen == 1) || (dlen == 2));
568
569 if (total_len < hlen) {
570 REDEBUG("(TLS) Missing length in %s extension", da->name);
571 return -1;
572 }
573
574 if (hlen == 1) {
575 extension_len = extension[0];
576 } else {
577 extension_len = (extension[0] << 8) + extension[1];
578 }
579 fr_assert(da->type == ((dlen == 1) ? FR_TYPE_UINT8 : FR_TYPE_UINT16));
580
581 if (extension_len + hlen > total_len) {
582 REDEBUG("(TLS) Invalid length %zu in %s extension", extension_len, da->name);
583 return -1;
584 }
585
586 data = extension + hlen;
587
588 for (i = 0; i < extension_len; i += dlen) {
589 fr_pair_t *vp;
590
591 MEM(fr_pair_append_by_da(container, &vp, &container->vp_group, da) >= 0);
592
593 switch (dlen) {
594 case 1:
595 vp->vp_uint8= data[0];
596 break;
597
598 case 2:
599 vp->vp_uint16 = (data[0] << 8) + data[1];
600 break;
601 }
602
603 data += dlen;
604 }
605
606 return 0;
607}
608
609/** Callback to extract pairs from a Client Hello
610 *
611 */
612int fr_tls_session_client_hello_pairs(SSL *ssl, request_t *request)
613{
614 request_t *parent = request->parent;
615 uint8_t const *ciphers, *extension;
616 int i, *extensions = NULL;
617 size_t data_size, j;
618 STACK_OF(SSL_CIPHER) *sk;
619 SSL_CIPHER const *cipher;
620 STACK_OF(SSL_CIPHER) *scsvs;
621 fr_pair_t *container, *vp;
622
624
625 container = fr_pair_find_by_da(&parent->session_state_pairs, NULL, attr_tls_client_hello);
626 if (container) return SSL_CLIENT_HELLO_SUCCESS;
627
628 MEM(container = fr_pair_afrom_da(parent->session_state_ctx, attr_tls_client_hello));
629
630 data_size = SSL_client_hello_get0_ciphers(ssl, &ciphers);
631 if (SSL_bytes_to_cipher_list(ssl, ciphers, data_size,
632#if OPENSSL_VERSION_NUMBER >= 0x40000000L
633 0, /* OpenSSL 4.0 removed SSLv2 ClientHello support */
634#else
635 SSL_client_hello_isv2(ssl),
636#endif
637 &sk, &scsvs) == 0) {
638 RPEDEBUG("(TLS) Failed to decode cipher list");
639 fail:
640 if (extensions) OPENSSL_free(extensions);
641 talloc_free(container);
642 return SSL_CLIENT_HELLO_ERROR;
643 }
644
645 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
646 fr_pair_append_by_da(container, &vp, &container->vp_group, attr_tls_client_hello_cipher);
647 cipher = sk_SSL_CIPHER_value(sk, i);
648 fr_value_box_strdup(vp, &vp->data, NULL, SSL_CIPHER_get_name(cipher), false);
649 }
650
651 sk_SSL_CIPHER_free(sk);
652 sk_SSL_CIPHER_free(scsvs);
653
654 /*
655 * Fetch the extensions and decode the ones we know about
656 * These are the ones which are returned as simple lists
657 * of values of known length which map to enum attributes.
658 */
659 if (SSL_client_hello_get1_extensions_present(ssl, &extensions, &data_size) == 0) {
660 RPEDEBUG("(TLS) Failed to fetch client hello extensions");
661 goto fail;
662 }
663
664 for (j = 0; j < data_size; j++) {
665 size_t total_len;
666
667 if (SSL_client_hello_get0_ext(ssl, extensions[j], &extension, &total_len) == 0) {
668 RPDEBUG("Failed getting client hello extension %d", extensions[j]);
669 goto fail;
670 }
671
672 switch (extensions[j]) {
673 case TLSEXT_TYPE_supported_groups: /* length[2] + 2*data */
674 if (fr_tls_extension_decode(request, container, extension, 2, 2, total_len,
676 break;
677
678 case TLSEXT_TYPE_ec_point_formats: /* length[1] + data */
679 if (fr_tls_extension_decode(request, container, extension, 1, 1, total_len,
681 break;
682
683 case TLSEXT_TYPE_signature_algorithms: /* length[2] + 2*data */
684 if (fr_tls_extension_decode(request, container, extension, 2, 2, total_len,
685 attr_tls_client_hello_sig_algo) < 0) goto fail;
686 break;
687
688 case TLSEXT_TYPE_supported_versions: /* length[1] + 2*data */
689 if (fr_tls_extension_decode(request, container, extension, 1, 2, total_len,
690 attr_tls_client_hello_tls_version) < 0) goto fail;
691 break;
692
693 case TLSEXT_TYPE_psk_kex_modes: /* length[1] + data */
694 if (fr_tls_extension_decode(request, container, extension, 1, 1, total_len,
696 break;
697 }
698 }
699
700 if (extensions) OPENSSL_free(extensions);
701
702 /*
703 * This is the version being negotiated by the client, but tops at 1.2.
704 * After that the supported_versions extension is where the real value is.
705 */
706 fr_pair_append_by_da(container, &vp, &container->vp_group, attr_tls_client_hello_tls_version);
707 vp->vp_uint16 = SSL_client_hello_get0_legacy_version(ssl);
708
709 fr_pair_append(&parent->session_state_pairs, container);
710
711 return SSL_CLIENT_HELLO_SUCCESS;
712}
713DIAG_ON_OPTIONAL(used-but-marked-unused)
714#endif
static uint8_t request[4]
#define USES_APPLE_DEPRECATED_API
Definition build.h:590
#define RCSID(id)
Definition build.h:603
#define DIAG_OFF_OPTIONAL(_x)
Definition build.h:577
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
#define DIAG_ON_OPTIONAL(_x)
Definition build.h:578
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition dbuff.h:963
#define fr_dbuff_set(_dst, _src)
Set the 'current' position in a dbuff or marker using another dbuff or marker, a char pointer,...
Definition dbuff.h:1056
#define fr_dbuff_end(_dbuff_or_marker)
Return the current 'end' position of a dbuff or marker.
Definition dbuff.h:990
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition dbuff.h:795
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition dbuff.h:1518
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:556
#define MEM(x)
Definition debug.h:38
TALLOC_CTX * tmp_ctx
ctx under which temporary data will be allocated
Definition der.h:143
bool const fr_dict_attr_allowed_chars[SBUFF_CHAR_CLASS]
Characters allowed in a single dictionary attribute name.
Definition dict_util.c:54
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.
Definition dict_util.c:3600
talloc_free(hp)
HIDDEN fr_dict_attr_t const * attr_tls_certificate
Attribute definitions for lib curl.
Definition base.c:36
#define RWDEBUG(fmt,...)
Definition log.h:378
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RWARN(fmt,...)
Definition log.h:314
#define RPDEBUG(fmt,...)
Definition log.h:363
#define RPEDEBUG(fmt,...)
Definition log.h:393
#define RPWDEBUG3(fmt,...)
Definition log.h:385
#define RPWDEBUG(fmt,...)
Definition log.h:383
#define RWDEBUG3(fmt,...)
Definition log.h:380
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject
HIDDEN fr_dict_attr_t const * attr_tls_client_hello
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_psk_key_mode
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_client_hello_supported_group
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_client_hello_sig_algo
HIDDEN fr_dict_attr_t const * attr_tls_certificate_ocsp_uri
HIDDEN fr_dict_attr_t const * attr_tls_certificate_common_name
HIDDEN fr_dict_attr_t const * attr_tls_certificate_ocsp_cert_id
HIDDEN fr_dict_attr_t const * attr_tls_certificate_issuer
HIDDEN fr_dict_attr_t const * attr_tls_certificate_x509v3_crl_distribution_points
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_ec_point_format
HIDDEN fr_dict_attr_t const * attr_der_certificate
HIDDEN fr_dict_attr_t const * attr_tls_certificate_signature
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_tls_version
HIDDEN fr_dict_attr_t const * attr_tls_client_hello_cipher
HIDDEN fr_dict_attr_t const * attr_tls_certificate_subject_alt_name_email
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
long int ssize_t
unsigned char uint8_t
static size_t used
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)
Definition pair.c:1416
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.
Definition pair.c:2897
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2598
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.
Definition pair.c:2818
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2552
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1297
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.
Definition pair.c:284
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:47
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.
Definition pair.c:2747
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
Definition pair.c:2846
ssize_t fr_der_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *in, fr_der_decode_ctx_t *decode_ctx)
Definition decode.c:2663
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
static bool done
Definition radclient.c:80
static char const * name
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:37
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:693
static const char * names[8]
Definition time.c:618
static fr_unix_time_t fr_unix_time_from_time(time_t time)
Convert a time_t into out internal fr_unix_time_t.
Definition time.h:545
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_prepend(fr_pair_list_t *dst, fr_pair_list_t *src)
Move a list of fr_pair_t from a temporary list to the head of a destination list.
static fr_slen_t parent
Definition pair.h:864
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:581
int fr_tls_utils_asn1time_to_epoch(time_t *out, ASN1_TIME const *asn1)
Convert OpenSSL's ASN1_TIME to an epoch time.
Definition utils.c:128
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition value.c:4763
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:5255
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
#define fr_box_strvalue_buffer(_val)
Definition value.h:343
static fr_slen_t data
Definition value.h:1366
#define fr_box_strvalue_len(_val, _len)
Definition value.h:340
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061