From 450c1e6ec5af32fb27aed5dd9f336f0d6519c419 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Wed, 19 Feb 2020 10:00:16 +0100 Subject: [PATCH] Bug #30921806 ENABLE CUSTOM KERBEROS FOR STANDALONE LINUX BUILDS WL#13759 MySQL 8.0: Support linking with 3rd party OpenLDAP and Cyrus SASL added support for custom LDAP and SASL libraries for standalone linux builds. This patch adds support for custom KERBEROS as well. Pushbuild will now build LDAP/SASL/KERBEROS/SSL as one "package" and invoke cmake with -DWITH_LDAP= -DWITH_SASL= -DWITH_KERBEROS= -DWITH_SSL= These builds depend on each other, so that the SASL build will use the KERBEROS and SSL builds, the LDAP build will use the SASL and SSL builds. The result is a set of headers and shared libraries which consistently use OpenSSL 1.1.1 We also need to support building *without* KERBEROS, i.e. LDAP/SASL/SSL where libsasl2.so does not depend on libkrb5 and the SASL kerberos plugins are missing. Change-Id: I4078c67cd41ce15842bbf139babe386d6d0e9e2d (cherry picked from commit 9c3f7e6d28fdf4cb29e3b0eedc8ecbf5671434a2) --- CMakeLists.txt | 32 ++- cmake/install_macros.cmake | 16 +- cmake/kerberos.cmake | 211 ++++++++++++------ cmake/sasl.cmake | 85 +++++-- config.h.cmake | 3 +- libmysql/CMakeLists.txt | 5 + libmysql/authentication_ldap/CMakeLists.txt | 37 +-- .../auth_ldap_sasl_client.cc | 12 +- .../auth_ldap_sasl_client.h | 2 + .../auth_ldap_sasl_mechanism.cc | 3 + .../auth_ldap_sasl_mechanism.h | 2 + mysql-test/lsan.supp | 6 + mysql-test/mysql-test-run.pl | 2 + mysql-test/valgrind.supp | 32 +++ scripts/CMakeLists.txt | 2 + 15 files changed, 331 insertions(+), 119 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf688cf34eae..ba974215d2ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -571,7 +571,7 @@ IF(NOT DEFINED WITH_INTERNAL) ENDIF() # On windows we need a non-standard package for SASL. -IF(WITH_INTERNAL AND NOT WIN32) +IF(WITH_INTERNAL AND (NOT WIN32 OR WITH_SASL)) SET(WITH_AUTHENTICATION_LDAP_DEFAULT ON) ELSE() SET(WITH_AUTHENTICATION_LDAP_DEFAULT OFF) @@ -1241,12 +1241,29 @@ IF(LINUX) SET(KNOWN_CUSTOM_LIBRARIES "" CACHE INTERNAL "" FORCE) ENDIF() +# If all custom packages are in the same directory: +IF(WITH_CUSTOM_LIBRARIES) + FILE(GLOB WITH_SSL "${WITH_CUSTOM_LIBRARIES}/openssl*") + FILE(GLOB WITH_KERBEROS "${WITH_CUSTOM_LIBRARIES}/krb5*") + FILE(GLOB WITH_SASL "${WITH_CUSTOM_LIBRARIES}/cyrus-sasl*") + FILE(GLOB WITH_LDAP "${WITH_CUSTOM_LIBRARIES}/openldap*") + FOREACH(WITH_OPT WITH_SSL WITH_KERBEROS WITH_SASL WITH_LDAP) + IF(IS_DIRECTORY ${${WITH_OPT}}) + SET(${WITH_OPT} ${${WITH_OPT}} CACHE INTERNAL "" FORCE) + MESSAGE(STATUS "${WITH_OPT} ${${WITH_SSL}}") + ELSE() + MESSAGE(WARNING "${WITH_OPT} not found") # This should be FATAL_ERROR + ENDIF() + ENDFOREACH() +ENDIF() + # Add system/custom openssl. MYSQL_CHECK_SSL() MYSQL_CHECK_SSL_DLLS() -# Add Kerberos library (custom DLLS not yet supported) +# Add Kerberos library MYSQL_CHECK_KERBEROS() +MYSQL_CHECK_KERBEROS_DLLS() # Add SASL library MYSQL_CHECK_SASL() @@ -1279,12 +1296,13 @@ ENDIF() IF(WITH_AUTHENTICATION_LDAP) IF(LINUX AND KNOWN_CUSTOM_LIBRARIES) - # LDAP / SASL / SSL must all be "system" or "custom", not a mix. + # LDAP / SASL / KERBEROS / SSL must all be "system" or "custom", not a mix. IF(WITH_LDAP STREQUAL "system" OR WITH_SASL STREQUAL "system" OR +# WITH_KERBEROS STREQUAL "system" OR # enable this later WITH_SSL STREQUAL "system") MESSAGE(WARNING "-DWITH_AUTHENTICATION_LDAP=ON") - MESSAGE(FATAL_ERROR "Inconsistent options for LDAP/SASL/SSL") + MESSAGE(FATAL_ERROR "Inconsistent options for LDAP/SASL/KERBEROS/SSL") ENDIF() ELSEIF(WIN32) # system LDAP, but SASL needs to be explicitly added @@ -1297,12 +1315,14 @@ IF(WITH_AUTHENTICATION_LDAP) ELSEIF(SOLARIS) # 11.3 has system LDAP and SASL, but there is no scram plugin. ELSE() - # We must have "system" LDAP and SASL (SSL is always required) + # We must have "system" LDAP, KERBEROS and SASL (SSL is always required) SET(LDAP_WARN_GIVEN) SET(SASL_WARN_GIVEN) + SET(KERBEROS_WARN_GIVEN) WARN_MISSING_SYSTEM_LDAP(LDAP_WARN_GIVEN) WARN_MISSING_SYSTEM_SASL(SASL_WARN_GIVEN) - IF(LDAP_WARN_GIVEN OR SASL_WARN_GIVEN) + WARN_MISSING_SYSTEM_KERBEROS(KERBEROS_WARN_GIVEN) + IF(LDAP_WARN_GIVEN OR SASL_WARN_GIVEN OR KERBEROS_WARN_GIVEN) # SUSE linux: may or may not have SCRAM, do not break the build. IF(LINUX_SUSE) MESSAGE(WARNING diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 0569a9e7ece6..c3a05ecac842 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -388,8 +388,8 @@ FUNCTION(SET_PATH_TO_SSL target target_out_dir) ENDFUNCTION() -# For standalone Linux build and -DWITH_LDAP -DWITH_SASL -DWITH_SSL -# set to custom path. +# For standalone Linux build and -DWITH_LDAP -DWITH_SASL -DWITH_SSL and +# -DWITH_KERBEROS set to custom path. # # Move the custom shared library and symlinks to library_output_directory. # The subdir argument is typically empty, but set to "sasl2" for SASL plugins, @@ -427,11 +427,11 @@ FUNCTION(COPY_CUSTOM_SHARED_LIBRARY library_full_filename subdir FIND_OBJECT_DEPENDENCIES(${library_full_filename} library_dependencies) MESSAGE(STATUS "CUSTOM library ${library_full_filename}") - MESSAGE(STATUS "CUSTOM version ${library_version}") - MESSAGE(STATUS "CUSTOM directory ${library_directory}") - MESSAGE(STATUS "CUSTOM name ${library_name}") - MESSAGE(STATUS "CUSTOM name_we ${library_name_we}") - MESSAGE(STATUS "CUSTOM soname ${library_soname}") +# MESSAGE(STATUS "CUSTOM version ${library_version}") +# MESSAGE(STATUS "CUSTOM directory ${library_directory}") +# MESSAGE(STATUS "CUSTOM name ${library_name}") +# MESSAGE(STATUS "CUSTOM name_we ${library_name_we}") +# MESSAGE(STATUS "CUSTOM soname ${library_soname}") SET(COPIED_LIBRARY_NAME "${CMAKE_BINARY_DIR}/library_output_directory/${subdir}/${library_name}") @@ -471,7 +471,7 @@ FUNCTION(COPY_CUSTOM_SHARED_LIBRARY library_full_filename subdir ADD_DEPENDENCIES(copy_linux_custom_dlls ${COPY_TARGET_NAME}) - MESSAGE(STATUS "INSTALL ${library_name} to ${INSTALL_PRIV_LIBDIR}") + MESSAGE(STATUS "INSTALL ${library_name} to ${INSTALL_PRIV_LIBDIR}/${subdir}") # Cannot use INSTALL_PRIVATE_LIBRARY because these are not targets. INSTALL(FILES diff --git a/cmake/kerberos.cmake b/cmake/kerberos.cmake index 04d8f14893c9..4cf0a9fbd614 100644 --- a/cmake/kerberos.cmake +++ b/cmake/kerberos.cmake @@ -23,19 +23,7 @@ # cmake -DWITH_KERBEROS=system||none # system is the default # none will diable the kerberos build -# -# Following algorithm will be used to find kerberos library. -# 1. If "WITH_KERBEROS" is set to system or not configured, -# we will search kerberos lib in system directory. -# System is used for unix alike OS. -# For windows we dont have system kerberos library. -# 2. If kerberos library path is provided using "WITH_KERBEROS" option, -# we will search kerberos library in that path. -# This will be used to build MySQL with custom kerberos library. -# 3. If kerberos library and header is found, kerberos library path, -# kerberos header path and KERBEROS_LIB_CONFIGURED will be set. -# 4. For windows, we need to install kerberos library from web, -# https://web.mit.edu/kerberos/kfw-4.1/kfw-4.1.html. +# Custom path is only supported for LINUX_STANDALONE. INCLUDE (CheckIncludeFile) INCLUDE (CheckIncludeFiles) @@ -46,35 +34,78 @@ STRING_APPEND(WITH_KERBEROS_DOC ", \nnone (skip kerberos)>") STRING(REPLACE "\n" "| " WITH_KERBEROS_DOC_STRING "${WITH_KERBEROS_DOC}") -MACRO(RESET_KERBEROS_VARIABLES) - UNSET(KERBEROS_INCLUDE_DIR) - UNSET(KERBEROS_INCLUDE_DIR CACHE) - UNSET(KERBEROS_SYSTEM_LIBRARY) - UNSET(KERBEROS_SYSTEM_LIBRARY CACHE) -ENDMACRO() +FUNCTION(WARN_MISSING_SYSTEM_KERBEROS OUTPUT_WARNING) + IF(NOT KERBEROS_FOUND AND WITH_KERBEROS STREQUAL "system") + MESSAGE(WARNING "Cannot find KERBEROS development libraries. " + "You need to install the required packages:\n" + " Debian/Ubuntu: apt install libkrb5-dev\n" + " RedHat/Fedora/Oracle Linux: yum install krb5-devel\n" + " SuSE: zypper install krb5-devel\n" + ) + SET(${OUTPUT_WARNING} 1 PARENT_SCOPE) + ENDIF() +ENDFUNCTION() + +MACRO(FIND_SYSTEM_KERBEROS) + # Typical result of running pkg-config is: + # SYSTEM_KRB5_LDFLAGS -lkrb5;-lk5crypto;-lcom_err + # SYSTEM_KRB5_INCLUDE_DIRS "" + # SYSTEM_KRB5_CFLAGS "" + # DEBIAN/UBUNTU: + # -L/usr/lib/x86_64-linux-gnu/mit-krb5;-lkrb5;-lk5crypto;-lcom_err + # "" + # -isystem;/usr/include/mit-krb5 + # FREEBSD : + # -L/usr/local/lib;-lkrb5;-lk5crypto;-lcom_err + # /usr/local/include + # -I/usr/local/include + IF(LINUX OR FREEBSD) + MYSQL_CHECK_PKGCONFIG() + PKG_CHECK_MODULES(SYSTEM_KRB5 krb5) + + MESSAGE(STATUS "SYSTEM_KRB5_FOUND ${SYSTEM_KRB5_FOUND}") + MESSAGE(STATUS "SYSTEM_KRB5_LIBRARIES ${SYSTEM_KRB5_LIBRARIES}") + MESSAGE(STATUS "SYSTEM_KRB5_LIBRARY_DIRS ${SYSTEM_KRB5_LIBRARY_DIRS}") + MESSAGE(STATUS "SYSTEM_KRB5_LDFLAGS ${SYSTEM_KRB5_LDFLAGS}") + MESSAGE(STATUS "SYSTEM_KRB5_LDFLAGS_OTHER ${SYSTEM_KRB5_LDFLAGS_OTHER}") + MESSAGE(STATUS "SYSTEM_KRB5_INCLUDE_DIRS ${SYSTEM_KRB5_INCLUDE_DIRS}") + MESSAGE(STATUS "SYSTEM_KRB5_CFLAGS ${SYSTEM_KRB5_CFLAGS}") + MESSAGE(STATUS "SYSTEM_KRB5_CFLAGS_OTHER ${SYSTEM_KRB5_CFLAGS_OTHER}") -MACRO (FIND_SYSTEM_KERBEROS) - FIND_LIBRARY(KERBEROS_SYSTEM_LIBRARY NAMES "krb5") - IF(LINUX_DEBIAN OR LINUX_UBUNTU) - FIND_LIBRARY(KERBEROS_SYSTEM_LIBRARY - NAMES "krb5" - HINTS /usr/lib/x86_64-linux-gnu) + IF(SYSTEM_KRB5_FOUND) + SET(KERBEROS_LIBRARIES "${SYSTEM_KRB5_LDFLAGS}") + ELSE() + # Oracle Linux 6 + FIND_PROGRAM(MY_KRB5_CONFIG krb5-config) + IF(MY_KRB5_CONFIG) + EXECUTE_PROCESS(COMMAND ${MY_KRB5_CONFIG} --libs + OUTPUT_VARIABLE MY_KRB5_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MY_KRB5_RESULT + ) + MESSAGE(STATUS "${MY_KRB5_CONFIG} --libs: ${MY_KRB5_LIBS}") + STRING(REPLACE " " ";" MY_KRB5_LIBS "${MY_KRB5_LIBS}") + SET(KERBEROS_LIBRARIES "${MY_KRB5_LIBS}") + ENDIF() + ENDIF() + ELSEIF(SOLARIS OR APPLE) + # Solaris: /usr/lib/64/libkrb5.so + # Apple: /usr/lib/libkrb5.dylib which depends on /System/..../Heimdal + FIND_LIBRARY(KERBEROS_SYSTEM_LIBRARY NAMES "krb5") + IF(KERBEROS_SYSTEM_LIBRARY) + SET(KERBEROS_LIBRARIES "${KERBEROS_SYSTEM_LIBRARY}") + ENDIF() ENDIF() - IF (KERBEROS_SYSTEM_LIBRARY) - SET(KERBEROS_LIBRARY_PATH ${KERBEROS_SYSTEM_LIBRARY}) - MESSAGE(STATUS "KERBEROS_LIBRARY_PATH ${KERBEROS_LIBRARY_PATH}") + IF(KERBEROS_LIBRARIES) CMAKE_PUSH_CHECK_STATE() IF(SOLARIS) - INCLUDE_DIRECTORIES(BEFORE SYSTEM /usr/include/kerberosv5) SET(CMAKE_REQUIRED_INCLUDES "/usr/include/kerberosv5") ELSEIF(FREEBSD) - # Do *not* INCLUDE_DIRECTORIES /usr/local/include here. - SET(CMAKE_REQUIRED_INCLUDES "/usr/local/include") + SET(CMAKE_REQUIRED_INCLUDES "${SYSTEM_KRB5_INCLUDE_DIRS}") ELSEIF(LINUX_DEBIAN OR LINUX_UBUNTU) - INCLUDE_DIRECTORIES(BEFORE SYSTEM /usr/include/mit-krb5) - SET(CMAKE_REQUIRED_INCLUDES "/usr/include/mit-krb5") + SET(CMAKE_REQUIRED_INCLUDES "${SYSTEM_KRB5_CFLAGS}") ENDIF() CHECK_INCLUDE_FILE(krb5/krb5.h HAVE_KRB5_KRB5_H) @@ -84,68 +115,89 @@ MACRO (FIND_SYSTEM_KERBEROS) HINTS ${CMAKE_REQUIRED_INCLUDES} ) ENDIF() - CMAKE_POP_CHECK_STATE() - ENDIF() + ENDMACRO() -# TODO: implement for standalone Linux and Windows. -# Lookup, and copy: libgssapi_krb5.so.2 libkrb5.so.3 libkrb5support.so.0 -MACRO(FIND_CUSTOM_KERBEROS) - FIND_LIBRARY(KERBEROS_LIBRARY_PATH - NAMES "krb5" - PATHS ${WITH_KERBEROS} ${WITH_KERBEROS}/lib - NO_DEFAULT_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH) +# Lookup and copy misc libraries, 'objdump -p xx | grep NEED' shows: +# libkrb5.so depends on: +# NEEDED libk5crypto.so.3 +# NEEDED libcom_err.so.3 +# NEEDED libkrb5support.so.0 +# libsasl2.so depends on: +# NEEDED libgssapi_krb5.so.2 +# NEEDED libkrb5.so.3 +# NEEDED libk5crypto.so.3 +# NEEDED libcom_err.so.2 +SET(CUSTOM_KERBEROS_EXTRA_LIBRARIES + com_err + gssapi_krb5 + k5crypto + krb5support + ) +MACRO(FIND_CUSTOM_KERBEROS) # Header file first search in WITH_KERBEROS. FIND_PATH(KERBEROS_ROOT_DIR - NAMES include/krb5.h + NAMES include/krb5/krb5.h NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH - HINTS ${WITH_KERBEROS} + HINTS ${WITH_KERBEROS_PATH} ) - # Header file search in standard places (if not found above). + # Then search in standard places (if not found above). FIND_PATH(KERBEROS_ROOT_DIR NAMES include/krb5/krb5.h - ) + ) + FIND_PATH(KERBEROS_INCLUDE_DIR - NAMES krb5.h + NAMES krb5/krb5.h HINTS ${KERBEROS_ROOT_DIR}/include - ) - IF(KERBEROS_INCLUDE_DIR AND KERBEROS_LIBRARY_PATH) + ) + + FIND_LIBRARY(KERBEROS_CUSTOM_LIBRARY + NAMES "krb5" + PATHS ${WITH_KERBEROS}/lib + NO_DEFAULT_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + ) + + FOREACH(EXTRA_LIB ${CUSTOM_KERBEROS_EXTRA_LIBRARIES}) + SET(VAR_NAME "KERBEROS_CUSTOM_LIBRARY_${EXTRA_LIB}") + FIND_LIBRARY(${VAR_NAME} + NAMES "${EXTRA_LIB}" + PATHS ${WITH_KERBEROS}/lib + NO_DEFAULT_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + ) + ENDFOREACH() + + IF(KERBEROS_INCLUDE_DIR AND KERBEROS_CUSTOM_LIBRARY) MESSAGE(STATUS "KERBEROS_INCLUDE_DIR ${KERBEROS_INCLUDE_DIR}") - SET(CMAKE_REQUIRED_INCLUDES ${KERBEROS_INCLUDE_DIR}) - ADD_DEFINITIONS(-DKERBEROS_LIB_CONFIGURED) SET(KERBEROS_FOUND 1) + SET(HAVE_KRB5_KRB5_H 1 CACHE INTERNAL "") ENDIF() ENDMACRO() -MACRO (MYSQL_CHECK_KERBEROS) - # For standalone linux: custom KERBEROS must match custom builds of - # LDAP/SASL/SSL. This is not yet supported, so we disable Kerberos. - IF(LINUX_STANDALONE AND KNOWN_CUSTOM_LIBRARIES) - SET(WITH_KERBEROS "none") - SET(WITH_KERBEROS "none" CACHE INTERNAL "") - RESET_KERBEROS_VARIABLES() - ENDIF() - +MACRO(MYSQL_CHECK_KERBEROS) # No Kerberos support for Windows. IF(WIN32) SET(WITH_KERBEROS "none") SET(WITH_KERBEROS "none" CACHE INTERNAL "") - RESET_KERBEROS_VARIABLES() ENDIF() IF(NOT WITH_KERBEROS) - SET(WITH_KERBEROS "system" CACHE STRING "${WITH_KERBEROS_DOC_STRING}" FORCE) + IF(WITH_AUTHENTICATION_LDAP) + SET(WITH_KERBEROS "system" CACHE STRING "${WITH_KERBEROS_DOC_STRING}") + ELSE() + SET(WITH_KERBEROS "none" CACHE STRING "${WITH_KERBEROS_DOC_STRING}") + ENDIF() ENDIF() # See if WITH_KERBEROS is of the form - # TODO: not implemented yet. Implement for STANDALONE_LINUX and Windows. FILE(GLOB WITH_KERBEROS_HEADER ${WITH_KERBEROS}/include/krb5/krb5.h) IF(WITH_KERBEROS_HEADER) FILE(TO_CMAKE_PATH "${WITH_KERBEROS}" WITH_KERBEROS) @@ -155,11 +207,9 @@ MACRO (MYSQL_CHECK_KERBEROS) IF(WITH_KERBEROS STREQUAL "system") FIND_SYSTEM_KERBEROS() ELSEIF(WITH_KERBEROS STREQUAL "none") - MESSAGE(STATUS "KERBEROS_LIBRARY path is none, disabling kerberos support.") - SET(KERBEROS_LIBRARY_PATH "") + MESSAGE(STATUS "KERBEROS path is none, disabling kerberos support.") SET(WITH_KERBEROS 0) SET(KERBEROS_FOUND 0) - SET(WITH_KERBEROS_NOT_SET 1) ELSEIF(WITH_KERBEROS_PATH) IF(LINUX_STANDALONE) FIND_CUSTOM_KERBEROS() @@ -171,7 +221,7 @@ MACRO (MYSQL_CHECK_KERBEROS) MESSAGE(FATAL_ERROR "Could not find KERBEROS") ENDIF() - IF(KERBEROS_SYSTEM_LIBRARY AND HAVE_KRB5_KRB5_H) + IF((KERBEROS_LIBRARIES OR KERBEROS_CUSTOM_LIBRARY) AND HAVE_KRB5_KRB5_H) SET(KERBEROS_FOUND 1) ELSE() SET(KERBEROS_FOUND 0) @@ -182,7 +232,28 @@ MACRO (MYSQL_CHECK_KERBEROS) ENDIF() IF(KERBEROS_FOUND) - ADD_DEFINITIONS(-DKERBEROS_LIB_CONFIGURED) + SET(KERBEROS_LIB_CONFIGURED 1) ENDIF() ENDMACRO() + +MACRO(MYSQL_CHECK_KERBEROS_DLLS) + IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY) + COPY_CUSTOM_SHARED_LIBRARY("${KERBEROS_CUSTOM_LIBRARY}" "" + KERBEROS_LIBRARIES kerberos_target + ) + FOREACH(EXTRA_LIB ${CUSTOM_KERBEROS_EXTRA_LIBRARIES}) + SET(COPIED_LIBRARY_NAME) + SET(COPIED_TARGET_NAME) + SET(VAR_NAME "KERBEROS_CUSTOM_LIBRARY_${EXTRA_LIB}") + COPY_CUSTOM_SHARED_LIBRARY("${${VAR_NAME}}" "" + COPIED_LIBRARY_NAME COPIED_TARGET_NAME + ) + ADD_DEPENDENCIES(${kerberos_target} ${COPIED_TARGET_NAME}) + # Append all which are NEEDED by libkrb5.so + IF(NOT COPIED_LIBRARY_NAME MATCHES "gssapi") + LIST(APPEND KERBEROS_LIBRARIES "${COPIED_LIBRARY_NAME}") + ENDIF() + ENDFOREACH() + ENDIF() +ENDMACRO() diff --git a/cmake/sasl.cmake b/cmake/sasl.cmake index f0b6e709486d..e934cdb21eb2 100644 --- a/cmake/sasl.cmake +++ b/cmake/sasl.cmake @@ -109,6 +109,24 @@ MACRO(FIND_SYSTEM_SASL) ENDIF() ENDMACRO() +# Lookup and copy all plugins +# lib/sasl2/libanonymous.so +# lib/sasl2/libcrammd5.so +# lib/sasl2/libdigestmd5.so +# lib/sasl2/libgs2.so +# lib/sasl2/libgssapiv2.so +# lib/sasl2/libplain.so +# lib/sasl2/libscram.so +SET(CUSTOM_SASL_PLUGINS + anonymous + crammd5 + digestmd5 + gs2 + gssapiv2 + plain + scram + ) + MACRO(FIND_CUSTOM_SASL) # First search in WITH_SASL_PATH. FIND_PATH(SASL_ROOT_DIR @@ -142,21 +160,32 @@ MACRO(FIND_CUSTOM_SASL) PATHS ${WITH_SASL}/lib NO_DEFAULT_PATH NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH) - - # The SCRAM plugin was introduced in 2.1.25 - FIND_LIBRARY(SASL_CUSTOM_SCRAM_LIBRARY - NAMES scram - PATHS ${WITH_SASL}/lib/sasl2 - NO_DEFAULT_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH) + NO_SYSTEM_ENVIRONMENT_PATH + ) IF(SASL_CUSTOM_LIBRARY) SET(SASL_LIBRARY ${SASL_CUSTOM_LIBRARY}) MESSAGE(STATUS "SASL_LIBRARY ${SASL_LIBRARY}") ENDIF() + IF(LINUX_STANDALONE) + FOREACH(SASL_PLUGIN ${CUSTOM_SASL_PLUGINS}) + SET(VAR_NAME "SASL_CUSTOM_PLUGIN_${SASL_PLUGIN}") + FIND_LIBRARY(${VAR_NAME} + NAMES "${SASL_PLUGIN}" + PATHS ${WITH_SASL}/lib/sasl2 + NO_DEFAULT_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + ) + IF(NOT ${VAR_NAME}) + # This should be FATAL_ERROR, enable later + MESSAGE(WARNING + "Could not find plugin lib${SASL_PLUGIN}.so in ${WITH_SASL}/lib/sasl2") + ENDIF() + ENDFOREACH() + ENDIF() + IF(SASL_INCLUDE_DIR) INCLUDE_DIRECTORIES(BEFORE SYSTEM "${SASL_INCLUDE_DIR}") @@ -226,11 +255,41 @@ ENDMACRO() MACRO(MYSQL_CHECK_SASL_DLLS) IF(LINUX_STANDALONE AND SASL_CUSTOM_LIBRARY) + FIND_OBJECT_DEPENDENCIES(${SASL_CUSTOM_LIBRARY} SASL_DEPENDS_ON) + STRING(REPLACE ";" " " SASL_DEPENDS_ON "${SASL_DEPENDS_ON}") + IF(NOT SASL_DEPENDS_ON MATCHES "libkrb5") + MESSAGE(WARNING "This SASL library is built without KERBEROS") + SET(SASL_WITHOUT_KERBEROS 1) + UNSET(KERBEROS_CUSTOM_LIBRARY CACHE) + UNSET(KERBEROS_CUSTOM_LIBRARY) + UNSET(KERBEROS_FOUND CACHE) + UNSET(KERBEROS_FOUND) + UNSET(KERBEROS_LIBRARIES CACHE) + UNSET(KERBEROS_LIBRARIES) + UNSET(KERBEROS_LIB_CONFIGURED CACHE) + UNSET(KERBEROS_LIB_CONFIGURED) + UNSET(KERBEROS_SYSTEM_LIBRARY CACHE) + UNSET(KERBEROS_SYSTEM_LIBRARY) + SET(WITH_KERBEROS "none" CACHE STRING "" FORCE) + ENDIF() + COPY_CUSTOM_SHARED_LIBRARY("${SASL_CUSTOM_LIBRARY}" "" SASL_LIBRARY sasl_target) - ENDIF() - IF(LINUX_STANDALONE AND SASL_CUSTOM_SCRAM_LIBRARY) - COPY_CUSTOM_SHARED_LIBRARY("${SASL_CUSTOM_SCRAM_LIBRARY}" "sasl2" - SCRAM_LIBRARY scram_target) + FOREACH(SASL_PLUGIN ${CUSTOM_SASL_PLUGINS}) + SET(COPIED_LIBRARY_NAME) + SET(COPIED_TARGET_NAME) + SET(VAR_NAME "SASL_CUSTOM_PLUGIN_${SASL_PLUGIN}") + IF(${VAR_NAME}) + COPY_CUSTOM_SHARED_LIBRARY("${${VAR_NAME}}" "sasl2" + COPIED_LIBRARY_NAME COPIED_TARGET_NAME + ) + ADD_DEPENDENCIES(${sasl_target} ${COPIED_TARGET_NAME}) + ELSEIF(SASL_WITHOUT_KERBEROS) + # This should be FATAL_ERROR + ELSE() + MESSAGE(FATAL_ERROR + "Could not find plugin lib${SASL_PLUGIN}.so in ${WITH_SASL}/lib/sasl2") + ENDIF() + ENDFOREACH() ENDIF() ENDMACRO() diff --git a/config.h.cmake b/config.h.cmake index 9a4ead3f54a2..ce6b3bbc94f2 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -208,6 +208,7 @@ #cmakedefine HAVE_UBSAN #cmakedefine HAVE_TSAN #cmakedefine ENABLED_LOCAL_INFILE 1 +#cmakedefine KERBEROS_LIB_CONFIGURED /* Lock Order */ #cmakedefine WITH_LOCK_ORDER 1 diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index c2bbf4606a02..605288d95e8f 100644 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -290,6 +290,11 @@ MERGE_LIBRARIES_SHARED(libmysql ${LIBS_TO_MERGE} COMPONENT SharedLibraries) TARGET_LINK_LIBRARIES(libmysql PRIVATE ${LIBS_TO_LINK}) +IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY) + ADD_DEPENDENCIES(libmysql ${kerberos_target}) + ADD_DEPENDENCIES(mysqlclient ${kerberos_target}) +ENDIF() + IF(WIN32) # So that libmysql_api_test below can find the .dll ADD_CUSTOM_COMMAND(TARGET libmysql POST_BUILD diff --git a/libmysql/authentication_ldap/CMakeLists.txt b/libmysql/authentication_ldap/CMakeLists.txt index b594f553a2f6..703edb9460dc 100644 --- a/libmysql/authentication_ldap/CMakeLists.txt +++ b/libmysql/authentication_ldap/CMakeLists.txt @@ -35,6 +35,10 @@ IF(FREEBSD AND KERBEROS_SYSTEM_LIBRARY) INCLUDE_DIRECTORIES(SYSTEM /usr/local/include) ENDIF() +IF(FREEBSD AND SASL_INCLUDE_DIR) + INCLUDE_DIRECTORIES(BEFORE SYSTEM ${SASL_INCLUDE_DIR}) +ENDIF() + INCLUDE(CheckIncludeFiles) # Several sasl_() functions are deprecated @@ -44,22 +48,20 @@ ENDIF() DISABLE_MISSING_PROFILE_WARNING() -IF (KERBEROS_FOUND) - IF(LINUX_STANDALONE AND SASL_CUSTOM_LIBRARY) - MESSAGE(STATUS "KERBEROS is not yet supported on this platform") - UNSET(KERBEROS_LIBRARY_PATH) - UNSET(KERBEROS_LIBRARY_PATH CACHE) - ELSE() - MESSAGE(STATUS "KERBEROS_LIBRARY_PATH = ${KERBEROS_LIBRARY_PATH}") - SET(AUTH_LDAP_KERBEROS_CC auth_ldap_kerberos.cc) - # mysys is required to use my_free and my_strdup when getting Kerberos user name. - # Adding mysys only when build has Kerberos support - SET(MY_SYS "mysys") +IF(KERBEROS_FOUND) + MESSAGE(STATUS + "Building authentication_ldap_sasl_client with Kerberos") + IF(KERBEROS_INCLUDE_DIR) + INCLUDE_DIRECTORIES(SYSTEM ${KERBEROS_INCLUDE_DIR}) ENDIF() + SET(AUTH_LDAP_KERBEROS_CC auth_ldap_kerberos.cc) + # mysys is required to use my_free and my_strdup when getting + # Kerberos user name. + # Adding mysys only when build has Kerberos support + SET(MY_SYS "mysys") ELSE() - MESSAGE(STATUS "Without Kerberos") - UNSET(KERBEROS_LIBRARY_PATH) - UNSET(KERBEROS_LIBRARY_PATH CACHE) + MESSAGE(STATUS + "Building authentication_ldap_sasl_client WITHOUT Kerberos") ENDIF() MYSQL_ADD_PLUGIN(authentication_ldap_sasl_client @@ -71,7 +73,7 @@ MYSQL_ADD_PLUGIN(authentication_ldap_sasl_client ${SASL_LIBRARY} # Uncomment to verify that all symbols are found. # ${LINK_FLAG_NO_UNDEFINED} - ${KERBEROS_LIBRARY_PATH} + ${KERBEROS_LIBRARIES} ${SSL_LIBRARIES} ${LIBDL} ${MY_SYS} @@ -83,7 +85,10 @@ IF(LINUX_STANDALONE AND SASL_CUSTOM_LIBRARY) TARGET_COMPILE_DEFINITIONS(authentication_ldap_sasl_client PRIVATE SASL_CUSTOM_LIBRARY) ADD_DEPENDENCIES(authentication_ldap_sasl_client ${sasl_target}) - ADD_DEPENDENCIES(authentication_ldap_sasl_client ${scram_target}) +ENDIF() + +IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY) + ADD_DEPENDENCIES(authentication_ldap_sasl_client ${kerberos_target}) ENDIF() IF(WIN32) diff --git a/libmysql/authentication_ldap/auth_ldap_sasl_client.cc b/libmysql/authentication_ldap/auth_ldap_sasl_client.cc index eb2b68f0abf6..baf721d5f0a5 100644 --- a/libmysql/authentication_ldap/auth_ldap_sasl_client.cc +++ b/libmysql/authentication_ldap/auth_ldap_sasl_client.cc @@ -20,20 +20,22 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "my_config.h" + /* In case of Kerberos authentication we need to fill user name as Kerberos user - name if it is empty. We need to fill user name inside mysql->user, client’s + name if it is empty. We need to fill user name inside mysql->user, clients uses my_strdup directly to create new string. To use MySQL alloc functions we - need to include "/mysql/service_mysql_alloc.h". Inside “service_mysql_alloc.h” + need to include "/mysql/service_mysql_alloc.h". Inside service_mysql_alloc.h there is #define which forces all dynamic plugins to use MySQL malloc function - via services. Client side plugin can’t use any services as of now. Code - check in “service_mysql_alloc.h” #ifdef MYSQL_DYNAMIC_PLUGIN #define my_strdup + via services. Client side plugin cannot use any services as of now. Code + check in service_mysql_alloc.h #ifdef MYSQL_DYNAMIC_PLUGIN #define my_strdup mysql_malloc_service->my_strdup #else extern char *my_strdup(PSI_memory_key key, const char *from, myf_t flags); #endif Client authentication plugin defines MYSQL_DYNAMIC_PLUGIN. And this forces to use always my_strdup via services. To use native direct my_strdup, we need to undefine MYSQL_DYNAMIC_PLUGIN. And again define MYSQL_DYNAMIC_PLUGIN once correct - my_strdup are declared. “service_mysql_alloc.h” should provide proper fix like + my_strdup are declared. service_mysql_alloc.h should provide proper fix like Instead of #ifdef MYSQL_DYNAMIC_PLUGIN #ifdef MYSQL_DYNAMIC_PLUGIN && ! MYSQL_CLIENT_PLUGIN */ diff --git a/libmysql/authentication_ldap/auth_ldap_sasl_client.h b/libmysql/authentication_ldap/auth_ldap_sasl_client.h index 1c9a7c545016..09cdec3ddaf1 100644 --- a/libmysql/authentication_ldap/auth_ldap_sasl_client.h +++ b/libmysql/authentication_ldap/auth_ldap_sasl_client.h @@ -23,6 +23,8 @@ #ifndef AUTH_LDAP_SASL_CLIENT_H_ #define AUTH_LDAP_SASL_CLIENT_H_ +#include "my_config.h" + #include "auth_ldap_sasl_mechanism.h" #include diff --git a/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.cc b/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.cc index f59bb824b446..223449a5d8e6 100644 --- a/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.cc +++ b/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.cc @@ -20,7 +20,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "my_config.h" + #include "auth_ldap_sasl_mechanism.h" + #include #include #include diff --git a/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.h b/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.h index 8166c5c98480..2d5c9b1aaa98 100644 --- a/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.h +++ b/libmysql/authentication_ldap/auth_ldap_sasl_mechanism.h @@ -23,6 +23,8 @@ #ifndef AUTH_LDAP_SASL_MECHANISM_H_ #define AUTH_LDAP_SASL_MECHANISM_H_ +#include "my_config.h" + #include #include #include diff --git a/mysql-test/lsan.supp b/mysql-test/lsan.supp index de201db78e54..634d77380c8b 100644 --- a/mysql-test/lsan.supp +++ b/mysql-test/lsan.supp @@ -32,3 +32,9 @@ leak:/bin/bash # OpenLDAP bug 9081 # Fixed in 2.4.49, we build with 2.4.48 leak:ldap_initialize + +# sasl_client_init will load all available plugins with _sasl_load_plugins(). +# It seems some of the SASL plugin have leaks. +# We *do* call sasl_client_done, which calls _sasl_done_with_plugins +# Both LSAN and Valgrind report leaks. +leak:sasl_client_add_plugin diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 43f78ebd269a..49901ba31a19 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2990,8 +2990,10 @@ sub environment_setup { $ENV{'UBSAN_OPTIONS'} = "print_stacktrace=1,halt_on_error=1" if $opt_sanitize; # Make sure LeakSanitizer exits if leaks are found + # We may get "Suppressions used:" reports in .result files, do not print them. $ENV{'LSAN_OPTIONS'} = "exitcode=42,suppressions=${glob_mysql_test_dir}/lsan.supp" + .",print_suppressions=0" if $opt_sanitize; $ENV{'ASAN_OPTIONS'} = "suppressions=${glob_mysql_test_dir}/asan.supp" diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index dd7680876899..995800e3dd33 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -794,6 +794,38 @@ fun:ldap_initialize } +# sasl_client_init will load all available plugins with _sasl_load_plugins(). +# It seems some of the SASL plugin have leaks. +# We *do* call sasl_client_done, which calls _sasl_done_with_plugins +# Both LSAN and Valgrind report leaks. +{ + Loading SASL plugins 1 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + fun:sasl_client_add_plugin +} + +{ + Loading SASL plugins 2 + Memcheck:Leak + match-leak-kinds: indirect + fun:malloc + ... + fun:sasl_client_add_plugin +} + +{ + Unloading SASL plugins + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:dlclose + fun:_sasl_done_with_plugins +} + { cyrus libsasl2 still reachable one Memcheck:Leak diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 2af4c5467a61..d1b54aea2a1e 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -281,6 +281,8 @@ IF(LINUX_INSTALL_RPATH_ORIGIN) SET(RPATH_OPTION " -Wl,-R,$pkglibdir") # for mysql_config SET(RPATH_OPTION_PC " -Wl,-R,\${libdir}") # for pkg_config # Do not use STRING_APPEND, it may eval the $. + SET(RPATH_OPTION "${RPATH_OPTION} -L$pkglibdir/private") + SET(RPATH_OPTION_PC "${RPATH_OPTION_PC} -L\${libdir}/private") SET(RPATH_OPTION "${RPATH_OPTION} -Wl,-rpath-link=$pkglibdir/private") SET(RPATH_OPTION_PC "${RPATH_OPTION_PC} -Wl,-rpath-link=\${libdir}/private") ENDIF()