Coverage Report

Created: 2026-05-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/lib/tls/conf.c
Line
Count
Source
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: aa52a9cdee156b208172d3b1144477d0b1a35e30 $
19
 *
20
 * @file tls/conf.c
21
 * @brief Configuration parsing for TLS servers and clients.
22
 *
23
 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
24
 * @copyright 2003 Alan DeKok (aland@freeradius.org)
25
 * @copyright 2006-2016 The FreeRADIUS server project
26
 */
27
RCSID("$Id: aa52a9cdee156b208172d3b1144477d0b1a35e30 $")
28
USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
29
30
#ifdef WITH_TLS
31
0
#define LOG_PREFIX "tls"
32
33
#ifdef HAVE_SYS_STAT_H
34
#  include <sys/stat.h>
35
#endif
36
#include <openssl/conf.h>
37
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>
43
44
#include "base.h"
45
#include "log.h"
46
47
static int tls_conf_parse_cache_mode(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
48
static int tls_virtual_server_cf_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
49
50
/** Certificate formats
51
 *
52
 */
53
static fr_table_num_sorted_t const certificate_format_table[] = {
54
  { L("ASN1"),      SSL_FILETYPE_ASN1     },
55
  { L("DER"),     SSL_FILETYPE_ASN1     },  /* Alternate name for ASN1 */
56
  { L("PEM"),     SSL_FILETYPE_PEM      }
57
};
58
static size_t certificate_format_table_len = NUM_ELEMENTS(certificate_format_table);
59
60
static fr_table_num_sorted_t const chain_verify_mode_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    }
64
};
65
static size_t chain_verify_mode_table_len = NUM_ELEMENTS(chain_verify_mode_table);
66
67
static fr_table_num_sorted_t const cache_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      }
72
};
73
static size_t cache_mode_table_len = NUM_ELEMENTS(cache_mode_table);
74
75
static fr_table_num_sorted_t const verify_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  }
81
};
82
static size_t verify_mode_table_len = NUM_ELEMENTS(verify_mode_table);
83
84
static conf_parser_t tls_cache_config[] = {
85
  { FR_CONF_OFFSET("mode", fr_tls_cache_conf_t, mode),
86
       .func = tls_conf_parse_cache_mode,
87
       .uctx = &(cf_table_parse_ctx_t){
88
        .table = cache_mode_table,
89
        .len = &cache_mode_table_len
90
       },
91
       .dflt = "auto" },
92
  { FR_CONF_OFFSET_HINT_TYPE("name", FR_TYPE_STRING, fr_tls_cache_conf_t, id_name),
93
       .dflt = "%{EAP-Type}%interpreter('server')", .quote = T_DOUBLE_QUOTED_STRING },
94
  { FR_CONF_OFFSET("lifetime", fr_tls_cache_conf_t, lifetime), .dflt = "1d" },
95
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" },
98
99
  { FR_CONF_OFFSET("session_ticket_key", fr_tls_cache_conf_t, session_ticket_key) },
100
101
  /*
102
   *  Deprecated
103
   */
104
  { FR_CONF_DEPRECATED("enable", fr_tls_cache_conf_t, NULL) },
105
  { FR_CONF_DEPRECATED("max_entries", fr_tls_cache_conf_t, NULL) },
106
  { FR_CONF_DEPRECATED("persist_dir", fr_tls_cache_conf_t, NULL) },
107
108
  CONF_PARSER_TERMINATOR
109
};
110
111
static conf_parser_t tls_chain_config[] = {
112
  { FR_CONF_OFFSET("format", fr_tls_chain_conf_t, file_format),
113
       .func = cf_table_parse_int,
114
       .uctx = &(cf_table_parse_ctx_t){
115
        .table = certificate_format_table,
116
        .len = &certificate_format_table_len
117
       },
118
       .dflt = "pem" },
119
  { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, certificate_file) },
120
  { FR_CONF_OFFSET_FLAGS("private_key_password", CONF_FLAG_SECRET, fr_tls_chain_conf_t, password) },
121
  { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, private_key_file) },
122
123
  { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_MULTI, fr_tls_chain_conf_t, ca_files) },
124
125
  { FR_CONF_OFFSET("verify_mode", fr_tls_chain_conf_t, verify_mode),
126
       .func = cf_table_parse_int,
127
       .uctx = &(cf_table_parse_ctx_t){
128
        .table = chain_verify_mode_table,
129
        .len = &chain_verify_mode_table_len
130
       },
131
       .dflt = "hard" },
132
  { FR_CONF_OFFSET("include_root_ca", fr_tls_chain_conf_t, include_root_ca), .dflt = "no" },
133
  CONF_PARSER_TERMINATOR
134
};
135
136
static conf_parser_t tls_verify_config[] = {
137
  { FR_CONF_OFFSET("mode", fr_tls_verify_conf_t, mode),
138
       .func = cf_table_parse_int,
139
       .uctx = &(cf_table_parse_ctx_t){
140
        .table = verify_mode_table,
141
        .len = &verify_mode_table_len
142
       },
143
       .dflt = "all" },
144
  { FR_CONF_OFFSET("attribute_mode", fr_tls_verify_conf_t, attribute_mode),
145
       .func = cf_table_parse_int,
146
       .uctx = &(cf_table_parse_ctx_t){
147
        .table = verify_mode_table,
148
        .len = &verify_mode_table_len
149
       },
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) },
154
  { FR_CONF_OFFSET("der_decode", fr_tls_verify_conf_t, der_decode) },
155
  CONF_PARSER_TERMINATOR
156
};
157
158
conf_parser_t fr_tls_server_config[] = {
159
  { FR_CONF_OFFSET_TYPE_FLAGS("virtual_server", FR_TYPE_VOID, 0, fr_tls_conf_t, virtual_server), .func = tls_virtual_server_cf_parse },
160
161
  { FR_CONF_OFFSET_SUBSECTION("chain", CONF_FLAG_MULTI, fr_tls_conf_t, chains, tls_chain_config),
162
    .subcs_size = sizeof(fr_tls_chain_conf_t), .subcs_type = "fr_tls_chain_conf_t", .name2 = CF_IDENT_ANY },
163
164
  { FR_CONF_DEPRECATED("pem_file_type", fr_tls_conf_t, NULL) },
165
  { FR_CONF_DEPRECATED("certificate_file", fr_tls_conf_t, NULL) },
166
  { FR_CONF_DEPRECATED("private_key_password", fr_tls_conf_t, NULL) },
167
  { FR_CONF_DEPRECATED("private_key_file", fr_tls_conf_t, NULL) },
168
169
  { FR_CONF_OFFSET("verify_depth", fr_tls_conf_t, verify_depth), .dflt = "0" },
170
  { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_path) },
171
  { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_file) },
172
173
#ifdef PSK_MAX_IDENTITY_LEN
174
  { FR_CONF_OFFSET("psk_identity", fr_tls_conf_t, psk_identity) },
175
  { FR_CONF_OFFSET_FLAGS("psk_hexphrase", CONF_FLAG_SECRET, fr_tls_conf_t, psk_password) },
176
  { FR_CONF_OFFSET("psk_query", fr_tls_conf_t, psk_query) },
177
#endif
178
  { FR_CONF_OFFSET("keylog_file", fr_tls_conf_t, keylog_file) },
179
180
  { FR_CONF_OFFSET_FLAGS("dh_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, dh_file) },
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), },
183
184
  { FR_CONF_OFFSET("disable_single_dh_use", fr_tls_conf_t, disable_single_dh_use) },
185
186
  { FR_CONF_OFFSET("cipher_list", fr_tls_conf_t, cipher_list) },
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" },
190
#endif
191
192
#ifndef OPENSSL_NO_ECDH
193
  { FR_CONF_OFFSET("ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt = "prime256v1" },
194
#endif
195
  { FR_CONF_OFFSET("tls_max_version", fr_tls_conf_t, tls_max_version) },
196
197
  { FR_CONF_OFFSET("tls_min_version", fr_tls_conf_t, tls_min_version), .dflt = "1.2" },
198
199
  { FR_CONF_OFFSET("client_hello_parse", fr_tls_conf_t, client_hello_parse )},
200
201
  { FR_CONF_OFFSET_SUBSECTION("session", 0, fr_tls_conf_t, cache, tls_cache_config) },
202
203
  { FR_CONF_OFFSET_SUBSECTION("verify", 0, fr_tls_conf_t, verify, tls_verify_config) },
204
205
  { FR_CONF_DEPRECATED("check_cert_issuer", fr_tls_conf_t, check_cert_issuer) },
206
  { FR_CONF_DEPRECATED("check_cert_cn", fr_tls_conf_t, check_cert_cn) },
207
  CONF_PARSER_TERMINATOR
208
};
209
210
conf_parser_t fr_tls_client_config[] = {
211
  { FR_CONF_OFFSET_SUBSECTION("chain", CONF_FLAG_OK_MISSING | CONF_FLAG_MULTI, fr_tls_conf_t, chains, tls_chain_config),
212
    .subcs_size = sizeof(fr_tls_chain_conf_t), .subcs_type = "fr_tls_chain_conf_t" },
213
214
  { FR_CONF_DEPRECATED("pem_file_type", fr_tls_conf_t, NULL) },
215
  { FR_CONF_DEPRECATED("certificate_file", fr_tls_conf_t, NULL) },
216
  { FR_CONF_DEPRECATED("private_key_password", fr_tls_conf_t, NULL) },
217
  { FR_CONF_DEPRECATED("private_key_file", fr_tls_conf_t, NULL) },
218
219
#ifdef PSK_MAX_IDENTITY_LEN
220
  { FR_CONF_OFFSET("psk_identity", fr_tls_conf_t, psk_identity) },
221
  { FR_CONF_OFFSET_FLAGS("psk_hexphrase", CONF_FLAG_SECRET, fr_tls_conf_t, psk_password) },
222
#endif
223
224
  { FR_CONF_OFFSET("keylog_file", fr_tls_conf_t, keylog_file) },
225
226
  { FR_CONF_OFFSET("verify_depth", fr_tls_conf_t, verify_depth), .dflt = "0" },
227
  { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_path) },
228
229
  { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_file) },
230
  { FR_CONF_OFFSET("dh_file", fr_tls_conf_t, dh_file) },
231
  { FR_CONF_OFFSET("random_file", fr_tls_conf_t, random_file) },
232
  { FR_CONF_OFFSET("fragment_size",  fr_tls_conf_t, fragment_size), .dflt = "1024" },
233
234
  { FR_CONF_OFFSET("cipher_list", fr_tls_conf_t, cipher_list) },
235
236
#ifndef OPENSSL_NO_ECDH
237
  { FR_CONF_OFFSET("ecdh_curve", fr_tls_conf_t, ecdh_curve), .dflt = "prime256v1" },
238
#endif
239
240
  { FR_CONF_OFFSET("tls_max_version", fr_tls_conf_t, tls_max_version) },
241
242
  { FR_CONF_OFFSET("tls_min_version", fr_tls_conf_t, tls_min_version), .dflt = "1.2" },
243
244
  { FR_CONF_DEPRECATED("check_cert_issuer", fr_tls_conf_t, check_cert_issuer) },
245
  { FR_CONF_DEPRECATED("check_cert_cn", fr_tls_conf_t, check_cert_cn) },
246
  CONF_PARSER_TERMINATOR
247
};
248
249
static int tls_virtual_server_cf_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
250
0
{
251
0
  fr_tls_conf_t *conf = talloc_get_type_abort(parent, fr_tls_conf_t);
252
0
  virtual_server_t const  *vs = NULL;
253
254
0
  if (virtual_server_cf_parse(ctx, &vs, parent, ci, rule) < 0) return -1;
255
256
0
  if (!vs) return 0;
257
258
  /*
259
   *  `out` points to conf->virtual_server
260
   */
261
0
  *((CONF_SECTION const **)out) = virtual_server_cs(vs);
262
0
  conf->verify_certificate = cf_section_find(conf->virtual_server, "verify", "certificate") ? true : false;
263
0
  conf->new_session = cf_section_find(conf->virtual_server, "new", "session") ? true : false;
264
0
  conf->establish_session = cf_section_find(conf->virtual_server, "establish", "session") ? true : false;
265
0
  return 0;
266
0
}
267
268
static int tls_conf_parse_cache_mode(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
269
{
270
  fr_tls_conf_t *conf = talloc_get_type_abort((uint8_t *)parent - offsetof(fr_tls_conf_t, cache), fr_tls_conf_t);
271
  int   cache_mode;
272
273
  if (cf_table_parse_int(ctx, &cache_mode, parent, ci, rule) < 0) return -1;
274
275
  /*
276
   *  Ensure our virtual server contains the
277
   *      correct sections for the specified
278
   *      cache mode.
279
   */
280
  switch (cache_mode) {
281
  case FR_TLS_CACHE_DISABLED:
282
  case FR_TLS_CACHE_STATELESS:
283
    break;
284
285
  case FR_TLS_CACHE_STATEFUL:
286
    if (!conf->virtual_server) {
287
      cf_log_err(ci, "A virtual_server must be set when cache.mode = \"stateful\"");
288
    error:
289
      return -1;
290
    }
291
292
    if (!cf_section_find(conf->virtual_server, "load", "session")) {
293
      cf_log_err(ci, "Specified virtual_server must contain a \"load session { ... }\" section "
294
           "when cache.mode = \"stateful\"");
295
      goto error;
296
    }
297
298
    if (!cf_section_find(conf->virtual_server, "store", "session")) {
299
      cf_log_err(ci, "Specified virtual_server must contain a \"store session { ... }\" section "
300
           "when cache.mode = \"stateful\"");
301
      goto error;
302
    }
303
304
    if (!cf_section_find(conf->virtual_server, "clear", "session")) {
305
      cf_log_err(ci, "Specified virtual_server must contain a \"clear session { ... }\" section "
306
                 "when cache.mode = \"stateful\"");
307
      goto error;
308
    }
309
310
    if (conf->tls_min_version >= (float)1.3) {
311
      cf_log_err(ci, "cache.mode = \"stateful\" is not supported with tls_min_version >= 1.3");
312
      goto error;
313
    }
314
    break;
315
316
  case FR_TLS_CACHE_AUTO:
317
    if (!conf->virtual_server) {
318
      WARN("A virtual_server must be provided for stateful caching. "
319
           "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
320
    cache_stateless:
321
      cache_mode = FR_TLS_CACHE_STATELESS;
322
      break;
323
    }
324
325
    if (!cf_section_find(conf->virtual_server, "load", "session")) {
326
      cf_log_warn(ci, "Specified virtual_server missing \"load session { ... }\" section. "
327
                  "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
328
      goto cache_stateless;
329
    }
330
331
    if (!cf_section_find(conf->virtual_server, "store", "session")) {
332
      cf_log_warn(ci, "Specified virtual_server missing \"store session { ... }\" section. "
333
                  "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
334
      goto cache_stateless;
335
    }
336
337
    if (!cf_section_find(conf->virtual_server, "clear", "session")) {
338
      cf_log_warn(ci, "Specified virtual_server missing \"clear cache { ... }\" section. "
339
            "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
340
      goto cache_stateless;
341
    }
342
343
    if (conf->tls_min_version >= (float)1.3) {
344
      cf_log_err(ci, "stateful session-resumption is not supported with tls_min_version >= 1.3. "
345
                 "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\"");
346
      goto cache_stateless;
347
    }
348
    break;
349
  }
350
351
  /*
352
   *  Generate random, ephemeral, session-ticket keys.
353
   */
354
  if (cache_mode & FR_TLS_CACHE_STATELESS) {
355
    /*
356
     *  Fill the key with randomness if one
357
     *  wasn't specified by the user.
358
     */
359
    if (!conf->cache.session_ticket_key) {
360
      MEM(conf->cache.session_ticket_key = talloc_array(conf, uint8_t, 256));
361
      fr_rand_buffer(UNCONST(uint8_t *, conf->cache.session_ticket_key),
362
               talloc_array_length(conf->cache.session_ticket_key));
363
    }
364
  }
365
366
  *((int *)out) = cache_mode;
367
368
  return 0;
369
}
370
371
#ifdef __APPLE__
372
/*
373
 *  We don't want to put the private key password in eap.conf, so check
374
 *  for our special string which indicates we should get the password
375
 *  programmatically.
376
 */
377
static char const *special_string = "Apple:UsecertAdmin";
378
379
/** Use cert_admin to retrieve the password for the private key
380
 *
381
 */
382
static int conf_cert_admin_password(fr_tls_conf_t *conf)
383
{
384
  size_t i, cnt;
385
386
  if (!conf->chains) return 0;
387
388
  cnt = talloc_array_length(conf->chains);
389
  for (i = 0; i < cnt; i++) {
390
    char    cmd[256];
391
    char    *password, *buf;
392
    long const  max_password_len = 128;
393
    FILE    *cmd_pipe;
394
395
    if (!conf->chains[i]->password) continue;
396
397
    if (strncmp(conf->chains[i]->password, special_string, strlen(special_string)) != 0) continue;
398
399
    snprintf(cmd, sizeof(cmd) - 1, "/usr/sbin/certadmin --get-private-key-passphrase \"%s\"",
400
       conf->chains[i]->private_key_file);
401
402
    DEBUG2("Getting private key passphrase using command \"%s\"", cmd);
403
404
    cmd_pipe = popen(cmd, "r");
405
    if (!cmd_pipe) {
406
      ERROR("%s command failed: Unable to get private_key_password", cmd);
407
      ERROR("Error reading private_key_file %s", conf->chains[i]->private_key_file);
408
      return -1;
409
    }
410
411
    password = talloc_array(conf, char, max_password_len);
412
    if (!password) {
413
      ERROR("Can't allocate space for private_key_password");
414
      ERROR("Error reading private_key_file %s", conf->chains[i]->private_key_file);
415
      pclose(cmd_pipe);
416
      return -1;
417
    }
418
419
    buf = fgets(password, max_password_len, cmd_pipe);
420
421
    if (!buf || ferror(cmd_pipe)) {
422
      pclose(cmd_pipe);
423
      talloc_free(password);
424
      ERROR("%s command failed: Unable to get private_key_password", cmd);
425
      ERROR("Error reading private_key_file %s", conf->chains[i]->private_key_file);
426
      return -1;
427
    }
428
    pclose(cmd_pipe);
429
430
    /* Get rid of newline at end of password. */
431
    for (buf = password; buf < (password + max_password_len); buf++) {
432
      if (*buf < ' ') {
433
        *buf = '\0';
434
        goto found;
435
      }
436
    }
437
438
    talloc_free(password);
439
    ERROR("%s command failed: Unable to get private_key_password", cmd);
440
    ERROR("Error reading private_key_file %s - password is too long", conf->chains[i]->private_key_file);
441
    return -1;
442
443
  found:
444
    DEBUG3("Password from command = \"%s\"", password);
445
    talloc_const_free(conf->chains[i]->password);
446
    conf->chains[i]->password = password;
447
  }
448
449
  return 0;
450
}
451
#endif
452
453
#ifdef HAVE_OPENSSL_OCSP_H
454
/*
455
 *  Create Global X509 revocation store and use it to verify
456
 *  OCSP responses
457
 *
458
 *  - Load the trusted CAs
459
 *  - Load the trusted issuer certificates
460
 */
461
static X509_STORE *conf_ocsp_revocation_store(fr_tls_conf_t *conf)
462
{
463
  X509_STORE *store = NULL;
464
465
  store = X509_STORE_new();
466
467
  /* Load the CAs we trust */
468
  if (conf->ca_file || conf->ca_path)
469
    if (!X509_STORE_load_locations(store, conf->ca_file, conf->ca_path)) {
470
      fr_tls_log(NULL, "Error reading Trusted root CA list \"%s\"", conf->ca_file);
471
      X509_STORE_free(store);
472
      return NULL;
473
    }
474
475
#ifdef X509_V_FLAG_CRL_CHECK_ALL
476
  if (conf->verify.check_crl) X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
477
#endif
478
479
  return store;
480
}
481
#endif
482
483
/*
484
 *  Free TLS client/server config
485
 *  Should not be called outside this code, as a callback is
486
 *  added to automatically free the data when the CONF_SECTION
487
 *  is freed.
488
 */
489
static int _conf_server_free(fr_tls_conf_t *conf)
490
0
{
491
0
  memset(conf, 0, sizeof(*conf));
492
0
  return 0;
493
0
}
494
495
fr_tls_conf_t *fr_tls_conf_alloc(TALLOC_CTX *ctx)
496
0
{
497
0
  fr_tls_conf_t *conf;
498
499
0
  MEM(conf = talloc_zero(ctx, fr_tls_conf_t));
500
0
  talloc_set_destructor(conf, _conf_server_free);
501
502
0
  return conf;
503
0
}
504
505
fr_tls_conf_t *fr_tls_conf_parse_server(CONF_SECTION *cs)
506
0
{
507
0
  fr_tls_conf_t *conf;
508
509
  /*
510
   *  If cs has already been parsed there should be a cached copy
511
   *  of conf already stored, so just return that.
512
   */
513
0
  conf = cf_data_value(cf_data_find(cs, fr_tls_conf_t, NULL));
514
0
  if (conf) {
515
0
    DEBUG("Using cached TLS configuration from previous invocation");
516
0
    return conf;
517
0
  }
518
519
0
  if (cf_section_rules_push(cs, fr_tls_server_config) < 0) return NULL;
520
521
0
  conf = fr_tls_conf_alloc(cs);
522
523
0
  if ((cf_section_parse(conf, conf, cs) < 0) ||
524
0
      (cf_section_parse_pass2(conf, cs) < 0)) {
525
#ifdef __APPLE__
526
  error:
527
#endif
528
0
    talloc_free(conf);
529
0
    return NULL;
530
0
  }
531
532
  /*
533
   *  Save people from their own stupidity.
534
   */
535
0
  if (conf->fragment_size < 100) conf->fragment_size = 100;
536
537
0
  FR_INTEGER_BOUND_CHECK("padding", conf->padding_block_size, <=, SSL3_RT_MAX_PLAIN_LENGTH);
538
539
#ifdef __APPLE__
540
  if (conf_cert_admin_password(conf) < 0) goto error;
541
#endif
542
543
  /*
544
   *  Cache conf in cs in case we're asked to parse this again.
545
   */
546
0
  cf_data_add(cs, conf, NULL, false);
547
548
0
  return conf;
549
0
}
550
551
fr_tls_conf_t *fr_tls_conf_parse_client(CONF_SECTION *cs)
552
0
{
553
0
  fr_tls_conf_t *conf;
554
555
0
  conf = cf_data_value(cf_data_find(cs, fr_tls_conf_t, NULL));
556
0
  if (conf) {
557
0
    DEBUG2("Using cached TLS configuration from previous invocation");
558
0
    return conf;
559
0
  }
560
561
0
  if (cf_section_rules_push(cs, fr_tls_client_config) < 0) return NULL;
562
563
0
  conf = fr_tls_conf_alloc(cs);
564
565
0
  if ((cf_section_parse(conf, conf, cs) < 0) ||
566
0
      (cf_section_parse_pass2(conf, cs) < 0)) {
567
#ifdef __APPLE__
568
  error:
569
#endif
570
0
    talloc_free(conf);
571
0
    return NULL;
572
0
  }
573
574
  /*
575
   *  Save people from their own stupidity.
576
   */
577
0
  if (conf->fragment_size < 100) conf->fragment_size = 100;
578
579
  /*
580
   *  Initialize TLS
581
   */
582
#ifdef __APPLE__
583
  if (conf_cert_admin_password(conf) < 0) goto error;
584
#endif
585
586
0
  cf_data_add(cs, conf, NULL, false);
587
588
0
  return conf;
589
0
}
590
#endif  /* WITH_TLS */