1#*************************************************************************** 2# _ _ ____ _ 3# Project ___| | | | _ \| | 4# / __| | | | |_) | | 5# | (__| |_| | _ <| |___ 6# \___|\___/|_| \_\_____| 7# 8# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9# 10# This software is licensed as described in the file COPYING, which 11# you should have received as part of this distribution. The terms 12# are also available at https://curl.se/docs/copyright.html. 13# 14# You may opt to use, copy, modify, merge, publish, distribute and/or sell 15# copies of the Software, and permit persons to whom the Software is 16# furnished to do so, under the terms of the COPYING file. 17# 18# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19# KIND, either express or implied. 20# 21# SPDX-License-Identifier: curl 22# 23########################################################################### 24# Find the GSS Kerberos library 25# 26# Input variables: 27# 28# GSS_ROOT_DIR Set this variable to the root installation of GSS 29# 30# Result variables: 31# 32# GSS_FOUND System has the Heimdal library 33# GSS_FLAVOUR "MIT" or "Heimdal" if anything found 34# GSS_INCLUDE_DIRS The GSS include directories 35# GSS_LIBRARIES The GSS library names 36# GSS_LIBRARY_DIRS The GSS library directories 37# GSS_LDFLAGS Required linker flags 38# GSS_CFLAGS Required compiler flags 39# GSS_VERSION This is set to version advertised by pkg-config or read from manifest. 40# In case the library is found but no version info available it is set to "unknown" 41 42set(_mit_modname "mit-krb5-gssapi") 43set(_heimdal_modname "heimdal-gssapi") 44 45include(CheckIncludeFile) 46include(CheckIncludeFiles) 47include(CheckTypeSize) 48 49set(_gss_root_hints 50 "${GSS_ROOT_DIR}" 51 "$ENV{GSS_ROOT_DIR}" 52) 53 54# Try to find library using system pkg-config if user did not specify root dir 55if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}") 56 if(CURL_USE_PKGCONFIG) 57 find_package(PkgConfig QUIET) 58 pkg_search_module(_GSS ${_mit_modname} ${_heimdal_modname}) 59 list(APPEND _gss_root_hints "${_GSS_PREFIX}") 60 endif() 61 if(WIN32) 62 list(APPEND _gss_root_hints "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]") 63 endif() 64endif() 65 66if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional approach. 67 find_file(_gss_configure_script 68 NAMES 69 "krb5-config" 70 HINTS 71 ${_gss_root_hints} 72 PATH_SUFFIXES 73 "bin" 74 NO_CMAKE_PATH 75 NO_CMAKE_ENVIRONMENT_PATH 76 ) 77 78 # If not found in user-supplied directories, maybe system knows better 79 find_file(_gss_configure_script 80 NAMES 81 "krb5-config" 82 PATH_SUFFIXES 83 "bin" 84 ) 85 86 if(_gss_configure_script) 87 execute_process( 88 COMMAND ${_gss_configure_script} "--cflags" "gssapi" 89 OUTPUT_VARIABLE _GSS_CFLAGS 90 RESULT_VARIABLE _gss_configure_failed 91 OUTPUT_STRIP_TRAILING_WHITESPACE 92 ) 93 message(STATUS "FindGSS CFLAGS: ${_GSS_CFLAGS}") 94 if(NOT _gss_configure_failed) # 0 means success 95 # Should also work in an odd case when multiple directories are given 96 string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS) 97 string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}") 98 string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}") 99 100 foreach(_flag IN LISTS _GSS_CFLAGS) 101 if(_flag MATCHES "^-I.*") 102 string(REGEX REPLACE "^-I" "" _val "${_flag}") 103 list(APPEND _GSS_INCLUDE_DIRS "${_val}") 104 else() 105 list(APPEND _GSS_CFLAGS "${_flag}") 106 endif() 107 endforeach() 108 endif() 109 110 execute_process( 111 COMMAND ${_gss_configure_script} "--libs" "gssapi" 112 OUTPUT_VARIABLE _gss_lib_flags 113 RESULT_VARIABLE _gss_configure_failed 114 OUTPUT_STRIP_TRAILING_WHITESPACE 115 ) 116 message(STATUS "FindGSS LDFLAGS: ${_gss_lib_flags}") 117 118 if(NOT _gss_configure_failed) # 0 means success 119 # This script gives us libraries and link directories. Blah. We have to deal with it. 120 string(STRIP "${_gss_lib_flags}" _gss_lib_flags) 121 string(REGEX REPLACE " +-(L|l)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}") 122 string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}") 123 124 foreach(_flag IN LISTS _gss_lib_flags) 125 if(_flag MATCHES "^-l.*") 126 string(REGEX REPLACE "^-l" "" _val "${_flag}") 127 list(APPEND _GSS_LIBRARIES "${_val}") 128 elseif(_flag MATCHES "^-L.*") 129 string(REGEX REPLACE "^-L" "" _val "${_flag}") 130 list(APPEND _GSS_LIBRARY_DIRS "${_val}") 131 else() 132 list(APPEND _GSS_LDFLAGS "${_flag}") 133 endif() 134 endforeach() 135 endif() 136 137 execute_process( 138 COMMAND ${_gss_configure_script} "--version" 139 OUTPUT_VARIABLE _GSS_VERSION 140 RESULT_VARIABLE _gss_configure_failed 141 OUTPUT_STRIP_TRAILING_WHITESPACE 142 ) 143 144 # Older versions may not have the "--version" parameter. In this case we just do not care. 145 if(_gss_configure_failed) 146 set(_GSS_VERSION 0) 147 endif() 148 149 execute_process( 150 COMMAND ${_gss_configure_script} "--vendor" 151 OUTPUT_VARIABLE _gss_vendor 152 RESULT_VARIABLE _gss_configure_failed 153 OUTPUT_STRIP_TRAILING_WHITESPACE 154 ) 155 156 # Older versions may not have the "--vendor" parameter. In this case we just do not care. 157 if(_gss_configure_failed) 158 set(GSS_FLAVOUR "Heimdal") # most probably, should not really matter 159 else() 160 if(_gss_vendor MATCHES ".*H|heimdal.*") 161 set(GSS_FLAVOUR "Heimdal") 162 else() 163 set(GSS_FLAVOUR "MIT") 164 endif() 165 endif() 166 167 else() # Either there is no config script or we are on a platform that does not provide one (Windows?) 168 169 find_path(_GSS_INCLUDE_DIRS NAMES "gssapi/gssapi.h" 170 HINTS 171 ${_gss_root_hints} 172 PATH_SUFFIXES 173 "include" 174 "inc" 175 ) 176 177 if(_GSS_INCLUDE_DIRS) # jay, we have found something 178 set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}") 179 check_include_files("gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _gss_have_mit_headers) 180 181 if(_gss_have_mit_headers) 182 set(GSS_FLAVOUR "MIT") 183 else() 184 # Prevent compiling the header - just check if we can include it 185 list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__") 186 check_include_file("roken.h" _gss_have_roken_h) 187 188 check_include_file("heimdal/roken.h" _gss_have_heimdal_roken_h) 189 if(_gss_have_roken_h OR _gss_have_heimdal_roken_h) 190 set(GSS_FLAVOUR "Heimdal") 191 endif() 192 list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__") 193 endif() 194 else() 195 # I am not convinced if this is the right way but this is what autotools do at the moment 196 find_path(_GSS_INCLUDE_DIRS NAMES "gssapi.h" 197 HINTS 198 ${_gss_root_hints} 199 PATH_SUFFIXES 200 "include" 201 "inc" 202 ) 203 204 if(_GSS_INCLUDE_DIRS) 205 set(GSS_FLAVOUR "Heimdal") 206 endif() 207 endif() 208 209 # If we have headers, check if we can link libraries 210 if(GSS_FLAVOUR) 211 set(_gss_libdir_suffixes "") 212 set(_gss_libdir_hints ${_gss_root_hints}) 213 get_filename_component(_gss_calculated_potential_root "${_GSS_INCLUDE_DIRS}" DIRECTORY) 214 list(APPEND _gss_libdir_hints ${_gss_calculated_potential_root}) 215 216 if(WIN32) 217 if(CMAKE_SIZEOF_VOID_P EQUAL 8) 218 list(APPEND _gss_libdir_suffixes "lib/AMD64") 219 if(GSS_FLAVOUR STREQUAL "MIT") 220 set(_gss_libname "gssapi64") 221 else() 222 set(_gss_libname "libgssapi") 223 endif() 224 else() 225 list(APPEND _gss_libdir_suffixes "lib/i386") 226 if(GSS_FLAVOUR STREQUAL "MIT") 227 set(_gss_libname "gssapi32") 228 else() 229 set(_gss_libname "libgssapi") 230 endif() 231 endif() 232 else() 233 list(APPEND _gss_libdir_suffixes "lib;lib64") # those suffixes are not checked for HINTS 234 if(GSS_FLAVOUR STREQUAL "MIT") 235 set(_gss_libname "gssapi_krb5") 236 else() 237 set(_gss_libname "gssapi") 238 endif() 239 endif() 240 241 find_library(_GSS_LIBRARIES NAMES ${_gss_libname} 242 HINTS 243 ${_gss_libdir_hints} 244 PATH_SUFFIXES 245 ${_gss_libdir_suffixes} 246 ) 247 endif() 248 endif() 249else() 250 if(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION) # _GSS_MODULE_NAME set since CMake 3.16 251 set(GSS_FLAVOUR "MIT") 252 if(NOT _GSS_VERSION) # for old CMake versions? 253 set(_GSS_VERSION ${_GSS_${_mit_modname}_VERSION}) 254 endif() 255 else() 256 set(GSS_FLAVOUR "Heimdal") 257 if(NOT _GSS_VERSION) # for old CMake versions? 258 set(_GSS_VERSION ${_GSS_${_heimdal_modname}_VERSION}) 259 endif() 260 endif() 261 message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_GSS_INCLUDE_DIRS} (found version \"${_GSS_VERSION}\")") 262endif() 263 264set(GSS_INCLUDE_DIRS ${_GSS_INCLUDE_DIRS}) 265set(GSS_LIBRARIES ${_GSS_LIBRARIES}) 266set(GSS_LIBRARY_DIRS ${_GSS_LIBRARY_DIRS}) 267set(GSS_LDFLAGS ${_GSS_LDFLAGS}) 268set(GSS_CFLAGS ${_GSS_CFLAGS}) 269set(GSS_VERSION ${_GSS_VERSION}) 270 271if(GSS_FLAVOUR) 272 if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal") 273 if(CMAKE_SIZEOF_VOID_P EQUAL 8) 274 set(_heimdal_manifest_file "Heimdal.Application.amd64.manifest") 275 else() 276 set(_heimdal_manifest_file "Heimdal.Application.x86.manifest") 277 endif() 278 279 if(EXISTS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}") 280 file(STRINGS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}" _heimdal_version_str 281 REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$") 282 283 string(REGEX MATCH "[0-9]\\.[^\"]+" GSS_VERSION "${_heimdal_version_str}") 284 endif() 285 286 if(NOT GSS_VERSION) 287 set(GSS_VERSION "Heimdal Unknown") 288 endif() 289 elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT") 290 get_filename_component(_mit_version "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME 291 CACHE) 292 if(WIN32 AND _mit_version) 293 set(GSS_VERSION "${_mit_version}") 294 else() 295 set(GSS_VERSION "MIT Unknown") 296 endif() 297 endif() 298endif() 299 300include(FindPackageHandleStandardArgs) 301find_package_handle_standard_args(GSS 302 REQUIRED_VARS 303 GSS_FLAVOUR 304 GSS_LIBRARIES 305 VERSION_VAR 306 GSS_VERSION 307 FAIL_MESSAGE 308 "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR" 309) 310 311mark_as_advanced( 312 _GSS_CFLAGS 313 _GSS_FOUND 314 _GSS_INCLUDE_DIRS 315 _GSS_LDFLAGS 316 _GSS_LIBRARIES 317 _GSS_LIBRARY_DIRS 318 _GSS_MODULE_NAME 319 _GSS_PREFIX 320 _GSS_VERSION 321) 322