FindGSS.cmake 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. (also supported as environment)
  29. #
  30. # Result variables:
  31. #
  32. # - `GSS_FOUND`: System has the Heimdal library.
  33. # - `GSS_FLAVOUR`: "GNU", "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_PC_REQUIRES`: The GSS pkg-config packages.
  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. set(_gnu_modname "gss")
  42. set(_mit_modname "mit-krb5-gssapi")
  43. set(_heimdal_modname "heimdal-gssapi")
  44. include(CheckIncludeFile)
  45. include(CheckIncludeFiles)
  46. include(CheckTypeSize)
  47. set(_gss_root_hints
  48. "${GSS_ROOT_DIR}"
  49. "$ENV{GSS_ROOT_DIR}"
  50. )
  51. # Try to find library using system pkg-config if user did not specify root dir
  52. if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
  53. if(CURL_USE_PKGCONFIG)
  54. find_package(PkgConfig QUIET)
  55. pkg_search_module(_GSS ${_gnu_modname} ${_mit_modname} ${_heimdal_modname})
  56. list(APPEND _gss_root_hints "${_GSS_PREFIX}")
  57. endif()
  58. if(WIN32)
  59. list(APPEND _gss_root_hints "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
  60. endif()
  61. endif()
  62. if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional approach.
  63. find_file(_gss_configure_script
  64. NAMES
  65. "krb5-config"
  66. HINTS
  67. ${_gss_root_hints}
  68. PATH_SUFFIXES
  69. "bin"
  70. NO_CMAKE_PATH
  71. NO_CMAKE_ENVIRONMENT_PATH
  72. )
  73. # If not found in user-supplied directories, maybe system knows better
  74. find_file(_gss_configure_script
  75. NAMES
  76. "krb5-config"
  77. PATH_SUFFIXES
  78. "bin"
  79. )
  80. if(_gss_configure_script)
  81. execute_process(
  82. COMMAND ${_gss_configure_script} "--cflags" "gssapi"
  83. OUTPUT_VARIABLE _GSS_CFLAGS
  84. RESULT_VARIABLE _gss_configure_failed
  85. OUTPUT_STRIP_TRAILING_WHITESPACE
  86. )
  87. message(STATUS "FindGSS krb5-config --cflags: ${_GSS_CFLAGS}")
  88. if(NOT _gss_configure_failed) # 0 means success
  89. # Should also work in an odd case when multiple directories are given
  90. string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
  91. string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
  92. string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
  93. foreach(_flag IN LISTS _GSS_CFLAGS)
  94. if(_flag MATCHES "^-I.*")
  95. string(REGEX REPLACE "^-I" "" _val "${_flag}")
  96. list(APPEND _GSS_INCLUDE_DIRS "${_val}")
  97. else()
  98. list(APPEND _GSS_CFLAGS "${_flag}")
  99. endif()
  100. endforeach()
  101. endif()
  102. execute_process(
  103. COMMAND ${_gss_configure_script} "--libs" "gssapi"
  104. OUTPUT_VARIABLE _gss_lib_flags
  105. RESULT_VARIABLE _gss_configure_failed
  106. OUTPUT_STRIP_TRAILING_WHITESPACE
  107. )
  108. message(STATUS "FindGSS krb5-config --libs: ${_gss_lib_flags}")
  109. if(NOT _gss_configure_failed) # 0 means success
  110. # This script gives us libraries and link directories. Blah. We have to deal with it.
  111. string(STRIP "${_gss_lib_flags}" _gss_lib_flags)
  112. string(REGEX REPLACE " +-(L|l)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
  113. string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
  114. foreach(_flag IN LISTS _gss_lib_flags)
  115. if(_flag MATCHES "^-l.*")
  116. string(REGEX REPLACE "^-l" "" _val "${_flag}")
  117. list(APPEND _GSS_LIBRARIES "${_val}")
  118. elseif(_flag MATCHES "^-L.*")
  119. string(REGEX REPLACE "^-L" "" _val "${_flag}")
  120. list(APPEND _GSS_LIBRARY_DIRS "${_val}")
  121. endif()
  122. endforeach()
  123. endif()
  124. execute_process(
  125. COMMAND ${_gss_configure_script} "--version"
  126. OUTPUT_VARIABLE _GSS_VERSION
  127. RESULT_VARIABLE _gss_configure_failed
  128. OUTPUT_STRIP_TRAILING_WHITESPACE
  129. )
  130. # Older versions may not have the "--version" parameter. In this case we just do not care.
  131. if(_gss_configure_failed)
  132. set(_GSS_VERSION 0)
  133. endif()
  134. execute_process(
  135. COMMAND ${_gss_configure_script} "--vendor"
  136. OUTPUT_VARIABLE _gss_vendor
  137. RESULT_VARIABLE _gss_configure_failed
  138. OUTPUT_STRIP_TRAILING_WHITESPACE
  139. )
  140. # Older versions may not have the "--vendor" parameter. In this case we just do not care.
  141. if(_gss_configure_failed)
  142. set(GSS_FLAVOUR "Heimdal") # most probably, should not really matter
  143. else()
  144. if(_gss_vendor MATCHES ".*H|heimdal.*")
  145. set(GSS_FLAVOUR "Heimdal")
  146. else()
  147. set(GSS_FLAVOUR "MIT")
  148. endif()
  149. endif()
  150. else() # Either there is no config script or we are on a platform that does not provide one (Windows?)
  151. find_path(_GSS_INCLUDE_DIRS NAMES "gssapi/gssapi.h"
  152. HINTS
  153. ${_gss_root_hints}
  154. PATH_SUFFIXES
  155. "include"
  156. "inc"
  157. )
  158. if(_GSS_INCLUDE_DIRS) # jay, we have found something
  159. cmake_push_check_state()
  160. list(APPEND CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
  161. check_include_files("gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _gss_have_mit_headers)
  162. if(_gss_have_mit_headers)
  163. set(GSS_FLAVOUR "MIT")
  164. else()
  165. # Prevent compiling the header - just check if we can include it
  166. list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__")
  167. check_include_file("roken.h" _gss_have_roken_h)
  168. check_include_file("heimdal/roken.h" _gss_have_heimdal_roken_h)
  169. if(_gss_have_roken_h OR _gss_have_heimdal_roken_h)
  170. set(GSS_FLAVOUR "Heimdal")
  171. endif()
  172. endif()
  173. cmake_pop_check_state()
  174. else()
  175. # I am not convinced if this is the right way but this is what autotools do at the moment
  176. find_path(_GSS_INCLUDE_DIRS NAMES "gssapi.h"
  177. HINTS
  178. ${_gss_root_hints}
  179. PATH_SUFFIXES
  180. "include"
  181. "inc"
  182. )
  183. if(_GSS_INCLUDE_DIRS)
  184. set(GSS_FLAVOUR "Heimdal")
  185. else()
  186. find_path(_GSS_INCLUDE_DIRS NAMES "gss.h"
  187. HINTS
  188. ${_gss_root_hints}
  189. PATH_SUFFIXES
  190. "include"
  191. )
  192. if(_GSS_INCLUDE_DIRS)
  193. set(GSS_FLAVOUR "GNU")
  194. set(GSS_PC_REQUIRES "gss")
  195. endif()
  196. endif()
  197. endif()
  198. # If we have headers, check if we can link libraries
  199. if(GSS_FLAVOUR)
  200. set(_gss_libdir_suffixes "")
  201. set(_gss_libdir_hints ${_gss_root_hints})
  202. get_filename_component(_gss_calculated_potential_root "${_GSS_INCLUDE_DIRS}" DIRECTORY)
  203. list(APPEND _gss_libdir_hints ${_gss_calculated_potential_root})
  204. if(WIN32)
  205. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  206. list(APPEND _gss_libdir_suffixes "lib/AMD64")
  207. if(GSS_FLAVOUR STREQUAL "GNU")
  208. set(_gss_libname "gss")
  209. elseif(GSS_FLAVOUR STREQUAL "MIT")
  210. set(_gss_libname "gssapi64")
  211. else()
  212. set(_gss_libname "libgssapi")
  213. endif()
  214. else()
  215. list(APPEND _gss_libdir_suffixes "lib/i386")
  216. if(GSS_FLAVOUR STREQUAL "GNU")
  217. set(_gss_libname "gss")
  218. elseif(GSS_FLAVOUR STREQUAL "MIT")
  219. set(_gss_libname "gssapi32")
  220. else()
  221. set(_gss_libname "libgssapi")
  222. endif()
  223. endif()
  224. else()
  225. list(APPEND _gss_libdir_suffixes "lib;lib64") # those suffixes are not checked for HINTS
  226. if(GSS_FLAVOUR STREQUAL "GNU")
  227. set(_gss_libname "gss")
  228. elseif(GSS_FLAVOUR STREQUAL "MIT")
  229. set(_gss_libname "gssapi_krb5")
  230. else()
  231. set(_gss_libname "gssapi")
  232. endif()
  233. endif()
  234. find_library(_GSS_LIBRARIES NAMES ${_gss_libname}
  235. HINTS
  236. ${_gss_libdir_hints}
  237. PATH_SUFFIXES
  238. ${_gss_libdir_suffixes}
  239. )
  240. endif()
  241. endif()
  242. else()
  243. # _GSS_MODULE_NAME set since CMake 3.16
  244. if(_GSS_MODULE_NAME STREQUAL _gnu_modname OR _GSS_${_gnu_modname}_VERSION)
  245. set(GSS_FLAVOUR "GNU")
  246. set(GSS_PC_REQUIRES "gss")
  247. if(NOT _GSS_VERSION) # for old CMake versions?
  248. set(_GSS_VERSION ${_GSS_${_gnu_modname}_VERSION})
  249. endif()
  250. elseif(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION)
  251. set(GSS_FLAVOUR "MIT")
  252. set(GSS_PC_REQUIRES "mit-krb5-gssapi")
  253. if(NOT _GSS_VERSION) # for old CMake versions?
  254. set(_GSS_VERSION ${_GSS_${_mit_modname}_VERSION})
  255. endif()
  256. else()
  257. set(GSS_FLAVOUR "Heimdal")
  258. set(GSS_PC_REQUIRES "heimdal-gssapi")
  259. if(NOT _GSS_VERSION) # for old CMake versions?
  260. set(_GSS_VERSION ${_GSS_${_heimdal_modname}_VERSION})
  261. endif()
  262. endif()
  263. message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_GSS_INCLUDE_DIRS} (found version \"${_GSS_VERSION}\")")
  264. endif()
  265. string(REPLACE ";" " " _GSS_CFLAGS "${_GSS_CFLAGS}")
  266. set(GSS_INCLUDE_DIRS ${_GSS_INCLUDE_DIRS})
  267. set(GSS_LIBRARIES ${_GSS_LIBRARIES})
  268. set(GSS_LIBRARY_DIRS ${_GSS_LIBRARY_DIRS})
  269. set(GSS_CFLAGS ${_GSS_CFLAGS})
  270. set(GSS_VERSION ${_GSS_VERSION})
  271. if(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. if(EXISTS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}")
  279. file(STRINGS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}" _heimdal_version_str
  280. REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
  281. string(REGEX MATCH "[0-9]\\.[^\"]+" GSS_VERSION "${_heimdal_version_str}")
  282. endif()
  283. if(NOT GSS_VERSION)
  284. set(GSS_VERSION "Heimdal Unknown")
  285. endif()
  286. elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
  287. get_filename_component(_mit_version "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME
  288. CACHE)
  289. if(WIN32 AND _mit_version)
  290. set(GSS_VERSION "${_mit_version}")
  291. else()
  292. set(GSS_VERSION "MIT Unknown")
  293. endif()
  294. elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "GNU")
  295. if(GSS_INCLUDE_DIRS AND EXISTS "${GSS_INCLUDE_DIRS}/gss.h")
  296. set(_version_regex "#[\t ]*define[\t ]+GSS_VERSION[\t ]+\"([^\"]*)\"")
  297. file(STRINGS "${GSS_INCLUDE_DIRS}/gss.h" _version_str REGEX "${_version_regex}")
  298. string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
  299. set(GSS_VERSION "${_version_str}")
  300. unset(_version_regex)
  301. unset(_version_str)
  302. endif()
  303. endif()
  304. endif()
  305. include(FindPackageHandleStandardArgs)
  306. find_package_handle_standard_args(GSS
  307. REQUIRED_VARS
  308. GSS_FLAVOUR
  309. GSS_LIBRARIES
  310. VERSION_VAR
  311. GSS_VERSION
  312. FAIL_MESSAGE
  313. "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
  314. )
  315. mark_as_advanced(
  316. _GSS_CFLAGS
  317. _GSS_FOUND
  318. _GSS_INCLUDE_DIRS
  319. _GSS_LIBRARIES
  320. _GSS_LIBRARY_DIRS
  321. _GSS_MODULE_NAME
  322. _GSS_PREFIX
  323. _GSS_VERSION
  324. )