fix and enable SSL support when OpenSSL is available

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-01-30 14:39:34 +01:00
parent acec84cf0b
commit f31fba8766
7 changed files with 158 additions and 239 deletions

View file

@ -19,7 +19,6 @@ FUNCTION(PREPEND var prefix)
SET(${var} "${listVar}" PARENT_SCOPE) SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND) ENDFUNCTION(PREPEND)
option(DDSC_SHARED "Build DDSC as a shared library" ON) option(DDSC_SHARED "Build DDSC as a shared library" ON)
if(DDSC_SHARED AND ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS)) if(DDSC_SHARED AND ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS))
@ -34,6 +33,14 @@ endif()
add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM)
find_package(OpenSSL)
if(OPENSSL_FOUND)
add_definitions(-DDDSI_INCLUDE_SSL)
include_directories(${OPENSSL_INCLUDE_DIR})
target_link_libraries(ddsc PRIVATE ${OPENSSL_LIBRARIES})
message(STATUS "Using OpenSSL ${OPENSSL_VERSION} at ${OPENSSL_INCLUDE_DIR}")
endif()
include(ddsi/CMakeLists.txt) include(ddsi/CMakeLists.txt)
include(ddsc/CMakeLists.txt) include(ddsc/CMakeLists.txt)

View file

@ -15,14 +15,13 @@
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
#ifdef _WIN32 #ifdef _WIN32
/* WinSock2 must be included before openssl headers /* supposedly WinSock2 must be included before openssl headers otherwise winsock will be used */
otherwise winsock will be used */
#include <WinSock2.h> #include <WinSock2.h>
#endif #endif
#include <openssl/ssl.h> #include <openssl/ssl.h>
void ddsi_ssl_plugin (void); struct ddsi_ssl_plugins;
void ddsi_ssl_config_plugin (struct ddsi_ssl_plugins *plugin);
#endif #endif
#endif #endif

View file

@ -20,20 +20,17 @@
struct ddsi_ssl_plugins struct ddsi_ssl_plugins
{ {
void (*config) (void); bool (*init) (void);
c_bool (*init) (void);
void (*fini) (void); void (*fini) (void);
void (*ssl_free) (SSL * ssl); void (*ssl_free) (SSL *ssl);
void (*bio_vfree) (BIO * bio); void (*bio_vfree) (BIO *bio);
os_ssize_t (*read) (SSL * ssl, void * buf, os_size_t len, int * err); ssize_t (*read) (SSL *ssl, void *buf, size_t len, int *err);
os_ssize_t (*write) (SSL * ssl, const void * msg, os_size_t len, int * err); ssize_t (*write) (SSL *ssl, const void *msg, size_t len, int *err);
SSL * (*connect) (os_socket sock); SSL * (*connect) (os_socket sock);
BIO * (*listen) (os_socket sock); BIO * (*listen) (os_socket sock);
SSL * (*accept) (BIO * bio, os_socket * sock); SSL * (*accept) (BIO *bio, os_socket *sock);
}; };
struct ddsi_ssl_plugins ddsi_tcp_ssl_plugin;
#endif #endif
int ddsi_tcp_init (void); int ddsi_tcp_init (void);

View file

@ -9,323 +9,242 @@
* *
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/ */
#include "os/os.h"
#include "ddsi/ddsi_tcp.h"
#include "ddsi/ddsi_ssl.h" #include "ddsi/ddsi_ssl.h"
#include "ddsi/q_config.h" #include "ddsi/q_config.h"
#include "ddsi/q_log.h" #include "ddsi/q_log.h"
#include "os/os_heap.h"
#include "ddsi/ddsi_tcp.h"
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/opensslconf.h>
static SSL_CTX * ddsi_ssl_ctx = NULL; static SSL_CTX *ddsi_ssl_ctx = NULL;
static SSL * ddsi_ssl_new (void) static SSL *ddsi_ssl_new (void)
{ {
return SSL_new (ddsi_ssl_ctx); return SSL_new (ddsi_ssl_ctx);
} }
static void ddsi_ssl_error (SSL * ssl, const char * str, int err) static void ddsi_ssl_error (SSL *ssl, const char *str, int err)
{ {
char buff [128]; char buff[128];
ERR_error_string ((unsigned) SSL_get_error (ssl, err), buff); ERR_error_string ((unsigned) SSL_get_error (ssl, err), buff);
DDS_ERROR("tcp/ssl %s %s %d\n", str, buff, err); DDS_ERROR ("tcp/ssl %s %s %d\n", str, buff, err);
} }
static int ddsi_ssl_verify (int ok, X509_STORE_CTX * store) static int ddsi_ssl_verify (int ok, X509_STORE_CTX *store)
{ {
if (!ok) if (!ok)
{ {
char issuer[256]; char issuer[256];
X509 * cert = X509_STORE_CTX_get_current_cert (store); X509 *cert = X509_STORE_CTX_get_current_cert (store);
int err = X509_STORE_CTX_get_error (store); int err = X509_STORE_CTX_get_error (store);
/* Check if allowing self-signed certificates */ /* Check if allowing self-signed certificates */
if (config.ssl_self_signed && ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)))
if
(
config.ssl_self_signed &&
((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ||
(err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN))
)
{
ok = 1; ok = 1;
}
else else
{ {
X509_NAME_oneline (X509_get_issuer_name (cert), issuer, sizeof (issuer)); X509_NAME_oneline (X509_get_issuer_name (cert), issuer, sizeof (issuer));
DDS_ERROR DDS_ERROR ("tcp/ssl failed to verify certificate from %s: %s\n", issuer, X509_verify_cert_error_string (err));
(
"tcp/ssl failed to verify certificate from %s : %s\n",
issuer,
X509_verify_cert_error_string (err)
);
} }
} }
return ok; return ok;
} }
static os_ssize_t ddsi_ssl_read (SSL * ssl, void * buf, os_size_t len, int * err) static ssize_t ddsi_ssl_read (SSL *ssl, void *buf, size_t len, int *err)
{ {
int ret;
assert (len <= INT32_MAX); assert (len <= INT32_MAX);
if (SSL_get_shutdown (ssl) != 0) if (SSL_get_shutdown (ssl) != 0)
{
return -1; return -1;
}
/* Returns -1 on error or 0 on shutdown */ /* Returns -1 on error or 0 on shutdown */
const int ret = SSL_read (ssl, buf, (int) len);
ret = SSL_read (ssl, buf, (int) len);
switch (SSL_get_error (ssl, ret)) switch (SSL_get_error (ssl, ret))
{ {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
{ return ret;
/* Success */
break;
}
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
{
*err = os_sockEAGAIN; *err = os_sockEAGAIN;
ret = -1; return -1;
break;
}
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
default: default:
{
/* Connection closed or error */ /* Connection closed or error */
*err = os_getErrno (); *err = os_getErrno ();
ret = -1; return -1;
break;
}
} }
return ret;
} }
static os_ssize_t ddsi_ssl_write (SSL * ssl, const void * buf, os_size_t len, int * err) static ssize_t ddsi_ssl_write (SSL *ssl, const void *buf, size_t len, int *err)
{ {
int ret;
assert(len <= INT32_MAX); assert(len <= INT32_MAX);
if (SSL_get_shutdown (ssl) != 0) if (SSL_get_shutdown (ssl) != 0)
{
return -1; return -1;
}
/* Returns -1 on error or 0 on shutdown */ /* Returns -1 on error or 0 on shutdown */
const int ret = SSL_write (ssl, buf, (int) len);
ret = SSL_write (ssl, buf, (int) len);
switch (SSL_get_error (ssl, ret)) switch (SSL_get_error (ssl, ret))
{ {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
{ return ret;
/* Success */
break;
}
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
{
*err = os_sockEAGAIN; *err = os_sockEAGAIN;
ret = -1; return -1;
break;
}
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
default: default:
{
/* Connection closed or error */ /* Connection closed or error */
*err = os_getErrno (); *err = os_getErrno ();
ret = -1; return -1;
break;
}
} }
return ret;
} }
/* Standard OpenSSL init and thread support routines. See O'Reilly. */ /* Standard OpenSSL init and thread support routines. See O'Reilly. */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static unsigned long ddsi_ssl_id (void) static unsigned long ddsi_ssl_id (void)
{ {
return os_threadIdToInteger (os_threadIdSelf ()); return (unsigned long) os_threadIdToInteger (os_threadIdSelf ());
} }
typedef struct CRYPTO_dynlock_value typedef struct CRYPTO_dynlock_value {
{
os_mutex m_mutex; os_mutex m_mutex;
} } CRYPTO_dynlock_value;
CRYPTO_dynlock_value;
static CRYPTO_dynlock_value * ddsi_ssl_locks = NULL; static CRYPTO_dynlock_value *ddsi_ssl_locks = NULL;
static void ddsi_ssl_dynlock_lock (int mode, CRYPTO_dynlock_value * lock, const char * file, int line) static void ddsi_ssl_dynlock_lock (int mode, CRYPTO_dynlock_value *lock, const char *file, int line)
{ {
(void) file; (void) file;
(void) line; (void) line;
if (mode & CRYPTO_LOCK) if (mode & CRYPTO_LOCK)
{
os_mutexLock (&lock->m_mutex); os_mutexLock (&lock->m_mutex);
}
else else
{
os_mutexUnlock (&lock->m_mutex); os_mutexUnlock (&lock->m_mutex);
}
} }
static void ddsi_ssl_lock (int mode, int n, const char * file, int line) static void ddsi_ssl_lock (int mode, int n, const char *file, int line)
{ {
ddsi_ssl_dynlock_lock (mode, &ddsi_ssl_locks[n], file, line); ddsi_ssl_dynlock_lock (mode, &ddsi_ssl_locks[n], file, line);
} }
static CRYPTO_dynlock_value * ddsi_ssl_dynlock_create (const char * file, int line) static CRYPTO_dynlock_value *ddsi_ssl_dynlock_create (const char *file, int line)
{ {
CRYPTO_dynlock_value * val = os_malloc (sizeof (*val));
(void) file; (void) file;
(void) line; (void) line;
CRYPTO_dynlock_value *val = os_malloc (sizeof (*val));
os_mutexInit (&val->m_mutex); os_mutexInit (&val->m_mutex);
return val; return val;
} }
static void ddsi_ssl_dynlock_destroy (CRYPTO_dynlock_value * lock, const char * file, int line) static void ddsi_ssl_dynlock_destroy (CRYPTO_dynlock_value *lock, const char *file, int line)
{ {
(void) file; (void) file;
(void) line; (void) line;
os_mutexDestroy (&lock->m_mutex); os_mutexDestroy (&lock->m_mutex);
os_free (lock); os_free (lock);
} }
#endif
static int ddsi_ssl_password (char * buf, int num, int rwflag, void * udata) static int ddsi_ssl_password (char *buf, int num, int rwflag, void *udata)
{ {
(void) rwflag; (void) rwflag;
(void) udata; (void) udata;
if ((unsigned int) num < strlen (config.ssl_key_pass) + 1) if (num < 0 || (size_t) num < strlen (config.ssl_key_pass) + 1)
{ return 0;
return (0); OS_WARNING_MSVC_OFF(4996);
}
strcpy (buf, config.ssl_key_pass); strcpy (buf, config.ssl_key_pass);
OS_WARNING_MSVC_ON(4996);
return (int) strlen (config.ssl_key_pass); return (int) strlen (config.ssl_key_pass);
} }
static SSL_CTX * ddsi_ssl_ctx_init (void) static SSL_CTX *ddsi_ssl_ctx_init (void)
{ {
int i; SSL_CTX *ctx = SSL_CTX_new (SSLv23_method ());
SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ());
/* Load certificates */ /* Load certificates */
if (! SSL_CTX_use_certificate_file (ctx, config.ssl_keystore, SSL_FILETYPE_PEM)) if (! SSL_CTX_use_certificate_file (ctx, config.ssl_keystore, SSL_FILETYPE_PEM))
{ {
DDS_LOG DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl failed to load certificate from file: %s\n", config.ssl_keystore);
(
DDS_LC_ERROR | DDS_LC_CONFIG,
"tcp/ssl failed to load certificate from file: %s\n",
config.ssl_keystore
);
goto fail; goto fail;
} }
/* Set password and callback */ /* Set password and callback */
SSL_CTX_set_default_passwd_cb (ctx, ddsi_ssl_password); SSL_CTX_set_default_passwd_cb (ctx, ddsi_ssl_password);
/* Get private key */ /* Get private key */
if (! SSL_CTX_use_PrivateKey_file (ctx, config.ssl_keystore, SSL_FILETYPE_PEM)) if (! SSL_CTX_use_PrivateKey_file (ctx, config.ssl_keystore, SSL_FILETYPE_PEM))
{ {
DDS_LOG DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl failed to load private key from file: %s\n", config.ssl_keystore);
(
DDS_LC_ERROR | DDS_LC_CONFIG,
"tcp/ssl failed to load private key from file: %s\n",
config.ssl_keystore
);
goto fail; goto fail;
} }
/* Load CAs */ /* Load CAs */
if (! SSL_CTX_load_verify_locations (ctx, config.ssl_keystore, 0)) if (! SSL_CTX_load_verify_locations (ctx, config.ssl_keystore, 0))
{ {
DDS_LOG DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl failed to load CA from file: %s\n", config.ssl_keystore);
(
DDS_LC_ERROR | DDS_LC_CONFIG,
"tcp/ssl failed to load CA from file: %s\n",
config.ssl_keystore
);
goto fail; goto fail;
} }
/* Set ciphers */ /* Set ciphers */
if (! SSL_CTX_set_cipher_list (ctx, config.ssl_ciphers)) if (! SSL_CTX_set_cipher_list (ctx, config.ssl_ciphers))
{ {
DDS_LOG DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl failed to set ciphers: %s\n", config.ssl_ciphers);
(
DDS_LC_ERROR | DDS_LC_CONFIG,
"tcp/ssl failed to set ciphers: %s\n",
config.ssl_ciphers
);
goto fail; goto fail;
} }
/* Load randomness from file (optional) */ /* Load randomness from file (optional) */
if (config.ssl_rand_file[0] != '\0') if (config.ssl_rand_file[0] != '\0')
{ {
if (! RAND_load_file (config.ssl_rand_file, 4096)) if (! RAND_load_file (config.ssl_rand_file, 4096))
{ {
DDS_LOG DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl failed to load random seed from file: %s\n", config.ssl_rand_file);
(
DDS_LC_ERROR | DDS_LC_CONFIG,
"tcp/ssl failed to load random seed from file: %s\n",
config.ssl_rand_file
);
goto fail; goto fail;
} }
} }
/* Set certificate verification policy from configuration */ /* Set certificate verification policy from configuration */
if (!config.ssl_verify)
if (config.ssl_verify) SSL_CTX_set_verify (ctx, SSL_VERIFY_NONE, NULL);
{
i = SSL_VERIFY_PEER;
if (config.ssl_verify_client)
{
i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
SSL_CTX_set_verify (ctx, i, ddsi_ssl_verify);
}
else else
{ {
SSL_CTX_set_verify (ctx, SSL_VERIFY_NONE, NULL); int i = SSL_VERIFY_PEER;
if (config.ssl_verify_client)
i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
SSL_CTX_set_verify (ctx, i, ddsi_ssl_verify);
} }
SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
return ctx; return ctx;
fail: fail:
SSL_CTX_free (ctx); SSL_CTX_free (ctx);
return NULL; return NULL;
} }
static SSL * ddsi_ssl_connect (os_socket sock) static void dds_report_tls_version (const SSL *ssl, const char *oper)
{ {
SSL * ssl; if (ssl)
{
char issuer[256], subject[256];
X509_NAME_oneline (X509_get_issuer_name (SSL_get_peer_certificate (ssl)), issuer, sizeof (issuer));
X509_NAME_oneline (X509_get_subject_name (SSL_get_peer_certificate (ssl)), subject, sizeof (subject));
DDS_TRACE("tcp/ssl %s %s issued by %s [%s]\n", oper, subject, issuer, SSL_get_version (ssl));
}
}
static SSL *ddsi_ssl_connect (os_socket sock)
{
SSL *ssl;
int err; int err;
/* Connect SSL over connected socket */ /* Connect SSL over connected socket */
ssl = ddsi_ssl_new (); ssl = ddsi_ssl_new ();
SSL_set_fd (ssl, sock); SSL_set_fd (ssl, sock);
err = SSL_connect (ssl); err = SSL_connect (ssl);
@ -335,20 +254,21 @@ static SSL * ddsi_ssl_connect (os_socket sock)
SSL_free (ssl); SSL_free (ssl);
ssl = NULL; ssl = NULL;
} }
dds_report_tls_version (ssl, "connected to");
return ssl; return ssl;
} }
static BIO * ddsi_ssl_listen (os_socket sock) static BIO *ddsi_ssl_listen (os_socket sock)
{ {
BIO * bio = BIO_new (BIO_s_accept ()); BIO * bio = BIO_new (BIO_s_accept ());
BIO_set_fd (bio, sock, BIO_NOCLOSE); BIO_set_fd (bio, sock, BIO_NOCLOSE);
return bio; return bio;
} }
static SSL * ddsi_ssl_accept (BIO * bio, os_socket * sock) static SSL *ddsi_ssl_accept (BIO *bio, os_socket *sock)
{ {
SSL * ssl = NULL; SSL *ssl = NULL;
BIO * nbio; BIO *nbio;
int err; int err;
if (BIO_do_accept (bio) > 0) if (BIO_do_accept (bio) > 0)
@ -365,23 +285,29 @@ static SSL * ddsi_ssl_accept (BIO * bio, os_socket * sock)
ssl = NULL; ssl = NULL;
} }
} }
dds_report_tls_version (ssl, "accepted from");
return ssl; return ssl;
} }
static c_bool ddsi_ssl_init (void) static bool ddsi_ssl_init (void)
{ {
unsigned locks = (unsigned) CRYPTO_num_locks ();
unsigned i;
ddsi_ssl_locks = os_malloc (sizeof (CRYPTO_dynlock_value) * locks);
for (i = 0; i < locks; i++)
{
os_mutexInit (&ddsi_ssl_locks[i].m_mutex);
}
ERR_load_BIO_strings (); ERR_load_BIO_strings ();
SSL_load_error_strings (); SSL_load_error_strings ();
SSL_library_init (); SSL_library_init ();
OpenSSL_add_all_algorithms (); OpenSSL_add_all_algorithms ();
#if OPENSSL_VERSION_NUMBER < 0x10100000L
{
const int locks = CRYPTO_num_locks ();
assert (locks >= 0);
ddsi_ssl_locks = os_malloc (sizeof (CRYPTO_dynlock_value) * (size_t) locks);
for (int i = 0; i < locks; i++)
os_mutexInit (&ddsi_ssl_locks[i].m_mutex);
}
#endif
/* Leave these in place: OpenSSL 1.1 defines them as no-op macros that not even reference the symbol,
therefore leaving them in means we get compile time errors if we the library expects the callbacks
to be defined and we somehow failed to detect that previously */
CRYPTO_set_id_callback (ddsi_ssl_id); CRYPTO_set_id_callback (ddsi_ssl_id);
CRYPTO_set_locking_callback (ddsi_ssl_lock); CRYPTO_set_locking_callback (ddsi_ssl_lock);
CRYPTO_set_dynlock_create_callback (ddsi_ssl_dynlock_create); CRYPTO_set_dynlock_create_callback (ddsi_ssl_dynlock_create);
@ -394,43 +320,36 @@ static c_bool ddsi_ssl_init (void)
static void ddsi_ssl_fini (void) static void ddsi_ssl_fini (void)
{ {
unsigned locks = (unsigned) CRYPTO_num_locks ();
unsigned i;
SSL_CTX_free (ddsi_ssl_ctx); SSL_CTX_free (ddsi_ssl_ctx);
CRYPTO_set_id_callback (NULL); CRYPTO_set_id_callback (0);
CRYPTO_set_locking_callback (NULL); CRYPTO_set_locking_callback (0);
CRYPTO_set_dynlock_create_callback (NULL); CRYPTO_set_dynlock_create_callback (0);
CRYPTO_set_dynlock_lock_callback (NULL); CRYPTO_set_dynlock_lock_callback (0);
CRYPTO_set_dynlock_destroy_callback (NULL); CRYPTO_set_dynlock_destroy_callback (0);
ERR_free_strings (); ERR_free_strings ();
EVP_cleanup (); EVP_cleanup ();
for (i = 0; i < locks; i++)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
{ {
os_mutexDestroy (&ddsi_ssl_locks[i].m_mutex); const int locks = CRYPTO_num_locks ();
for (int i = 0; i < locks; i++)
os_mutexDestroy (&ddsi_ssl_locks[i].m_mutex);
os_free (ddsi_ssl_locks);
} }
os_free (ddsi_ssl_locks); #endif
} }
static void ddsi_ssl_config (void) void ddsi_ssl_config_plugin (struct ddsi_ssl_plugins *plugin)
{ {
if (config.ssl_enable) plugin->init = ddsi_ssl_init;
{ plugin->fini = ddsi_ssl_fini;
ddsi_tcp_ssl_plugin.init = ddsi_ssl_init; plugin->ssl_free = SSL_free;
ddsi_tcp_ssl_plugin.fini = ddsi_ssl_fini; plugin->bio_vfree = BIO_vfree;
ddsi_tcp_ssl_plugin.ssl_free = SSL_free; plugin->read = ddsi_ssl_read;
ddsi_tcp_ssl_plugin.bio_vfree = BIO_vfree; plugin->write = ddsi_ssl_write;
ddsi_tcp_ssl_plugin.read = ddsi_ssl_read; plugin->connect = ddsi_ssl_connect;
ddsi_tcp_ssl_plugin.write = ddsi_ssl_write; plugin->listen = ddsi_ssl_listen;
ddsi_tcp_ssl_plugin.connect = ddsi_ssl_connect; plugin->accept = ddsi_ssl_accept;
ddsi_tcp_ssl_plugin.listen = ddsi_ssl_listen;
ddsi_tcp_ssl_plugin.accept = ddsi_ssl_accept;
}
}
void ddsi_ssl_plugin (void)
{
ddsi_tcp_ssl_plugin.config = ddsi_ssl_config;
} }
#endif /* DDSI_INCLUDE_SSL */ #endif /* DDSI_INCLUDE_SSL */

View file

@ -30,16 +30,11 @@ typedef struct ddsi_tran_factory * ddsi_tcp_factory_g_t;
static os_atomic_uint32_t ddsi_tcp_init_g = OS_ATOMIC_UINT32_INIT(0); static os_atomic_uint32_t ddsi_tcp_init_g = OS_ATOMIC_UINT32_INIT(0);
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
struct ddsi_ssl_plugins ddsi_tcp_ssl_plugin = static struct ddsi_ssl_plugins ddsi_tcp_ssl_plugin;
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
#endif #endif
static const char * ddsi_name = "tcp"; static const char * ddsi_name = "tcp";
/* Stateless singleton instance handed out as client connection */
static struct ddsi_tran_conn ddsi_tcp_conn_client;
/* /*
ddsi_tcp_conn: TCP connection for reading and writing. Mutex prevents concurrent ddsi_tcp_conn: TCP connection for reading and writing. Mutex prevents concurrent
writes to socket. Is reference counted. Peer port is actually contained in peer writes to socket. Is reference counted. Peer port is actually contained in peer
@ -74,6 +69,10 @@ typedef struct ddsi_tcp_listener
} }
* ddsi_tcp_listener_t; * ddsi_tcp_listener_t;
/* Stateless singleton instance handed out as client connection */
static struct ddsi_tcp_conn ddsi_tcp_conn_client;
static int ddsi_tcp_cmp_conn (const struct ddsi_tcp_conn *c1, const struct ddsi_tcp_conn *c2) static int ddsi_tcp_cmp_conn (const struct ddsi_tcp_conn *c1, const struct ddsi_tcp_conn *c2)
{ {
const os_sockaddr *a1s = (os_sockaddr *)&c1->m_peer_addr; const os_sockaddr *a1s = (os_sockaddr *)&c1->m_peer_addr;
@ -348,7 +347,7 @@ OS_WARNING_MSVC_ON(4267);
} }
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
static os_ssize_t ddsi_tcp_conn_read_ssl (ddsi_tcp_conn_t tcp, void * buf, os_size_t len, int * err) static ssize_t ddsi_tcp_conn_read_ssl (ddsi_tcp_conn_t tcp, void * buf, size_t len, int * err)
{ {
return (ddsi_tcp_ssl_plugin.read) (tcp->m_ssl, buf, len, err); return (ddsi_tcp_ssl_plugin.read) (tcp->m_ssl, buf, len, err);
} }
@ -471,7 +470,7 @@ OS_WARNING_MSVC_OFF(4267);
} }
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
static os_ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, os_size_t len, int * err) static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, size_t len, int * err)
{ {
return (ddsi_tcp_ssl_plugin.write) (conn->m_ssl, buf, len, err); return (ddsi_tcp_ssl_plugin.write) (conn->m_ssl, buf, len, err);
} }
@ -541,7 +540,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d
{ {
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
char msgbuf[4096]; /* stack buffer for merging smallish writes without requiring allocations */ char msgbuf[4096]; /* stack buffer for merging smallish writes without requiring allocations */
struct iovec iovec; /* iovec used for msgbuf */ os_iovec_t iovec; /* iovec used for msgbuf */
#endif #endif
ssize_t ret; ssize_t ret;
size_t len; size_t len;
@ -732,8 +731,7 @@ static ddsi_tran_conn_t ddsi_tcp_create_conn (uint32_t port, ddsi_tran_qos_t qos
{ {
(void) qos; (void) qos;
(void) port; (void) port;
return &ddsi_tcp_conn_client.m_base;
return (ddsi_tran_conn_t) &ddsi_tcp_conn_client;
} }
static int ddsi_tcp_listen (ddsi_tran_listener_t listener) static int ddsi_tcp_listen (ddsi_tran_listener_t listener)
@ -936,7 +934,7 @@ static void ddsi_tcp_conn_delete (ddsi_tcp_conn_t conn)
static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc) static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc)
{ {
if (tc != (ddsi_tran_conn_t) &ddsi_tcp_conn_client) if (tc != &ddsi_tcp_conn_client.m_base)
{ {
char buff[DDSI_LOCSTRLEN]; char buff[DDSI_LOCSTRLEN];
nn_locator_t loc; nn_locator_t loc;
@ -952,7 +950,7 @@ static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc)
static void ddsi_tcp_release_conn (ddsi_tran_conn_t conn) static void ddsi_tcp_release_conn (ddsi_tran_conn_t conn)
{ {
if (conn != (ddsi_tran_conn_t) &ddsi_tcp_conn_client) if (conn != &ddsi_tcp_conn_client.m_base)
{ {
ddsi_tcp_conn_delete ((ddsi_tcp_conn_t) conn); ddsi_tcp_conn_delete ((ddsi_tcp_conn_t) conn);
} }
@ -964,13 +962,6 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener)
os_socket sock; os_socket sock;
int ret; int ret;
#ifdef DDSI_INCLUDE_SSL
if (ddsi_tcp_ssl_plugin.bio_vfree)
{
(ddsi_tcp_ssl_plugin.bio_vfree) (tl->m_bio);
}
#endif
/* Connect to own listener socket to wake listener from blocking 'accept()' */ /* Connect to own listener socket to wake listener from blocking 'accept()' */
ddsi_tcp_sock_new (&sock, 0); ddsi_tcp_sock_new (&sock, 0);
if (sock != OS_INVALID_SOCKET) if (sock != OS_INVALID_SOCKET)
@ -1020,6 +1011,12 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener)
static void ddsi_tcp_release_listener (ddsi_tran_listener_t listener) static void ddsi_tcp_release_listener (ddsi_tran_listener_t listener)
{ {
ddsi_tcp_listener_t tl = (ddsi_tcp_listener_t) listener; ddsi_tcp_listener_t tl = (ddsi_tcp_listener_t) listener;
#ifdef DDSI_INCLUDE_SSL
if (ddsi_tcp_ssl_plugin.bio_vfree)
{
(ddsi_tcp_ssl_plugin.bio_vfree) (tl->m_bio);
}
#endif
ddsi_tcp_sock_free (tl->m_sock, "listener"); ddsi_tcp_sock_free (tl->m_sock, "listener");
os_free (tl); os_free (tl);
} }
@ -1097,17 +1094,14 @@ int ddsi_tcp_init (void)
#endif #endif
memset (&ddsi_tcp_conn_client, 0, sizeof (ddsi_tcp_conn_client)); memset (&ddsi_tcp_conn_client, 0, sizeof (ddsi_tcp_conn_client));
ddsi_tcp_base_init (&ddsi_tcp_conn_client); ddsi_tcp_base_init (&ddsi_tcp_conn_client.m_base);
#ifdef DDSI_INCLUDE_SSL #ifdef DDSI_INCLUDE_SSL
if (ddsi_tcp_ssl_plugin.config) if (config.ssl_enable)
{
(ddsi_tcp_ssl_plugin.config) ();
}
if (ddsi_tcp_ssl_plugin.init)
{ {
ddsi_name = "tcp/ssl"; ddsi_name = "tcp/ssl";
if (! (ddsi_tcp_ssl_plugin.init) ()) ddsi_ssl_config_plugin (&ddsi_tcp_ssl_plugin);
if (! ddsi_tcp_ssl_plugin.init ())
{ {
DDS_ERROR("Failed to initialize OpenSSL\n"); DDS_ERROR("Failed to initialize OpenSSL\n");
return -1; return -1;

View file

@ -59,12 +59,15 @@ ddsi_tran_factory_t ddsi_factory_find (const char * type)
void ddsi_tran_factories_fini (void) void ddsi_tran_factories_fini (void)
{ {
ddsi_tran_factory_t factory; ddsi_tran_factory_t factory;
while ((factory = ddsi_tran_factories) != NULL)
while ((factory = ddsi_tran_factories) != NULL) { {
ddsi_tran_factories = factory->m_factory; /* Keep the factory in the list for the duration of "factory_free" so that
ddsi_factory_free(factory); conversion of locator kind to factory remains possible. */
} ddsi_tran_factory_t next = factory->m_factory;
ddsi_factory_free (factory);
ddsi_tran_factories = next;
}
} }
static ddsi_tran_factory_t ddsi_factory_find_with_len (const char * type, size_t len) static ddsi_tran_factory_t ddsi_factory_find_with_len (const char * type, size_t len)

View file

@ -679,7 +679,7 @@ static const struct cfgelem ssl_cfgelems[] = {
"<p>This enables SSL/TLS for TCP.</p>" }, "<p>This enables SSL/TLS for TCP.</p>" },
{ LEAF("CertificateVerification"), 1, "true", ABSOFF(ssl_verify), 0, uf_boolean, 0, pf_boolean, { LEAF("CertificateVerification"), 1, "true", ABSOFF(ssl_verify), 0, uf_boolean, 0, pf_boolean,
"<p>If disabled this allows SSL connections to occur even if an X509 certificate fails verification.</p>" }, "<p>If disabled this allows SSL connections to occur even if an X509 certificate fails verification.</p>" },
{ LEAF("VerifyClient"), 1, "false", ABSOFF(ssl_verify_client), 0, uf_boolean, 0, pf_boolean, { LEAF("VerifyClient"), 1, "true", ABSOFF(ssl_verify_client), 0, uf_boolean, 0, pf_boolean,
"<p>This enables an SSL server checking the X509 certificate of a connecting client.</p>" }, "<p>This enables an SSL server checking the X509 certificate of a connecting client.</p>" },
{ LEAF("SelfSignedCertificates"), 1, "false", ABSOFF(ssl_self_signed), 0, uf_boolean, 0, pf_boolean, { LEAF("SelfSignedCertificates"), 1, "false", ABSOFF(ssl_self_signed), 0, uf_boolean, 0, pf_boolean,
"<p>This enables the use of self signed X509 certificates.</p>" }, "<p>This enables the use of self signed X509 certificates.</p>" },