problem: sha1 external module conflict with czmq

Solution: allow to use external library (nss) for sha1 to avoid the conflict
This commit is contained in:
somdoron 2019-09-11 13:09:22 +03:00
parent 52e0d965b3
commit 9be8334938
11 changed files with 205 additions and 56 deletions

View File

@ -94,6 +94,47 @@ if(APPLE)
option(ZMQ_BUILD_FRAMEWORK "Build as OS X framework" OFF)
endif()
# Disable webSocket transport
option(DISABLE_WS "Disable WebSocket transport" OFF)
option(WITH_NSS "Use NSS instead of builtin sha1" OFF)
if (NOT DISABLE_WS)
list(APPEND sources
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_address.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_connecter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_decoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_encoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_engine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_listener.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_address.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_connecter.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_decoder.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_encoder.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_engine.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_listener.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_protocol.hpp)
set(ZMQ_HAVE_WS 1)
if (WITH_NSS)
find_package("NSS3")
if (NSS3_FOUND)
message(STATUS "Using NSS")
include_directories(${NSS3_INCLUDE_DIRS})
set(pkg_config_names_private "${pkg_config_names_private} nss3")
set(pkg_config_libs_private "${pkg_config_libs_private} -lnss3")
set(ZMQ_USE_NSS 1)
else()
message(FATAL_ERROR
"nss is not installed. Install it, then run CMake again")
endif()
else()
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.c ${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.h)
message("Using builtin sha1")
set(ZMQ_USE_BUILTIN_SHA1 1)
endif()
endif()
# Select curve encryption library, defaults to tweetnacl
# To use libsodium instead, use --with-libsodium(must be installed)
# To disable curve, use --disable-curve
@ -223,8 +264,6 @@ else()
message(FATAL_ERROR "Invalid polling method")
endif()
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.c ${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.h)
if(POLLER STREQUAL "epoll" AND WIN32)
message(STATUS "Including wepoll")
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/external/wepoll/wepoll.c ${CMAKE_CURRENT_SOURCE_DIR}/external/wepoll/wepoll.h)
@ -785,12 +824,6 @@ set(cxx-sources
gather.cpp
ip_resolver.cpp
zap_client.cpp
ws_address.cpp
ws_connecter.cpp
ws_decoder.cpp
ws_encoder.cpp
ws_engine.cpp
ws_listener.cpp
zmtp_engine.cpp
# at least for VS, the header files must also be listed
address.hpp
@ -924,13 +957,6 @@ set(cxx-sources
vmci_listener.hpp
windows.hpp
wire.hpp
ws_address.hpp
ws_connecter.hpp
ws_decoder.hpp
ws_encoder.hpp
ws_engine.hpp
ws_listener.hpp
ws_protocol.hpp
xpub.hpp
xsub.hpp
ypipe.hpp
@ -1232,6 +1258,10 @@ endforeach()
if(BUILD_SHARED)
target_link_libraries(libzmq ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(NSS3_FOUND)
target_link_libraries(libzmq ${NSS3_LIBRARIES})
endif()
if(SODIUM_FOUND)
target_link_libraries(libzmq ${SODIUM_LIBRARIES})
# On Solaris, libsodium depends on libssp
@ -1262,6 +1292,10 @@ endif()
if(BUILD_STATIC)
target_link_libraries(libzmq-static ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(NSS3_FOUND)
target_link_libraries(libzmq-static ${NSS3_LIBRARIES})
endif()
if(SODIUM_FOUND)
target_link_libraries(libzmq-static ${SODIUM_LIBRARIES})
# On Solaris, libsodium depends on libssp

View File

@ -250,19 +250,6 @@ src_libzmq_la_SOURCES = \
src/vmci_listener.hpp \
src/windows.hpp \
src/wire.hpp \
src/ws_address.cpp \
src/ws_address.hpp \
src/ws_connecter.cpp \
src/ws_connecter.hpp \
src/ws_decoder.cpp \
src/ws_decoder.hpp \
src/ws_encoder.cpp \
src/ws_encoder.hpp \
src/ws_engine.cpp \
src/ws_engine.hpp \
src/ws_listener.cpp \
src/ws_listener.hpp \
src/ws_protocol.hpp \
src/xpub.cpp \
src/xpub.hpp \
src/xsub.cpp \
@ -281,9 +268,7 @@ src_libzmq_la_SOURCES = \
src/zap_client.hpp \
src/zmtp_engine.cpp \
src/zmtp_engine.hpp \
src/zmq_draft.h \
external/sha1/sha1.c \
external/sha1/sha1.h
src/zmq_draft.h
if USE_WEPOLL
src_libzmq_la_SOURCES += \
@ -297,6 +282,29 @@ src_libzmq_la_SOURCES += \
src/tweetnacl.h
endif
if HAVE_WS
src_libzmq_la_SOURCES += \
src/ws_address.cpp \
src/ws_address.hpp \
src/ws_connecter.cpp \
src/ws_connecter.hpp \
src/ws_decoder.cpp \
src/ws_decoder.hpp \
src/ws_encoder.cpp \
src/ws_encoder.hpp \
src/ws_engine.cpp \
src/ws_engine.hpp \
src/ws_listener.cpp \
src/ws_listener.hpp \
src/ws_protocol.hpp
endif
if USE_BUILTIN_SHA1
src_libzmq_la_SOURCES += \
external/sha1/sha1.c \
external/sha1/sha1.h
endif
if ON_MINGW
src_libzmq_la_LDFLAGS = \
-no-undefined \
@ -334,6 +342,11 @@ src_libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ $(CODE_COVERAGE_CXXFLAGS) \
$(LIBUNWIND_CFLAGS)
src_libzmq_la_LIBADD = $(CODE_COVERAGE_LDFLAGS) $(LIBUNWIND_LIBS)
if HAVE_WS
src_libzmq_la_CPPFLAGS += ${NSS3_CFLAGS}
src_libzmq_la_LIBADD += ${NSS3_LIBS}
endif
if USE_LIBSODIUM
src_libzmq_la_CPPFLAGS += ${sodium_CFLAGS}
src_libzmq_la_LIBADD += ${sodium_LIBS}
@ -479,8 +492,7 @@ test_apps = \
tests/test_sodium \
tests/test_reconnect_ivl \
tests/test_mock_pub_sub \
tests/test_socket_null \
tests/test_ws_transport
tests/test_socket_null
UNITY_CPPFLAGS = -I$(top_srcdir)/external/unity -DUNITY_USE_COMMAND_LINE_ARGS -DUNITY_EXCLUDE_FLOAT
UNITY_LIBS = $(top_builddir)/external/unity/libunity.a
@ -795,10 +807,6 @@ tests_test_mock_pub_sub_SOURCES = tests/test_mock_pub_sub.cpp
tests_test_mock_pub_sub_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_mock_pub_sub_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_ws_transport_SOURCES = tests/test_ws_transport.cpp
tests_test_ws_transport_LDADD = ${TESTUTIL_LIBS} src/libzmq.la
tests_test_ws_transport_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
if HAVE_CURVE
test_apps += \
@ -834,6 +842,14 @@ endif
endif
if HAVE_WS
test_apps += \
tests/test_ws_transport
tests_test_ws_transport_SOURCES = tests/test_ws_transport.cpp
tests_test_ws_transport_LDADD = ${TESTUTIL_LIBS} src/libzmq.la ${NSS3_LIBS}
tests_test_ws_transport_CPPFLAGS = ${TESTUTIL_CPPFLAGS} ${NSS3_CFLAGS}
endif
if !ON_MINGW
if !ON_CYGWIN
test_apps += \

View File

@ -0,0 +1,8 @@
include(FindPackageHandleStandardArgs)
if (NOT MSVC)
find_package(PkgConfig REQUIRED)
pkg_check_modules(NSS3 "nss>=3.19")
find_package_handle_standard_args(NSS3 DEFAULT_MSG NSS3_LIBRARIES NSS3_CFLAGS)
endif()

View File

@ -51,6 +51,10 @@
#cmakedefine HAVE_ACCEPT4
#cmakedefine HAVE_STRNLEN
#cmakedefine ZMQ_USE_BUILTIN_SHA1
#cmakedefine ZMQ_USE_NSS
#cmakedefine ZMQ_HAVE_WS
#cmakedefine ZMQ_HAVE_OPENPGM
#cmakedefine ZMQ_MAKE_VALGRIND_HAPPY

View File

@ -548,9 +548,40 @@ AM_CONDITIONAL(ENABLE_CURVE_KEYGEN, test "x$enable_curve" = "xyes" -a "x$zmq_ena
AM_CONDITIONAL(USE_LIBSODIUM, test "$curve_library" = "libsodium")
AM_CONDITIONAL(USE_TWEETNACL, test "$curve_library" = "tweetnacl")
AM_CONDITIONAL(HAVE_CURVE, test "x$curve_library" != "x")
AM_CONDITIONAL(USE_WEPOLL, test "$poller" = "wepoll")
# Check requiring packages for WebSocket
sha1_library=""
AC_ARG_ENABLE([ws],
[AS_HELP_STRING([--disable-ws], [Disable WebSocket transport [default=no]])])
AC_ARG_WITH([nss],
[AS_HELP_STRING([--with-nss], [use nss instead of built-in sha1 [default=no]])])
if test "x$enable_ws" != "xno"; then
if test "x$with_nss" = "xyes"; then
PKG_CHECK_MODULES([NSS3], [nss], [
PKGCFG_NAMES_PRIVATE="$PKGCFG_NAMES_PRIVATE nss"
AC_DEFINE(ZMQ_USE_NSS, [1], [Using NSS])
AC_DEFINE(ZMQ_HAVE_WS, [1], [Using websocket])
sha1_library="nss"
AC_MSG_NOTICE(Using NSS)
], [
AC_MSG_ERROR(nss is not installed. Install it, then run configure again)
])
else
AC_DEFINE(ZMQ_USE_BUILTIN_SHA1, [1], [Using built-in sha1])
AC_DEFINE(ZMQ_HAVE_WS, [1], [Using websocket])
sha1_library="builtin"
AC_MSG_NOTICE(Using builting SHA1)
fi
fi
AM_CONDITIONAL(HAVE_WS, test "x$sha1_library" != "x")
AM_CONDITIONAL(USE_NSS, test "x$sha1_library" = "xnss")
AM_CONDITIONAL(USE_BUILTIN_SHA1, test "x$sha1_library" = "xbuiltin")
# build using pgm
have_pgm_library="no"

View File

@ -61,9 +61,13 @@ zmq::address_t::~address_t ()
LIBZMQ_DELETE (resolved.tcp_addr);
} else if (protocol == protocol_name::udp) {
LIBZMQ_DELETE (resolved.udp_addr);
} else if (protocol == protocol_name::ws) {
}
#ifdef ZMQ_HAVE_WS
else if (protocol == protocol_name::ws) {
LIBZMQ_DELETE (resolved.ws_addr);
}
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
else if (protocol == protocol_name::ipc) {
@ -88,8 +92,10 @@ int zmq::address_t::to_string (std::string &addr_) const
return resolved.tcp_addr->to_string (addr_);
if (protocol == protocol_name::udp && resolved.udp_addr)
return resolved.udp_addr->to_string (addr_);
#ifdef ZMQ_HAVE_WS
if (protocol == protocol_name::ws && resolved.ws_addr)
return resolved.ws_addr->to_string (addr_);
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
if (protocol == protocol_name::ipc && resolved.ipc_addr)

View File

@ -61,7 +61,9 @@ namespace protocol_name
static const char inproc[] = "inproc";
static const char tcp[] = "tcp";
static const char udp[] = "udp";
#ifdef ZMQ_HAVE_WS
static const char ws[] = "ws";
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
static const char ipc[] = "ipc";
@ -93,7 +95,9 @@ struct address_t
void *dummy;
tcp_address_t *tcp_addr;
udp_address_t *udp_addr;
#ifdef ZMQ_HAVE_WS
ws_address_t *ws_addr;
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
ipc_address_t *ipc_addr;

View File

@ -52,6 +52,10 @@
#include <vmci_sockets.h>
#endif
#ifdef ZMQ_USE_NSS
#include <nss.h>
#endif
#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef
@ -87,6 +91,10 @@ zmq::ctx_t::ctx_t () :
// Initialise crypto library, if needed.
zmq::random_open ();
#ifdef ZMQ_USE_NSS
NSS_NoDB_Init (NULL);
#endif
}
bool zmq::ctx_t::check_tag ()
@ -119,6 +127,10 @@ zmq::ctx_t::~ctx_t ()
// De-initialise crypto library, if needed.
zmq::random_close ();
#ifdef ZMQ_USE_NSS
NSS_Shutdown ();
#endif
// Remove the tag, so that the object is considered dead.
_tag = ZMQ_CTX_TAG_VALUE_BAD;
}

View File

@ -559,8 +559,10 @@ zmq::session_base_t::connecter_factory_entry_t
zmq::session_base_t::_connecter_factories[] = {
connecter_factory_entry_t (protocol_name::tcp,
&zmq::session_base_t::create_connecter_tcp),
#ifdef ZMQ_HAVE_WS
connecter_factory_entry_t (protocol_name::ws,
&zmq::session_base_t::create_connecter_ws),
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
connecter_factory_entry_t (protocol_name::ipc,
@ -683,12 +685,14 @@ zmq::own_t *zmq::session_base_t::create_connecter_tcp (io_thread_t *io_thread_,
tcp_connecter_t (io_thread_, this, options, _addr, wait_);
}
#ifdef ZMQ_HAVE_WS
zmq::own_t *zmq::session_base_t::create_connecter_ws (io_thread_t *io_thread_,
bool wait_)
{
return new (std::nothrow)
ws_connecter_t (io_thread_, this, options, _addr, wait_);
}
#endif
#ifdef ZMQ_HAVE_OPENPGM
void zmq::session_base_t::start_connecting_pgm (io_thread_t *io_thread_)

View File

@ -54,6 +54,7 @@
#include "ipc_listener.hpp"
#include "tipc_listener.hpp"
#include "tcp_connecter.hpp"
#include "ws_address.hpp"
#include "io_thread.hpp"
#include "session_base.hpp"
#include "config.hpp"
@ -65,7 +66,6 @@
#include "address.hpp"
#include "ipc_address.hpp"
#include "tcp_address.hpp"
#include "ws_address.hpp"
#include "udp_address.hpp"
#include "tipc_address.hpp"
#include "mailbox.hpp"
@ -335,7 +335,9 @@ int zmq::socket_base_t::check_protocol (const std::string &protocol_) const
&& protocol_ != protocol_name::ipc
#endif
&& protocol_ != protocol_name::tcp
#ifdef ZMQ_HAVE_WS
&& protocol_ != protocol_name::ws
#endif
#if defined ZMQ_HAVE_OPENPGM
// pgm/epgm transports only available if 0MQ is compiled with OpenPGM.
&& protocol_ != "pgm"
@ -632,6 +634,7 @@ int zmq::socket_base_t::bind (const char *endpoint_uri_)
return 0;
}
#ifdef ZMQ_HAVE_WS
if (protocol == protocol_name::ws) {
ws_listener_t *listener =
new (std::nothrow) ws_listener_t (io_thread, this, options);
@ -652,6 +655,7 @@ int zmq::socket_base_t::bind (const char *endpoint_uri_)
options.connected = true;
return 0;
}
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
@ -889,7 +893,9 @@ int zmq::socket_base_t::connect (const char *endpoint_uri_)
}
// Defer resolution until a socket is opened
paddr->resolved.tcp_addr = NULL;
} else if (protocol == protocol_name::ws) {
}
#ifdef ZMQ_HAVE_WS
else if (protocol == protocol_name::ws) {
paddr->resolved.ws_addr = new (std::nothrow) ws_address_t ();
alloc_assert (paddr->resolved.ws_addr);
rc = paddr->resolved.ws_addr->resolve (address.c_str (), false,
@ -899,6 +905,8 @@ int zmq::socket_base_t::connect (const char *endpoint_uri_)
return -1;
}
}
#endif
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \
&& !defined ZMQ_HAVE_VXWORKS
else if (protocol == protocol_name::ipc) {

View File

@ -29,6 +29,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "precompiled.hpp"
#ifdef ZMQ_USE_NSS
#include <secoid.h>
#include <sechash.h>
#define SHA_DIGEST_LENGTH 20
#else
#include "../external/sha1/sha1.h"
#endif
#if !defined ZMQ_HAVE_WINDOWS
#include <sys/types.h>
#include <unistd.h>
@ -46,7 +54,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "err.hpp"
#include "ip.hpp"
#include "random.hpp"
#include "../external/sha1/sha1.h"
#include "ws_decoder.hpp"
#include "ws_encoder.hpp"
@ -66,6 +73,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
static int
encode_base64 (const unsigned char *in, int in_len, char *out, int out_len);
static void compute_accept_key (char *key,
unsigned char output[SHA_DIGEST_LENGTH]);
zmq::ws_engine_t::ws_engine_t (fd_t fd_,
const options_t &options_,
const endpoint_uri_pair_t &endpoint_uri_pair_,
@ -407,21 +417,8 @@ bool zmq::ws_engine_t::server_handshake ()
&& _websocket_key[0] != '\0') {
_server_handshake_state = handshake_complete;
const char *magic_string =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
char plain[MAX_HEADER_VALUE_LENGTH + 36 + 1];
strcpy (plain, _websocket_key);
strcat (plain, magic_string);
sha1_ctxt ctx;
SHA1_Init (&ctx);
SHA1_Update (&ctx, (unsigned char *) _websocket_key,
strlen (_websocket_key));
SHA1_Update (&ctx, (unsigned char *) magic_string,
strlen (magic_string));
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final (hash, &ctx);
compute_accept_key (_websocket_key, hash);
int accept_key_len = encode_base64 (
hash, SHA_DIGEST_LENGTH, _websocket_accept,
@ -855,3 +852,28 @@ encode_base64 (const unsigned char *in, int in_len, char *out, int out_len)
out[io] = 0;
return io;
}
static void compute_accept_key (char *key, unsigned char *hash)
{
const char *magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
#ifdef ZMQ_USE_NSS
unsigned int len;
HASH_HashType type = HASH_GetHashTypeByOidTag (SEC_OID_SHA1);
HASHContext *ctx = HASH_Create (type);
assert (ctx);
HASH_Begin (ctx);
HASH_Update (ctx, (unsigned char *) key, (unsigned int) strlen (key));
HASH_Update (ctx, (unsigned char *) magic_string,
(unsigned int) strlen (magic_string));
HASH_End (ctx, hash, &len, SHA_DIGEST_LENGTH);
HASH_Destroy (ctx);
#else
sha1_ctxt ctx;
SHA1_Init (&ctx);
SHA1_Update (&ctx, (unsigned char *) key, strlen (key));
SHA1_Update (&ctx, (unsigned char *) magic_string, strlen (magic_string));
SHA1_Final (hash, &ctx);
#endif
}