X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Futils%2Fssl.c;h=12beac528fbcfb36d9643469fb8213159ee6a80a;hp=f75223c03667d18d077be5bc770b9198d254aefc;hb=dcf7802ad0958d4752b2c13f70e2fdf345d3509f;hpb=2db6eca73081252f6af31f17c84e892cc4d33e36 diff --git a/src/utils/ssl.c b/src/utils/ssl.c index f75223c..12beac5 100644 --- a/src/utils/ssl.c +++ b/src/utils/ssl.c @@ -37,8 +37,11 @@ #include #include +#include + #include #include +#include #include #include @@ -60,6 +63,40 @@ struct sdb_ssl_session { 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 */ @@ -131,33 +168,35 @@ ssl_log_err(int prio, SSL *ssl, int status, const char *prefix, ...) 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; } @@ -168,8 +207,54 @@ copy_options(sdb_ssl_options_t *dst, sdb_ssl_options_t *src) * 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; @@ -191,7 +276,8 @@ sdb_ssl_client_create(sdb_ssl_options_t *opts) if (! SSL_CTX_load_verify_locations(client->ctx, client->opts.ca_file, NULL)) { - ssl_log(SDB_LOG_ERR, "ssl: Failed to load CA file"); + ssl_log(SDB_LOG_ERR, "ssl: Failed to load CA file '%s'", + client->opts.ca_file); sdb_ssl_client_destroy(client); return NULL; } @@ -277,7 +363,7 @@ sdb_ssl_client_connect(sdb_ssl_client_t *client, int fd) } /* 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; @@ -312,6 +398,7 @@ sdb_ssl_server_create(sdb_ssl_options_t *opts) 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, @@ -321,16 +408,19 @@ sdb_ssl_server_create(sdb_ssl_options_t *opts) 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; }