From c9e61ff0c59e80898d0999781d1e250e014eab8d Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 24 Feb 2023 15:31:36 +0100 Subject: [PATCH] [cmake] simplify krb5 detection --- cmake/FindKRB5.cmake | 591 ++++++-------------- winpr/CMakeLists.txt | 30 - winpr/libwinpr/sspi/CMakeLists.txt | 51 +- winpr/libwinpr/sspi/Kerberos/kerberos.c | 3 +- winpr/libwinpr/sspi/Kerberos/kerberos.h | 6 - winpr/libwinpr/sspi/Kerberos/krb5glue.h | 15 +- winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c | 2 - winpr/libwinpr/sspi/sspi_gss.h | 2 +- 8 files changed, 222 insertions(+), 478 deletions(-) diff --git a/cmake/FindKRB5.cmake b/cmake/FindKRB5.cmake index 5750f86a1..eef19b34e 100644 --- a/cmake/FindKRB5.cmake +++ b/cmake/FindKRB5.cmake @@ -1,465 +1,222 @@ # - Try to find the Kerberos libraries # Once done this will define # -# KRB_ROOT_DIR - Set this variable to the root installation of Kerberos -# KRB_ROOT_FLAVOUR - Set this variable to the flavour of Kerberos installation (MIT or Heimdal) +# KRB5_ROOT_CONFIG - Set this variable to the full path of krb5-config of Kerberos +# KRB5_ROOT_FLAVOUR - Set this variable to the flavour of Kerberos installation (MIT or Heimdal) # # Read-Only variables: # KRB5_FOUND - system has the Heimdal library # KRB5_FLAVOUR - "MIT" or "Heimdal" if anything found. -# KRB5_INCLUDE_DIR - the Heimdal include directory +# KRB5_INCLUDE_DIRS - the Heimdal include directory # KRB5_LIBRARIES - The libraries needed to use Kerberos -# KRB5_LINK_DIRECTORIES - Directories to add to linker search path -# KRB5_LINKER_FLAGS - Additional linker flags -# KRB5_COMPILER_FLAGS - Additional compiler flags +# KRB5_LIBRARY_DIRS - Directories to add to linker search path +# KRB5_LDFLAGS - Additional linker flags +# KRB5_CFLAGS - Additional compiler flags # KRB5_VERSION - This is set to version advertised by pkg-config or read from manifest. # In case the library is found but no version info availabe it'll be set to "unknown" -set(_MIT_MODNAME mit-krb5) -set(_HEIMDAL_MODNAME heimdal-krb5) - include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckTypeSize) -# export KRB_ROOT_FLAVOUR to use pkg-config system under UNIX -if (NOT KRB_ROOT_FLAVOUR) - set(KRB_ROOT_FLAVOUR $ENV{KRB_ROOT_FLAVOUR}) -endif() +set(_KRB5_REQUIRED_VARS + KRB5_FOUND + KRB5_VERSION + KRB5_FLAVOUR + KRB5_INCLUDE_DIRS + KRB5_LIBRARIES) -if (NOT KRB_ROOT_DIR) - set(KRB_ROOT_DIR $ENV{KRB_ROOT_DIR}) -endif() +macro(PROVIDES_KRB5) + set(PREFIX "MACRO_KRB5") -if(UNIX) - if(NOT "${KRB_ROOT_FLAVOUR} " STREQUAL " ") - string(REGEX MATCH "^[M|m]it$" MIT_FLAVOUR "${KRB_ROOT_FLAVOUR}") - if(NOT MIT_FLAVOUR) - string(REGEX MATCH "^MIT$" MIT_FLAVOUR "${KRB_ROOT_FLAVOUR}") - endif() - string(REGEX MATCH "^[H|h]eimdal$" HEIMDAL_FLAVOUR "${KRB_ROOT_FLAVOUR}") - if(NOT HEIMDAL_FLAVOUR) - string(REGEX MATCH "^HEIMDAL$" HEIMDAL_FLAVOUR "${KRB_ROOT_FLAVOUR}") - endif() - if(MIT_FLAVOUR) - set(KRB5_FLAVOUR "MIT") - elseif(HEIMDAL_FLAVOUR) - set(KRB5_FLAVOUR "Heimdal") - else() - message(SEND_ERROR "Kerberos flavour unknown (${KRB_ROOT_FLAVOUR}). Choose MIT or Heimdal.") - endif() + cmake_parse_arguments( + "${PREFIX}" + "" + "NAME" + "" + ${ARGN}) + + set(KRB5_FLAVOUR ${MACRO_KRB5_NAME}) + string(TOUPPER "${MACRO_KRB5_NAME}" MACRO_KRB5_NAME) + + # This is a list of all variables that pkg_check_modules exports. + set(VARIABLES "CFLAGS;CFLAGS_I;CFLAGS_OTHER;FOUND;INCLUDEDIR;INCLUDE_DIRS;LDFLAGS;LDFLAGS_OTHER;LIBDIR;LIBRARIES;LIBRARY_DIRS;LIBS;LIBS_L;LIBS_OTHER;LIBS_PATHS;LINK_LIBRARIS;MODULE_NAME;PREFIX;VERSION;STATIC_CFLAGS;STATIC_CFLAGS_I;STATIC_CFLAGS_OTHER;STATIC_INCLUDE_DIRS;STATIC_LDFLAGS;STATIC_LDFLAGS_OTHER;STATIC_LIBDIR;STATIC_LIBRARIES;STATIC_LIBRARY_DIRS;STATIC_LIBS;STATIC_LIBS_L;STATIC_LIBS_OTHER;STATIC_LIBS_PATHS") + foreach(VAR ${VARIABLES}) + set(KRB5_${VAR} ${KRB5_${MACRO_KRB5_NAME}_${VAR}}) + endforeach() + + # Bugfix for older installations: + # KRB5_INCLUDE_DIRS might not be set, fall back to KRB5_INCLUDEDIR + if (NOT KRB5_INCLUDE_DIRS) + set(KRB5_INCLUDE_DIRS ${KRB5_INCLUDEDIR}) endif() -endif() +endmacro() -set(_KRB5_ROOT_HINTS - "${KRB_ROOT_DIR}" -) - -# try to find library using system pkg-config if user did not specify root dir -if(UNIX) - if("${KRB_ROOT_DIR} " STREQUAL " ") - if (NOT KRB5_FLAVOUR) - message("KRB5_FLAVOUR not defined, defaulting to MIT") - set(KRB5_FLAVOUR "MIT") - endif() - - if(KRB5_FLAVOUR) - find_package(PkgConfig QUIET) - if(KRB5_FLAVOUR STREQUAL "MIT") - pkg_search_module(_KRB5_PKG ${_MIT_MODNAME}) - else() - pkg_search_module(_KRB5_PKG ${_HEIMDAL_MODNAME}) - endif() - - if("${_KRB5_PKG_PREFIX} " STREQUAL " ") - if(NOT "$ENV{PKG_CONFIG_PATH} " STREQUAL " ") - list(APPEND _KRB5_ROOT_HINTS "$ENV{PKG_CONFIG_PATH}") - else() - message(WARNING "pkg_search_module failed : try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") - endif() - else() - if("${KRB_ROOT_FLAVOUR}" STREQUAL "Heimdal") - string(FIND "${_KRB5_PKG_PREFIX}" "heimdal" PKG_HEIMDAL_PREFIX_POSITION) - if(PKG_HEIMDAL_PREFIX_POSITION STREQUAL "-1") - message(WARNING "Try to set PKG_CONFIG_PATH to \"PREFIX_OF_KERBEROS/lib/pkgconfig\"") - else() - list(APPEND _KRB5_ROOT_HINTS "${_KRB5_PKG_PREFIX}") - endif() - else() - list(APPEND _KRB5_ROOT_HINTS "${_KRB5_PKG_PREFIX}") - endif() - endif() - else() - message(WARNING "export KRB_ROOT_FLAVOUR to use pkg-config") - endif() - endif() -elseif(WIN32) - list(APPEND _KRB5_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]") -endif() - -if(NOT KRB5_FOUND) # not found by pkg-config. Let's take more traditional approach. - if(KRB5_FLAVOUR STREQUAL "MIT") - set(_KRB5_CONFIGURE_SCRIPT_SUFFIX ".mit") - elseif(KRB5_FLAVOUR STREQUAL "Heimdal") - set(_KRB5_CONFIGURE_SCRIPT_SUFFIX ".heimdal") - endif() - - find_file(_KRB5_CONFIGURE_SCRIPT - NAMES - "krb5-config${_KRB5_CONFIGURE_SCRIPT_SUFFIX}" - "krb5-config" - HINTS - ${_KRB5_ROOT_HINTS} - PATH_SUFFIXES - bin - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH +function(GET_KRB5_CONFIG KRB5_CONFIG COMMAND RESULT) + execute_process( + COMMAND ${KRB5_CONFIG} ${COMMAND} + OUTPUT_VARIABLE _KRB5_RESULT + RESULT_VARIABLE _KRB5_CONFIGURE_FAILED ) + if (_KRB5_CONFIGURE_FAILED) + message(FATAL_ERROR "Failed to detect krb5-config [${COMMAND}]") + endif() - if (${_KRB5_CONFIGURE_SCRIPT} STREQUAL "_KRB5_CONFIGURE_SCRIPT-NOTFOUND") - # if not found in user-supplied directories, maybe system knows better - find_file(_KRB5_CONFIGURE_SCRIPT - NAMES - "krb5-config${_KRB5_CONFIGURE_SCRIPT_SUFFIX}" - PATH_SUFFIXES + string(REGEX REPLACE "[\r\n]" "" _KRB5_RESULT ${_KRB5_RESULT}) + set(${RESULT} "${_KRB5_RESULT}" PARENT_SCOPE) +endfunction() + +function(string_starts_with str search RES) + string(FIND "${str}" "${search}" out) + if("${out}" EQUAL 0) + set(${RES} ON PARENT_SCOPE) + else() + set(${RES} OFF PARENT_SCOPE) + endif() +endfunction() + +function(GET_KRB5_BY_CONFIG KRB5_CONFIG) + if (NOT KRB5_CONFIG) + find_file(KRB5_CONFIG + NAMES + "krb5-config" + "krb5-config.mit" + "krb5-config.heimdal" + PATH_SUFFIXES bin - ) - endif() - - if (NOT ${_KRB5_CONFIGURE_SCRIPT} STREQUAL "_KRB5_CONFIGURE_SCRIPT-NOTFOUND") - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--vendor" - OUTPUT_VARIABLE _KRB5_VENDOR - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + REQUIRED + ) + message("autodetected krb5-config at ${KRB5_CONFIG}") else() - set(_KRB5_CONFIGURE_FAILED 1) + message("using krb5-config ${KRB5_CONFIG} provided by KRB5_ROOT_CONFIG") endif() - if(NOT _KRB5_CONFIGURE_FAILED) - string(STRIP "${_KRB5_VENDOR}" _KRB5_VENDOR) - if( (KRB5_FLAVOUR STREQUAL "Heimdal" AND NOT _KRB5_VENDOR STREQUAL "Heimdal") - OR (KRB5_FLAVOUR STREQUAL "MIT" AND NOT _KRB5_VENDOR STREQUAL "Apple MITKerberosShim") - OR (KRB5_FLAVOUR STREQUAL "MIT" AND NOT _KRB5_VENDOR STREQUAL "Massachusetts Institute of Technology")) - message(WARNING "Kerberos vendor and Kerberos flavour are not matching : _KRB5_VENDOR=${_KRB5_VENDOR} ; KRB5_FLAVOUR=${KRB5_FLAVOUR}") - message(STATUS "Try to set the path to Kerberos root folder in the system variable KRB_ROOT_DIR") - endif() + GET_KRB5_CONFIG("${KRB5_CONFIG}" "--vendor" _KRB5_VENDOR) + + if ("${_KRB5_VENDOR}" STREQUAL "Apple MITKerberosShim") + message(FATAL_ERROR "Apple MITKerberosShim is deprecated and not supported") + elseif ("${_KRB5_VENDOR}" STREQUAL "Massachusetts Institute of Technology") + set(KRB5_FLAVOUR "MIT") else() - message(SEND_ERROR "Kerberos configure script failed to get vendor") + set(KRB5_FLAVOUR "${_KRB5_VENDOR}") endif() - # NOTE: fail to link Heimdal libraries using configure script due to limitations - # during Heimdal linking process. Then, we do it "manually". - if(NOT "${_KRB5_CONFIGURE_SCRIPT} " STREQUAL " " AND KRB5_FLAVOUR AND NOT _KRB5_VENDOR STREQUAL "Heimdal") - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--cflags" - OUTPUT_VARIABLE _KRB5_CFLAGS - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED + GET_KRB5_CONFIG("${KRB5_CONFIG}" "--cflags" KRB5_CFLAGS) + GET_KRB5_CONFIG("${KRB5_CONFIG}" "--version" KRB5_VERSION_RAW) + + string(REGEX REPLACE "[ ]" ";" KRB5_VERSION_LIST "${KRB5_VERSION_RAW}") + list(LENGTH KRB5_VERSION_LIST KRB5_VERSION_LIST_LEN) + math(EXPR KRB5_VERSION_LIST_LAST "${KRB5_VERSION_LIST_LEN} - 1") + list(GET KRB5_VERSION_LIST ${KRB5_VERSION_LIST_LAST} KRB5_VERSION) + + if (KRB5_FLAVOUR STREQUAL "MIT") + if (KRB5_VERSION VERSION_LESS "1.14") + message(FATAL_ERROR "MIT kerberos ${KRB5_VERSION} < 1.14 is not supported, upgrade the library!") + endif() + endif() + + GET_KRB5_CONFIG("${KRB5_CONFIG}" "--libs" KRB5_LDFLAGS) + + string(REGEX REPLACE "[ ]" ";" KRB5_CFLAG_LIST "${KRB5_CFLAGS}") + foreach(FLAG ${KRB5_CFLAG_LIST}) + string_starts_with("${FLAG}" "-I" RES) + if (RES) + string(SUBSTRING "${FLAG}" 2 -1 FLAG) + endif() + + if (IS_DIRECTORY "${FLAG}") + list(APPEND KRB5_INCLUDEDIR ${FLAG}) + endif() + endforeach() + if (NOT KRB5_INCLUDEDIR) + find_file(KRB5_INCLUDEDIR_HEADER + NAMES krb5.h + REQUIRED ) + get_filename_component(KRB5_INCLUDEDIR "${KRB5_INCLUDEDIR_HEADER}" DIRECTORY) + endif() - if(NOT _KRB5_CONFIGURE_FAILED) # 0 means success - # should also work in an odd case when multiple directories are given - string(STRIP "${_KRB5_CFLAGS}" _KRB5_CFLAGS) - string(REGEX REPLACE " +-I" ";" _KRB5_CFLAGS "${_KRB5_CFLAGS}") - string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _KRB5_CFLAGS "${_KRB5_CFLAGS}") - - foreach(_flag ${_KRB5_CFLAGS}) - if(_flag MATCHES "^-I.*") - string(REGEX REPLACE "^-I" "" _val "${_flag}") - list(APPEND _KRB5_INCLUDE_DIR "${_val}") - else() - list(APPEND _KRB5_COMPILER_FLAGS "${_flag}") - endif() - endforeach() + string(REGEX REPLACE "[ ]" ";" KRB5_LDFLAG_LIST "${KRB5_LDFLAGS}") + foreach(FLAG ${KRB5_LDFLAG_LIST}) + string_starts_with("${FLAG}" "-L" RES) + if (RES) + string(SUBSTRING "${FLAG}" 2 -1 SUBFLAG) + list(APPEND KRB5_LIBRARY_DIRS ${SUBFLAG}) endif() - - if(_KRB5_VENDOR STREQUAL "Apple MITKerberosShim") - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--libs" - OUTPUT_VARIABLE _KRB5_LIB_FLAGS - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) - elseif(_KRB5_VENDOR STREQUAL "Massachusetts Institute of Technology") - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--libs" - OUTPUT_VARIABLE _KRB5_LIB_FLAGS - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) - elseif(_KRB5_VENDOR STREQUAL "Heimdal") - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--deps --libs" - OUTPUT_VARIABLE _KRB5_LIB_FLAGS - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) - else() - message(SEND_ERROR "Unknown vendor '${_KRB5_VENDOR}'") + string_starts_with("${FLAG}" "-l" RES) + if (RES) + string(SUBSTRING "${FLAG}" 2 -1 SUBFLAG) + list(APPEND KRB5_LIBRARIES ${SUBFLAG}) endif() + endforeach() - if(NOT _KRB5_CONFIGURE_FAILED) # 0 means success - # this script gives us libraries and link directories. We have to deal with it. - string(STRIP "${_KRB5_LIB_FLAGS}" _KRB5_LIB_FLAGS) - string(REGEX REPLACE " +-(L|l)" ";-\\1" _KRB5_LIB_FLAGS "${_KRB5_LIB_FLAGS}") - string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _KRB5_LIB_FLAGS "${_KRB5_LIB_FLAGS}") + set(KRB5_FOUND ON PARENT_SCOPE) + set(KRB5_VERSION ${KRB5_VERSION} PARENT_SCOPE) + set(KRB5_FLAVOUR ${KRB5_FLAVOUR} PARENT_SCOPE) + set(KRB5_CFLAGS ${KRB5_CFLAGS} PARENT_SCOPE) + set(KRB5_LDFLAGS ${KRB5_LDFLAGS} PARENT_SCOPE) + set(KRB5_INCLUDEDIR ${KRB5_INCLUDEDIR} PARENT_SCOPE) + set(KRB5_INCLUDE_DIRS ${KRB5_INCLUDEDIR} PARENT_SCOPE) + set(KRB5_LIBRARIES ${KRB5_LIBRARIES} PARENT_SCOPE) + set(KRB5_LIBRARY_DIRS ${KRB5_LIBRARY_DIRS} PARENT_SCOPE) +endfunction() - foreach(_flag ${_KRB5_LIB_FLAGS}) - if(_flag MATCHES "^-l.*") - string(REGEX REPLACE "^-l" "" _val "${_flag}") - list(APPEND _KRB5_LIBRARIES "${_val}") - elseif(_flag MATCHES "^-L.*") - string(REGEX REPLACE "^-L" "" _val "${_flag}") - list(APPEND _KRB5_LINK_DIRECTORIES "${_val}") - else() - list(APPEND _KRB5_LINKER_FLAGS "${_flag}") - endif() - endforeach() +# try to find kerberos to compile against. +# +# * First search with pkg-config (prefer MIT over Heimdal) +# * Then try to find krb5-config (generic, krb5-config.mit and last krb5-config.heimdal) +include(FindPkgConfig) +find_package(PkgConfig REQUIRED) - endif() - - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--version" - OUTPUT_VARIABLE _KRB5_VERSION - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) - - # older versions may not have the "--version" parameter. In this case we just don't care. - if(_KRB5_CONFIGURE_FAILED) - set(_KRB5_VERSION 0) - endif() - - else() # either there is no config script or we are on platform that doesn't provide one (Windows?) - if(_KRB5_VENDOR STREQUAL "Massachusetts Institute of Technology") - find_path(_KRB5_INCLUDE_DIR - NAMES - "gssapi/gssapi_generic.h" - HINTS - ${_KRB5_ROOT_HINTS} - PATH_SUFFIXES - include - inc - ) - - if(_KRB5_INCLUDE_DIR) # we've found something - set(CMAKE_REQUIRED_INCLUDES "${_KRB5_INCLUDE_DIR}") - check_include_files( "krb5/krb5.h" _KRB5_HAVE_MIT_HEADERS) - if(_KRB5_HAVE_MIT_HEADERS) - set(KRB5_FLAVOUR "MIT") - else() - message(SEND_ERROR "Try to set the Kerberos flavour (KRB_ROOT_FLAVOUR)") - endif() - elseif("$ENV{PKG_CONFIG_PATH} " STREQUAL " ") - message(WARNING "Try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") - endif() - elseif(_KRB5_VENDOR STREQUAL "Heimdal") - find_path(_KRB5_INCLUDE_DIR - NAMES - "gssapi/gssapi_spnego.h" - HINTS - ${_KRB5_ROOT_HINTS} - PATHS - /usr/heimdal - /usr/local/heimdal - PATH_SUFFIXES - include - inc - ) - - if(_KRB5_INCLUDE_DIR) # we've found something - set(CMAKE_REQUIRED_INCLUDES "${_KRB5_INCLUDE_DIR}") - # prevent compiling the header - just check if we can include it - set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__") - check_include_file( "roken.h" _KRB5_HAVE_ROKEN_H) - check_include_file( "heimdal/roken.h" _KRB5_HAVE_HEIMDAL_ROKEN_H) - if(_KRB5_HAVE_ROKEN_H OR _KRB5_HAVE_HEIMDAL_ROKEN_H) - set(KRB5_FLAVOUR "Heimdal") - endif() - set(CMAKE_REQUIRED_DEFINITIONS "") - elseif("$ENV{PKG_CONFIG_PATH} " STREQUAL " ") - message(WARNING "Try to set PKG_CONFIG_PATH to PREFIX_OF_KERBEROS/lib/pkgconfig") - endif() - else() - message(SEND_ERROR "Kerberos vendor unknown (${_KRB5_VENDOR})") - endif() - - # if we have headers, check if we can link libraries - if(KRB5_FLAVOUR) - set(_KRB5_LIBDIR_SUFFIXES "") - set(_KRB5_LIBDIR_HINTS ${_KRB5_ROOT_HINTS}) - get_filename_component(_KRB5_CALCULATED_POTENTIAL_ROOT "${_KRB5_INCLUDE_DIR}" PATH) - list(APPEND _KRB5_LIBDIR_HINTS ${_KRB5_CALCULATED_POTENTIAL_ROOT}) - - if(WIN32) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - list(APPEND _KRB5_LIBDIR_SUFFIXES "lib/AMD64") - if(KRB5_FLAVOUR STREQUAL "MIT") - set(_KRB5_LIBNAME "krb5_64") - else() - set(_KRB5_LIBNAME "libkrb5") - endif() - else() - list(APPEND _KRB5_LIBDIR_SUFFIXES "lib/i386") - if(KRB5_FLAVOUR STREQUAL "MIT") - set(_KRB5_LIBNAME "krb5_32") - else() - set(_KRB5_LIBNAME "libkrb5") - endif() - endif() - else() - list(APPEND _KRB5_LIBDIR_SUFFIXES "lib;lib64;x86_64-linux-gnu") # those suffixes are not checked for HINTS - if(KRB5_FLAVOUR STREQUAL "MIT") - set(_KRB5_LIBNAME "krb5") - set(_COMERR_LIBNAME "com_err") - set(_KRB5SUPPORT_LIBNAME "krb5support") - else() - set(_KRB5_LIBNAME "krb5") - set(_ROKEN_LIBNAME "roken") - endif() - endif() - - if(KRB5_FLAVOUR STREQUAL "MIT") - find_library(_KRB5_LIBRARY - NAMES - ${_KRB5_LIBNAME} - HINTS - ${_KRB5_LIBDIR_HINTS} - PATH_SUFFIXES - ${_KRB5_LIBDIR_SUFFIXES} - ) - find_library(_COMERR_LIBRARY - NAMES - ${_COMERR_LIBNAME} - HINTS - ${_KRB5_LIBDIR_HINTS} - PATH_SUFFIXES - ${_KRB5_LIBDIR_SUFFIXES} - ) - find_library(_KRB5SUPPORT_LIBRARY - NAMES - ${_KRB5SUPPORT_LIBNAME} - HINTS - ${_KRB5_LIBDIR_HINTS} - PATH_SUFFIXES - ${_KRB5_LIBDIR_SUFFIXES} - ) - list(APPEND _KRB5_LIBRARIES ${_KRB5_LIBRARY} ${_KRB5SUPPORT_LIBRARY} ${_COMERR_LIBRARY}) - endif() - - if(KRB5_FLAVOUR STREQUAL "Heimdal") - find_library(_KRB5_LIBRARY - NAMES - ${_KRB5_LIBNAME} - HINTS - ${_KRB5_LIBDIR_HINTS} - PATH_SUFFIXES - ${_KRB5_LIBDIR_SUFFIXES} - ) - find_library(_ROKEN_LIBRARY - NAMES - ${_ROKEN_LIBNAME} - HINTS - ${_KRB5_LIBDIR_HINTS} - PATH_SUFFIXES - ${_KRB5_LIBDIR_SUFFIXES} - ) - list(APPEND _KRB5_LIBRARIES ${_KRB5_LIBRARY}) - endif() - endif() - - execute_process( - COMMAND ${_KRB5_CONFIGURE_SCRIPT} "--version" - OUTPUT_VARIABLE _KRB5_VERSION - RESULT_VARIABLE _KRB5_CONFIGURE_FAILED - ) - - # older versions may not have the "--version" parameter. In this case we just don't care. - if(_KRB5_CONFIGURE_FAILED) - set(_KRB5_VERSION 0) - endif() +if (KRB5_ROOT_CONFIG) +elseif (KRB5_ROOT_FLAVOUR) + if (KRB5_ROOT_FLAVOUR STREQUAL "Heimdal") + pkg_check_modules(KRB5_HEIMDAL heimdal-krb5) + elseif (KRB5_ROOT_FLAVOUR STREQUAL "MIT") + pkg_check_modules(KRB5_HEIMDAL mit-krb5) + else() + message(FATAL_ERROR "Invalid KRB5_ROOT_FLAVOUR=${KRB5_ROOT_FLAVOUR}, only 'MIT' or 'Heimdal' are supported") endif() else() - if(_KRB5_PKG_${_MIT_MODNAME}_VERSION) - set(KRB5_FLAVOUR "MIT") - set(_KRB5_VERSION _KRB5_PKG_${_MIT_MODNAME}_VERSION) - else() - set(KRB5_FLAVOUR "Heimdal") - set(_KRB5_VERSION _KRB5_PKG_${_HEIMDAL_MODNAME}_VERSION) - endif() + pkg_check_modules(KRB5_MIT mit-krb5) + pkg_check_modules(KRB5_HEIMDAL heimdal-krb5) endif() -set(KRB5_INCLUDE_DIR ${_KRB5_INCLUDE_DIR}) -set(KRB5_LIBRARIES ${_KRB5_LIBRARIES}) -set(KRB5_LINK_DIRECTORIES ${_KRB5_LINK_DIRECTORIES}) -set(KRB5_LINKER_FLAGS ${_KRB5_LINKER_FLAGS}) -set(KRB5_COMPILER_FLAGS ${_KRB5_COMPILER_FLAGS}) -set(KRB5_VERSION ${_KRB5_VERSION}) - -if(KRB5_FLAVOUR) - if(NOT KRB5_VERSION AND KRB5_FLAVOUR STREQUAL "Heimdal") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest") - else() - set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest") - endif() - if(EXISTS "${KRB5_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}") - file(STRINGS "${KRB5_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str - REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$") - - string(REGEX MATCH "[0-9]\\.[^\"]+" - KRB5_VERSION "${heimdal_version_str}") - endif() - if(NOT KRB5_VERSION) - set(KRB5_VERSION "Heimdal Unknown") - endif() - elseif(NOT KRB5_VERSION AND KRB5_FLAVOUR STREQUAL "MIT") - get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE) - if(WIN32 AND _MIT_VERSION) - set(KRB5_VERSION "${_MIT_VERSION}") - else() - set(KRB5_VERSION "MIT Unknown") - endif() +if (KRB5_MIT_FOUND) + PROVIDES_KRB5(NAME "MIT") + if (KRB5_VERSION VERSION_LESS "1.14") + message(FATAL_ERROR "MIT kerberos < 1.14 is not supported, upgrade the library!") endif() +elseif(KRB5_HEIMDAL_FOUND) + PROVIDES_KRB5(NAME "Heimdal") +elseif(KRB5_ANY_FOUND) + GET_KRB5_VENDOR(ANY_VENDOR) + PROVIDES_KRB5(NAME "${ANY_VENDOR}") +else() + GET_KRB5_BY_CONFIG(${KRB5_ROOT_CONFIG}) endif() +#message("using KRB5_FOUND ${KRB5_FOUND} ") +#message("using KRB5_VERSION ${KRB5_VERSION} ") +#message("using KRB5_FLAVOUR ${KRB5_FLAVOUR} ") +#message("using KRB5_CFLAGS ${KRB5_CFLAGS} ") +#message("using KRB5_LDFLAGS ${KRB5_LDFLAGS} ") +#message("using KRB5_INCLUDEDIR ${KRB5_INCLUDEDIR} ") +#message("using KRB5_INCLUDE_DIRS ${KRB5_INCLUDEDIR} ") +#message("using KRB5_LIBRARIES ${KRB5_LIBRARIES} ") + include(FindPackageHandleStandardArgs) -set(_KRB5_REQUIRED_VARS KRB5_LIBRARIES KRB5_FLAVOUR) - find_package_handle_standard_args(KRB5 - REQUIRED_VARS - ${_KRB5_REQUIRED_VARS} - VERSION_VAR - KRB5_VERSION - FAIL_MESSAGE - "Could NOT find Kerberos, try to set the path to Kerberos root folder in the system variable KRB_ROOT_DIR" + REQUIRED_VARS + ${_KRB5_REQUIRED_VARS} + VERSION_VAR + KRB5_VERSION + FAIL_MESSAGE + "Could NOT find Kerberos, try to set the path to Kerberos root folder in the system variable KRB_ROOT_DIR" ) -if(KRB5_FLAVOUR STREQUAL "MIT") - string(STRIP "${KRB5_VERSION}" KRB5_VERSION) - string(SUBSTRING ${KRB5_VERSION} 19 -1 KRB5_RELEASE_NUMBER) - string(REGEX MATCH "([0-9]+)\\." KRB5_VERSION_MAJOR ${KRB5_RELEASE_NUMBER}) - string(REGEX REPLACE "\\." "" KRB5_VERSION_MAJOR "${KRB5_VERSION_MAJOR}") - string(REGEX MATCH "\\.([0-9]+)$" KRB5_VERSION_MINOR ${KRB5_RELEASE_NUMBER}) - if(NOT KRB5_VERSION_MINOR) - string(REGEX MATCH "\\.([0-9]+)[-\\.]" KRB5_VERSION_MINOR ${KRB5_RELEASE_NUMBER}) - string(REGEX REPLACE "\\." "" KRB5_VERSION_MINOR "${KRB5_VERSION_MINOR}") - string(REGEX REPLACE "\\." "" KRB5_VERSION_MINOR "${KRB5_VERSION_MINOR}") - string(REGEX REPLACE "-" "" KRB5_VERSION_MINOR "${KRB5_VERSION_MINOR}") - string(REGEX MATCH "\\.([0-9]+)$" KRB5_VERSION_PATCH "${KRB5_RELEASE_NUMBER}") - string(REGEX REPLACE "\\." "" KRB5_VERSION_PATCH "${KRB5_VERSION_PATCH}") - if(NOT KRB5_VERSION_PATCH) - set(KRB5_VERSION_PATCH "0") - endif() - else() - string(REGEX REPLACE "\\." "" KRB5_VERSION_MINOR "${KRB5_VERSION_MINOR}") - set(KRB5_VERSION_PATCH "0") - endif() - if(KRB5_VERSION_MAJOR AND KRB5_VERSION_MINOR) - string(COMPARE GREATER ${KRB5_VERSION_MAJOR} 0 KRB5_VERSION_1) - string(COMPARE GREATER ${KRB5_VERSION_MINOR} 12 KRB5_VERSION_1_13) - else() - message(SEND_ERROR "Failed to retrieved Kerberos version number") - endif() - message(STATUS "Located Kerberos ${KRB5_VERSION_MAJOR}.${KRB5_VERSION_MINOR}.${KRB5_VERSION_PATCH}") -endif() - -mark_as_advanced(KRB5_INCLUDE_DIR KRB5_LIBRARIES) +mark_as_advanced(${_KRB5_REQUIRED_VARS}) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index da26fc2ce..5de3f5277 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -67,36 +67,6 @@ option(WITH_DEBUG_MUTEX "Print mutex debug messages" ${DEFAULT_DEBUG_OPTION}) option(WITH_INTERNAL_MD4 "Use compiled in md4 hash functions instead of OpenSSL/MBedTLS" OFF) option(WITH_INTERNAL_MD5 "Use compiled in md5 hash functions instead of OpenSSL/MBedTLS" OFF) -if (NOT WIN32 AND NOT ANDROID AND NOT IOS) - option(WITH_KRB5 "Compile support for kerberos authentication. (EXPERIMENTAL)" OFF) - if (WITH_KRB5) - find_package(KRB5 REQUIRED) - endif() - - if ( (WITH_KRB5) AND (NOT KRB5_FOUND)) - message(WARNING "-DWITH_KRB5=ON is set, but no kerberos implementation was found, disabling") - elseif(WITH_KRB5) - if(KRB5_FLAVOUR STREQUAL "MIT") - add_definitions("-DWITH_KRB5 -DWITH_KRB5_MIT") - if(KRB5_VERSION_1_13) - add_definitions("-DWINPR_HAVE_AT_LEAST_KRB_V1_13") - endif() - include_directories(${_KRB5_INCLUDE_DIR}) - elseif(KRB5_FLAVOUR STREQUAL "Heimdal") - add_definitions("-DWITH_KRB5 -DWITH_KRB5_HEIMDAL") - include_directories(${_KRB5_INCLUDE_DIR}) - else() - message(WARNING "Kerberos version not detected") - endif() - endif() - - include(CMakeDependentOption) - CMAKE_DEPENDENT_OPTION(WITH_KRB5_NO_NTLM_FALLBACK "Do not fall back to NTLM if no kerberos ticket available" OFF "WITH_KRB5" OFF) - if (WITH_KRB5_NO_NTLM_FALLBACK) - add_definitions("-DWITH_KRB5_NO_NTLM_FALLBACK") - endif() -endif() - # This option MUST be off to avoid symbol conflicts when loading an external SSPI module library option(SSPI_DLL "Define and export SSPI API symbols for usage as a Windows SSPI DLL replacement" OFF) diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index b656ff98f..36b45d087 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -32,13 +32,6 @@ set(${MODULE_PREFIX}_KERBEROS_SRCS Kerberos/kerberos.c Kerberos/kerberos.h) -if(KRB5_FOUND) - list(APPEND ${MODULE_PREFIX}_KERBEROS_SRCS - Kerberos/krb5glue_mit.c - Kerberos/krb5glue_heimdal.c - Kerberos/krb5glue.h) -endif() - set(${MODULE_PREFIX}_NEGOTIATE_SRCS Negotiate/negotiate.c Negotiate/negotiate.h) @@ -62,6 +55,45 @@ set(${MODULE_PREFIX}_SRCS sspi.c sspi.h) +set(KRB5_DEFAULT OFF) +if (NOT WIN32 AND NOT ANDROID AND NOT IOS AND NOT APPLE) + set(KRB5_DEFAULT ON) +endif() + +option(WITH_KRB5 "Compile support for kerberos authentication." ${KRB5_DEFAULT}) +if (WITH_KRB5) + find_package(KRB5 REQUIRED) + + list(APPEND ${MODULE_PREFIX}_KERBEROS_SRCS + Kerberos/krb5glue_mit.c + Kerberos/krb5glue_heimdal.c + Kerberos/krb5glue.h) + + winpr_include_directory_add(${KRB5_INCLUDEDIR}) + winpr_include_directory_add(${KRB5_INCLUDE_DIRS}) + winpr_library_add_private(${KRB5_LIBRARIES}) + winpr_library_add_private(${KRB5_LIBRARY}) + winpr_library_add_compile_options(${KRB5_CFLAGS}) + winpr_library_add_link_options(${KRB5_LDFLAGS}) + winpr_library_add_link_directory(${KRB5_LIBRARY_DIRS}) + + winpr_definition_add("-DWITH_KRB5") + + if(KRB5_FLAVOUR STREQUAL "MIT") + winpr_definition_add("-DWITH_KRB5_MIT") + elseif(KRB5_FLAVOUR STREQUAL "Heimdal") + winpr_definition_add("-DWITH_KRB5_HEIMDAL") + else() + message(WARNING "Kerberos version not detected") + endif() + + include(CMakeDependentOption) + CMAKE_DEPENDENT_OPTION(WITH_KRB5_NO_NTLM_FALLBACK "Do not fall back to NTLM if no kerberos ticket available" OFF "WITH_KRB5" OFF) + if (WITH_KRB5_NO_NTLM_FALLBACK) + add_definitions("-DWITH_KRB5_NO_NTLM_FALLBACK") + endif() +endif() + winpr_module_add(${${MODULE_PREFIX}_CREDSSP_SRCS} ${${MODULE_PREFIX}_NTLM_SRCS} ${${MODULE_PREFIX}_KERBEROS_SRCS} @@ -79,11 +111,6 @@ if(MBEDTLS_FOUND) winpr_library_add_private(${MBEDTLS_LIBRARIES}) endif() -if(KRB5_FOUND) - winpr_include_directory_add(${KRB5_INCLUDE_DIR}) - winpr_library_add_private(${KRB5_LIBRARIES}) -endif() - if(WIN32) winpr_library_add_public(ws2_32) endif() diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c index bf9a63866..3ff2feeec 100644 --- a/winpr/libwinpr/sspi/Kerberos/kerberos.c +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c @@ -41,13 +41,14 @@ #include #include "kerberos.h" -#include "krb5glue.h" #ifdef WITH_KRB5_MIT +#include "krb5glue.h" #include #endif #ifdef WITH_KRB5_HEIMDAL +#include "krb5glue.h" #include #endif diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.h b/winpr/libwinpr/sspi/Kerberos/kerberos.h index 5c12ad6c2..ced97a4cf 100644 --- a/winpr/libwinpr/sspi/Kerberos/kerberos.h +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.h @@ -27,12 +27,6 @@ #include "../sspi.h" #include "../../log.h" -#ifdef WITH_KRB5_MIT -#include -#elif defined(WITH_KRB5_HEIMDAL) -#include -#endif - typedef struct s_KRB_CONTEXT KRB_CONTEXT; extern const SecPkgInfoA KERBEROS_SecPkgInfoA; diff --git a/winpr/libwinpr/sspi/Kerberos/krb5glue.h b/winpr/libwinpr/sspi/Kerberos/krb5glue.h index d325f16f0..287468877 100644 --- a/winpr/libwinpr/sspi/Kerberos/krb5glue.h +++ b/winpr/libwinpr/sspi/Kerberos/krb5glue.h @@ -20,13 +20,12 @@ #ifndef WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H #define WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H -#ifdef WITH_KRB5 - #include #include -#ifdef WITH_KRB5_MIT -#include +#include + +#if defined(WITH_KRB5_MIT) typedef krb5_key krb5glue_key; typedef krb5_authenticator* krb5glue_authenticator; @@ -54,8 +53,7 @@ krb5_prompt_type krb5glue_get_prompt_type(krb5_context ctx, krb5_prompt prompts[ #define krb5glue_creds_getkey(creds) creds.keyblock -#else -#include +#elif defined(WITH_KRB5_HEIMDAL) typedef krb5_crypto krb5glue_key; typedef krb5_authenticator krb5glue_authenticator; @@ -82,7 +80,8 @@ krb5_error_code krb5glue_verify_checksum_iov(krb5_context ctx, krb5glue_key key, #define krb5glue_get_prompt_type(ctx, prompts, index) prompts[index].type #define krb5glue_creds_getkey(creds) creds.session - +#else +#error "Missing implementation for KRB5 provider" #endif struct krb5glue_keyset @@ -102,6 +101,4 @@ krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, krb5_prompter_fct prompter, char* password, SEC_WINPR_KERBEROS_SETTINGS* krb_settings); -#endif /* WITH_KRB5 */ - #endif /* WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c b/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c index 6d166a13d..9c8941f50 100644 --- a/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c +++ b/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c @@ -198,9 +198,7 @@ krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, cleanup: krb5_init_creds_free(ctx, creds_ctx); -#ifdef WINPR_HAVE_AT_LEAST_KRB_V1_13 krb5_get_init_creds_opt_free(ctx, gic_opt); -#endif winpr_DeleteFile(tmp_profile_path); free(tmp_profile_path); diff --git a/winpr/libwinpr/sspi/sspi_gss.h b/winpr/libwinpr/sspi/sspi_gss.h index 2dd896937..205f86afb 100644 --- a/winpr/libwinpr/sspi/sspi_gss.h +++ b/winpr/libwinpr/sspi/sspi_gss.h @@ -26,7 +26,7 @@ #include #ifdef WITH_KRB5_MIT -#include +#include typedef krb5_data sspi_gss_data; #elif defined(WITH_KRB5_HEIMDAL) #include