27RCSID(
"$Id: bb190214c501c9f062dc9f78145e7a8c0de6c8d3 $")
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);
267 fr_tls_conf_t *
conf = talloc_get_type_abort((
uint8_t *)
parent - offsetof(fr_tls_conf_t, cache), fr_tls_conf_t);
277 switch (cache_mode) {
278 case FR_TLS_CACHE_DISABLED:
279 case FR_TLS_CACHE_STATELESS:
282 case FR_TLS_CACHE_STATEFUL:
283 if (!
conf->virtual_server) {
284 cf_log_err(ci,
"A virtual_server must be set when cache.mode = \"stateful\"");
290 cf_log_err(ci,
"Specified virtual_server must contain a \"load session { ... }\" section "
291 "when cache.mode = \"stateful\"");
296 cf_log_err(ci,
"Specified virtual_server must contain a \"store session { ... }\" section "
297 "when cache.mode = \"stateful\"");
302 cf_log_err(ci,
"Specified virtual_server must contain a \"clear session { ... }\" section "
303 "when cache.mode = \"stateful\"");
307 if (
conf->tls_min_version >= (
float)1.3) {
308 cf_log_err(ci,
"cache.mode = \"stateful\" is not supported with tls_min_version >= 1.3");
313 case FR_TLS_CACHE_AUTO:
314 if (!
conf->virtual_server) {
315 WARN(
"A virtual_server must be provided for stateful caching. "
316 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
318 cache_mode = FR_TLS_CACHE_STATELESS;
323 cf_log_warn(ci,
"Specified virtual_server missing \"load session { ... }\" section. "
324 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
325 goto cache_stateless;
329 cf_log_warn(ci,
"Specified virtual_server missing \"store session { ... }\" section. "
330 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
331 goto cache_stateless;
335 cf_log_warn(ci,
"Specified virtual_server missing \"clear cache { ... }\" section. "
336 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
337 goto cache_stateless;
340 if (
conf->tls_min_version >= (
float)1.3) {
341 cf_log_err(ci,
"stateful session-resumption is not supported with tls_min_version >= 1.3. "
342 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
351 if (cache_mode & FR_TLS_CACHE_STATELESS) {
356 if (!
conf->cache.session_ticket_key) {
359 talloc_array_length(
conf->cache.session_ticket_key));
363 *((
int *)
out) = cache_mode;
374static char const *special_string =
"Apple:UsecertAdmin";
379static int conf_cert_admin_password(fr_tls_conf_t *
conf)
383 if (!
conf->chains)
return 0;
385 cnt = talloc_array_length(
conf->chains);
386 for (i = 0; i < cnt; i++) {
389 long const max_password_len = 128;
392 if (!
conf->chains[i]->password)
continue;
394 if (strncmp(
conf->chains[i]->password, special_string, strlen(special_string)) != 0)
continue;
396 snprintf(cmd,
sizeof(cmd) - 1,
"/usr/sbin/certadmin --get-private-key-passphrase \"%s\"",
397 conf->chains[i]->private_key_file);
399 DEBUG2(
"Getting private key passphrase using command \"%s\"", cmd);
401 cmd_pipe = popen(cmd,
"r");
403 ERROR(
"%s command failed: Unable to get private_key_password", cmd);
404 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
408 password = talloc_array(
conf,
char, max_password_len);
410 ERROR(
"Can't allocate space for private_key_password");
411 ERROR(
"Error reading private_key_file %s",
conf->chains[i]->private_key_file);
416 fgets(password, max_password_len, cmd_pipe);
420 password[strlen(password) - 1] =
'\0';
422 DEBUG3(
"Password from command = \"%s\"", password);
424 conf->chains[i]->password = password;
431#ifdef HAVE_OPENSSL_OCSP_H
439static X509_STORE *conf_ocsp_revocation_store(fr_tls_conf_t *
conf)
441 X509_STORE *
store = NULL;
443 store = X509_STORE_new();
447 if (!X509_STORE_load_locations(
store,
conf->ca_file,
conf->ca_path)) {
448 fr_tls_log(NULL,
"Error reading Trusted root CA list \"%s\"",
conf->ca_file);
449 X509_STORE_free(
store);
453#ifdef X509_V_FLAG_CRL_CHECK_ALL
454 if (
conf->verify.check_crl) X509_STORE_set_flags(
store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
473fr_tls_conf_t *fr_tls_conf_alloc(TALLOC_CTX *ctx)
477 MEM(
conf = talloc_zero(ctx, fr_tls_conf_t));
483fr_tls_conf_t *fr_tls_conf_parse_server(
CONF_SECTION *cs)
493 DEBUG(
"Using cached TLS configuration from previous invocation");
499 conf = fr_tls_conf_alloc(cs);
513 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
518 if (conf_cert_admin_password(
conf) < 0)
goto error;
529fr_tls_conf_t *fr_tls_conf_parse_client(
CONF_SECTION *cs)
535 DEBUG2(
"Using cached TLS configuration from previous invocation");
541 conf = fr_tls_conf_alloc(cs);
555 if (
conf->fragment_size < 100)
conf->fragment_size = 100;
561 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_HINT_TYPE(_name, _type, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#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_READABLE
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,...)
@ FR_TYPE_STRING
String of printable characters.
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.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.