From 98834596f1b70659ab6f47880dd61d402ba186e0 Mon Sep 17 00:00:00 2001 From: Pieter Hintjens Date: Sat, 12 Mar 2016 15:26:26 +0100 Subject: [PATCH] Problem: cannot disable encryption if libsodium is installed The sodium/tweetnacl detection logic does not yet you disable encryption if libsodium is installed. Fixes #1850 in libzmq/master --- CMakeLists.txt | 58 ++++++++++------ Makefile.am | 2 +- NEWS | 2 + configure.ac | 77 ++++++++++----------- src/ctx.cpp | 10 ++- src/curve_client.cpp | 4 +- src/curve_client.hpp | 16 ++--- src/curve_server.cpp | 4 +- src/curve_server.hpp | 16 +++-- src/options.cpp | 8 +-- src/stream_engine.cpp | 2 +- src/zmq.cpp | 2 +- src/zmq_utils.cpp | 17 ++--- tests/test_capabilities.cpp | 2 +- tests/test_security_curve.cpp | 4 +- tweetnacl/contrib/randombytes/randombytes.h | 10 +++ tweetnacl/src/tweetnacl_base.h | 10 +++ 17 files changed, 138 insertions(+), 106 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6125db0..6df98b28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,32 +9,46 @@ if(APPLE) option(ZMQ_BUILD_FRAMEWORK "Build as OS X framework" ON) endif() -if(WIN32) -option(WITH_TWEETNACL "Build with tweetnacl" OFF) -else() -option(WITH_TWEETNACL "Build with tweetnacl" ON) -endif() -if(WITH_TWEETNACL) - add_definitions(-DHAVE_TWEETNACL -DHAVE_LIBSODIUM) - include_directories( - tweetnacl/contrib/randombytes - tweetnacl/src - ) +# Select curve encryption library, defaults to tweetnacl +# To use libsodium instead, use --with-libsodium (must be installed) +# To disable curve, use --disable-curve - set(TWEETNACL_SOURCES - tweetnacl/src/tweetnacl.c - ) - if(WIN32) - list(APPEND TWEETNACL_SOURCES tweetnacl/contrib/randombytes/winrandom.c) - else() - list(APPEND TWEETNACL_SOURCES tweetnacl/contrib/randombytes/devurandom.c) - endif() -else() - find_library(SODIUM_FOUND sodium) -endif() +option (WITH_LIBSODIUM "Use libsodium instead of built-in tweetnacl" OFF) +option (ENABLE_CURVE "Enable CURVE security" ON) +if (NOT ENABLE_CURVE) + message (STATUS "CURVE security is disabled") +elseif (WITH_LIBSODIUM) + find_package (Sodium) + if (SODIUM_FOUND) + message (STATUS "Using libsodium for CURVE security") + include_directories (${SODIUM_INCLUDE_DIRS}) + + # On Solaris, libsodium depends on libssp + if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + target_link_libraries (libzmq ssp) + endif () + set (ZMQ_USE_LIBSODIUM 1) + set (ZMQ_HAVE_CURVE 1) + else () + message (FATAL_ERROR + "libsodium is not installed. Install it, then run CMake again") + endif () + +else () + message (STATUS "Using tweetnacl for CURVE security") + set (ZMQ_USE_TWEETNACL 1) + set (ZMQ_HAVE_CURVE 1) + set (TWEETNACL_SOURCES tweetnacl/src/tweetnacl.c) + if (WIN32) + list(APPEND TWEETNACL_SOURCES tweetnacl/contrib/randombytes/winrandom.c) + else () + list(APPEND TWEETNACL_SOURCES tweetnacl/contrib/randombytes/devurandom.c) + endif () + include_directories (tweetnacl/contrib/randombytes tweetnacl/src) +endif () set(POLLER "" CACHE STRING "Choose polling system. valid values are kqueue, epoll, devpoll, poll or select [default=autodetect]") diff --git a/Makefile.am b/Makefile.am index 2cfa015f..bdbc0435 100644 --- a/Makefile.am +++ b/Makefile.am @@ -232,7 +232,7 @@ libzmq_la_CPPFLAGS = libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ libzmq_la_LIBADD = -if HAVE_SODIUM +if USE_LIBSODIUM libzmq_la_CPPFLAGS += ${sodium_CFLAGS} libzmq_la_LIBADD += ${sodium_LIBS} endif diff --git a/NEWS b/NEWS index 11131709..37b3ef35 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ * Fixed #1831 - potential assertion failure with latest libsodium. +* Fixed #1850 - detection issues with tweetnacl/libsodium. + 0MQ version 4.1.4 stable, released on 2015/12/18 ================================================ diff --git a/configure.ac b/configure.ac index 492002e6..ecc3c0a3 100644 --- a/configure.ac +++ b/configure.ac @@ -138,7 +138,7 @@ libzmq_on_android="no" libzmq_on_linux="no" # Set some default features required by 0MQ code. -CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS" +CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE -Wno-long-long $CPPFLAGS" # For host type checks AC_CANONICAL_HOST @@ -389,49 +389,48 @@ if test "x$require_libgssapi_krb5_ext" != "xno"; then AC_MSG_ERROR(libgssapi_krb5 is needed for GSSAPI security)) fi -# build using libsodium -have_sodium_library="no" +# Select curve encryption library, defaults to tweetnacl +# To use libsodium instead, use --with-libsodium (must be installed) +# To disable curve, use --disable-curve -AC_ARG_WITH([libsodium], [AS_HELP_STRING([--with-libsodium], - [require libzmq build with libsodium crypto library. Requires pkg-config [default=check]])], - [require_libsodium_ext=$withval], - [require_libsodium_ext=check]) +AC_ARG_WITH([libsodium], + [AS_HELP_STRING([--with-libsodium], [use libsodium instead of built-in tweetnacl [default=no]])]) -AC_ARG_WITH([tweetnacl], [AS_HELP_STRING([--with-tweetnacl], - [build libzmq with bundled tweetnacl crypto library [default=no]])], - [require_libsodium_ext=no - with_tweetnacl=yes - AC_MSG_CHECKING(for sodium) - AC_MSG_RESULT(tweetnacl)], - [with_tweetnacl=check]) - -# conditionally require libsodium package -if test "x$require_libsodium_ext" != "xno"; then - PKG_CHECK_MODULES([sodium], [libsodium], - [ - have_sodium_library=yes - with_tweetnacl=no - ], - [ - if test "x$require_libsodium_ext" == "xyes"; then - AC_MSG_ERROR(libsodium has been requested but not found) - else - AC_MSG_RESULT([ libsodium not found, using tweetnacl]) - have_sodium_library=no - with_tweetnacl=yes - fi +AS_IF([test "x$with_libsodium" = "xyes"], [ + PKG_CHECK_MODULES([sodium], [libsodium], [libsodium_found=yes], [ + AC_MSG_ERROR(libsodium is not installed. Install it, then run configure again) ]) +]) + +AC_ARG_ENABLE([curve], + [AS_HELP_STRING([--disable-curve], [disable CURVE security [default=no]])]) + +if test "x$enable_curve" = "xno"; then + curve_library="" + AC_MSG_NOTICE([CURVE security is disabled]) + +elif test "x$with_libsodium" = "xyes"; then + AC_MSG_NOTICE([Using libsodium for CURVE security]) + AC_DEFINE(ZMQ_HAVE_CURVE, [1], [Using curve encryption]) + AC_DEFINE(ZMQ_USE_LIBSODIUM, [1], [Using libsodium for curve encryption]) + curve_library="libsodium" + + # On Solaris, libsodium depends on libssp + case "${host_os}" in + *solaris*) + LDFLAGS="-lssp $LDFLAGS" + ;; + esac +else + AC_MSG_NOTICE([Using tweetnacl for CURVE security]) + AC_DEFINE(ZMQ_HAVE_CURVE, [1], [Using curve encryption]) + AC_DEFINE(ZMQ_USE_TWEETNACL, [1], [Using tweetnacl for curve encryption]) + curve_library="tweetnacl" fi -if test "x$have_sodium_library" != "xno"; then - AC_DEFINE(HAVE_LIBSODIUM, 1, [The libsodium library is to be used.]) -elif test "x$with_tweetnacl" != "xno"; then - AC_DEFINE(HAVE_LIBSODIUM, 1, [Sodium is provided by tweetnacl.]) - AC_DEFINE(HAVE_TWEETNACL, 1, [Using tweetnacl.]) -fi - -AM_CONDITIONAL(HAVE_SODIUM, test "x$have_sodium_library" != "xno") -AM_CONDITIONAL(USE_TWEETNACL, test "x$with_tweetnacl" != "xno") +AM_CONDITIONAL(ENABLE_CURVE_KEYGEN, test "x$enable_curve" = "xyes") +AM_CONDITIONAL(USE_LIBSODIUM, test "$curve_library" = "libsodium") +AM_CONDITIONAL(USE_TWEETNACL, test "$curve_library" = "tweetnacl") # build using pgm have_pgm_library="no" diff --git a/src/ctx.cpp b/src/ctx.cpp index 0dd3cc48..86fcb986 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -46,12 +46,10 @@ #include "err.hpp" #include "msg.hpp" -#ifdef HAVE_LIBSODIUM -#ifdef HAVE_TWEETNACL -#include "randombytes.h" -#else -#include "sodium.h" -#endif +#if defined (ZMQ_USE_TWEETNACL) +# include "randombytes.h" +#elif defined (ZMQ_USE_LIBSODIUM) +# include "sodium.h" #endif #define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe diff --git a/src/curve_client.cpp b/src/curve_client.cpp index 14104d9c..d67007f3 100644 --- a/src/curve_client.cpp +++ b/src/curve_client.cpp @@ -29,7 +29,7 @@ #include "platform.hpp" -#ifdef HAVE_LIBSODIUM +#ifdef ZMQ_HAVE_CURVE #ifdef ZMQ_HAVE_WINDOWS #include "windows.hpp" @@ -53,7 +53,7 @@ zmq::curve_client_t::curve_client_t (const options_t &options_) : memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); memcpy (server_key, options_.curve_server_key, crypto_box_PUBLICKEYBYTES); scoped_lock_t lock (sync); -#if defined(HAVE_TWEETNACL) +#if defined (ZMQ_USE_TWEETNACL) // allow opening of /dev/urandom unsigned char tmpbytes[4]; randombytes(tmpbytes, 4); diff --git a/src/curve_client.hpp b/src/curve_client.hpp index ffae1236..83ea1faa 100644 --- a/src/curve_client.hpp +++ b/src/curve_client.hpp @@ -30,15 +30,16 @@ #ifndef __ZMQ_CURVE_CLIENT_HPP_INCLUDED__ #define __ZMQ_CURVE_CLIENT_HPP_INCLUDED__ +#ifdef ZMQ_HAVE_CURVE + #include "platform.hpp" #include "mutex.hpp" -#ifdef HAVE_LIBSODIUM -#ifdef HAVE_TWEETNACL -#include "tweetnacl_base.h" -#include "randombytes.h" -#else -#include "sodium.h" +#if defined (ZMQ_USE_TWEETNACL) +# include "tweetnacl_base.h" +# include "randombytes.h" +#elif defined (ZMQ_USE_LIBSODIUM) +# include "sodium.h" #endif #if crypto_box_NONCEBYTES != 24 \ @@ -46,7 +47,7 @@ || crypto_box_SECRETKEYBYTES != 32 \ || crypto_box_ZEROBYTES != 32 \ || crypto_box_BOXZEROBYTES != 16 -#error "libsodium not built properly" +# error "CURVE library not built properly" #endif #include "mechanism.hpp" @@ -121,7 +122,6 @@ namespace zmq int process_error (const uint8_t *cmd_data, size_t data_size); mutex_t sync; }; - } #endif diff --git a/src/curve_server.cpp b/src/curve_server.cpp index acc1f29e..cfdd89d9 100644 --- a/src/curve_server.cpp +++ b/src/curve_server.cpp @@ -29,7 +29,7 @@ #include "platform.hpp" -#ifdef HAVE_LIBSODIUM +#ifdef ZMQ_HAVE_CURVE #ifdef ZMQ_HAVE_WINDOWS #include "windows.hpp" @@ -56,7 +56,7 @@ zmq::curve_server_t::curve_server_t (session_base_t *session_, // Fetch our secret key from socket options memcpy (secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES); scoped_lock_t lock (sync); -#if defined(HAVE_TWEETNACL) +#if defined (ZMQ_USE_TWEETNACL) // allow opening of /dev/urandom unsigned char tmpbytes[4]; randombytes(tmpbytes, 4); diff --git a/src/curve_server.hpp b/src/curve_server.hpp index fe7cf877..51ed245e 100644 --- a/src/curve_server.hpp +++ b/src/curve_server.hpp @@ -30,15 +30,17 @@ #ifndef __ZMQ_CURVE_SERVER_HPP_INCLUDED__ #define __ZMQ_CURVE_SERVER_HPP_INCLUDED__ +#ifdef ZMQ_HAVE_CURVE + #include "platform.hpp" -#ifdef HAVE_LIBSODIUM -#ifdef HAVE_TWEETNACL -#include "tweetnacl_base.h" -#include "randombytes.h" -#else -#include "sodium.h" +#if defined (ZMQ_USE_TWEETNACL) +# include "tweetnacl_base.h" +# include "randombytes.h" +#elif defined (ZMQ_USE_LIBSODIUM) +# include "sodium.h" #endif + #if crypto_box_NONCEBYTES != 24 \ || crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 \ @@ -47,7 +49,7 @@ || crypto_secretbox_NONCEBYTES != 24 \ || crypto_secretbox_ZEROBYTES != 32 \ || crypto_secretbox_BOXZEROBYTES != 16 -#error "libsodium not built properly" +# error "CURVE library not built properly" #endif #include "mechanism.hpp" diff --git a/src/options.cpp b/src/options.cpp index 577763bb..f36cdf20 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -368,8 +368,8 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, } break; - // If libsodium isn't installed, these options provoke EINVAL -# ifdef HAVE_LIBSODIUM + // If CURVE encryption isn't built, these options provoke EINVAL +# ifdef ZMQ_HAVE_CURVE case ZMQ_CURVE_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; @@ -759,8 +759,8 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) } break; - // If libsodium isn't installed, these options provoke EINVAL -# ifdef HAVE_LIBSODIUM + // If CURVE encryption isn't built, these options provoke EINVAL +# ifdef ZMQ_HAVE_CURVE case ZMQ_CURVE_SERVER: if (is_int) { *value = as_server && mechanism == ZMQ_CURVE; diff --git a/src/stream_engine.cpp b/src/stream_engine.cpp index faca8929..3dbfb7da 100644 --- a/src/stream_engine.cpp +++ b/src/stream_engine.cpp @@ -654,7 +654,7 @@ bool zmq::stream_engine_t::handshake () plain_client_t (options); alloc_assert (mechanism); } -#ifdef HAVE_LIBSODIUM +#ifdef ZMQ_HAVE_CURVE else if (options.mechanism == ZMQ_CURVE && memcmp (greeting_recv + 12, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) { diff --git a/src/zmq.cpp b/src/zmq.cpp index 22faee85..6f9d2290 100644 --- a/src/zmq.cpp +++ b/src/zmq.cpp @@ -1083,7 +1083,7 @@ int zmq_has (const char *capability) if (strcmp (capability, "norm") == 0) return true; #endif -#if defined (HAVE_LIBSODIUM) +#if defined (ZMQ_HAVE_CURVE) if (strcmp (capability, "curve") == 0) return true; #endif diff --git a/src/zmq_utils.cpp b/src/zmq_utils.cpp index f8a69714..84af96c3 100644 --- a/src/zmq_utils.cpp +++ b/src/zmq_utils.cpp @@ -41,14 +41,11 @@ #include "windows.hpp" #endif -#ifdef HAVE_LIBSODIUM -#ifdef HAVE_TWEETNACL -#include "tweetnacl_base.h" -#else -#include "sodium.h" +#if defined (ZMQ_USE_TWEETNACL) +# include "tweetnacl_base.h" +#elif defined (ZMQ_USE_LIBSODIUM) +# include "sodium.h" #endif -#endif - void zmq_sleep (int seconds_) { @@ -190,10 +187,10 @@ uint8_t *zmq_z85_decode (uint8_t *dest, const char *string) int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) { -#ifdef HAVE_LIBSODIUM +#ifdef ZMQ_HAVE_CURVE # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 -# error "libsodium not built correctly" +# error "CURVE encryption library not built correctly" # endif uint8_t public_key [32]; @@ -208,7 +205,7 @@ int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key) zmq_z85_encode (z85_secret_key, secret_key, 32); return 0; -#else // requires libsodium +#else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; diff --git a/tests/test_capabilities.cpp b/tests/test_capabilities.cpp index f3188164..81090ec8 100644 --- a/tests/test_capabilities.cpp +++ b/tests/test_capabilities.cpp @@ -55,7 +55,7 @@ int main (void) assert (!zmq_has ("norm")); #endif -#if defined (HAVE_LIBSODIUM) +#if defined (ZMQ_HAVE_CURVE) assert (zmq_has ("curve")); #else assert (!zmq_has ("curve")); diff --git a/tests/test_security_curve.cpp b/tests/test_security_curve.cpp index a8ba3b22..ebfb9538 100644 --- a/tests/test_security_curve.cpp +++ b/tests/test_security_curve.cpp @@ -102,8 +102,8 @@ static void zap_handler (void *handler) int main (void) { -#ifndef HAVE_LIBSODIUM - printf ("libsodium not installed, skipping CURVE test\n"); +#ifndef ZMQ_HAVE_CURVE + printf ("CURVE encryption not installed, skipping test\n"); return 0; #endif diff --git a/tweetnacl/contrib/randombytes/randombytes.h b/tweetnacl/contrib/randombytes/randombytes.h index 2945738b..d724f4a2 100644 --- a/tweetnacl/contrib/randombytes/randombytes.h +++ b/tweetnacl/contrib/randombytes/randombytes.h @@ -7,6 +7,16 @@ Public domain. #ifndef randombytes_H #define randombytes_H +/* + Disable warnings for this source only, rather than for the whole + codebase when building with C99 or with Microsoft's compiler +*/ +#if defined __GNUC__ && __STDC_VERSION__ < 201112L +# pragma GCC diagnostic ignored "-Wsign-compare" +#elif defined _MSC_VER +# pragma warning (disable:4018 4244 4146) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/tweetnacl/src/tweetnacl_base.h b/tweetnacl/src/tweetnacl_base.h index 2fe4a4a7..42b99726 100644 --- a/tweetnacl/src/tweetnacl_base.h +++ b/tweetnacl/src/tweetnacl_base.h @@ -1,6 +1,16 @@ #ifndef TWEETNACL_BASE_H #define TWEETNACL_BASE_H +/* + Disable warnings for this source only, rather than for the whole + codebase when building with C99 or with Microsoft's compiler +*/ +#if defined __GNUC__ && __STDC_VERSION__ < 201112L +# pragma GCC diagnostic ignored "-Wsign-compare" +#elif defined _MSC_VER +# pragma warning (disable:4018 4244 4146) +#endif + /* the original file seems to be a compability layer for NaCL */ /* This here is for direct tweetnacl usage */