The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
verify.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: fdbb16fa726f5935721182da1236b9ad411d1144 $
19 *
20 * @file tls/verify.c
21 * @brief Expose certificate OIDs as attributes, and call validation virtual
22 * server to check cert is valid.
23 *
24 * @copyright 2003 Alan DeKok (aland@freeradius.org)
25 * @copyright 2006-2016 The FreeRADIUS server project
26 */
27#ifdef WITH_TLS
28#define LOG_PREFIX "tls"
29
30#define _TLS_PRIVATE 1
31
32#include <freeradius-devel/server/exec.h>
33#include <freeradius-devel/server/pair.h>
34#include <freeradius-devel/tls/log.h>
35#include <freeradius-devel/unlang/function.h>
36#include <freeradius-devel/unlang/subrequest.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/util/strerror.h>
39#include <freeradius-devel/util/syserror.h>
40
41#include <freeradius-devel/protocol/tls/freeradius.h>
42
43#include <openssl/x509v3.h>
44
45#include "attrs.h"
46#include "base.h"
47
48/** Check to see if a verification operation should apply to a certificate
49 *
50 * @param[in] depth starting at 0.
51 * Certificate 0 is the leaf cert (i.e. the client or server cert);
52 * @param[in] untrusted The number of untrusted certificates.
53 * @param[in] mode to check
54 * @return
55 * - true if a given validation check should apply.
56 ** - false if a validation check should not apply.
57 */
58static inline CC_HINT(always_inline)
59bool verify_applies(fr_tls_verify_mode_t mode, int depth, int untrusted)
60{
61 if (mode == FR_TLS_VERIFY_MODE_ALL) return true;
62 if (mode == FR_TLS_VERIFY_MODE_DISABLED) return false;
63
64 if ((mode & FR_TLS_VERIFY_MODE_LEAF) && (depth == 0)) return true;
65 if ((mode & FR_TLS_VERIFY_MODE_ISSUER) && (depth == 1)) return true;
66 if ((mode & FR_TLS_VERIFY_MODE_UNTRUSTED) && (depth < untrusted)) return true;
67
68 return false;
69}
70
71DIAG_OFF_OPTIONAL(used-but-marked-unused) /* fix spurious warnings for sk macros */
72
73/** Print verbose humanly readable messages about why certificate validation failed
74 *
75 */
76static void tls_verify_error_detail(request_t *request, SSL_CTX *ctx, int err)
77{
78 X509_STORE *store = SSL_CTX_get_ex_data(ctx, FR_TLS_EX_CTX_INDEX_VERIFY_STORE);
79
80 switch (err) {
81 /*
82 * We linked the provided cert to at least one
83 * other in a chain, but the chain doesn't terminate
84 * in a root CA.
85 */
86 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
88
89 /*
90 * We failed to link the provided cert to any
91 * other local certificates in the chain.
92 */
93 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
94 RDEBUG2("(TLS) Static certificates in verification store are");
95 if (RDEBUG_ENABLED2) {
96 RINDENT();
97 fr_tls_x509_objects_log(request, L_DBG, X509_STORE_get0_objects(store));
98 REXDENT();
99 }
100 break;
101
102 default:
103 break;
104 }
105}
106
107/** Validates a certificate using custom logic
108 *
109 * Before trusting a certificate, we make sure that the certificate is
110 * 'valid'. There are several checks we perform to verify its validity.
111 *
112 * 1. Verify the certificate's signature, and verifying that the certificate has
113 * been issued by a trusted Certificate Authority (this is done for us by OpenSSL).
114 *
115 * 2. Verify that the certificate is valid for the present date (i.e. it is being
116 * presented within its validity dates).
117 *
118 * 3. Verify that the certificate has not been revoked by its issuing Certificate
119 * Authority, by checking with respect to a Certificate Revocation List (CRL).
120 *
121 * @note This callback will be called multiple times based on the depth of the root
122 * certificate chain.
123 *
124 * @note OpenSSL runs the handshake (including this callback) on a fibre with a
125 * limited stack (32 KB on OpenSSL releases without ASYNC_set_mem_functions()).
126 * Because of that limited stack, we need to perform all certificate decoding
127 * outside of the fibre on the main stack, i.e. after OpenSSL has yielded and
128 * the handshake has paused. See fr_tls_verify_cert_pending_push().
129 *
130 * @param ok preverify ok. 1 if true, 0 if false.
131 * @param x509_ctx containing certs to verify.
132 * @return
133 * - 0 if not valid.
134 * - 1 if valid.
135 */
136int fr_tls_verify_cert_cb(int ok, X509_STORE_CTX *x509_ctx)
137{
138 X509 *cert;
139
140 SSL_CTX *ssl_ctx;
141 SSL *ssl;
142 fr_tls_session_t *tls_session;
143 int err, depth;
144 fr_tls_conf_t *conf;
145 int my_ok = ok;
146 int untrusted;
147
149 fr_pair_t *depth_pair;
150
151 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
152 err = X509_STORE_CTX_get_error(x509_ctx);
153 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
154 untrusted = X509_STORE_CTX_get_num_untrusted(x509_ctx);
155
156 /*
157 * Retrieve the pointer to the SSL of the connection currently treated
158 * and the application specific data stored into the SSL object.
159 */
160 ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
161 ssl_ctx = SSL_get_SSL_CTX(ssl);
162 conf = fr_tls_session_conf(ssl);
163 tls_session = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t);
164 request = fr_tls_session_request(tls_session->ssl);
165
166 /*
167 * If this error appears it suggests
168 * that OpenSSL is trying to perform post-handshake
169 * certificate validation which we don't support.
170 */
171 if (!tls_session->can_pause) {
172 fr_assert_msg("Unexpected call to %s. "
173 "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
174 return 0;
175 }
176
177 /*
178 * Bail out as quickly as possible, producing
179 * as few errors as possible.
180 */
182 X509_STORE_CTX_set_error(x509_ctx, 0);
183 return 1;
184 }
185
186 /*
187 * Find or add the chain depth attribute and record the greatest depth we see + 1,
188 * as depth is zero based.
189 */
190 if (unlikely(fr_pair_find_or_append_by_da(request->session_state_ctx, &depth_pair, &request->session_state_pairs,
192 REDEBUG("(TLS) Failed to add certificate chain depth pair");
193 return 0;
194 }
195 if (depth_pair->vp_uint32 < ((uint32_t)depth) + 1) depth_pair->vp_uint32 = (uint32_t)depth + 1;
196
197 if (RDEBUG_ENABLED3) {
198 char subject[2048];
199 STACK_OF(X509) *our_chain;
200 int i;
201
202 our_chain = X509_STORE_CTX_get0_chain(x509_ctx);
203 RDEBUG3("(TLS) Certificate chain - %i cert(s) untrusted", untrusted);
204 for (i = sk_X509_num(our_chain); i > 0 ; i--) {
205 X509 *this_cert = sk_X509_value(our_chain, i - 1);
206
207 X509_NAME_oneline(X509_get_subject_name(this_cert), subject, sizeof(subject));
208 subject[sizeof(subject) - 1] = '\0';
209
210 RDEBUG3("(TLS) %s [%i] %s", this_cert == cert ? ">" : " ", i - 1, subject);
211 }
212 }
213
214 /*
215 * See if the user has disabled verification for
216 * this certificate. If they have, force verification
217 * to succeed.
218 */
219 if (!my_ok) {
220 char const *p = X509_verify_cert_error_string(err);
221 if (!verify_applies(conf->verify.mode, depth, untrusted)) {
222 RDEBUG2("(TLS) Ignoring verification error - %s (%i)", p, err);
223 tls_verify_error_detail(request, ssl_ctx, err);
224
225 my_ok = 1;
226 X509_STORE_CTX_set_error(x509_ctx, 0);
227 } else {
228 REDEBUG("(TLS) Verification error - %s (%i)", p, err);
229 fr_tls_session_error_add(request, FR_ERROR_VALUE_CERTIFICATE_VERIFY_FAILED);
230 tls_verify_error_detail(request, ssl_ctx, err);
231 goto done;
232 }
233 }
234
235done:
236 /*
237 * The chain is complete once OpenSSL reaches depth 0. Pause the handshake
238 * here so that fr_tls_verify_cert_pending_push() can decode the chain and run
239 * the `verify certificate` section on the main stack. Execution continues
240 * after the ASYNC_pause_job() call below once the section has run.
241 */
242 if (my_ok && (depth == 0)) {
243 bool want_pairs = conf->verify.attribute_mode != FR_TLS_VERIFY_MODE_DISABLED;
244 bool want_verify = conf->verify_certificate && tls_session->verify_peer_cert;
245
246 if (want_pairs || want_verify) {
247 fr_tls_verify_cert_request(tls_session, x509_ctx);
248
249 /*
250 * Be aware that if the request is cancelled
251 * whatever was meant to be done during the
252 * time we yielded may not have been completed.
253 */
254 ASYNC_pause_job();
255
256 /*
257 * Just try and bail out as quickly as possible.
258 */
260 X509_STORE_CTX_set_error(x509_ctx, 0);
261 fr_tls_verify_cert_reset(tls_session);
262 return 1;
263 }
264
265 /*
266 * If we couldn't decode the chain, or the
267 * `verify certificate` section rejected it,
268 * then validation overall fails.
269 */
270 if (!fr_tls_verify_cert_result(tls_session)) {
271 REDEBUG("(TLS) Certificate validation failed");
272 my_ok = 0;
273 X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
274 }
275 }
276 }
277
278 tls_session->peer_cert_ok = (my_ok > 0);
279 RDEBUG2("(TLS) [verify] = %s", my_ok ? "ok" : "invalid");
280
281 return my_ok;
282}
283DIAG_ON_OPTIONAL(used-but-marked-unused)
284
285/** Revalidates the client's certificate chain
286 *
287 * Wraps the fr_tls_verify_cert_cb callback, allowing us to use the same
288 * validation logic whenever we need to.
289 *
290 * @note Only use so far is forcing the chain to be re-validated on session
291 * resumption.
292 *
293 * @return
294 * - 1 if the chain could be validated.
295 * - 0 if the chain failed validation.
296 */
297int fr_tls_verify_cert_chain(request_t *request, SSL *ssl)
298{
299 int err;
300 int verify;
301 int ret = 1;
302
303 SSL_CTX *ssl_ctx;
304 STACK_OF(X509) *chain;
305 X509 *cert;
306 X509_STORE *store;
307 X509_STORE_CTX *store_ctx;
308
309 /*
310 * If there's no client certificate, we just return OK.
311 */
312 cert = SSL_get0_peer_certificate(ssl); /* Does not increase ref count */
313 if (!cert) return 1;
314
315 ssl_ctx = SSL_get_SSL_CTX(ssl);
316 store_ctx = X509_STORE_CTX_new();
317 if (unlikely(store_ctx == NULL)) {
318 REDEBUG("(TLS) Failed allocating X509_STORE_CTX");
319 return 0;
320 }
321
322 chain = SSL_get_peer_cert_chain(ssl); /* Does not increase ref count */
323 store = SSL_CTX_get_ex_data(ssl_ctx, FR_TLS_EX_CTX_INDEX_VERIFY_STORE); /* Gets the verification store */
324
325 /*
326 * This sets up a store_ctx for doing peer certificate verification.
327 *
328 * store_ctx - Is the ctx to initialise
329 * store - Is an X509_STORE of implicitly
330 * trusted certificates. Here we're using
331 * the verify store that was created when we
332 * allocated the SSL_CTX.
333 * cert - Is the certificate to validate.
334 * chain - Is any other certificates the peer provided
335 * us in order to build a chain from a trusted
336 * root or intermediary to its leaf (cert).
337 *
338 * Note: SSL_CTX_get_cert_store() returns the ctx->cert_store, which
339 * is not the same as the verification cert store.
340 */
341 if (unlikely(X509_STORE_CTX_init(store_ctx, store, cert, chain) != 1)) {
342 REDEBUG("(TLS) Failed initialising X509_STORE_CTX");
343 X509_STORE_CTX_free(store_ctx);
344 return 0;
345 }
346
347 X509_STORE_CTX_set_ex_data(store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
348 X509_STORE_CTX_set_verify_cb(store_ctx, fr_tls_verify_cert_cb);
349
350 verify = X509_verify_cert(store_ctx);
351 if (verify != 1) {
352 err = X509_STORE_CTX_get_error(store_ctx);
353
354 if (err != X509_V_OK) {
355 REDEBUG("(TLS) Failed re-validating resumed session: %s", X509_verify_cert_error_string(err));
356 fr_tls_session_error_add(request, FR_ERROR_VALUE_CERTIFICATE_REVALIDATION_FAILED);
357 ret = 0;
358 }
359 }
360
361 X509_STORE_CTX_free(store_ctx);
362
363 return ret;
364}
365
366/** Process the result of `verify certificate { ... }`
367 *
368 */
369static unlang_action_t tls_verify_peer_cert_result(request_t *request, void *uctx)
370{
371 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
372 fr_pair_t *vp, *next;
373
374 fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_REQUESTED);
375
376 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
377 if (!vp || (vp->vp_uint32 != enum_tls_packet_type_success->vb_uint32)) {
378 REDEBUG("(TLS) Failed (re-)validating certificates");
379 fr_tls_session_error_add(request->parent, FR_ERROR_VALUE_VERIFY_CERTIFICATE_FAILED);
380
381 /*
382 * Hoist any instances of Module-Failure-Message from the subrequest
383 * so they can be used for logging failures.
384 */
386 while (vp && request->parent) {
388 fr_pair_remove(&request->request_pairs, vp);
389 fr_pair_steal_append(request->parent->request_ctx, &request->parent->request_pairs, vp);
390 vp = next;
391 }
392
393 tls_session->validate.state = FR_TLS_VALIDATION_FAILED;
395 }
396
397 tls_session->validate.state = FR_TLS_VALIDATION_SUCCESS;
398
399 RDEBUG2("(TLS) Certificates (re-)validated");
400
402}
403
404/** Push a `verify certificate { ... }` call into the current request, using a subrequest
405 *
406 * @param[in] request The current request.
407 * @param[in] tls_session The current TLS session.
408 * @return
409 * - UNLANG_ACTION_CALCULATE_RESULT on noop.
410 * - UNLANG_ACTION_PUSHED_CHILD on success.
411 * - UNLANG_ACTION_FAIL on failure.
412 */
413static unlang_action_t tls_verify_peer_cert_push(request_t *request, fr_tls_session_t *tls_session)
414{
415 fr_tls_conf_t *conf = tls_session->conf;
416 request_t *child;
417 fr_pair_t *vp;
419
420 fr_assert(conf->virtual_server);
421
422 MEM(child = tls_subrequest_alloc(request, enum_tls_packet_type_verify_certificate->vb_uint32,
423 &tls_session->session_id));
424 request = child;
425
426 /*
427 * Add extra pairs to the subrequest
428 */
429 fr_tls_session_extra_pairs_copy_to_child(child, tls_session);
430
431 /*
432 * Copy certificate pairs to the child session state
433 */
434 vp = NULL;
435 while ((vp = fr_pair_find_by_da(&request->parent->session_state_pairs, vp, attr_tls_certificate))) {
436 fr_pair_append(&request->session_state_pairs, fr_pair_copy(request->session_state_ctx, vp));
437 }
438 if (conf->verify.der_decode) {
439 while ((vp = fr_pair_find_by_da(&request->parent->session_state_pairs, vp, attr_der_certificate))) {
440 fr_pair_append(&request->session_state_pairs, fr_pair_copy(request->session_state_ctx, vp));
441 }
442 }
443
445 vp->vp_bool = tls_session->validate.resumed;
446
447 /*
448 * Allocate a child, and set it up to call
449 * the TLS virtual server.
450 */
451 ua = fr_tls_call_push(child, tls_verify_peer_cert_result, conf, tls_session, false);
452 if (ua == UNLANG_ACTION_FAIL) {
453 REDEBUG("(TLS) Failed calling TLS virtual server");
454 talloc_free(child);
455 return UNLANG_ACTION_FAIL;
456 }
457
458 return ua;
459}
460
461/** Clear any previous validation result
462 *
463 * Should be called by the validation requestor to get the result and reset
464 * the validation state.
465 *
466 * @return
467 * - true if the certificate chain was validated.
468 * - false if the certificate chain failed validation.
469 */
470bool fr_tls_verify_cert_result(fr_tls_session_t *tls_session)
471{
472 bool result;
473
474 fr_assert(tls_session->validate.state != FR_TLS_VALIDATION_INIT);
475
476 result = tls_session->validate.state == FR_TLS_VALIDATION_SUCCESS;
477
478 tls_session->validate.state = FR_TLS_VALIDATION_INIT;
479 tls_session->validate.resumed = false;
480
481 return result;
482}
483
484/** Reset the verification state
485 *
486 */
487void fr_tls_verify_cert_reset(fr_tls_session_t *tls_session)
488{
489 tls_session->validate.state = FR_TLS_VALIDATION_INIT;
490 tls_session->validate.resumed = false;
491 tls_session->validate.x509_ctx = NULL;
492}
493
494/** Request validation of the chain OpenSSL is verifying
495 *
496 * Called by fr_tls_verify_cert_cb() before it pauses the handshake.
497 *
498 * @param[in] tls_session The current TLS session.
499 * @param[in] x509_ctx holding the chain. Only valid while the
500 * handshake is paused inside the callback.
501 */
502void fr_tls_verify_cert_request(fr_tls_session_t *tls_session, X509_STORE_CTX *x509_ctx)
503{
504 fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_INIT);
505
506 tls_session->validate.state = FR_TLS_VALIDATION_REQUESTED;
507 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_VERIFY);
508 tls_session->validate.resumed = false;
509 tls_session->validate.x509_ctx = x509_ctx;
510}
511
512/** Request re-validation of the certificate pairs restored with a resumed session
513 *
514 * Called by the session cache code before it pauses the handshake. A resumed
515 * session has no chain to decode, the `TLS-Certificate` pairs came back with
516 * the session.
517 *
518 * @param[in] tls_session The current TLS session.
519 */
520void fr_tls_verify_resumed_request(fr_tls_session_t *tls_session)
521{
522 fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_INIT);
523
524 tls_session->validate.state = FR_TLS_VALIDATION_REQUESTED;
525 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_VERIFY);
526 tls_session->validate.resumed = true;
527 tls_session->validate.x509_ctx = NULL;
528}
529
530DIAG_OFF_OPTIONAL(used-but-marked-unused) /* fix spurious warnings for sk macros */
531/** Decode the chain OpenSSL is verifying into `session-state.TLS-Certificate` pairs
532 *
533 * Runs on the request's own stack while the handshake is paused in
534 * fr_tls_verify_cert_cb(). The certificate at depth 0 is the peer's, and
535 * `TLS-Certificate[n]` holds the certificate at depth n.
536 *
537 * @param[in] request The current request.
538 * @param[in] tls_session The current TLS session.
539 * @param[in] conf The TLS configuration.
540 * @return
541 * - 0 on success.
542 * - -1 if a certificate could not be decoded. No `TLS-Certificate`
543 * pairs remain in the session-state list.
544 */
545static int tls_verify_chain_pairs_add(request_t *request, fr_tls_session_t *tls_session, fr_tls_conf_t const *conf)
546{
547 X509_STORE_CTX *x509_ctx = tls_session->validate.x509_ctx;
548 STACK_OF(X509) *chain = X509_STORE_CTX_get0_chain(x509_ctx);
549 int untrusted = X509_STORE_CTX_get_num_untrusted(x509_ctx);
550 int num = sk_X509_num(chain);
551 int depth;
552
553 /*
554 * Deepest first, so each DER decoded certificate is prepended ahead
555 * of its issuer and `DER-Certificate[0]` is the peer's.
556 */
557 for (depth = num - 1; depth >= 0; depth--) {
558 X509 *cert = sk_X509_value(chain, depth);
559 X509 *issuer;
560 fr_pair_t *container;
561 unsigned int i;
562
563 if (!verify_applies(conf->verify.attribute_mode, depth, untrusted)) continue;
564
565 /*
566 * Already decoded, the pairs came back with a resumed session.
567 */
568 container = fr_pair_find_by_da_idx(&request->session_state_pairs, attr_tls_certificate, depth);
569 if (container && !fr_pair_list_empty(&container->vp_group)) continue;
570
571 /*
572 * Build out sufficient TLS-Certificate containers so the
573 * TLS-Certificate indexes match the chain depth.
574 */
575 for (i = fr_pair_count_by_da(&request->session_state_pairs, attr_tls_certificate);
576 i <= (unsigned int)depth;
577 i++) {
578 MEM(container = fr_pair_afrom_da(request->session_state_ctx, attr_tls_certificate));
579 fr_pair_append(&request->session_state_pairs, container);
580 }
581
582#ifdef STATIC_ANALYZER
583 /*
584 * Container can never be NULL, because if container
585 * was previously NULL, i will be <= depth.
586 */
587 if (!fr_cond_assert(container)) return -1;
588#endif
589
590 /*
591 * The issuer is the next certificate up the chain. The last
592 * certificate is its own issuer when it is self-issued, which
593 * is what OpenSSL reports as the current issuer when it calls
594 * the verify callback for that certificate.
595 */
596 if ((depth + 1) < num) {
597 issuer = sk_X509_value(chain, depth + 1);
598 } else if (X509_check_issued(cert, cert) == X509_V_OK) {
599 issuer = cert;
600 } else {
601 issuer = NULL;
602 }
603
604 /*
605 * If we fail to populate the cert attributes,
606 * trash all instances in the session-state list
607 * and cause validation to fail.
608 */
609 if (fr_tls_session_pairs_from_x509_cert(&container->vp_group, container,
610 request, cert, issuer, conf->verify.der_decode) < 0) {
611 fr_pair_delete_by_da(&request->session_state_pairs, attr_tls_certificate);
612 if (conf->verify.der_decode) {
613 fr_pair_delete_by_da(&request->session_state_pairs, attr_der_certificate);
614 }
615 fr_tls_session_error_add(request, FR_ERROR_VALUE_CERTIFICATE_ATTRIBUTES_FAILED);
616 return -1;
617 }
618
619 log_request_pair(L_DBG_LVL_2, request, NULL, container, "session-state.");
620 }
621
622 return 0;
623}
624DIAG_ON_OPTIONAL(used-but-marked-unused)
625
626/** Decode the chain, then push a `verify certificate { ... }` section
627 *
628 * tls_session_async_handshake_cont() calls the function once the handshake
629 * has paused, after the pushes for the session cache and `load psk` sections.
630 *
631 * @param[in] request The current request.
632 * @param[in] tls_session The current TLS session.
633 * @return
634 * - UNLANG_ACTION_CALCULATE_RESULT - Nothing to push, resume the handshake.
635 * - UNLANG_ACTION_PUSHED_CHILD - The section is running.
636 * - UNLANG_ACTION_FAIL - The section could not be pushed.
637 */
638unlang_action_t fr_tls_verify_cert_pending_push(request_t *request, fr_tls_session_t *tls_session)
639{
640 fr_tls_conf_t *conf = tls_session->conf;
641
642 if (tls_session->validate.state != FR_TLS_VALIDATION_REQUESTED) return UNLANG_ACTION_CALCULATE_RESULT;
643
644 /*
645 * A resumed session has no chain, its pairs came back with the session.
646 */
647 if (!tls_session->validate.resumed) {
648 RDEBUG2("(TLS) Decoding certificate chain");
649 if (tls_verify_chain_pairs_add(request, tls_session, conf) < 0) {
650 tls_session->validate.state = FR_TLS_VALIDATION_FAILED;
652 }
653 }
654
655 /*
656 * Pairs were all that was wanted.
657 */
658 if (!conf->verify_certificate || !tls_session->verify_peer_cert) {
659 tls_session->validate.state = FR_TLS_VALIDATION_SUCCESS;
661 }
662
663 RDEBUG2("(TLS) Requesting certificate validation");
664
665 return tls_verify_peer_cert_push(request, tls_session);
666}
667#endif /* WITH_TLS */
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:38
#define store(_store, _var)
static uint8_t request[4]
#define DIAG_OFF_OPTIONAL(_x)
Definition build.h:577
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:422
#define unlikely(_x)
Definition build.h:486
#define DIAG_ON_OPTIONAL(_x)
Definition build.h:578
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define MEM(x)
Definition debug.h:38
talloc_free(hp)
bool unlang_request_is_cancelled(request_t const *request)
Return whether a request has been cancelled.
Definition interpret.c:1971
HIDDEN fr_dict_attr_t const * attr_tls_certificate
Attribute definitions for lib curl.
Definition base.c:36
static fr_dict_attr_t const * attr_module_failure_message
Definition log.c:206
void log_request_pair(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_t const *vp, char const *prefix)
Print a fr_pair_t.
Definition log.c:790
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:460
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:352
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RINDENT()
Indent R* messages by one level.
Definition log.h:447
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
HIDDEN fr_dict_attr_t const * attr_tls_session_resumed
fr_value_box_t const * enum_tls_packet_type_success
HIDDEN fr_dict_attr_t const * attr_der_certificate
fr_value_box_t const * enum_tls_packet_type_verify_certificate
HIDDEN fr_dict_attr_t const * attr_tls_certificate_chain_depth
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
Definition log.h:68
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
unsigned int uint32_t
static size_t used
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
unsigned int fr_pair_count_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *da)
Return the number of instances of a given da in the specified list.
Definition pair.c:684
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
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
Definition pair.c:1641
fr_pair_t * fr_pair_find_by_da_idx(fr_pair_list_t const *list, fr_dict_attr_t const *da, unsigned int idx)
Find a pair with a matching da at a given index.
Definition pair.c:754
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
int fr_pair_steal_append(TALLOC_CTX *list_ctx, fr_pair_list_t *list, fr_pair_t *vp)
Change a vp's talloc ctx and insert it into a new list.
Definition pair.c:562
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:500
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED2()
#define RDEBUG2(fmt,...)
static bool done
Definition radclient.c:80
static rs_t * conf
Definition radsniff.c:52
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
Definition pair.h:37
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
Definition pair_inline.c:93
static int fr_pair_find_or_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Definition pair.h:541