The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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: 4fa71237698596e98c0b2849f86be943ac2defea $
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: 4fa71237698596e98c0b2849f86be943ac2defea $")
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
47DIAG_OFF(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, X509_EXTENSION *ext)
52{
53 GENERAL_NAMES *names = NULL;
54 int i;
56
57 if (!(names = X509V3_EXT_d2i(ext))) return false;
58
59 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
60 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
61
62 switch (name->type) {
63#ifdef GEN_EMAIL
64 case GEN_EMAIL:
68 (char const *)ASN1_STRING_get0_data(name->d.rfc822Name),
69 ASN1_STRING_length(name->d.rfc822Name), true) == 0);
70 break;
71#endif /* GEN_EMAIL */
72#ifdef GEN_DNS
73 case GEN_DNS:
77 (char const *)ASN1_STRING_get0_data(name->d.dNSName),
78 ASN1_STRING_length(name->d.dNSName), true) == 0);
79 break;
80#endif /* GEN_DNS */
81#ifdef GEN_OTHERNAME
82 case GEN_OTHERNAME:
83 /* look for a MS UPN */
84 if (NID_ms_upn != OBJ_obj2nid(name->d.otherName->type_id)) break;
85
86 /* we've got a UPN - Must be ASN1-encoded UTF8 string */
87 if (name->d.otherName->value->type == V_ASN1_UTF8STRING) {
91 (char const *)ASN1_STRING_get0_data(name->d.otherName->value->value.utf8string),
92 ASN1_STRING_length(name->d.otherName->value->value.utf8string),
93 true) == 0);
94 break;
95 }
96 RWARN("Invalid UPN in Subject Alt Name (should be UTF-8)");
97 break;
98#endif /* GEN_OTHERNAME */
99 default:
100 /* XXX TODO handle other SAN types */
101 break;
102 }
103 }
104 if (names != NULL) GENERAL_NAMES_free(names);
105
106 return true;
107}
108
109/** Extract session pairs from the X509v3-CRL-Distribution-Points extension
110 *
111 */
112static bool tls_session_pairs_from_crl(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, UNUSED request_t *request, X509_EXTENSION *ext)
113{
114 ASN1_STRING *s = X509_EXTENSION_get_data(ext);
115 char unsigned const *data = ASN1_STRING_get0_data(s);
116 STACK_OF(DIST_POINT) *dps;
117 DIST_POINT *dp;
118 STACK_OF(GENERAL_NAME) *names;
119 GENERAL_NAME *name;
120 fr_pair_t *vp;
121 int i, j;
122
123 if (!(dps = d2i_CRL_DIST_POINTS(NULL, &data, ASN1_STRING_length(s)))) return false;
124
125 for (i = 0; i < sk_DIST_POINT_num(dps); i++) {
126 dp = sk_DIST_POINT_value(dps, i);
127
128 /*
129 * RFC 5280 Section 4.2.1.13 says that the distpoint is optional.
130 */
131 if (!dp->distpoint) {
132 CRL_DIST_POINTS_free(dps);
133 return false;
134 }
135
136 names = dp->distpoint->name.fullname;
137
138 /*
139 * We only want CRL distribution points that cover all reasons,
140 * so ignore any where reasons are set.
141 */
142 if (dp->reasons) continue;
143
144 for (j = 0; j < sk_GENERAL_NAME_num(names); j++) {
145 name = sk_GENERAL_NAME_value(names, j);
146
147 if (name->type != GEN_URI) continue;
151 (char const *)ASN1_STRING_get0_data(name->d.uniformResourceIdentifier),
152 true) == 0);
153 }
154 }
155
156 CRL_DIST_POINTS_free(dps);
157
158 return true;
159}
160
161/** Extract attributes from an X509 certificate
162 *
163 * @param[out] pair_list to copy attributes to.
164 * @param[in] ctx to allocate attributes in.
165 * @param[in] request the current request.
166 * @param[in] cert to validate.
167 * @param[in] der_decode should the certificate be parsed with the DER decoder.
168 * @return
169 * - 1 already exists.
170 * - 0 on success.
171 * - < 0 on failure.
172 */
173int fr_tls_session_pairs_from_x509_cert(fr_pair_list_t *pair_list, TALLOC_CTX *ctx, request_t *request, X509 *cert,
174#if OPENSSL_VERSION_NUMBER >= 0x30400000L
175 bool der_decode
176#else
177 UNUSED bool der_decode
178#endif
179 )
180{
181 int loc;
182 char buff[1024];
183
184 ASN1_TIME const *asn_time;
185 time_t time;
186
187 STACK_OF(X509_EXTENSION) const *ext_list = NULL;
188
189 fr_pair_t *vp = NULL;
190 ssize_t slen;
191 bool san_found = false, crl_found = false;
192
193 /*
194 * We require OpenSSL >= 3.4 to call the DER decoder due to the stack size
195 * needed to handle the recursive calls involved in certificate decoding.
196 */
197#if OPENSSL_VERSION_NUMBER >= 0x30400000L
198 if (der_decode) {
199 uint8_t *cert_der;
200 uint8_t *cd;
201 int der_len;
202 fr_der_decode_ctx_t der_ctx;
203 fr_pair_list_t tmp_list;
204
205 der_len = i2d_X509(cert, NULL);
206 if (der_len < 0) {
207 fr_tls_log(request, "Failed retrieving certificate");
208 return -1;
209 }
210 der_ctx = (fr_der_decode_ctx_t) {
211 .tmp_ctx = talloc_new(ctx),
212 .root = attr_der_certificate,
213 };
214 cert_der = cd = talloc_array(der_ctx.tmp_ctx, uint8_t, der_len);
215 i2d_X509(cert, &cd);
216 fr_pair_list_init(&tmp_list);
217 slen = fr_der_decode_pair_dbuff(request->session_state_ctx, &tmp_list,
218 attr_der_certificate, &FR_DBUFF_TMP(cert_der, (size_t)der_len), &der_ctx);
219 talloc_free(der_ctx.tmp_ctx);
220 if (slen < 0) {
221 fr_tls_log(request, "Failed decoding certificate");
222 fr_pair_list_free(&tmp_list);
223 return -1;
224 }
225 /*
226 * Certificates are decoded in CA .. intermediate .. client sequence
227 * so, prepend each decoded one to get the client cert first.
228 */
229 fr_pair_list_prepend(&request->session_state_pairs, &tmp_list);
230 }
231#endif
232
233 /*
234 * Subject
235 */
237 if (unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(vp, 256, 0),
238 X509_get_subject_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
239 fr_tls_bio_dbuff_thread_local_clear();
240 fr_tls_log(request, "Failed retrieving certificate subject");
241 error:
243 return -1;
244 }
245 fr_pair_value_bstrdup_buffer_shallow(vp, fr_tls_bio_dbuff_thread_local_finalise_bstr(), true);
246
247 RDEBUG3("Creating attributes for \"%pV\":", fr_box_strvalue_buffer(vp->vp_strvalue));
248
249 /*
250 * Common name
251 */
252 slen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
253 NID_commonName, NULL, 0);
254 if (slen > 0) {
255 char *cn;
256
258 MEM(fr_pair_value_bstr_alloc(vp, &cn, (size_t)slen, true) == 0); /* Allocs \0 byte in addition to len */
259
260 slen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, cn, (size_t)slen + 1);
261 if (slen < 0) {
262 fr_tls_log(request, "Failed retrieving certificate common name");
263 goto error;
264 }
265 }
266
267 /*
268 * Signature
269 */
270 {
271 ASN1_BIT_STRING const *sig;
272 X509_ALGOR const *alg;
273
274 X509_get0_signature(&sig, &alg, cert);
275
278 (uint8_t const *)ASN1_STRING_get0_data(sig),
279 ASN1_STRING_length(sig), true) == 0);
280
281 OBJ_obj2txt(buff, sizeof(buff), alg->algorithm, 0);
284 }
285
286 /*
287 * Issuer
288 */
290 if (unlikely(X509_NAME_print_ex(fr_tls_bio_dbuff_thread_local(vp, 256, 0),
291 X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE) < 0)) {
292 fr_tls_bio_dbuff_thread_local_clear();
293 fr_tls_log(request, "Failed retrieving certificate issuer");
294 goto error;
295 }
296 fr_pair_value_bstrdup_buffer_shallow(vp, fr_tls_bio_dbuff_thread_local_finalise_bstr(), true);
297
298 /*
299 * Serial number
300 */
301 {
302 ASN1_INTEGER const *serial = NULL;
303 unsigned char *der;
304 int len;
305
306 serial = X509_get0_serialNumber(cert);
307 if (!serial) {
308 fr_tls_log(request, "Failed retrieving certificate serial");
309 goto error;
310 }
311
312 len = i2d_ASN1_INTEGER(serial, NULL); /* get length */
314 MEM(fr_pair_value_mem_alloc(vp, &der, len, false) == 0);
315 i2d_ASN1_INTEGER(serial, &der);
316 }
317
318 /*
319 * Not valid before
320 */
321 asn_time = X509_get0_notBefore(cert);
322
323 if (fr_tls_utils_asn1time_to_epoch(&time, asn_time) < 0) {
324 RPWDEBUG("Failed parsing certificate not-before");
325 goto error;
326 }
327
329 vp->vp_date = fr_unix_time_from_time(time);
330
331 /*
332 * Not valid after
333 */
334 asn_time = X509_get0_notAfter(cert);
335
336 if (fr_tls_utils_asn1time_to_epoch(&time, asn_time) < 0) {
337 RPWDEBUG("Failed parsing certificate not-after");
338 goto error;
339 }
340
342 vp->vp_date = fr_unix_time_from_time(time);
343
344 /*
345 * Get the RFC822 Subject Alternative Name
346 */
347 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, 0);
348 if (loc >= 0) {
349 X509_EXTENSION *ext = X509_get_ext(cert, loc);
350 if (ext) san_found = tls_session_pairs_from_san(pair_list, ctx, request, ext);
351 }
352
353 loc = X509_get_ext_by_NID(cert, NID_crl_distribution_points, 0);
354 if (loc >= 0) {
355 X509_EXTENSION *ext = X509_get_ext(cert, loc);
356 if (ext) crl_found = tls_session_pairs_from_crl(pair_list, ctx, request, ext);
357 }
358
359 /*
360 * Only add extensions for the actual client certificate
361 */
362 ext_list = X509_get0_extensions(cert);
363 if (unlikely(!ext_list)) {
364 RWDEBUG("Failed retrieving extensions");
365 goto done;
366 }
367
368 /*
369 * Grab the X509 extensions, and create attributes out of them.
370 * For laziness, we reuse the OpenSSL names
371 */
372 if (sk_X509_EXTENSION_num(ext_list) > 0) {
373 int i;
374 BIO *bio;
375 fr_tls_bio_dbuff_t *bd;
376 fr_dbuff_t *in, *out;
377
378 bio = fr_tls_bio_dbuff_alloc(&bd, NULL, NULL, 257, 4097, true);
379 in = fr_tls_bio_dbuff_in(bd);
380 out = fr_tls_bio_dbuff_out(bd);
381
382 for (i = 0; i < sk_X509_EXTENSION_num(ext_list); i++) {
383 ASN1_OBJECT *obj;
384 X509_EXTENSION *ext;
385 fr_dict_attr_t const *da;
386 char *p;
387
388 ext = sk_X509_EXTENSION_value(ext_list, i);
389
390 obj = X509_EXTENSION_get_object(ext);
391
392 /*
393 * If this is extension is Subject Alternate Name have we already
394 * handled it? If not, do that now.
395 *
396 * Some certificate encodings have been observed where the SAN extension
397 * was not found by X509_get_ext_by_NID() but then seen when the list
398 * of extensions is handled here.
399 */
400 if (OBJ_obj2nid(obj) == NID_subject_alt_name) {
401 if (!san_found) san_found = tls_session_pairs_from_san(pair_list, ctx, request, ext);
402 goto again;
403 }
404
405 if (OBJ_obj2nid(obj) == NID_crl_distribution_points) {
406 if (!crl_found) crl_found = tls_session_pairs_from_crl(pair_list, ctx, request, ext);
407 goto again;
408 }
409
410 if (i2a_ASN1_OBJECT(bio, obj) <= 0) {
411 RPWDEBUG("Skipping X509 Extension (%i) conversion to attribute. "
412 "Conversion from ASN1 failed...", i);
413 again:
414 fr_tls_bio_dbuff_reset(bd);
415 continue;
416 }
417
418 if (fr_dbuff_remaining(out) == 0) goto again; /* Nothing written ? */
419
420 /*
421 * All disallowed chars get mashed to '-'
422 */
423 for (p = (char *)fr_dbuff_current(out);
424 p < (char *)fr_dbuff_end(out);
425 p++) if (!fr_dict_attr_allowed_chars[(uint8_t)*p]) *p = '-';
426
427 /*
428 * Terminate the buffer (after char replacement,
429 * so we do don't replace the \0)
430 */
431 if (unlikely(fr_dbuff_in_bytes(in, (uint8_t)'\0') <= 0)) {
432 RWDEBUG("Attribute name too long");
433 goto again;
434 }
435
437
438 fr_dbuff_set(in, fr_dbuff_current(in) - 1); /* Ensure the \0 isn't counted in remaining */
439
440 if (!da) {
441 RWDEBUG3("Skipping attribute \"%pV\": "
442 "Add a dictionary definition if you want to access it",
445 fr_strerror_clear(); /* Don't leave spurious errors from failed resolution */
446 goto again;
447 }
448
449 fr_tls_bio_dbuff_reset(bd); /* 'free' any data used */
450
451 if (X509V3_EXT_print(bio, ext, X509V3_EXT_PARSE_UNKNOWN, 0) != 1) {
452 REDEBUG("Failed extracting data for \"%s\"", da->name);
453 goto again;
454 }
455
456 MEM(vp = fr_pair_afrom_da(ctx, da));
458 NULL, true) < 0) {
459 RPWDEBUG3("Skipping: %s += \"%pV\"",
460 da->name, fr_box_strvalue_len((char *)fr_dbuff_current(out),
463 goto again;
464 }
465 fr_tls_bio_dbuff_reset(bd); /* 'free' any data used */
466
468 }
469 talloc_free(bd);
470 }
471
472done:
473 return 0;
474}
475
476static int fr_tls_extension_decode(request_t *request, fr_pair_t *container, uint8_t const *extension,
477 size_t hlen, size_t dlen, size_t total_len, fr_dict_attr_t const *da)
478{
479 size_t i,extension_len;
480 uint8_t const *data;
481
482 fr_assert((hlen == 1) || (hlen == 2));
483 fr_assert((dlen == 1) || (dlen == 2));
484
485 if (total_len < hlen) {
486 REDEBUG("Missing length in %s extension", da->name);
487 return -1;
488 }
489
490 if (hlen == 1) {
491 fr_assert(da->type == FR_TYPE_UINT8);
492 extension_len = extension[0];
493 } else {
494 fr_assert(da->type == FR_TYPE_UINT16);
495 extension_len = (extension[0] << 8) + extension[1];
496 }
497
498 if (extension_len * dlen + hlen > total_len) {
499 REDEBUG("Invalid length in %s extension", da->name);
500 return -1;
501 }
502
503 data = extension + hlen;
504
505 for (i = 0; i < extension_len; i += dlen) {
506 fr_pair_t *vp;
507
508 MEM(fr_pair_append_by_da(container, &vp, &container->vp_group, da) >= 0);
509
510 switch (dlen) {
511 case 1:
512 vp->vp_uint8= data[0];
513 break;
514
515 case 2:
516 vp->vp_uint16 = (data[0] << 8) + data[1];
517 break;
518 }
519
520 data += dlen;
521 }
522
523 return 0;
524}
525
526/** Callback to extract pairs from a Client Hello
527 *
528 */
529int fr_tls_session_client_hello_cb(SSL *ssl, UNUSED int *al, UNUSED void *arg)
530{
531 request_t *request = SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_REQUEST);
532 request_t *parent = request->parent;
533 uint8_t const *ciphers, *extension;
534 int i, *extensions = NULL;
535 size_t data_size, j;
536 STACK_OF(SSL_CIPHER) *sk;
537 SSL_CIPHER const *cipher;
538 STACK_OF(SSL_CIPHER) *scsvs;
539 fr_pair_t *container, *vp;
540
542
543 container = fr_pair_find_by_da(&parent->session_state_pairs, NULL, attr_tls_client_hello);
544 if (container) return SSL_CLIENT_HELLO_SUCCESS;
545
546 MEM(container = fr_pair_afrom_da(parent->session_state_ctx, attr_tls_client_hello));
547
548 data_size = SSL_client_hello_get0_ciphers(ssl, &ciphers);
549 if (SSL_bytes_to_cipher_list(ssl, ciphers, data_size, SSL_client_hello_isv2(ssl), &sk, &scsvs) == 0) {
550 RPEDEBUG("Failed to decode cipher list");
551 fail:
552 if (extensions) OPENSSL_free(extensions);
553 talloc_free(container);
554 return SSL_CLIENT_HELLO_ERROR;
555 }
556
557 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
558 fr_pair_append_by_da(container, &vp, &container->vp_group, attr_tls_client_hello_cipher);
559 cipher = sk_SSL_CIPHER_value(sk, i);
560 fr_value_box_strdup(vp, &vp->data, NULL, SSL_CIPHER_get_name(cipher), false);
561 }
562
563 sk_SSL_CIPHER_free(sk);
564 sk_SSL_CIPHER_free(scsvs);
565
566 /*
567 * Fetch the extensions and decode the ones we know about
568 * These are the ones which are returned as simple lists
569 * of values of known length which map to enum attributes.
570 */
571 if (SSL_client_hello_get1_extensions_present(ssl, &extensions, &data_size) == 0) {
572 RPEDEBUG("Failed to fetch client hello extensions");
573 goto fail;
574 }
575
576 for (j = 0; j < data_size; j++) {
577 size_t total_len;
578
579 if (SSL_client_hello_get0_ext(ssl, extensions[j], &extension, &total_len) == 0) {
580 RPDEBUG("Failed getting client hello extension %d", extensions[j]);
581 goto fail;
582 }
583
584 switch (extensions[j]) {
585 case TLSEXT_TYPE_supported_groups: /* length[2] + 2*data */
586 if (fr_tls_extension_decode(request, container, extension, 2, 2, total_len,
588 break;
589
590 case TLSEXT_TYPE_ec_point_formats: /* length[1] + data */
591 if (fr_tls_extension_decode(request, container, extension, 1, 1, total_len,
593 break;
594
595 case TLSEXT_TYPE_signature_algorithms: /* length[2] + 2*data */
596 if (fr_tls_extension_decode(request, container, extension, 2, 2, total_len,
597 attr_tls_client_hello_sig_algo) < 0) goto fail;
598 break;
599
600 case TLSEXT_TYPE_supported_versions: /* length[1] + 2*data */
601 if (fr_tls_extension_decode(request, container, extension, 1, 2, total_len,
602 attr_tls_client_hello_tls_version) < 0) goto fail;
603 break;
604
605 case TLSEXT_TYPE_psk_kex_modes: /* length[1] + data */
606 if (fr_tls_extension_decode(request, container, extension, 1, 1, total_len,
608 break;
609 }
610 }
611
612 if (extensions) OPENSSL_free(extensions);
613
614 /*
615 * This is the version being negotiated by the client, but tops at 1.2.
616 * After that the supported_versions extension is where the real value is.
617 */
618 fr_pair_append_by_da(container, &vp, &container->vp_group, attr_tls_client_hello_tls_version);
619 vp->vp_uint16 = SSL_client_hello_get0_legacy_version(ssl);
620
621 fr_pair_append(&parent->session_state_pairs, container);
622
623 return SSL_CLIENT_HELLO_SUCCESS;
624}
625DIAG_ON(used-but-marked-unused)
627#endif
#define USES_APPLE_DEPRECATED_API
Definition build.h:499
#define RCSID(id)
Definition build.h:512
#define DIAG_UNKNOWN_PRAGMAS
Definition build.h:485
#define DIAG_ON(_x)
Definition build.h:487
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#define DIAG_OFF(_x)
Definition build.h:486
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition dbuff.h:919
#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:1012
#define fr_dbuff_end(_dbuff_or_marker)
Return the current 'end' position of a dbuff or marker.
Definition dbuff.h:946
#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:751
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition dbuff.h:1474
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:522
#define MEM(x)
Definition debug.h:36
TALLOC_CTX * tmp_ctx
ctx under which temporary data will be allocated
Definition der.h:119
bool const fr_dict_attr_allowed_chars[SBUFF_CHAR_CLASS]
Characters allowed in a single dictionary attribute name.
Definition dict_util.c:56
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:3505
static fr_slen_t in
Definition dict.h:882
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:373
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RWARN(fmt,...)
Definition log.h:309
#define RPDEBUG(fmt,...)
Definition log.h:358
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RPWDEBUG3(fmt,...)
Definition log.h:380
#define RPWDEBUG(fmt,...)
Definition log.h:378
#define RWDEBUG3(fmt,...)
Definition log.h:375
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_common_name
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:1471
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:2962
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2663
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:2883
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:2617
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:1352
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:290
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
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:2812
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.
Definition pair.c:2759
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:2911
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:2473
#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
static const char * names[8]
Definition time.c:600
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:536
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:858
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:115
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:4619
#define fr_box_strvalue_buffer(_val)
Definition value.h:312
static fr_slen_t data
Definition value.h:1340
#define fr_box_strvalue_len(_val, _len)
Definition value.h:309
static size_t char ** out
Definition value.h:1030