mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-06-09 08:34:02 -04:00
- Fix #278: DoT: complete unbound restart required on certificate
renew. Fix so that a reload checks if the files have changed, and if so, reload the contexts. Also for DoH, DoQ and outgoing DoT.
This commit is contained in:
parent
4672fa5b53
commit
2eff1d8ab5
11 changed files with 267 additions and 62 deletions
|
|
@ -735,6 +735,12 @@
|
|||
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
||||
|
||||
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
|
||||
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
|
|
|
|||
17
configure
vendored
17
configure
vendored
|
|
@ -23268,6 +23268,23 @@ printf "%s\n" "no" >&6; }
|
|||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" "ac_cv_member_struct_stat_st_mtimensec" "$ac_includes_default"
|
||||
if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" "ac_cv_member_struct_stat_st_mtim_tv_nsec" "$ac_includes_default"
|
||||
if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" "
|
||||
|
|
|
|||
|
|
@ -1769,6 +1769,7 @@ if test $ac_cv_func_daemon = yes; then
|
|||
])
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
|
||||
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
|
|
|||
186
daemon/daemon.c
186
daemon/daemon.c
|
|
@ -199,6 +199,181 @@ signal_handling_playback(struct worker* wrk)
|
|||
sig_record_reload = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
|
||||
struct config_file* cfg, char* chroot)
|
||||
{
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
if(!(*ctx = listen_sslctx_create(key, pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_use_system_policy_versions))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void
|
||||
daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
char* bundle, *chroot = daemon->chroot;
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first, chroot)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0,
|
||||
cfg, chroot);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx,
|
||||
0, 1, cfg, chroot);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
|
||||
key, pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* Store the file name and mtime to detect changes later. */
|
||||
daemon->ssl_service_key = strdup(cfg->ssl_service_key);
|
||||
if(!daemon->ssl_service_key)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
daemon->ssl_service_pem = strdup(cfg->ssl_service_pem);
|
||||
if(!daemon->ssl_service_pem)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
if(!file_get_mtime(key,
|
||||
&daemon->mtime_ssl_service_key,
|
||||
&daemon->mtime_ns_ssl_service_key, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
if(!file_get_mtime(pem,
|
||||
&daemon->mtime_ssl_service_pem,
|
||||
&daemon->mtime_ns_ssl_service_pem, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
}
|
||||
bundle = cfg->tls_cert_bundle;
|
||||
if(chroot && bundle && strncmp(bundle, chroot, strlen(chroot)) == 0)
|
||||
bundle += strlen(chroot);
|
||||
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/** Delete the ssl ctxs */
|
||||
static void
|
||||
daemon_delete_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
daemon->listen_dot_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
daemon->listen_doh_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
daemon->connect_dot_sslctx = NULL;
|
||||
free(daemon->ssl_service_key);
|
||||
daemon->ssl_service_key = NULL;
|
||||
free(daemon->ssl_service_pem);
|
||||
daemon->ssl_service_pem = NULL;
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
daemon->listen_quic_sslctx = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** See if the SSL cert files have changed */
|
||||
static int
|
||||
ssl_cert_changed(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
time_t mtime = 0;
|
||||
long ns = 0;
|
||||
log_assert(daemon->ssl_service_key && cfg->ssl_service_key);
|
||||
if(strcmp(daemon->ssl_service_key, cfg->ssl_service_key) != 0)
|
||||
return 1;
|
||||
if(strcmp(daemon->ssl_service_pem, cfg->ssl_service_pem) != 0)
|
||||
return 1;
|
||||
if(!file_get_mtime(daemon->ssl_service_key, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
daemon->ssl_service_key, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_key ||
|
||||
ns != daemon->mtime_ns_ssl_service_key)
|
||||
return 1;
|
||||
if(!file_get_mtime(daemon->ssl_service_pem, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
daemon->ssl_service_pem, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_pem ||
|
||||
ns != daemon->mtime_ns_ssl_service_pem)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Reload the sslctxs if they have changed */
|
||||
static void
|
||||
daemon_reload_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(daemon->cfg->ssl_service_key && daemon->cfg->ssl_service_key[0]) {
|
||||
/* See if changed */
|
||||
if(!daemon->ssl_service_key ||
|
||||
ssl_cert_changed(daemon,daemon->cfg)) {
|
||||
verbose(VERB_ALGO, "Reloading certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
daemon_setup_sslctxs(daemon, daemon->cfg);
|
||||
}
|
||||
} else {
|
||||
/* See if sslctxs are removed from config. */
|
||||
if(daemon->ssl_service_key) {
|
||||
verbose(VERB_ALGO, "Removing certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init(void)
|
||||
{
|
||||
|
|
@ -745,6 +920,7 @@ daemon_fork(struct daemon* daemon)
|
|||
#endif
|
||||
|
||||
log_assert(daemon);
|
||||
daemon_reload_sslctxs(daemon);
|
||||
if(!(daemon->env->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
/* create individual views and their localzone/data trees */
|
||||
|
|
@ -991,15 +1167,7 @@ daemon_delete(struct daemon* daemon)
|
|||
free(daemon->pidfile);
|
||||
free(daemon->cfgfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
#endif
|
||||
daemon_delete_sslctxs(daemon);
|
||||
free(daemon);
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
|
|
|
|||
|
|
@ -107,6 +107,18 @@ struct daemon {
|
|||
void* listen_doh_sslctx;
|
||||
/** ssl context for listening to quic */
|
||||
void* listen_quic_sslctx;
|
||||
/** the file name that the ssl context is made with, private key. */
|
||||
char* ssl_service_key;
|
||||
/** the file name that the ssl context is made with, certificate. */
|
||||
char* ssl_service_pem;
|
||||
/** modification time for ssl_service_key, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_key;
|
||||
long mtime_ns_ssl_service_key;
|
||||
/** modification time for ssl_service_pem, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_pem;
|
||||
long mtime_ns_ssl_service_pem;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** num threads allocated in the previous config or 0 at first */
|
||||
|
|
@ -229,4 +241,7 @@ void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
|||
*/
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
#endif /* DAEMON_H */
|
||||
|
|
|
|||
|
|
@ -463,57 +463,13 @@ detach(void)
|
|||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
/** setup the remote and ticket keys */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg)
|
||||
{
|
||||
if(!(*ctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_use_system_policy_versions))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
setup_sslctx_remote(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
}
|
||||
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
|
|
@ -545,7 +501,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||
#endif
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
(void)setup_sslctxs(daemon, cfg);
|
||||
setup_sslctx_remote(daemon, cfg);
|
||||
daemon_setup_sslctxs(daemon, cfg);
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
to Yuxiao Wu, Yiyi Wang, Zhang Chao, Baojun Liu, and Haixin Duan from
|
||||
Tsinghua University.
|
||||
|
||||
13 March 2026: Wouter
|
||||
- Fix #278: DoT: complete unbound restart required on certificate
|
||||
renew. Fix so that a reload checks if the files have changed, and
|
||||
if so, reload the contexts. Also for DoH, DoQ and outgoing DoT.
|
||||
|
||||
9 March 2026: Wouter
|
||||
- Fix compile failure in unbound-checkconf for older gcc compiler.
|
||||
- Merge #1418: Apply cache TTL policy to DNAME and synthesized
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@
|
|||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
#include "iterator/iterator.h"
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_GLOB_H
|
||||
# include <glob.h>
|
||||
#endif
|
||||
|
|
@ -2984,3 +2987,27 @@ cfg_has_quic(struct config_file* cfg)
|
|||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
file_get_mtime(const char* file, time_t* mtime, long* ns, int* nonexist)
|
||||
{
|
||||
struct stat s;
|
||||
if(stat(file, &s) != 0) {
|
||||
*mtime = 0;
|
||||
*ns = 0;
|
||||
if(nonexist)
|
||||
*nonexist = (errno == ENOENT);
|
||||
return 0;
|
||||
}
|
||||
if(nonexist)
|
||||
*nonexist = 0;
|
||||
*mtime = s.st_mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
*ns = s.st_mtimensec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
*ns = s.st_mtim.tv_nsec;
|
||||
#else
|
||||
*ns = 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1493,4 +1493,7 @@ size_t getmem_str(char* str);
|
|||
*/
|
||||
int cfg_ports_list_contains(char* ports, int p);
|
||||
|
||||
/** get the file mtime stat (or error, with errno and nonexist) */
|
||||
int file_get_mtime(const char* file, time_t* mtime, long* ns, int* nonexist);
|
||||
|
||||
#endif /* UTIL_CONFIG_FILE_H */
|
||||
|
|
|
|||
|
|
@ -1799,7 +1799,7 @@ void ub_openssl_lock_delete(void)
|
|||
#endif /* OPENSSL_THREADS */
|
||||
}
|
||||
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys) {
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys, char* chroot) {
|
||||
#ifdef HAVE_SSL
|
||||
size_t s = 1;
|
||||
struct config_strlist* p;
|
||||
|
|
@ -1817,14 +1817,18 @@ int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_ke
|
|||
size_t n;
|
||||
unsigned char *data;
|
||||
FILE *f;
|
||||
char* fstr;
|
||||
|
||||
data = (unsigned char *)malloc(80);
|
||||
if(!data)
|
||||
return 0;
|
||||
|
||||
f = fopen(p->str, "rb");
|
||||
fstr = p->str;
|
||||
if(chroot && strncmp(fstr, chroot, strlen(chroot)) == 0)
|
||||
fstr += strlen(chroot);
|
||||
f = fopen(fstr, "rb");
|
||||
if(!f) {
|
||||
log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
|
||||
log_err("could not read tls-session-ticket-key %s: %s", fstr, strerror(errno));
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1832,11 +1836,11 @@ int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_ke
|
|||
fclose(f);
|
||||
|
||||
if(n != 80) {
|
||||
log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
|
||||
log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", fstr, (int)n);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
|
||||
verbose(VERB_OPS, "read tls-session-ticket-key: %s", fstr);
|
||||
|
||||
keys->key_name = data;
|
||||
keys->aes_key = data + 16;
|
||||
|
|
|
|||
|
|
@ -567,9 +567,11 @@ void ub_openssl_lock_delete(void);
|
|||
/**
|
||||
* setup TLS session ticket
|
||||
* @param tls_session_ticket_keys: TLS ticket secret filenames
|
||||
* @param chroot: if not NULL, the chroot that is in use.
|
||||
* @return false on failure (alloc failure).
|
||||
*/
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys);
|
||||
int listen_sslctx_setup_ticket_keys(
|
||||
struct config_strlist* tls_session_ticket_keys, char* chroot);
|
||||
|
||||
/** Free memory used for TLS session ticket keys */
|
||||
void listen_sslctx_delete_ticket_keys(void);
|
||||
|
|
|
|||
Loading…
Reference in a new issue