diff --git a/src/utils/ssl.c b/src/utils/ssl.c
index d9ad060bb2270a86157135cb57e442b1a15af76e..12beac528fbcfb36d9643469fb8213159ee6a80a 100644 (file)
--- a/src/utils/ssl.c
+++ b/src/utils/ssl.c
#include <stdlib.h>
#include <string.h>
+#include <pthread.h>
+
#include <openssl/ssl.h>
#include <openssl/bio.h>
+#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/err.h>
SSL *ssl;
};
+/*
+ * OpenSSL helper functions
+ */
+
+static pthread_mutex_t *mutexes = NULL;
+static int mutexes_num = 0;
+
+static void
+locking_callback(int mode, int n, const char *file, int line)
+{
+ if (! mutexes) {
+ sdb_log(SDB_LOG_EMERG, "ssl: CRYPTO_lock called from %s:%d "
+ "before initializing SSL", file, line);
+ return;
+ }
+ if (n >= mutexes_num) {
+ sdb_log(SDB_LOG_EMERG, "ssl: CRYPTO_lock called from %s:%d "
+ "for mutex %d but only %d are available",
+ file, line, n, mutexes_num);
+ return;
+ }
+
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock(&mutexes[n]);
+ else
+ pthread_mutex_unlock(&mutexes[n]);
+} /* locking_callback */
+
+static void
+threadid_callback(CRYPTO_THREADID *id)
+{
+ CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self());
+} /* threadid_callback */
+
/*
* private helper functions
*/
if (errno) {
char errbuf[1024];
- sdb_log(prio, "%s: %s", msg,
- sdb_strerror(errno, errbuf, sizeof(errbuf)));
+ sdb_log(prio, "%s: %s", msg, sdb_strerror(errno, errbuf, sizeof(errbuf)));
}
} /* ssl_log_err */
static int
-copy_options(sdb_ssl_options_t *dst, sdb_ssl_options_t *src)
+copy_options(sdb_ssl_options_t *dst, const sdb_ssl_options_t *src)
{
+ sdb_ssl_options_t tmp;
sdb_ssl_options_t def = SDB_SSL_DEFAULT_OPTIONS;
- if (! src)
- src = &def;
-
- if (! src->ca_file)
- src->ca_file = def.ca_file;
- if (! src->key_file)
- src->key_file = def.key_file;
- if (! src->cert_file)
- src->cert_file = def.cert_file;
-
- dst->ca_file = strdup(src->ca_file);
- dst->key_file = strdup(src->key_file);
- dst->cert_file = strdup(src->cert_file);
+ if (src)
+ tmp = *src;
+ else
+ tmp = def;
+
+ if (! tmp.ca_file)
+ tmp.ca_file = def.ca_file;
+ if (! tmp.key_file)
+ tmp.key_file = def.key_file;
+ if (! tmp.cert_file)
+ tmp.cert_file = def.cert_file;
+
+ dst->ca_file = strdup(tmp.ca_file);
+ dst->key_file = strdup(tmp.key_file);
+ dst->cert_file = strdup(tmp.cert_file);
if ((! dst->ca_file) || (! dst->key_file) || (! dst->cert_file))
return -1;
- if (src->crl_file) {
- dst->crl_file = strdup(src->crl_file);
+ if (tmp.crl_file) {
+ dst->crl_file = strdup(tmp.crl_file);
if (! dst->crl_file)
return -1;
}
* public API
*/
+int
+sdb_ssl_init(void)
+{
+ int i;
+
+ SSL_load_error_strings();
+ OpenSSL_add_ssl_algorithms();
+
+ mutexes = calloc(CRYPTO_num_locks(), sizeof(*mutexes));
+ if (! mutexes) {
+ char errbuf[1024];
+ sdb_log(SDB_LOG_ERR, "ssl: Failed to allocate mutexes: %s",
+ sdb_strerror(errno, errbuf, sizeof(errbuf)));
+ return -1;
+ }
+ for (i = 0; i < CRYPTO_num_locks(); ++i) {
+ errno = pthread_mutex_init(&mutexes[i], /* attr = */ NULL);
+ if (errno) {
+ char errbuf[1024];
+ sdb_log(SDB_LOG_ERR, "ssl: Failed to initialize mutex: %s",
+ sdb_strerror(errno, errbuf, sizeof(errbuf)));
+ return -1;
+ }
+ mutexes_num = i + 1;
+ }
+
+ CRYPTO_set_locking_callback(locking_callback);
+ CRYPTO_THREADID_set_callback(threadid_callback);
+ return 0;
+} /* sdb_ssl_init */
+
+void
+sdb_ssl_shutdown(void)
+{
+ int i;
+
+ ERR_free_strings();
+
+ for (i = 0; i < mutexes_num; ++i)
+ pthread_mutex_destroy(&mutexes[i]);
+ if (mutexes)
+ free(mutexes);
+ mutexes = NULL;
+ mutexes_num = 0;
+} /* sdb_ssl_shutdown */
+
sdb_ssl_client_t *
-sdb_ssl_client_create(sdb_ssl_options_t *opts)
+sdb_ssl_client_create(const sdb_ssl_options_t *opts)
{
sdb_ssl_client_t *client;
} /* sdb_ssl_client_connect */
sdb_ssl_server_t *
-sdb_ssl_server_create(sdb_ssl_options_t *opts)
+sdb_ssl_server_create(const sdb_ssl_options_t *opts)
{
sdb_ssl_server_t *server;
server->opts.ca_file, NULL)) {
ssl_log(SDB_LOG_ERR, "Failed to load CA file %s",
server->opts.ca_file);
+ sdb_ssl_server_destroy(server);
return NULL;
}
SSL_CTX_set_client_CA_list(server->ctx,
server->opts.cert_file, SSL_FILETYPE_PEM)) {
ssl_log(SDB_LOG_ERR, "Failed to load SSL cert file %s",
server->opts.cert_file);
+ sdb_ssl_server_destroy(server);
return NULL;
}
if (! SSL_CTX_use_PrivateKey_file(server->ctx,
server->opts.key_file, SSL_FILETYPE_PEM)) {
ssl_log(SDB_LOG_ERR, "Failed to load SSL key file %s",
server->opts.key_file);
+ sdb_ssl_server_destroy(server);
return NULL;
}
if (! SSL_CTX_check_private_key(server->ctx)) {
ssl_log(SDB_LOG_ERR, "Failed to verify SSL private key");
+ sdb_ssl_server_destroy(server);
return NULL;
}