27 RCSID(
"$Id: 421cf4e8ee42fb00dc3a6add203353a4f07b246e $")
31 #define LOG_PREFIX "tls"
33 #ifdef HAVE_SYS_STAT_H
34 # include <sys/stat.h>
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>
53 {
L(
"ASN1"), SSL_FILETYPE_ASN1 },
54 {
L(
"DER"), SSL_FILETYPE_ASN1 },
55 {
L(
"PEM"), SSL_FILETYPE_PEM }
57 static size_t certificate_format_table_len =
NUM_ELEMENTS(certificate_format_table);
60 {
L(
"hard"), FR_TLS_CHAIN_VERIFY_HARD },
61 {
L(
"none"), FR_TLS_CHAIN_VERIFY_NONE },
62 {
L(
"soft"), FR_TLS_CHAIN_VERIFY_SOFT }
64 static size_t chain_verify_mode_table_len =
NUM_ELEMENTS(chain_verify_mode_table);
67 {
L(
"auto"), FR_TLS_CACHE_AUTO },
68 {
L(
"disabled"), FR_TLS_CACHE_DISABLED },
69 {
L(
"stateful"), FR_TLS_CACHE_STATEFUL },
70 {
L(
"stateless"), FR_TLS_CACHE_STATELESS }
72 static size_t cache_mode_table_len =
NUM_ELEMENTS(cache_mode_table);
75 {
L(
"all"), FR_TLS_VERIFY_MODE_ALL },
76 {
L(
"client"), FR_TLS_VERIFY_MODE_LEAF },
77 {
L(
"client-and-issuer"), FR_TLS_VERIFY_MODE_LEAF | FR_TLS_VERIFY_MODE_ISSUER },
78 {
L(
"disabled"), FR_TLS_VERIFY_MODE_DISABLED },
79 {
L(
"untrusted"), FR_TLS_VERIFY_MODE_UNTRUSTED }
81 static size_t verify_mode_table_len =
NUM_ELEMENTS(verify_mode_table);
85 .func = tls_conf_parse_cache_mode,
87 .table = cache_mode_table,
88 .len = &cache_mode_table_len
93 {
FR_CONF_OFFSET(
"lifetime", fr_tls_cache_conf_t, lifetime), .dflt =
"1d" },
95 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
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" },
100 {
FR_CONF_OFFSET(
"session_ticket_key", fr_tls_cache_conf_t, session_ticket_key) },
116 .table = certificate_format_table,
117 .len = &certificate_format_table_len
126 {
FR_CONF_OFFSET(
"verify_mode", fr_tls_chain_conf_t, verify_mode),
129 .table = chain_verify_mode_table,
130 .len = &chain_verify_mode_table_len
133 {
FR_CONF_OFFSET(
"include_root_ca", fr_tls_chain_conf_t, include_root_ca), .dflt =
"no" },
141 .table = verify_mode_table,
142 .len = &verify_mode_table_len
145 {
FR_CONF_OFFSET(
"attribute_mode", fr_tls_verify_conf_t, attribute_mode),
148 .table = verify_mode_table,
149 .len = &verify_mode_table_len
151 .dflt =
"client-and-issuer" },
152 {
FR_CONF_OFFSET(
"check_crl", fr_tls_verify_conf_t, check_crl), .dflt =
"no" },
153 {
FR_CONF_OFFSET(
"allow_expired_crl", fr_tls_verify_conf_t, allow_expired_crl) },
154 {
FR_CONF_OFFSET(
"allow_not_yet_valid_crl", fr_tls_verify_conf_t, allow_not_yet_valid_crl) },
162 .subcs_size =
sizeof(fr_tls_chain_conf_t), .subcs_type =
"fr_tls_chain_conf_t", .name2 =
CF_IDENT_ANY },
169 {
FR_CONF_OFFSET(
"verify_depth", fr_tls_conf_t, verify_depth), .dflt =
"0" },
173 #ifdef PSK_MAX_IDENTITY_LEN
181 {
FR_CONF_OFFSET(
"fragment_size", fr_tls_conf_t, fragment_size), .dflt =
"1024" },
182 {
FR_CONF_OFFSET(
"padding", fr_tls_conf_t, padding_block_size), },
184 {
FR_CONF_OFFSET(
"disable_single_dh_use", fr_tls_conf_t, disable_single_dh_use) },
187 {
FR_CONF_OFFSET(
"cipher_server_preference", fr_tls_conf_t, cipher_server_preference), .dflt =
"yes" },
188 #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
189 {
FR_CONF_OFFSET(
"allow_renegotiation", fr_tls_conf_t, allow_renegotiation), .dflt =
"no" },
192 #ifndef OPENSSL_NO_ECDH
193 {
FR_CONF_OFFSET(
"ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt =
"prime256v1" },
195 {
FR_CONF_OFFSET(
"tls_max_version", fr_tls_conf_t, tls_max_version) },
197 {
FR_CONF_OFFSET(
"tls_min_version", fr_tls_conf_t, tls_min_version), .dflt =
"1.2" },
210 .subcs_size =
sizeof(fr_tls_chain_conf_t), .subcs_type =
"fr_tls_chain_conf_t" },
217 #ifdef PSK_MAX_IDENTITY_LEN
224 {
FR_CONF_OFFSET(
"verify_depth", fr_tls_conf_t, verify_depth), .dflt =
"0" },
230 {
FR_CONF_OFFSET(
"fragment_size", fr_tls_conf_t, fragment_size), .dflt =
"1024" },
234 #ifndef OPENSSL_NO_ECDH
235 {
FR_CONF_OFFSET(
"ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt =
"prime256v1" },
238 {
FR_CONF_OFFSET(
"tls_max_version", fr_tls_conf_t, tls_max_version) },
240 {
FR_CONF_OFFSET(
"tls_min_version", fr_tls_conf_t, tls_min_version), .dflt =
"1.2" },
249 fr_tls_conf_t *
conf = talloc_get_type_abort((
uint8_t *)
parent - offsetof(fr_tls_conf_t, cache), fr_tls_conf_t);
259 switch (cache_mode) {
260 case FR_TLS_CACHE_DISABLED:
261 case FR_TLS_CACHE_STATELESS:
264 case FR_TLS_CACHE_STATEFUL:
265 if (!
conf->virtual_server) {
266 cf_log_err(ci,
"A virtual_server must be set when cache.mode = \"stateful\"");
272 cf_log_err(ci,
"Specified virtual_server must contain a \"load session { ... }\" section "
273 "when cache.mode = \"stateful\"");
278 cf_log_err(ci,
"Specified virtual_server must contain a \"store session { ... }\" section "
279 "when cache.mode = \"stateful\"");
284 cf_log_err(ci,
"Specified virtual_server must contain a \"clear session { ... }\" section "
285 "when cache.mode = \"stateful\"");
289 if (
conf->tls_min_version >= (
float)1.3) {
290 cf_log_err(ci,
"cache.mode = \"stateful\" is not supported with tls_min_version >= 1.3");
295 case FR_TLS_CACHE_AUTO:
296 if (!
conf->virtual_server) {
297 WARN(
"A virtual_server must be provided for stateful caching. "
298 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
300 conf->cache.mode = FR_TLS_CACHE_STATELESS;
305 cf_log_warn(ci,
"Specified virtual_server missing \"load session { ... }\" section. "
306 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
307 goto cache_stateless;
311 cf_log_warn(ci,
"Specified virtual_server missing \"store session { ... }\" section. "
312 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
313 goto cache_stateless;
317 cf_log_warn(ci,
"Specified virtual_server missing \"clear cache { ... }\" section. "
318 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
319 goto cache_stateless;
322 if (
conf->tls_min_version >= (
float)1.3) {
323 cf_log_err(ci,
"stateful session-resumption is not supported with tls_min_version >= 1.3. "
324 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
333 if (cache_mode & FR_TLS_CACHE_STATELESS) {
338 if (!
conf->cache.session_ticket_key) {
341 talloc_array_length(
conf->cache.session_ticket_key));
345 *((
int *)
out) = cache_mode;
356 static char const *special_string =
"Apple:UsecertAdmin";
361 static int conf_cert_admin_password(fr_tls_conf_t *
conf)
365 if (!
conf->chains)
return 0;
367 cnt = talloc_array_length(
conf->chains);
368 for (i = 0; i < cnt; i++) {
371 long const max_password_len = 128;
374 if (!
conf->chains[i]->password)
continue;
376 if (strncmp(
conf->chains[i]->password, special_string, strlen(special_string)) != 0)
continue;
378 snprintf(cmd,
sizeof(cmd) - 1,
"/usr/sbin/certadmin --get-private-key-passphrase \"%s\"",
379 conf->chains[i]->private_key_file);
381 DEBUG2(
"Getting private key passphrase using command \"%s\"", cmd);
383 cmd_pipe = popen(cmd,
"r");
385 ERROR(
"%s command failed: Unable to get private_key_password", cmd);
386 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
390 password = talloc_array(
conf,
char, max_password_len);
392 ERROR(
"Can't allocate space for private_key_password");
393 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
398 fgets(password, max_password_len, cmd_pipe);
402 password[strlen(password) - 1] =
'\0';
404 DEBUG3(
"Password from command = \"%s\"", password);
406 conf->chains[i]->password = password;
413 #ifdef HAVE_OPENSSL_OCSP_H
421 static X509_STORE *conf_ocsp_revocation_store(fr_tls_conf_t *
conf)
423 X509_STORE *
store = NULL;
425 store = X509_STORE_new();
429 if (!X509_STORE_load_locations(
store,
conf->ca_file,
conf->ca_path)) {
430 fr_tls_log(NULL,
"Error reading Trusted root CA list \"%s\"",
conf->ca_file);
431 X509_STORE_free(
store);
435 #ifdef X509_V_FLAG_CRL_CHECK_ALL
436 if (
conf->verify.check_crl) X509_STORE_set_flags(
store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
455 fr_tls_conf_t *fr_tls_conf_alloc(TALLOC_CTX *ctx)
459 MEM(
conf = talloc_zero(ctx, fr_tls_conf_t));
465 fr_tls_conf_t *fr_tls_conf_parse_server(
CONF_SECTION *cs)
475 DEBUG(
"Using cached TLS configuration from previous invocation");
481 conf = fr_tls_conf_alloc(cs);
495 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
500 if (conf_cert_admin_password(
conf) < 0)
goto error;
511 fr_tls_conf_t *fr_tls_conf_parse_client(
CONF_SECTION *cs)
517 DEBUG2(
"Using cached TLS configuration from previous invocation");
523 conf = fr_tls_conf_alloc(cs);
537 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
543 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
#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.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
#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)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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.