From 9cb0788702e6187eafccabba0758095ced04552c Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 24 Mar 2010 13:15:41 -0700 Subject: [PATCH] stream-ssl: Only re-read certificates and keys if they change. Commit 415f6c0b1 "stream-ssl: Make no-op reconfiguration cheap" caused ovsdb-server to re-read its certificates and keys every 60 seconds just in case they changed. However, doing this causes OpenSSL to drop its connections. This commit solves the problem by making stream-ssl re-read certificates and keys only if the files changed. Bug #2535. Reported-by: Ram Jothikumar --- configure.ac | 2 ++ lib/stream-ssl.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 1fc6a479..6d49484f 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,8 @@ OVS_CHECK_PCRE OVS_CHECK_PYTHON OVS_CHECK_IF_PACKET OVS_CHECK_STRTOK_R +AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec], + [], [], [[#include ]]) OVS_CHECK_PKIDIR OVS_CHECK_RUNDIR diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c index 78582908..215934d1 100644 --- a/lib/stream-ssl.c +++ b/lib/stream-ssl.c @@ -133,8 +133,7 @@ static SSL_CTX *ctx; struct ssl_config_file { bool read; /* Whether the file was successfully read. */ char *file_name; /* Configured file name, if any. */ - long long int next_retry; /* If 'file_name' but not 'read', next time to - * retry reading. */ + struct timespec mtime; /* File mtime as of last time we read it. */ }; /* SSL configuration files. */ @@ -335,9 +334,10 @@ do_ca_cert_bootstrap(struct stream *stream) fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { if (errno == EEXIST) { - VLOG_INFO("reading CA cert %s created by another process", + VLOG_INFO("CA cert %s created by another process", ca_cert.file_name); - stream_ssl_set_ca_cert_file__(ca_cert.file_name, true); + /* We'll read it the next time around the main loop because + * update_ssl_config() will see that it now exists. */ return EPROTO; } else { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", @@ -910,18 +910,46 @@ stream_ssl_is_configured(void) return private_key.file_name || certificate.file_name || ca_cert.file_name; } +static void +get_mtime(const char *file_name, struct timespec *mtime) +{ + struct stat s; + + if (!stat(file_name, &s)) { + mtime->tv_sec = s.st_mtime; + +#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + mtime->tv_nsec = s.st_mtim.tv_nsec; +#elif HAVE_STRUCT_STAT_ST_MTIMENSEC + mtime->tv_nsec = s.st_mtimensec; +#else + mtime->tv_nsec = 0; +#endif + } else { + mtime->tv_sec = mtime->tv_nsec = 0; + } +} + static bool update_ssl_config(struct ssl_config_file *config, const char *file_name) { - if (ssl_init() - || !file_name - || (config->file_name - && !strcmp(config->file_name, file_name) - && time_msec() < config->next_retry)) { + struct timespec mtime; + + if (ssl_init() || !file_name) { + return false; + } + + /* If the file name hasn't changed and neither has the file contents, stop + * here. */ + get_mtime(file_name, &mtime); + if (config->file_name + && !strcmp(config->file_name, file_name) + && mtime.tv_sec == config->mtime.tv_sec + && mtime.tv_nsec == config->mtime.tv_nsec) { return false; } - config->next_retry = time_msec() + 60 * 1000; + config->mtime = mtime; free(config->file_name); config->file_name = xstrdup(file_name); return true; -- 2.30.2