From 994c64ccf0151b0353d2a84ac90fd31b5cd7ac49 Mon Sep 17 00:00:00 2001 From: Meltie2013 Date: Mon, 2 Aug 2021 15:04:47 -0500 Subject: [PATCH] OpenSSL Version Check & Ensure Version Package (#160) * Impement Ensure Version for OpenSSL * Fix OpenSSL library linking to most of the project * Cleanup of old file * Make error message a bit more clear on invalid versions * Link Submodule changes to main PR * Attempt to fix missing symbol DSO compile issue linux * Sometimes I need to learn to look into things a bit more. --- CMakeLists.txt | 5 +- cmake/EnsureVersion.cmake | 73 +++++++++++ cmake/FindOpenSSL.cmake | 231 +++++++++++++++++++++++++++++++++++ src/mangosd/CMakeLists.txt | 3 +- src/realmd | 2 +- src/shared/CMakeLists.txt | 4 +- src/tools/Extractor_projects | 2 +- 7 files changed, 314 insertions(+), 6 deletions(-) create mode 100644 cmake/EnsureVersion.cmake create mode 100644 cmake/FindOpenSSL.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 214cfa96..113d6e58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,15 +98,16 @@ else() endif() endif() - find_package(Threads REQUIRED) find_package(MySQL REQUIRED) -find_package(OpenSSL REQUIRED) find_package(DL REQUIRED) find_package(ZLIB QUIET) find_package(BZip2 QUIET) +include(${CMAKE_SOURCE_DIR}/cmake/EnsureVersion.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/FindOpenSSL.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/MangosParams.cmake) include(${CMAKE_SOURCE_DIR}/cmake/SetDefinitions.cmake) diff --git a/cmake/EnsureVersion.cmake b/cmake/EnsureVersion.cmake new file mode 100644 index 00000000..1dc98303 --- /dev/null +++ b/cmake/EnsureVersion.cmake @@ -0,0 +1,73 @@ +# MaNGOS is a full featured server for World of Warcraft, supporting +# the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 +# +# Copyright (C) 2005-2021 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +MACRO(NORMALIZE_VERSION _requested_version _normalized_version) + STRING(REGEX MATCH "[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" _threePartMatch "${_requested_version}") + if(_threePartMatch) + # parse the parts of the version string + STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major_vers "${_requested_version}") + STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor_vers "${_requested_version}") + STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _patch_vers "${_requested_version}") + else(_threePartMatch) + STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" _major_vers "${_requested_version}") + STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" _minor_vers "${_requested_version}") + set(_patch_vers "0") + endif(_threePartMatch) + + # compute an overall version number which can be compared at once + MATH(EXPR ${_normalized_version} "${_major_vers}*10000 + ${_minor_vers}*100 + ${_patch_vers}") +ENDMACRO(NORMALIZE_VERSION) + +MACRO(CHECK_RANGE_INCLUSIVE_LOWER _lower_limit _value _upper_limit _ok) + if(${_value} LESS ${_lower_limit}) + set(${_ok} FALSE) + elseif(${_value} EQUAL ${_lower_limit}) + set(${_ok} TRUE) + elseif(${_value} EQUAL ${_upper_limit}) + set(${_ok} FALSE) + elseif(${_value} GREATER ${_upper_limit}) + set(${_ok} FALSE) + else(${_value} LESS ${_lower_limit}) + set(${_ok} TRUE) + endif(${_value} LESS ${_lower_limit}) +ENDMACRO(CHECK_RANGE_INCLUSIVE_LOWER) + +MACRO(ENSURE_VERSION requested_version found_version var_too_old) + NORMALIZE_VERSION(${requested_version} req_vers_num) + NORMALIZE_VERSION(${found_version} found_vers_num) + + if(found_vers_num LESS req_vers_num) + set(${var_too_old} FALSE) + else(found_vers_num LESS req_vers_num) + set(${var_too_old} TRUE) + endif(found_vers_num LESS req_vers_num) + +ENDMACRO(ENSURE_VERSION) + +MACRO(ENSURE_VERSION2 requested_version2 found_version2 var_too_old2) + ENSURE_VERSION(${requested_version2} ${found_version2} ${var_too_old2}) +ENDMACRO(ENSURE_VERSION2) + +MACRO(ENSURE_VERSION_RANGE min_version found_version max_version var_ok) + NORMALIZE_VERSION(${min_version} req_vers_num) + NORMALIZE_VERSION(${found_version} found_vers_num) + NORMALIZE_VERSION(${max_version} max_vers_num) + + CHECK_RANGE_INCLUSIVE_LOWER(${req_vers_num} ${found_vers_num} ${max_vers_num} ${var_ok}) +ENDMACRO(ENSURE_VERSION_RANGE) diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake new file mode 100644 index 00000000..0f790f3d --- /dev/null +++ b/cmake/FindOpenSSL.cmake @@ -0,0 +1,231 @@ +# MaNGOS is a full featured server for World of Warcraft, supporting +# the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 +# +# Copyright (C) 2005-2021 MaNGOS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +set(OPENSSL_EXPECTED_VERSION "1.0") +set(OPENSSL_MAX_VERSION "1.2") + +SET(_OPENSSL_ROOT_HINTS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]" + ) + +IF(PLATFORM EQUAL 64) + SET(_OPENSSL_ROOT_PATHS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;InstallLocation]" + "C:/OpenSSL-Win64/" + "C:/OpenSSL/" + ) +ELSE() + SET(_OPENSSL_ROOT_PATHS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;InstallLocation]" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;InstallLocation]" + "C:/OpenSSL/" + ) +ENDIF() + +FIND_PATH(OPENSSL_ROOT_DIR + NAMES + include/openssl/ssl.h + HINTS + ${_OPENSSL_ROOT_HINTS} + PATHS + ${_OPENSSL_ROOT_PATHS} +) +MARK_AS_ADVANCED(OPENSSL_ROOT_DIR) + +# Re-use the previous path: +FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h + ${OPENSSL_ROOT_DIR}/include +) + +IF(WIN32 AND NOT CYGWIN) + # MINGW should go here too + IF(MSVC) + # /MD and /MDd are the standard values - if someone wants to use + # others, the libnames have to change here too + # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b + # TODO: handle /MT and static lib + # In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix: + # * MD for dynamic-release + # * MDd for dynamic-debug + # * MT for static-release + # * MTd for static-debug + + # Implementation details: + # We are using the libraries located in the VC subdir instead of the parent directory eventhough : + # libeay32MD.lib is identical to ../libeay32.lib, and + # ssleay32MD.lib is identical to ../ssleay32.lib + + # Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib + if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set(_OPENSSL_MSVC_ARCH_SUFFIX "64") + else() + set(_OPENSSL_MSVC_ARCH_SUFFIX "32") + endif() + + FIND_LIBRARY(LIB_EAY_DEBUG + NAMES + libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MDd libeay32MDd libeay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib/VC + ) + + FIND_LIBRARY(LIB_EAY_RELEASE + NAMES + libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MD libeay32MD libeay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib/VC + ) + + FIND_LIBRARY(SSL_EAY_DEBUG + NAMES + libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MDd ssleay32MDd ssleay32 ssl + PATHS + ${OPENSSL_ROOT_DIR}/lib/VC + ) + + FIND_LIBRARY(SSL_EAY_RELEASE + NAMES + libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MD ssleay32MD ssleay32 ssl + PATHS + ${OPENSSL_ROOT_DIR}/lib/VC + ) + + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + set(OPENSSL_LIBRARIES + optimized ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} + debug ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} + ) + else() + set(OPENSSL_LIBRARIES + ${SSL_EAY_RELEASE} + ${LIB_EAY_RELEASE} + ) + endif() + + MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE LIB_EAY_DEBUG LIB_EAY_RELEASE) + ELSEIF(MINGW) + + # same player, for MingW + FIND_LIBRARY(LIB_EAY + NAMES + libeay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib/MinGW + ) + + FIND_LIBRARY(SSL_EAY NAMES + NAMES + ssleay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib/MinGW + ) + + MARK_AS_ADVANCED(SSL_EAY LIB_EAY) + + set(OPENSSL_LIBRARIES + ${SSL_EAY} + ${LIB_EAY} + ) + ELSE(MSVC) + # Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues: + FIND_LIBRARY(LIB_EAY + NAMES + libeay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib + ${OPENSSL_ROOT_DIR}/lib/VC + ) + + FIND_LIBRARY(SSL_EAY + NAMES + ssleay32 + PATHS + ${OPENSSL_ROOT_DIR}/lib + ${OPENSSL_ROOT_DIR}/lib/VC + ) + MARK_AS_ADVANCED(SSL_EAY LIB_EAY) + + SET(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY}) + ENDIF(MSVC) +ELSE(WIN32 AND NOT CYGWIN) + FIND_LIBRARY(OPENSSL_SSL_LIBRARIES NAMES ssl ssleay32 ssleay32MD) + FIND_LIBRARY(OPENSSL_CRYPTO_LIBRARIES NAMES crypto) + MARK_AS_ADVANCED(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES) + + SET(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES}) + +ENDIF(WIN32 AND NOT CYGWIN) + +if(NOT OPENSSL_INCLUDE_DIR) + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(OpenSSL DEFAULT_MSG + OPENSSL_LIBRARIES + OPENSSL_INCLUDE_DIR + ) +endif() + +if(OPENSSL_INCLUDE_DIR) + message(STATUS "Found OpenSSL library: ${OPENSSL_LIBRARIES}") + message(STATUS "Found OpenSSL headers: ${OPENSSL_INCLUDE_DIR}") + if(_OPENSSL_VERSION) + set(OPENSSL_VERSION "${_OPENSSL_VERSION}") + else(_OPENSSL_VERSION) + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str + REGEX "^# *define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9][0-9][0-9][0-9][0-9][0-9].*") + + # The version number is encoded as 0xMNNFFPPS: major minor fix patch status + # The status gives if this is a developer or prerelease and is ignored here. + # Major, minor, and fix directly translate into the version numbers shown in + # the string. The patch field translates to the single character suffix that + # indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so + # on. + + string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f]).*$" + "\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}") + list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR) + list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR) + list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX) + list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH) + + string(REGEX REPLACE "^0(.)" "\\1" OPENSSL_VERSION_MINOR "${OPENSSL_VERSION_MINOR}") + string(REGEX REPLACE "^0(.)" "\\1" OPENSSL_VERSION_FIX "${OPENSSL_VERSION_FIX}") + + if(NOT OPENSSL_VERSION_PATCH STREQUAL "00") + # 96 is the ASCII code of 'a' minus 1 + math(EXPR OPENSSL_VERSION_PATCH_ASCII "${OPENSSL_VERSION_PATCH} + 96") + # Once anyone knows how OpenSSL would call the patch versions beyond 'z' + # this should be updated to handle that, too. This has not happened yet + # so it is simply ignored here for now. + string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING) + endif(NOT OPENSSL_VERSION_PATCH STREQUAL "00") + + set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}") + endif(_OPENSSL_VERSION) + + include(EnsureVersion) + ENSURE_VERSION_RANGE("${OPENSSL_EXPECTED_VERSION}" "${OPENSSL_VERSION}" "${OPENSSL_MAX_VERSION}" OPENSSL_VERSION_OK) + if(NOT OPENSSL_VERSION_OK) + message(FATAL_ERROR "MaNGOS requires OpenSSL version ${OPENSSL_EXPECTED_VERSION} but you have version ${OPENSSL_VERSION} installed. Please upgrade to ${OPENSSL_EXPECTED_VERSION} or better.") + else() + message(STATUS "Installed OpenSSL Version: ${OPENSSL_VERSION}") + endif() +endif(OPENSSL_INCLUDE_DIR) + +MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES) diff --git a/src/mangosd/CMakeLists.txt b/src/mangosd/CMakeLists.txt index a2be88de..eb9895ee 100644 --- a/src/mangosd/CMakeLists.txt +++ b/src/mangosd/CMakeLists.txt @@ -63,6 +63,7 @@ target_include_directories(mangosd PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${OPENSSL_INCLUDE_DIR} ) target_link_libraries(mangosd @@ -70,7 +71,7 @@ target_link_libraries(mangosd game $<$:gsoap> Threads::Threads - DL::DL + ${OPENSSL_LIBRARIES} ) install( diff --git a/src/realmd b/src/realmd index 88ea5f98..3bbaa601 160000 --- a/src/realmd +++ b/src/realmd @@ -1 +1 @@ -Subproject commit 88ea5f98abbd48920a006b767cc9dce1b00c5975 +Subproject commit 3bbaa6010d509602e15367dafc4678d1a8c2b520 diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index 10a8e2ed..13312970 100644 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -213,6 +213,7 @@ target_include_directories(shared PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${OPENSSL_INCLUDE_DIR} ${TGT_INCL} ) @@ -229,5 +230,6 @@ target_link_libraries(shared ace utf8 MySQL::MySQL - OpenSSL::Crypto + DL::DL + ${OPENSSL_LIBRARIES} ) diff --git a/src/tools/Extractor_projects b/src/tools/Extractor_projects index 8fd801de..f6d96d5d 160000 --- a/src/tools/Extractor_projects +++ b/src/tools/Extractor_projects @@ -1 +1 @@ -Subproject commit 8fd801de7ed7c7fdf15827dd9888ec4b642eaead +Subproject commit f6d96d5da55a22b2da2a5dfb2f66830d572289d3