27RCSID(
"$Id: 76c45b1808ce09cc5903322d1d67e387b4f9d8b2 $")
31#define LOG_PREFIX "tls"
36#include <openssl/conf.h>
38#include <freeradius-devel/server/module.h>
39#include <freeradius-devel/server/virtual_servers.h>
40#include <freeradius-devel/util/debug.h>
41#include <freeradius-devel/util/syserror.h>
42#include <freeradius-devel/util/rand.h>
54 {
L(
"ASN1"), SSL_FILETYPE_ASN1 },
55 {
L(
"DER"), SSL_FILETYPE_ASN1 },
56 {
L(
"PEM"), SSL_FILETYPE_PEM }
58static size_t certificate_format_table_len =
NUM_ELEMENTS(certificate_format_table);
61 {
L(
"hard"), FR_TLS_CHAIN_VERIFY_HARD },
62 {
L(
"none"), FR_TLS_CHAIN_VERIFY_NONE },
63 {
L(
"soft"), FR_TLS_CHAIN_VERIFY_SOFT }
65static size_t chain_verify_mode_table_len =
NUM_ELEMENTS(chain_verify_mode_table);
68 {
L(
"auto"), FR_TLS_CACHE_AUTO },
69 {
L(
"disabled"), FR_TLS_CACHE_DISABLED },
70 {
L(
"stateful"), FR_TLS_CACHE_STATEFUL },
71 {
L(
"stateless"), FR_TLS_CACHE_STATELESS }
73static size_t cache_mode_table_len =
NUM_ELEMENTS(cache_mode_table);
76 {
L(
"all"), FR_TLS_VERIFY_MODE_ALL },
77 {
L(
"client"), FR_TLS_VERIFY_MODE_LEAF },
78 {
L(
"client-and-issuer"), FR_TLS_VERIFY_MODE_LEAF | FR_TLS_VERIFY_MODE_ISSUER },
79 {
L(
"disabled"), FR_TLS_VERIFY_MODE_DISABLED },
80 {
L(
"untrusted"), FR_TLS_VERIFY_MODE_UNTRUSTED }
82static size_t verify_mode_table_len =
NUM_ELEMENTS(verify_mode_table);
86 .
func = tls_conf_parse_cache_mode,
88 .table = cache_mode_table,
89 .len = &cache_mode_table_len
94 {
FR_CONF_OFFSET(
"lifetime", fr_tls_cache_conf_t, lifetime), .dflt =
"1d" },
96 {
FR_CONF_OFFSET(
"require_extended_master_secret", fr_tls_cache_conf_t, require_extms), .dflt =
"yes" },
97 {
FR_CONF_OFFSET(
"require_perfect_forward_secrecy", fr_tls_cache_conf_t, require_pfs), .dflt =
"no" },
99 {
FR_CONF_OFFSET(
"session_ticket_key", fr_tls_cache_conf_t, session_ticket_key) },
115 .table = certificate_format_table,
116 .len = &certificate_format_table_len
125 {
FR_CONF_OFFSET(
"verify_mode", fr_tls_chain_conf_t, verify_mode),
128 .table = chain_verify_mode_table,
129 .len = &chain_verify_mode_table_len
132 {
FR_CONF_OFFSET(
"include_root_ca", fr_tls_chain_conf_t, include_root_ca), .dflt =
"no" },
140 .table = verify_mode_table,
141 .len = &verify_mode_table_len
144 {
FR_CONF_OFFSET(
"attribute_mode", fr_tls_verify_conf_t, attribute_mode),
147 .table = verify_mode_table,
148 .len = &verify_mode_table_len
150 .dflt =
"client-and-issuer" },
151 {
FR_CONF_OFFSET(
"check_crl", fr_tls_verify_conf_t, check_crl), .dflt =
"no" },
152 {
FR_CONF_OFFSET(
"allow_expired_crl", fr_tls_verify_conf_t, allow_expired_crl) },
153 {
FR_CONF_OFFSET(
"allow_not_yet_valid_crl", fr_tls_verify_conf_t, allow_not_yet_valid_crl) },
161 .subcs_size =
sizeof(fr_tls_chain_conf_t), .subcs_type =
"fr_tls_chain_conf_t", .name2 =
CF_IDENT_ANY },
168 {
FR_CONF_OFFSET(
"verify_depth", fr_tls_conf_t, verify_depth), .dflt =
"0" },
172#ifdef PSK_MAX_IDENTITY_LEN
180 {
FR_CONF_OFFSET(
"fragment_size", fr_tls_conf_t, fragment_size), .dflt =
"1024" },
181 {
FR_CONF_OFFSET(
"padding", fr_tls_conf_t, padding_block_size), },
183 {
FR_CONF_OFFSET(
"disable_single_dh_use", fr_tls_conf_t, disable_single_dh_use) },
186 {
FR_CONF_OFFSET(
"cipher_server_preference", fr_tls_conf_t, cipher_server_preference), .dflt =
"yes" },
187#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
188 {
FR_CONF_OFFSET(
"allow_renegotiation", fr_tls_conf_t, allow_renegotiation), .dflt =
"no" },
191#ifndef OPENSSL_NO_ECDH
192 {
FR_CONF_OFFSET(
"ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt =
"prime256v1" },
194 {
FR_CONF_OFFSET(
"tls_max_version", fr_tls_conf_t, tls_max_version) },
196 {
FR_CONF_OFFSET(
"tls_min_version", fr_tls_conf_t, tls_min_version), .dflt =
"1.2" },
209 .subcs_size =
sizeof(fr_tls_chain_conf_t), .subcs_type =
"fr_tls_chain_conf_t" },
216#ifdef PSK_MAX_IDENTITY_LEN
223 {
FR_CONF_OFFSET(
"verify_depth", fr_tls_conf_t, verify_depth), .dflt =
"0" },
229 {
FR_CONF_OFFSET(
"fragment_size", fr_tls_conf_t, fragment_size), .dflt =
"1024" },
233#ifndef OPENSSL_NO_ECDH
234 {
FR_CONF_OFFSET(
"ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt =
"prime256v1" },
237 {
FR_CONF_OFFSET(
"tls_max_version", fr_tls_conf_t, tls_max_version) },
239 {
FR_CONF_OFFSET(
"tls_min_version", fr_tls_conf_t, tls_min_version), .dflt =
"1.2" },
248 fr_tls_conf_t *
conf = talloc_get_type_abort(
parent, fr_tls_conf_t);
252 if (!
conf->virtual_server)
return 0;
262 fr_tls_conf_t *
conf = talloc_get_type_abort((
uint8_t *)
parent - offsetof(fr_tls_conf_t, cache), fr_tls_conf_t);
272 switch (cache_mode) {
273 case FR_TLS_CACHE_DISABLED:
274 case FR_TLS_CACHE_STATELESS:
277 case FR_TLS_CACHE_STATEFUL:
278 if (!
conf->virtual_server) {
279 cf_log_err(ci,
"A virtual_server must be set when cache.mode = \"stateful\"");
285 cf_log_err(ci,
"Specified virtual_server must contain a \"load session { ... }\" section "
286 "when cache.mode = \"stateful\"");
291 cf_log_err(ci,
"Specified virtual_server must contain a \"store session { ... }\" section "
292 "when cache.mode = \"stateful\"");
297 cf_log_err(ci,
"Specified virtual_server must contain a \"clear session { ... }\" section "
298 "when cache.mode = \"stateful\"");
302 if (
conf->tls_min_version >= (
float)1.3) {
303 cf_log_err(ci,
"cache.mode = \"stateful\" is not supported with tls_min_version >= 1.3");
308 case FR_TLS_CACHE_AUTO:
309 if (!
conf->virtual_server) {
310 WARN(
"A virtual_server must be provided for stateful caching. "
311 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
313 cache_mode = FR_TLS_CACHE_STATELESS;
318 cf_log_warn(ci,
"Specified virtual_server missing \"load session { ... }\" section. "
319 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
320 goto cache_stateless;
324 cf_log_warn(ci,
"Specified virtual_server missing \"store session { ... }\" section. "
325 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
326 goto cache_stateless;
330 cf_log_warn(ci,
"Specified virtual_server missing \"clear cache { ... }\" section. "
331 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
332 goto cache_stateless;
335 if (
conf->tls_min_version >= (
float)1.3) {
336 cf_log_err(ci,
"stateful session-resumption is not supported with tls_min_version >= 1.3. "
337 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
346 if (cache_mode & FR_TLS_CACHE_STATELESS) {
351 if (!
conf->cache.session_ticket_key) {
354 talloc_array_length(
conf->cache.session_ticket_key));
358 *((
int *)
out) = cache_mode;
369static char const *special_string =
"Apple:UsecertAdmin";
374static int conf_cert_admin_password(fr_tls_conf_t *
conf)
378 if (!
conf->chains)
return 0;
380 cnt = talloc_array_length(
conf->chains);
381 for (i = 0; i < cnt; i++) {
384 long const max_password_len = 128;
387 if (!
conf->chains[i]->password)
continue;
389 if (strncmp(
conf->chains[i]->password, special_string, strlen(special_string)) != 0)
continue;
391 snprintf(cmd,
sizeof(cmd) - 1,
"/usr/sbin/certadmin --get-private-key-passphrase \"%s\"",
392 conf->chains[i]->private_key_file);
394 DEBUG2(
"Getting private key passphrase using command \"%s\"", cmd);
396 cmd_pipe = popen(cmd,
"r");
398 ERROR(
"%s command failed: Unable to get private_key_password", cmd);
399 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
403 password = talloc_array(
conf,
char, max_password_len);
405 ERROR(
"Can't allocate space for private_key_password");
406 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
411 fgets(password, max_password_len, cmd_pipe);
415 password[strlen(password) - 1] =
'\0';
417 DEBUG3(
"Password from command = \"%s\"", password);
419 conf->chains[i]->password = password;
426#ifdef HAVE_OPENSSL_OCSP_H
434static X509_STORE *conf_ocsp_revocation_store(fr_tls_conf_t *
conf)
436 X509_STORE *
store = NULL;
438 store = X509_STORE_new();
442 if (!X509_STORE_load_locations(
store,
conf->ca_file,
conf->ca_path)) {
443 fr_tls_log(NULL,
"Error reading Trusted root CA list \"%s\"",
conf->ca_file);
444 X509_STORE_free(
store);
448#ifdef X509_V_FLAG_CRL_CHECK_ALL
449 if (
conf->verify.check_crl) X509_STORE_set_flags(
store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
468fr_tls_conf_t *fr_tls_conf_alloc(TALLOC_CTX *ctx)
472 MEM(
conf = talloc_zero(ctx, fr_tls_conf_t));
478fr_tls_conf_t *fr_tls_conf_parse_server(
CONF_SECTION *cs)
488 DEBUG(
"Using cached TLS configuration from previous invocation");
494 conf = fr_tls_conf_alloc(cs);
508 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
513 if (conf_cert_admin_password(
conf) < 0)
goto error;
524fr_tls_conf_t *fr_tls_conf_parse_client(
CONF_SECTION *cs)
530 DEBUG2(
"Using cached TLS configuration from previous invocation");
536 conf = fr_tls_conf_alloc(cs);
550 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
556 if (conf_cert_admin_password(
conf) < 0)
goto error;
#define store(_store, _var)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define USES_APPLE_DEPRECATED_API
#define L(_str)
Helper for initialising arrays of string literals.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
@ CONF_FLAG_OK_MISSING
OK if it's missing.
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_log_warn(_cf, _fmt,...)
static int _conf_server_free(fr_tls_conf_t *conf)
void fr_rand_buffer(void *start, size_t length)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
An element in a lexicographically sorted array of name to num mappings.
static int talloc_const_free(void const *ptr)
Free const'd memory.
static size_t char ** out
int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.