From 89815e2ff80620150f5043906e41e9ea729d10dd Mon Sep 17 00:00:00 2001 From: Jianhui Zhao Date: Tue, 27 Apr 2021 16:43:20 +0800 Subject: [PATCH] ssl: use https://github.com/zhaojh329/ssl Signed-off-by: Jianhui Zhao --- .gitmodules | 3 + CMakeLists.txt | 22 +++- cmake/Modules/FindMbedTLS.cmake | 37 ------ cmake/Modules/FindWolfSSL.cmake | 62 ---------- example/CMakeLists.txt | 14 ++- src/CMakeLists.txt | 101 +++------------ src/buffer | 2 +- src/config.h.in | 6 +- src/log.h | 1 + src/lua/CMakeLists.txt | 19 ++- src/ssl | 1 + src/ssl.c | 210 -------------------------------- src/ssl.h | 46 ------- src/umqtt.c | 151 +++++++++++++++++------ src/umqtt.h | 5 +- 15 files changed, 186 insertions(+), 494 deletions(-) delete mode 100644 cmake/Modules/FindMbedTLS.cmake delete mode 100644 cmake/Modules/FindWolfSSL.cmake create mode 160000 src/ssl delete mode 100644 src/ssl.c delete mode 100644 src/ssl.h diff --git a/.gitmodules b/.gitmodules index c1e5dba..f47845a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "src/buffer"] path = src/buffer url = https://github.com/zhaojh329/buffer +[submodule "src/ssl"] + path = src/ssl + url = https://github.com/zhaojh329/ssl diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b7b0e7..400013c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.0) project(libumqtt C) @@ -6,5 +6,23 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/") #set(CMAKE_VERBOSE_MAKEFILE ON) +add_definitions(-D_GNU_SOURCE) +add_compile_options(-O -Wall -Werror --std=gnu99) + +option(BUILD_STATIC "Build static library" OFF) + +option(BUILD_EXAMPLE "Build example" ON) + +if(BUILD_STATIC) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +endif() + +find_package(Libev REQUIRED) + +add_subdirectory(src/ssl) + add_subdirectory(src) -add_subdirectory(example) + +if(BUILD_EXAMPLE) + add_subdirectory(example) +endif() diff --git a/cmake/Modules/FindMbedTLS.cmake b/cmake/Modules/FindMbedTLS.cmake deleted file mode 100644 index 266f6c1..0000000 --- a/cmake/Modules/FindMbedTLS.cmake +++ /dev/null @@ -1,37 +0,0 @@ -find_path(MBEDTLS_INCLUDE_DIR mbedtls/ssl.h) - -find_library(MBEDTLS_LIBRARY mbedtls) -find_library(MBEDX509_LIBRARY mbedx509) -find_library(MBEDCRYPTO_LIBRARY mbedcrypto) - -if(MBEDTLS_INCLUDE_DIR) - file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" - MBEDTLS_VERSION_MAJOR REGEX "^#define[ \t]+MBEDTLS_VERSION_MAJOR[ \t]+[0-9]+") - file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" - MBEDTLS_VERSION_MINOR REGEX "^#define[ \t]+MBEDTLS_VERSION_MINOR[ \t]+[0-9]+") - file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" - MBEDTLS_VERSION_PATCH REGEX "^#define[ \t]+MBEDTLS_VERSION_PATCH[ \t]+[0-9]+") - string(REGEX REPLACE "[^0-9]+" "" MBEDTLS_VERSION_MAJOR "${MBEDTLS_VERSION_MAJOR}") - string(REGEX REPLACE "[^0-9]+" "" MBEDTLS_VERSION_MINOR "${MBEDTLS_VERSION_MINOR}") - string(REGEX REPLACE "[^0-9]+" "" MBEDTLS_VERSION_PATCH "${MBEDTLS_VERSION_PATCH}") - set(MBEDTLS_VERSION "${MBEDTLS_VERSION_MAJOR}.${MBEDTLS_VERSION_MINOR}.${MBEDTLS_VERSION_PATCH}") - unset(MBEDTLS_VERSION_MINOR) - unset(MBEDTLS_VERSION_MAJOR) - unset(MBEDTLS_VERSION_PATCH) -endif() - -set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") - -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(MbedTLS - REQUIRED_VARS - MBEDTLS_LIBRARY - MBEDX509_LIBRARY - MBEDCRYPTO_LIBRARY - MBEDTLS_INCLUDE_DIR - VERSION_VAR - MBEDTLS_VERSION -) - -mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) \ No newline at end of file diff --git a/cmake/Modules/FindWolfSSL.cmake b/cmake/Modules/FindWolfSSL.cmake deleted file mode 100644 index 4cf3111..0000000 --- a/cmake/Modules/FindWolfSSL.cmake +++ /dev/null @@ -1,62 +0,0 @@ -if(WOLFSSL_PREFER_STATIC_LIB) - set(WOLFSSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib ${CMAKE_FIND_LIBRARY_SUFFIXES}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) - endif() -endif() - -if(UNIX) - find_package(PkgConfig QUIET) - pkg_check_modules(_WOLFSSL QUIET wolfssl) -endif() - -find_path(WOLFSSL_INCLUDE_DIR NAMES wolfssl/version.h HINTS ${_WOLFSSL_INCLUDEDIR}) -find_library(WOLFSSL_LIBRARY NAMES wolfssl HINTS ${_WOLFSSL_LIBDIR}) -if(WOLFSSL_INCLUDE_DIR AND WOLFSSL_LIBRARY) - set(WOLFSSL_INCLUDE_DIR ${WOLFSSL_INCLUDE_DIR}) - set(WOLFSSL_LIBRARY ${WOLFSSL_LIBRARY}) - set(WOLFSSL_VERSION ${_WOLFSSL_VERSION}) - set(WOLFSSL_IS_WOLFSSL ON) -else() - if(UNIX) - pkg_check_modules(_WOLFSSL QUIET WOLFSSL) - endif() - - find_path(WOLFSSL_INCLUDE_DIR NAMES WOLFSSL/version.h HINTS ${_WOLFSSL_INCLUDEDIR}) - find_library(WOLFSSL_LIBRARY NAMES WOLFSSL HINTS ${_WOLFSSL_LIBDIR}) - set(WOLFSSL_VERSION ${_WOLFSSL_VERSION}) - set(WOLFSSL_IS_WOLFSSL OFF) -endif() - -if(NOT WOLFSSL_VERSION AND WOLFSSL_INCLUDE_DIR) - if(WOLFSSL_IS_WOLFSSL) - file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h" WOLFSSL_VERSION_STR REGEX "^#define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"[^\"]+\"") - else() - file(STRINGS "${WOLFSSL_INCLUDE_DIR}/WOLFSSL/version.h" WOLFSSL_VERSION_STR REGEX "^#define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"[^\"]+\"") - endif() - if(WOLFSSL_VERSION_STR MATCHES "\"([^\"]+)\"") - set(WOLFSSL_VERSION "${CMAKE_MATCH_1}") - endif() -endif() - -set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR}) -set(WOLFSSL_LIBRARIES ${WOLFSSL_LIBRARY}) - -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(WOLFSSL - REQUIRED_VARS - WOLFSSL_LIBRARY - WOLFSSL_INCLUDE_DIR - VERSION_VAR - WOLFSSL_VERSION -) - -mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY) - -if(WOLFSSL_PREFER_STATIC_LIB) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${WOLFSSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) - unset(WOLFSSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES) -endif() \ No newline at end of file diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index a013a1b..dc823d6 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,4 +1,14 @@ -include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/buffer ${CMAKE_BINARY_DIR}/src) +set(LIBS ${LIBEV_LIBRARY} umqtt) + +if(SSL_SUPPORT) + list(APPEND LIBS ${SSL_LIBS}) +endif() + +include_directories( + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/src/buffer + ${CMAKE_BINARY_DIR}/src + ${LIBEV_INCLUDE_DIR}) add_executable(example example.c) -target_link_libraries(example umqtt ${LIBEV_LIBRARY}) +target_link_libraries(example PRIVATE ${LIBS}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5ec079..06225d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,93 +1,34 @@ -add_definitions(-O -Wall -Werror --std=gnu99 -D_GNU_SOURCE) - # The version number. set(UMQTT_VERSION_MAJOR 1) set(UMQTT_VERSION_MINOR 0) set(UMQTT_VERSION_PATCH 3) -# Check the third party Libraries -find_package(Libev REQUIRED) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/buffer ${CMAKE_CURRENT_BINARY_DIR} ${LIBEV_INCLUDE_DIR}) - -set(EXTRA_LIBS ${LIBEV_LIBRARY} dl) -set(SOURCE_FILES umqtt.c log.c utils.c buffer/buffer.c ssl.c) - -set(UMQTT_SSL_SUPPORT_CONFIG 1) -option(UMQTT_SSL_SUPPORT "SSL support" ON) - -option(UMQTT_USE_OPENSSL "Force select OpenSSL" OFF) -option(UMQTT_USE_WOLFSSL "Force select WolfSSL(CyaSSL)" OFF) -option(UMQTT_USE_MBEDTLS "Force select MbedTLS(PolarSSL)" OFF) +aux_source_directory(. SOURCES) +list(APPEND SOURCES buffer/buffer.c) -set(SSL_NAME OFF) -set(UMQTT_HAVE_OPENSSL_CONFIG 0) -set(UMQTT_HAVE_WOLFSSL_CONFIG 0) -set(UMQTT_HAVE_MBEDTLS_CONFIG 0) +if(BUILD_STATIC) + if(SSL_SUPPORT) + list(APPEND SOURCES ${SSL_SRC}) + endif() -if(NOT UMQTT_SSL_SUPPORT) - set(UMQTT_SSL_SUPPORT_CONFIG 0) -else() - find_package(OpenSSL) - find_package(WolfSSL) - find_package(MbedTLS) + add_library(umqtt STATIC ${SOURCES}) - if(UMQTT_USE_OPENSSL) - if (NOT OPENSSL_FOUND) - set(UMQTT_SSL_SUPPORT OFF) - message(WARNING "Force select OpenSSL, but not found it") - endif() - elseif(UMQTT_USE_WOLFSSL) - if (NOT WOLFSSL_FOUND) - set(UMQTT_SSL_SUPPORT OFF) - message(WARNING "Force select WolfSSL(CyaSSL), but not found it") - endif() - elseif(UMQTT_USE_MBEDTLS) - if (NOT MBEDTLS_FOUND) - set(UMQTT_SSL_SUPPORT OFF) - message(WARNING "Force select MbedTLS(PolarSSL), but not found it") - endif() - elseif(OPENSSL_FOUND) - set(UMQTT_USE_OPENSSL ON) - elseif(WOLFSSL_FOUND) - set(UMQTT_USE_WOLFSSL ON) - elseif(MBEDTLS_FOUND) - set(UMQTT_USE_MBEDTLS ON) - else() - set(UMQTT_SSL_SUPPORT OFF) - message(WARNING "No available SSL libraries found") + if(SSL_SUPPORT) + target_compile_definitions(umqtt PRIVATE ${SSL_DEFINE}) + target_include_directories(umqtt PRIVATE ${SSL_INC}) endif() +else() + add_library(umqtt SHARED ${SOURCES}) - if(UMQTT_USE_OPENSSL) - set(SSL_NAME "OpenSSL") - set(SSL_INC ${OPENSSL_INCLUDE_DIR}) - set(SSL_LIB ${OPENSSL_LIBRARIES}) - set(UMQTT_HAVE_OPENSSL_CONFIG 1) - elseif(UMQTT_USE_WOLFSSL) - set(SSL_NAME "WolfSSL(CyaSSL)") - set(SSL_INC ${WOLFSSL_INCLUDE_DIR}) - set(SSL_LIB ${WOLFSSL_LIBRARIES}) - set(UMQTT_HAVE_WOLFSSL_CONFIG 1) - elseif(UMQTT_USE_MBEDTLS) - set(SSL_NAME "MbedTLS(PolarSSL)") - set(SSL_INC ${MBEDTLS_INCLUDE_DIR}) - set(SSL_LIB ${MBEDTLS_LIBRARIES}) - set(UMQTT_HAVE_MBEDTLS_CONFIG 1) + if(SSL_SUPPORT) + target_link_libraries(umqtt PRIVATE ${SSL_TARGET}) endif() - if(UMQTT_SSL_SUPPORT) - include_directories(${SSL_INC}) - list(APPEND EXTRA_LIBS ${SSL_LIB}) - message(STATUS "Select ${SSL_NAME} as the SSL backend") - else() - set(SSL_NAME OFF) - set(UMQTT_SSL_SUPPORT_CONFIG 0) - endif() + target_link_libraries(umqtt PRIVATE ${LIBEV_LIBRARY}) + set_target_properties(umqtt PROPERTIES VERSION ${UMQTT_VERSION_MAJOR}.${UMQTT_VERSION_MINOR}.${UMQTT_VERSION_PATCH}) endif() -add_library(umqtt SHARED ${SOURCE_FILES}) -set_target_properties(umqtt PROPERTIES VERSION ${UMQTT_VERSION_MAJOR}.${UMQTT_VERSION_MINOR}.${UMQTT_VERSION_PATCH}) -target_link_libraries(umqtt ${EXTRA_LIBS}) +target_include_directories(umqtt PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${LIBEV_INCLUDE_DIR} buffer) # configure a header file to pass some of the CMake settings to the source code configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) @@ -97,20 +38,16 @@ add_subdirectory(lua) install( FILES log.h - ssl.h umqtt.h utils.h buffer/buffer.h ${CMAKE_CURRENT_BINARY_DIR}/config.h - DESTINATION - include/umqtt + DESTINATION include/umqtt ) install( - TARGETS umqtt LIBRARY + TARGETS umqtt DESTINATION lib ) message(STATUS "UMQTT_VERSION: ${UMQTT_VERSION_MAJOR}.${UMQTT_VERSION_MINOR}.${UMQTT_VERSION_PATCH}") -message(STATUS "UMQTT_SSL_SUPPORT: ${SSL_NAME}") - diff --git a/src/buffer b/src/buffer index 84763ea..6bedd70 160000 --- a/src/buffer +++ b/src/buffer @@ -1 +1 @@ -Subproject commit 84763eaaf879f0f2d98a98542ef76d0f5c8ea9ea +Subproject commit 6bedd70121d53fac4799f137a9d1ce6cb9d3e42d diff --git a/src/config.h.in b/src/config.h.in index 2196e21..58b33c6 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -30,10 +30,6 @@ #define UMQTT_VERSION_PATCH @UMQTT_VERSION_PATCH@ #define UMQTT_VERSION_STRING "@UMQTT_VERSION_MAJOR@.@UMQTT_VERSION_MINOR@.@UMQTT_VERSION_PATCH@" -#define UMQTT_SSL_SUPPORT @UMQTT_SSL_SUPPORT_CONFIG@ - -#define UMQTT_HAVE_OPENSSL @UMQTT_HAVE_OPENSSL_CONFIG@ -#define UMQTT_HAVE_WOLFSSL @UMQTT_HAVE_WOLFSSL_CONFIG@ -#define UMQTT_HAVE_MBEDTLS @UMQTT_HAVE_MBEDTLS_CONFIG@ +#cmakedefine SSL_SUPPORT #endif diff --git a/src/log.h b/src/log.h index 69bed10..417b27a 100644 --- a/src/log.h +++ b/src/log.h @@ -37,6 +37,7 @@ void umqtt_log_close(); #define umqtt_log_debug(fmt...) umqtt_log(LOG_DEBUG, fmt) #define umqtt_log_info(fmt...) umqtt_log(LOG_INFO, fmt) +#define umqtt_log_warn(fmt...) umqtt_log(LOG_WARNING, fmt) #define umqtt_log_err(fmt...) umqtt_log(LOG_ERR, fmt) void __umqtt_log(const char *filename, int line, int priority, const char *fmt, ...); diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index 5e7e0bd..e11ae6e 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -3,20 +3,19 @@ find_package(Lua) set(UMQTT_LUA_SUPPORT_DEFAULT "ON") if (NOT LUA_FOUND) - set(BUILD_LUA_DEFAULT "OFF") + set(BUILD_LUA_DEFAULT "OFF") endif (NOT LUA_FOUND) option(UMQTT_LUA_SUPPORT "Enable build of Lua module" ${UMQTT_LUA_SUPPORT_DEFAULT}) if(UMQTT_LUA_SUPPORT) - include_directories(${LUA_INCLUDE_DIR}) + add_library(umqtt-lua MODULE umqtt_lua.c) + target_include_directories(umqtt-lua PRIVATE ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/buffer ${CMAKE_BINARY_DIR}/src ${LUA_INCLUDE_DIR}) + target_link_libraries(umqtt-lua PRIVATE umqtt) + set_target_properties(umqtt-lua PROPERTIES OUTPUT_NAME umqtt PREFIX "") - add_library(umqtt-lua MODULE umqtt_lua.c) - set_target_properties(umqtt-lua PROPERTIES OUTPUT_NAME umqtt PREFIX "") - - target_link_libraries(umqtt-lua umqtt) - - install(TARGETS umqtt-lua - LIBRARY DESTINATION lib/lua/${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR} - ) + install( + TARGETS umqtt-lua + DESTINATION lib/lua/${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR} + ) endif(UMQTT_LUA_SUPPORT) diff --git a/src/ssl b/src/ssl new file mode 160000 index 0000000..e3c49e5 --- /dev/null +++ b/src/ssl @@ -0,0 +1 @@ +Subproject commit e3c49e59d79ee0dd5282a32b420289382fbd7020 diff --git a/src/ssl.c b/src/ssl.c deleted file mode 100644 index f3b481d..0000000 --- a/src/ssl.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2019 Jianhui Zhao - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "log.h" -#include "ssl.h" -#include "buffer.h" - -#if UMQTT_SSL_SUPPORT - -#if UMQTT_HAVE_MBEDTLS -#include -#include -#include -#include - -struct umqtt_ssl_ctx { - mbedtls_net_context net; - mbedtls_ssl_context ssl; - mbedtls_ssl_config cfg; - mbedtls_ctr_drbg_context drbg; - mbedtls_entropy_context etpy; - mbedtls_x509_crt x509; - bool last_read_ok; -}; - -#else - -#if UMQTT_HAVE_OPENSSL -#include -#include -#elif UMQTT_HAVE_WOLFSSL -#define WC_NO_HARDEN -#include -#include -#endif - -struct umqtt_ssl_ctx { - SSL_CTX *ctx; - SSL *ssl; -}; - -#endif - -int umqtt_ssl_init(struct umqtt_ssl_ctx **ctx, int sock) -{ - struct umqtt_ssl_ctx *c = calloc(1, sizeof(struct umqtt_ssl_ctx)); - - if (!ctx) { - umqtt_log_err("calloc failed: %s\n", strerror(errno)); - return -1; - } - -#if UMQTT_HAVE_MBEDTLS - mbedtls_net_init(&c->net); - mbedtls_ssl_init(&c->ssl); - mbedtls_ssl_config_init(&c->cfg); - mbedtls_ctr_drbg_init(&c->drbg); - mbedtls_x509_crt_init(&c->x509); - - mbedtls_entropy_init(&c->etpy); - mbedtls_ctr_drbg_seed(&c->drbg, mbedtls_entropy_func, &c->etpy, NULL, 0); - - mbedtls_ssl_config_defaults(&c->cfg, MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); - - mbedtls_ssl_conf_authmode(&c->cfg, MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&c->cfg, &c->x509, NULL); - mbedtls_ssl_conf_rng(&c->cfg, mbedtls_ctr_drbg_random, &c->drbg); - - mbedtls_ssl_set_bio(&c->ssl, &c->net, mbedtls_net_send, - mbedtls_net_recv, mbedtls_net_recv_timeout); - - mbedtls_ssl_setup(&c->ssl, &c->cfg); - - c->net.fd = sock; -#else - SSL_library_init(); - SSL_load_error_strings(); - - c->ctx = SSL_CTX_new(SSLv23_client_method()); - SSL_CTX_set_verify(c->ctx, SSL_VERIFY_NONE, NULL); - - c->ssl = SSL_new(c->ctx); - SSL_set_fd(c->ssl, sock); -#endif - - *ctx = c; - return 0; -} - -int umqtt_ssl_handshake(struct umqtt_ssl_ctx *ctx) -{ -#if UMQTT_HAVE_MBEDTLS - int ret = mbedtls_ssl_handshake(&ctx->ssl); - if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) - return 0; - if (ret == 0) - return 1; - return -1; -#else - int ret = SSL_connect(ctx->ssl); - if (ret == 1) { - return 1; - } else { - int err = SSL_get_error(ctx->ssl, ret); - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) - return 0; - umqtt_log_err("%s\n", ERR_error_string(err, NULL)); - return -1; - } -#endif -} - -void umqtt_ssl_free(struct umqtt_ssl_ctx *ctx) -{ - if (!ctx) - return; - -#if UMQTT_HAVE_MBEDTLS - mbedtls_ssl_free(&ctx->ssl); - mbedtls_ssl_config_free(&ctx->cfg); -#else - SSL_shutdown(ctx->ssl); - SSL_CTX_free(ctx->ctx); -#endif - free(ctx); -} - -int umqtt_ssl_read(int fd, void *buf, size_t count, void *arg) -{ - struct umqtt_ssl_ctx *ctx = arg; - -#if UMQTT_HAVE_MBEDTLS - int ret; - - if (ctx->last_read_ok) { - ctx->last_read_ok = false; - return P_FD_PENDING; - } - - ret = mbedtls_ssl_read(&ctx->ssl, buf, count); - if (ret < 0) { - if (ret == MBEDTLS_ERR_SSL_WANT_READ) - return P_FD_PENDING; - return P_FD_ERR; - } - if (ret > 0) - ctx->last_read_ok = true; -#else - int ret = SSL_read(ctx->ssl, buf, count); - if (ret < 0) { - int err = SSL_get_error(ctx->ssl, ret); - if (err == SSL_ERROR_WANT_READ) - return P_FD_PENDING; - umqtt_log_err("%s\n", ERR_error_string(err, NULL)); - return P_FD_ERR; - } -#endif - return ret; -} - -int umqtt_ssl_write(int fd, void *buf, size_t count, void *arg) -{ - struct umqtt_ssl_ctx *ctx = arg; - -#if UMQTT_HAVE_MBEDTLS - int ret = mbedtls_ssl_write(&ctx->ssl, buf, count); - if (ret < 0) { - if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) - return P_FD_PENDING; - return P_FD_ERR; - } -#else - int ret = SSL_write(ctx->ssl, buf, count); - if (ret < 0) { - int err = SSL_get_error(ctx->ssl, ret); - if (err == SSL_ERROR_WANT_WRITE) - return P_FD_PENDING; - umqtt_log_err("%s\n", ERR_error_string(err, NULL)); - return P_FD_ERR; - } -#endif - return ret; -} - -#endif diff --git a/src/ssl.h b/src/ssl.h deleted file mode 100644 index 07a6ac5..0000000 --- a/src/ssl.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2019 Jianhui Zhao - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _UMQTT_SSL_H -#define _UMQTT_SSL_H - -#include -#include - -#include "config.h" - -#if UMQTT_SSL_SUPPORT - -struct umqtt_ssl_ctx; - -int umqtt_ssl_init(struct umqtt_ssl_ctx **ctx, int sock); -int umqtt_ssl_handshake(struct umqtt_ssl_ctx *ctx); -void umqtt_ssl_free(struct umqtt_ssl_ctx *ctx); - -int umqtt_ssl_read(int fd, void *buf, size_t count, void *arg); -int umqtt_ssl_write(int fd, void *buf, size_t count, void *arg); - -#endif - -#endif diff --git a/src/umqtt.c b/src/umqtt.c index 96a9fe2..7039241 100644 --- a/src/umqtt.c +++ b/src/umqtt.c @@ -32,10 +32,17 @@ #include #include -#include "ssl.h" #include "utils.h" #include "umqtt.h" +#ifdef SSL_SUPPORT +#include "ssl/ssl.h" +#endif + +#ifdef SSL_SUPPORT +static struct ssl_context *ssl_ctx; +#endif + static const char *umqtt_packet_type_to_string(int type) { #define T2S(t) case t: return (#t) + 6; @@ -708,19 +715,69 @@ static int check_socket_state(struct umqtt_client *cl) return -1; } -#if UMQTT_SSL_SUPPORT +#ifdef SSL_SUPPORT if (cl->ssl) cl->state = UMQTT_STATE_SSL_HANDSHAKE; else #endif cl->state = UMQTT_STATE_PARSE_FH; - if (cl->state == UMQTT_STATE_PARSE_FH && cl->on_net_connected) cl->on_net_connected(cl); return 0; } +#ifdef SSL_SUPPORT +static void on_ssl_verify_error(int error, const char *str, void *arg) +{ + umqtt_log_warn("SSL certificate error(%d): %s\n", error, str); +} + +/* -1 error, 0 pending, 1 ok */ +static int ssl_negotiated(struct umqtt_client *cl) +{ + char err_buf[128]; + int ret; + + ret = ssl_connect(cl->ssl, false, on_ssl_verify_error, NULL); + if (ret == SSL_PENDING) + return 0; + + if (ret == SSL_ERROR) { + umqtt_log_err("ssl connect error(%d): %s\n", ssl_err_code, ssl_strerror(ssl_err_code, err_buf, sizeof(err_buf))); + umqtt_error(cl, UMQTT_ERROR_SSL_HANDSHAKE, err_buf); + return -1; + } + + cl->state = UMQTT_STATE_PARSE_FH; + + if (cl->on_net_connected) + cl->on_net_connected(cl); + + return 1; +} + +static int umqtt_ssl_read(int fd, void *buf, size_t count, void *arg) +{ + struct umqtt_client *cl = arg; + static char err_buf[128]; + int ret; + + ret = ssl_read(cl->ssl, buf, count); + if (ret == SSL_ERROR) { + umqtt_log_err("ssl_read(%d): %s\n", ssl_err_code, + ssl_strerror(ssl_err_code, err_buf, sizeof(err_buf))); + umqtt_error(cl, UMQTT_ERROR_IO, err_buf); + return P_FD_ERR; + } + + if (ret == SSL_PENDING) + return P_FD_PENDING; + + return ret; +} +#endif + static void umqtt_io_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) { struct umqtt_client *cl = container_of(w, struct umqtt_client, ior); @@ -733,17 +790,25 @@ static void umqtt_io_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) return; } -#if UMQTT_SSL_SUPPORT - if (cl->ssl) - ret = buffer_put_fd_ex(rb, w->fd, -1, &eof, umqtt_ssl_read, cl->ssl); - else + if (cl->ssl) { +#ifdef SSL_SUPPORT + if (unlikely(cl->state == UMQTT_STATE_SSL_HANDSHAKE)) { + ret = ssl_negotiated(cl); + if (ret <= 0) + return; + } + + ret = buffer_put_fd_ex(&cl->rb, w->fd, 4096, &eof, umqtt_ssl_read, cl); + if (ret < 0) + return; #endif + } else { ret = buffer_put_fd(rb, w->fd, -1, &eof); - - if (ret < 0) { - umqtt_error(cl, UMQTT_ERROR_IO, strerror(errno)); - return; - } + if (ret < 0) { + umqtt_error(cl, UMQTT_ERROR_IO, strerror(errno)); + return; + } + } if (eof) { umqtt_free(cl); @@ -765,34 +830,37 @@ static void umqtt_io_write_cb(struct ev_loop *loop, struct ev_io *w, int revents return; } -#if UMQTT_SSL_SUPPORT - if (unlikely(cl->state == UMQTT_STATE_SSL_HANDSHAKE)) { - ret = umqtt_ssl_handshake(cl->ssl); - if (ret == -1) { - umqtt_error(cl, UMQTT_ERROR_SSL_HANDSHAKE, "ssl handshake failed"); - return; + if (cl->ssl) { +#ifdef SSL_SUPPORT + static char err_buf[128]; + struct buffer *b = &cl->wb; + + if (unlikely(cl->state == UMQTT_STATE_SSL_HANDSHAKE)) { + ret = ssl_negotiated(cl); + if (ret <= 0) + return; } - if (ret == 1) { - cl->state = UMQTT_STATE_PARSE_FH; - if (cl->on_net_connected) - cl->on_net_connected(cl); + ret = ssl_write(cl->ssl, buffer_data(b), buffer_length(b)); + if (ret == SSL_ERROR) { + umqtt_log_err("ssl_write(%d): %s\n", ssl_err_code, + ssl_strerror(ssl_err_code, err_buf, sizeof(err_buf))); + umqtt_error(cl, UMQTT_ERROR_IO, err_buf); + return; } - return; - } -#endif -#if UMQTT_SSL_SUPPORT - if (cl->ssl) - ret = buffer_pull_to_fd_ex(&cl->wb, w->fd, buffer_length(&cl->wb), umqtt_ssl_write, cl->ssl); - else + if (ret == SSL_PENDING) + return; + + buffer_pull(b, NULL, ret); #endif + } else { ret = buffer_pull_to_fd(&cl->wb, w->fd, buffer_length(&cl->wb)); - - if (ret < 0) { - umqtt_error(cl, UMQTT_ERROR_IO, "write error"); - return; - } + if (ret < 0) { + umqtt_error(cl, UMQTT_ERROR_IO, "write error"); + return; + } + } if (buffer_length(&cl->wb) < 1) ev_io_stop(loop, w); @@ -827,8 +895,19 @@ int umqtt_init(struct umqtt_client *cl, struct ev_loop *loop, const char *host, cl->start_time = ev_now(cl->loop); if (ssl) { -#if (UMQTT_SSL_SUPPORT) - umqtt_ssl_init((struct umqtt_ssl_ctx **)&cl->ssl, cl->sock); +#ifdef SSL_SUPPORT + if (!ssl_ctx) { + ssl_ctx = ssl_context_new(false); + if (!ssl_ctx) { + umqtt_log_err("SSL context init fail\n"); + return -1; + } + } + cl->ssl = ssl_session_new(ssl_ctx, sock); + if (!cl->ssl) { + umqtt_log_err("SSL session init fail\n"); + return -1; + } #else umqtt_log_err("SSL is not enabled at compile\n"); umqtt_free(cl); diff --git a/src/umqtt.h b/src/umqtt.h index 2d45953..a8fe292 100644 --- a/src/umqtt.h +++ b/src/umqtt.h @@ -144,6 +144,8 @@ struct umqtt_topic { uint8_t qos; }; +struct ssl_context; + struct umqtt_client { int sock; struct ev_loop *loop; @@ -152,7 +154,8 @@ struct umqtt_client { struct buffer rb; struct buffer wb; int state; - void *ssl; /* Context wrap of openssl, wolfssl and mbedtls */ + + void *ssl; ev_tstamp start_time; /* Time stamp of begin connect */ ev_tstamp last_ping; /* Time stamp of last ping */