Merge pull request #107 from eboasson/master

fix and enable SSL support when OpenSSL is available

This has been sitting pretty for some days now and in my opinion it makes sense to merge it — so merging it. The AppVeyor build is not done yet, but it is successful for the exact same commit on the source branch and it also succesful for the next-to-last commit. The last commit in the PR is no more than Travis CI configuration, so it doesn't even affect AppVeyor builds.
This commit is contained in:
eboasson 2019-02-04 16:09:14 +00:00 committed by GitHub
commit 413d9d36eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 314 additions and 269 deletions

View file

@ -5,27 +5,33 @@ language: c
# anchor/alias YAML features. # anchor/alias YAML features.
linux_gcc8: &linux_gcc8 linux_gcc8: &linux_gcc8
os: linux os: linux
dist: xenial
compiler: gcc compiler: gcc
addons: addons:
apt: apt:
update: true update: true
sources: [ ubuntu-toolchain-r-test ] sources: [ ubuntu-toolchain-r-test ]
packages: [ gcc-8 g++-8 oracle-java8-set-default maven ] #packages: [ gcc-8 g++-8 maven cmake ]
packages: [ gcc-8 g++-8 ]
linux_clang60: &linux_clang60 linux_clang: &linux_clang
os: linux os: linux
dist: xenial
compiler: clang compiler: clang
addons: addons:
apt: apt:
update: true update: true
sources: [ llvm-toolchain-trusty-6.0, ubuntu-toolchain-r-test ] #sources: [ ubuntu-toolchain-r-test ]
packages: [ clang-6.0 oracle-java8-set-default maven ] #packages: [ maven clang ]
osx_xcode94: &osx_xcode94 osx_xcode10_1: &osx_xcode10_1
os: osx os: osx
osx_image: xcode94 osx_image: xcode10.1
compiler: clang compiler: clang
addons:
homebrew:
packages:
- pyenv-virtualenv
matrix: matrix:
include: include:
@ -33,13 +39,13 @@ matrix:
env: [ BUILD_TYPE=Debug, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ] env: [ BUILD_TYPE=Debug, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ]
- <<: *linux_gcc8 - <<: *linux_gcc8
env: [ BUILD_TYPE=Release, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ] env: [ BUILD_TYPE=Release, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ]
- <<: *linux_clang60 - <<: *linux_clang
env: [ BUILD_TYPE=Debug, C_COMPILER=clang-6.0, CXX_COMPILER=clang++-6.0, USE_SANITIZER=address ]
- <<: *linux_clang60
env: [ BUILT_TYPE=Release, C_COMPILER=clang-6.0, CXX_COMPILER=clang++-6.0, USE_SANITIZER=none ]
- <<: *osx_xcode94
env: [ BUILD_TYPE=Debug, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=address ] env: [ BUILD_TYPE=Debug, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=address ]
- <<: *osx_xcode94 - <<: *linux_clang
env: [ BUILT_TYPE=Release, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=none ]
- <<: *osx_xcode10_1
env: [ BUILD_TYPE=Debug, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=address ]
- <<: *osx_xcode10_1
env: [ BUILD_TYPE=Release, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=none ] env: [ BUILD_TYPE=Release, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=none ]
@ -49,7 +55,6 @@ before_install:
install: install:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
brew install pyenv-virtualenv;
eval "$(pyenv init -)"; eval "$(pyenv init -)";
pyenv virtualenv conan; pyenv virtualenv conan;
pyenv rehash; pyenv rehash;
@ -66,7 +71,7 @@ before_script:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- conan install .. - conan install .. --build missing
- cmake -DBUILD_TESTING=on -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DUSE_SANITIZER=${USE_SANITIZER} -DCMAKE_INSTALL_PREFIX=${PWD}/install ../src - cmake -DBUILD_TESTING=on -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DUSE_SANITIZER=${USE_SANITIZER} -DCMAKE_INSTALL_PREFIX=${PWD}/install ../src
- cmake --build . --target install - cmake --build . --target install
- mkdir install/share/CycloneDDS/examples/helloworld/build - mkdir install/share/CycloneDDS/examples/helloworld/build

View file

@ -1,5 +1,6 @@
[requires] [requires]
cunit/2.1-3@bincrafters/stable cunit/2.1-3@bincrafters/stable
OpenSSL/1.1.1a@conan/stable
[generators] [generators]
cmake cmake

View file

@ -80,6 +80,7 @@ if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
else() else()
conan_basic_setup() conan_basic_setup()
endif() endif()
conan_define_targets()
endif() endif()
# Set reasonably strict warning options for clang, gcc, msvc # Set reasonably strict warning options for clang, gcc, msvc

View file

@ -0,0 +1,34 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
if(TARGET CONAN_PKG::OpenSSL)
add_library(OpenSSL::SSL INTERFACE IMPORTED)
target_link_libraries(OpenSSL::SSL INTERFACE CONAN_PKG::OpenSSL)
set(OPENSSL_FOUND TRUE)
else()
# Loop over a list of possible module paths (without the current directory).
get_filename_component(DIR "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE)
foreach(MODULE_DIR ${CMAKE_MODULE_PATH} ${CMAKE_ROOT}/Modules)
get_filename_component(MODULE_DIR "${MODULE_DIR}" ABSOLUTE)
if(NOT MODULE_DIR STREQUAL DIR)
if(EXISTS "${MODULE_DIR}/FindOpenSSL.cmake")
set(FIND_PACKAGE_FILE "${MODULE_DIR}/FindOpenSSL.cmake")
break()
endif()
endif()
endforeach()
if(FIND_PACKAGE_FILE)
include("${FIND_PACKAGE_FILE}")
endif()
endif()

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,20 @@ endif()
add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM)
option(DDSC_ENABLE_OPENSSL "Enable openssl support" ON)
if(DDSC_ENABLE_OPENSSL)
find_package(OpenSSL)
if(OPENSSL_FOUND)
add_definitions(-DDDSI_INCLUDE_SSL)
target_link_libraries(ddsc PRIVATE OpenSSL::SSL)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099")
endif()
else()
message(FATAL_ERROR "To build without openssl support, set DDSC_ENABLE_OPENSSL to OFF")
endif()
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

@ -36,7 +36,7 @@ typedef struct ddsi_tran_qos * ddsi_tran_qos_t;
/* Function pointer types */ /* Function pointer types */
typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t, unsigned char *, size_t, nn_locator_t *); typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t, unsigned char *, size_t, bool, nn_locator_t *);
typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const nn_locator_t *, size_t, const os_iovec_t *, uint32_t); typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const nn_locator_t *, size_t, const os_iovec_t *, uint32_t);
typedef int (*ddsi_tran_locator_fn_t) (ddsi_tran_base_t, nn_locator_t *); typedef int (*ddsi_tran_locator_fn_t) (ddsi_tran_base_t, nn_locator_t *);
typedef bool (*ddsi_tran_supports_fn_t) (int32_t); typedef bool (*ddsi_tran_supports_fn_t) (int32_t);
@ -220,8 +220,8 @@ inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc) {
inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) { inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) {
return conn->m_closed ? -1 : (conn->m_write_fn) (conn, dst, niov, iov, flags); return conn->m_closed ? -1 : (conn->m_write_fn) (conn, dst, niov, iov, flags);
} }
inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) { inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc) {
return conn->m_closed ? -1 : conn->m_read_fn (conn, buf, len, srcloc); return conn->m_closed ? -1 : conn->m_read_fn (conn, buf, len, allow_spurious, srcloc);
} }
bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc); bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc);
void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn); void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn);

View file

@ -213,6 +213,13 @@ enum many_sockets_mode {
MSM_MANY_UNICAST MSM_MANY_UNICAST
}; };
#ifdef DDSI_INCLUDE_SSL
struct ssl_min_version {
int major;
int minor;
};
#endif
struct config struct config
{ {
int valid; int valid;
@ -301,6 +308,7 @@ struct config
char * ssl_rand_file; char * ssl_rand_file;
char * ssl_key_pass; char * ssl_key_pass;
char * ssl_ciphers; char * ssl_ciphers;
struct ssl_min_version ssl_min_version;
#endif #endif

View file

@ -63,7 +63,7 @@ static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t
return dst; return dst;
} }
static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
int err; int err;
ssize_t ret; ssize_t ret;
@ -71,6 +71,7 @@ static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf
struct sockaddr_ll src; struct sockaddr_ll src;
struct iovec msg_iov; struct iovec msg_iov;
socklen_t srclen = (socklen_t) sizeof (src); socklen_t srclen = (socklen_t) sizeof (src);
(void) allow_spurious;
msg_iov.iov_base = (void*) buf; msg_iov.iov_base = (void*) buf;
msg_iov.iov_len = len; msg_iov.iov_len = len;

View file

@ -9,325 +9,275 @@
* *
* 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 ()); unsigned disallow_TLSv1_2;
/* 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); switch (config.ssl_min_version.major)
{
case 1:
switch (config.ssl_min_version.minor)
{
case 2:
disallow_TLSv1_2 = 0;
break;
case 3:
#ifdef SSL_OP_NO_TLSv1_2
disallow_TLSv1_2 = SSL_OP_NO_TLSv1_2;
#else
DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: openssl version does not support disabling TLSv1.2 as required by config\n");
goto fail;
#endif
break;
default:
DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: can't set minimum requested TLS version to %d.%d\n", config.ssl_min_version.major, config.ssl_min_version.minor);
goto fail;
}
break;
default:
DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: can't set minimum requested TLS version to %d.%d\n", config.ssl_min_version.major, config.ssl_min_version.minor);
goto fail;
}
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 | disallow_TLSv1_2);
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; on Win64 a SOCKET is 64-bit type is forced into an int by
the OpenSSL API. Lots of software does use openssl on Win64, so it appears that it is
safe to do so, and moreover, that it will remain safe to do so, given Microsoft's track
record of maintaining backwards compatibility. The SSL API is in the wrong of course ... */
ssl = ddsi_ssl_new (); ssl = ddsi_ssl_new ();
OS_WARNING_MSVC_OFF(4244);
SSL_set_fd (ssl, sock); SSL_set_fd (ssl, sock);
OS_WARNING_MSVC_ON(4244);
err = SSL_connect (ssl); err = SSL_connect (ssl);
if (err != 1) if (err != 1)
{ {
@ -335,20 +285,24 @@ 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)
{ {
/* See comment in ddsi_ssl_connect concerning casting the socket to an int */
BIO * bio = BIO_new (BIO_s_accept ()); BIO * bio = BIO_new (BIO_s_accept ());
OS_WARNING_MSVC_OFF(4244);
BIO_set_fd (bio, sock, BIO_NOCLOSE); BIO_set_fd (bio, sock, BIO_NOCLOSE);
OS_WARNING_MSVC_ON(4244);
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 +319,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 +354,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
{ {
const int locks = CRYPTO_num_locks ();
for (int i = 0; i < locks; i++)
os_mutexDestroy (&ddsi_ssl_locks[i].m_mutex); os_mutexDestroy (&ddsi_ssl_locks[i].m_mutex);
}
os_free (ddsi_ssl_locks); os_free (ddsi_ssl_locks);
}
static void ddsi_ssl_config (void)
{
if (config.ssl_enable)
{
ddsi_tcp_ssl_plugin.init = ddsi_ssl_init;
ddsi_tcp_ssl_plugin.fini = ddsi_ssl_fini;
ddsi_tcp_ssl_plugin.ssl_free = SSL_free;
ddsi_tcp_ssl_plugin.bio_vfree = BIO_vfree;
ddsi_tcp_ssl_plugin.read = ddsi_ssl_read;
ddsi_tcp_ssl_plugin.write = ddsi_ssl_write;
ddsi_tcp_ssl_plugin.connect = ddsi_ssl_connect;
ddsi_tcp_ssl_plugin.listen = ddsi_ssl_listen;
ddsi_tcp_ssl_plugin.accept = ddsi_ssl_accept;
} }
#endif
} }
void ddsi_ssl_plugin (void) void ddsi_ssl_config_plugin (struct ddsi_ssl_plugins *plugin)
{ {
ddsi_tcp_ssl_plugin.config = ddsi_ssl_config; plugin->init = ddsi_ssl_init;
plugin->fini = ddsi_ssl_fini;
plugin->ssl_free = SSL_free;
plugin->bio_vfree = BIO_vfree;
plugin->read = ddsi_ssl_read;
plugin->write = ddsi_ssl_write;
plugin->connect = ddsi_ssl_connect;
plugin->listen = ddsi_ssl_listen;
plugin->accept = ddsi_ssl_accept;
} }
#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);
} }
@ -396,7 +395,7 @@ static int err_is_AGAIN_or_WOULDBLOCK (int err)
return 0; return 0;
} }
static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn; ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn;
ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain; ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain;
@ -437,11 +436,11 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
{ {
if (err_is_AGAIN_or_WOULDBLOCK (err)) if (err_is_AGAIN_or_WOULDBLOCK (err))
{ {
if (ddsi_tcp_select (tcp->m_sock, true, pos) == false) if (allow_spurious && pos == 0)
{ return 0;
else if (ddsi_tcp_select (tcp->m_sock, true, pos) == false)
break; break;
} }
}
else else
{ {
DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIsock" error %d\n", ddsi_name, tcp->m_sock, err); DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIsock" error %d\n", ddsi_name, tcp->m_sock, 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;
@ -603,7 +602,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d
{ {
int i; int i;
char * ptr; char * ptr;
iovec.iov_len = len; iovec.iov_len = (os_iov_len_t) len;
iovec.iov_base = (len <= sizeof (msgbuf)) ? msgbuf : os_malloc (len); iovec.iov_base = (len <= sizeof (msgbuf)) ? msgbuf : os_malloc (len);
ptr = iovec.iov_base; ptr = iovec.iov_base;
for (i = 0; i < (int) msg.msg_iovlen; i++) for (i = 0; i < (int) msg.msg_iovlen; i++)
@ -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

@ -31,7 +31,7 @@ extern inline int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc);
extern inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc); extern inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc);
extern inline int ddsi_listener_listen (ddsi_tran_listener_t listener); extern inline int ddsi_listener_listen (ddsi_tran_listener_t listener);
extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener); extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener);
extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc); extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc);
extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags); extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags);
void ddsi_factory_add (ddsi_tran_factory_t factory) void ddsi_factory_add (ddsi_tran_factory_t factory)
@ -60,10 +60,13 @@ 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;
} }
} }

View file

@ -48,7 +48,7 @@ static struct ddsi_udp_config ddsi_udp_config_g;
static struct ddsi_tran_factory ddsi_udp_factory_g; static struct ddsi_tran_factory ddsi_udp_factory_g;
static os_atomic_uint32_t ddsi_udp_init_g = OS_ATOMIC_UINT32_INIT(0); static os_atomic_uint32_t ddsi_udp_init_g = OS_ATOMIC_UINT32_INIT(0);
static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
int err; int err;
ssize_t ret; ssize_t ret;
@ -56,6 +56,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
os_sockaddr_storage src; os_sockaddr_storage src;
os_iovec_t msg_iov; os_iovec_t msg_iov;
socklen_t srclen = (socklen_t) sizeof (src); socklen_t srclen = (socklen_t) sizeof (src);
(void) allow_spurious;
msg_iov.iov_base = (void*) buf; msg_iov.iov_base = (void*) buf;
msg_iov.iov_len = (os_iov_len_t)len; /* Windows uses unsigned, POSIX (except Linux) int */ msg_iov.iov_len = (os_iov_len_t)len; /* Windows uses unsigned, POSIX (except Linux) int */

View file

@ -165,6 +165,9 @@ DUPF(durability_cdr);
DUPF(transport_selector); DUPF(transport_selector);
DUPF(many_sockets_mode); DUPF(many_sockets_mode);
DU(deaf_mute); DU(deaf_mute);
#ifdef DDSI_INCLUDE_SSL
DUPF(min_tls_version);
#endif
#undef DUPF #undef DUPF
#undef DU #undef DU
#undef PF #undef PF
@ -679,7 +682,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>" },
@ -691,6 +694,8 @@ static const struct cfgelem ssl_cfgelems[] = {
"<p>The set of ciphers used by SSL/TLS</p>" }, "<p>The set of ciphers used by SSL/TLS</p>" },
{ LEAF("EntropyFile"), 1, "", ABSOFF(ssl_rand_file), 0, uf_string, ff_free, pf_string, { LEAF("EntropyFile"), 1, "", ABSOFF(ssl_rand_file), 0, uf_string, ff_free, pf_string,
"<p>The SSL/TLS random entropy file name.</p>" }, "<p>The SSL/TLS random entropy file name.</p>" },
{ LEAF("MinimumTLSVersion"), 1, "1.3", ABSOFF(ssl_min_version), 0, uf_min_tls_version, 0, pf_min_tls_version,
"<p>The minimum TLS version that may be negotiated, valid values are 1.2 and 1.3.</p>" },
END_MARKER END_MARKER
}; };
#endif #endif
@ -1408,6 +1413,30 @@ static void pf_besmode(struct cfgst *cfgst, void *parent, struct cfgelem const *
cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
} }
#ifdef DDSI_INCLUDE_SSL
static int uf_min_tls_version(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
{
static const char *vs[] = {
"1.2", "1.3", NULL
};
static const struct ssl_min_version ms[] = {
{1,2}, {1,3}, {0,0}
};
int idx = list_index(vs, value);
struct ssl_min_version *elem = cfg_address(cfgst, parent, cfgelem);
assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms));
if ( idx < 0 )
return cfg_error(cfgst, "'%s': undefined value", value);
*elem = ms[idx];
return 1;
}
static void pf_min_tls_version(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
{
struct ssl_min_version *p = cfg_address(cfgst, parent, cfgelem);
cfg_log(cfgst, "%d.%d%s", p->major, p->minor, is_default ? " [def]" : "");
}
#endif
static int uf_durability_cdr(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) static int uf_durability_cdr(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
{ {

View file

@ -2970,7 +2970,13 @@ static bool do_packet
/* Read in DDSI header plus MSG_LEN sub message that follows it */ /* Read in DDSI header plus MSG_LEN sub message that follows it */
sz = ddsi_conn_read (conn, buff, stream_hdr_size, &srcloc); sz = ddsi_conn_read (conn, buff, stream_hdr_size, true, &srcloc);
if (sz == 0)
{
/* Spurious read -- which at this point is still ok */
nn_rmsg_commit (rmsg);
return true;
}
/* Read in remainder of packet */ /* Read in remainder of packet */
@ -2998,7 +3004,7 @@ static bool do_packet
} }
else else
{ {
sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size, NULL); sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size, false, NULL);
if (sz > 0) if (sz > 0)
{ {
sz = (ssize_t) ml->length; sz = (ssize_t) ml->length;
@ -3010,7 +3016,7 @@ static bool do_packet
{ {
/* Get next packet */ /* Get next packet */
sz = ddsi_conn_read (conn, buff, buff_len, &srcloc); sz = ddsi_conn_read (conn, buff, buff_len, true, &srcloc);
} }
if (sz > 0 && !gv.deaf) if (sz > 0 && !gv.deaf)