mysql-server/cmake/fido2.cmake
2025-03-05 14:31:37 +07:00

215 lines
7.3 KiB
CMake

# Copyright (c) 2020, 2024, Oracle and/or its affiliates.
#
# 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,
# as published by the Free Software Foundation.
#
# This program is designed to work with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have either included with
# the program or referenced in the documentation.
#
# 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# cmake -DWITH_FIDO=bundled|system
# Version 1.3.1 on Ubuntu 20.04 does *not* work.
# Version 1.4.0 on Fedora 33 passes all tests.
SET(MIN_FIDO_VERSION_REQUIRED "1.4.0")
SET(FIDO_BUNDLED_VERSION "1.15.0")
MACRO(FIND_FIDO_VERSION)
IF(WITH_FIDO STREQUAL "bundled")
SET(FIDO_VERSION "${FIDO_BUNDLED_VERSION}")
ELSE()
# This does not set any version information:
# PKG_CHECK_MODULES(SYSTEM_FIDO fido2)
IF(APPLE)
EXECUTE_PROCESS(
COMMAND otool -L "${FIDO_LIBRARY}"
OUTPUT_VARIABLE OTOOL_FIDO_DEPS)
STRING(REPLACE "\n" ";" DEPS_LIST ${OTOOL_FIDO_DEPS})
FOREACH(LINE ${DEPS_LIST})
STRING(REGEX MATCH
".*libfido2.*current version ([.0-9]+).*" UNUSED ${LINE})
IF(CMAKE_MATCH_1)
SET(FIDO_VERSION "${CMAKE_MATCH_1}")
BREAK()
ENDIF()
ENDFOREACH()
ELSE()
MYSQL_CHECK_PKGCONFIG()
EXECUTE_PROCESS(
COMMAND ${MY_PKG_CONFIG_EXECUTABLE} --modversion libfido2
OUTPUT_VARIABLE MY_FIDO_MODVERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE MY_MODVERSION_RESULT
)
IF(MY_MODVERSION_RESULT EQUAL 0)
SET(FIDO_VERSION ${MY_FIDO_MODVERSION})
ENDIF()
ENDIF()
ENDIF()
MESSAGE(STATUS "FIDO_VERSION (${WITH_FIDO}) is ${FIDO_VERSION}")
ENDMACRO(FIND_FIDO_VERSION)
# libudev is needed on Linux only.
FUNCTION(WARN_MISSING_SYSTEM_UDEV OUTPUT_WARNING)
IF(LINUX AND WITH_FIDO STREQUAL "bundled" AND NOT LIBUDEV_DEVEL_FOUND)
MESSAGE(WARNING "Cannot find development libraries. "
"You need to install the required packages:\n"
" Debian/Ubuntu: apt install libudev-dev\n"
" RedHat/Fedora/Oracle Linux: yum install libudev-devel\n"
" SuSE: zypper install libudev-devel\n"
)
SET(${OUTPUT_WARNING} 1 PARENT_SCOPE)
ENDIF()
IF(SOLARIS)
MESSAGE(STATUS "No known libudev on SOLARIS")
SET(${OUTPUT_WARNING} 1 PARENT_SCOPE)
ENDIF()
ENDFUNCTION(WARN_MISSING_SYSTEM_UDEV)
# Bundled FIDO requires libudev.
FUNCTION(FIND_SYSTEM_UDEV_OR_HID)
IF(LINUX)
FIND_LIBRARY(UDEV_SYSTEM_LIBRARY NAMES udev)
CHECK_INCLUDE_FILE(libudev.h HAVE_LIBUDEV_H)
IF(UDEV_SYSTEM_LIBRARY AND HAVE_LIBUDEV_H)
SET(LIBUDEV_DEVEL_FOUND 1 CACHE INTERNAL "")
SET(UDEV_LIBRARIES ${UDEV_SYSTEM_LIBRARY} CACHE INTERNAL "")
MESSAGE(STATUS "UDEV_SYSTEM_LIBRARY ${UDEV_SYSTEM_LIBRARY}")
ENDIF()
ELSEIF(FREEBSD)
FIND_LIBRARY(HID_LIBRARY NAMES hidapi)
IF(HID_LIBRARY)
MESSAGE(STATUS "HID_LIBRARY ${HID_LIBRARY}")
ELSE()
MESSAGE(WARNING "Cannot find development libraries. "
"You need to install the required packages:\n"
"FreeBSD: pkg install hidapi\n"
)
ENDIF()
ENDIF()
ENDFUNCTION(FIND_SYSTEM_UDEV_OR_HID)
FUNCTION(WARN_MISSING_SYSTEM_FIDO OUTPUT_WARNING)
IF(WITH_FIDO STREQUAL "system" AND NOT FIDO_FOUND)
MESSAGE(WARNING "Cannot find development libraries. "
"You need to install the required packages:\n"
" Debian/Ubuntu: apt install libfido2-dev\n"
" RedHat/Fedora/Oracle Linux: yum install libfido2-devel\n"
" SuSE: zypper install libfido2-devel\n"
)
SET(${OUTPUT_WARNING} 1 PARENT_SCOPE)
ENDIF()
ENDFUNCTION(WARN_MISSING_SYSTEM_FIDO)
# Look for system fido2. If we find it, there is no need to look for libudev.
FUNCTION(FIND_SYSTEM_FIDO)
IF(APPLE)
SET(CMAKE_REQUIRED_INCLUDES
"${HOMEBREW_HOME}/include"
"${HOMEBREW_HOME}/libfido2/include"
"${OPENSSL_INCLUDE_DIR}"
)
ENDIF()
CHECK_INCLUDE_FILE(fido.h HAVE_FIDO_H)
FIND_LIBRARY(FIDO_LIBRARY fido2)
IF (FIDO_LIBRARY AND HAVE_FIDO_H)
SET(FIDO_FOUND TRUE)
SET(FIDO_FOUND TRUE PARENT_SCOPE)
FIND_PATH(FIDO_INCLUDE_DIR
NAMES fido.h
HINTS ${CMAKE_REQUIRED_INCLUDES}
)
ADD_LIBRARY(fido_interface INTERFACE)
TARGET_LINK_LIBRARIES(fido_interface INTERFACE ${FIDO_LIBRARY})
IF(NOT FIDO_INCLUDE_DIR STREQUAL "/usr/include")
TARGET_INCLUDE_DIRECTORIES(fido_interface SYSTEM INTERFACE
${FIDO_INCLUDE_DIR})
ENDIF()
ADD_LIBRARY(ext::fido ALIAS fido_interface)
ENDIF()
ENDFUNCTION(FIND_SYSTEM_FIDO)
FUNCTION(MYSQL_USE_BUNDLED_FIDO)
FIND_SYSTEM_UDEV_OR_HID()
# We use the bundled version, so:
SET(FIDO_FOUND TRUE)
SET(FIDO_FOUND TRUE PARENT_SCOPE)
# Mark it as not found if libudev is missing, so we can give proper warnings.
IF(LINUX AND NOT LIBUDEV_DEVEL_FOUND)
SET(FIDO_FOUND FALSE)
SET(FIDO_FOUND FALSE PARENT_SCOPE)
ENDIF()
# So that we skip authentication_webauthn_client.so
IF(SOLARIS)
SET(FIDO_FOUND FALSE)
SET(FIDO_FOUND FALSE PARENT_SCOPE)
ENDIF()
ENDFUNCTION(MYSQL_USE_BUNDLED_FIDO)
MACRO(MYSQL_CHECK_FIDO)
IF("${OPENSSL_MAJOR_MINOR_FIX_VERSION}" VERSION_GREATER "1.1.0")
SET(OPENSSL_IS_COMPATIBLE_WITH_BUNDLED_FIDO ON)
ELSE()
SET(OPENSSL_IS_COMPATIBLE_WITH_BUNDLED_FIDO OFF)
SET(WITH_AUTHENTICATION_WEBAUTHN OFF)
ENDIF()
IF (NOT WITH_FIDO)
IF(OPENSSL_IS_COMPATIBLE_WITH_BUNDLED_FIDO)
SET(WITH_FIDO "bundled"
CACHE STRING "By default use bundled libfido2.")
ELSE()
SET(WITH_FIDO "none"
CACHE STRING "Do not compile libfido2 for OpenSSL < 1.1.1")
ENDIF()
ENDIF()
IF(WITH_FIDO STREQUAL "none")
MESSAGE(WARNING
"WITH_FIDO is set to \"none\". \
FIDO based authentication plugins will be skipped.")
ELSE()
IF(WITH_FIDO STREQUAL "bundled")
IF(OPENSSL_IS_COMPATIBLE_WITH_BUNDLED_FIDO)
MYSQL_USE_BUNDLED_FIDO()
ELSE()
MESSAGE(FATAL_ERROR
"Bundled libfido2 requires OpenSSL version >= 1.1.1")
ENDIF()
ELSEIF(WITH_FIDO STREQUAL "system")
FIND_SYSTEM_FIDO()
IF(NOT FIDO_FOUND)
MESSAGE(WARNING "Cannot find system fido2 libraries/headers.")
ENDIF()
ELSE()
MESSAGE(WARNING "WITH_FIDO must be none, bundled or system")
ENDIF()
FIND_FIDO_VERSION()
IF(FIDO_VERSION VERSION_LESS MIN_FIDO_VERSION_REQUIRED)
MESSAGE(FATAL_ERROR
"FIDO version must be at least ${MIN_FIDO_VERSION_REQUIRED}, "
"found ${FIDO_VERSION}.\nPlease use -DWITH_FIDO=bundled")
ENDIF()
ENDIF()
ENDMACRO(MYSQL_CHECK_FIDO)