1# Copyright (c) 2009, 2021, Oracle and/or its affiliates.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License, version 2.0,
5# as published by the Free Software Foundation.
6#
7# This program is also distributed with certain software (including
8# but not limited to OpenSSL) that is licensed under separate terms,
9# as designated in a particular file or component or in included license
10# documentation.  The authors of MySQL hereby grant you an additional
11# permission to link the program and your derivative works with the
12# separately licensed software that they have included with MySQL.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License, version 2.0, for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
23# We support different versions of SSL:
24# - "system"  (typically) uses headers/libraries in /usr/lib and /usr/lib64
25# - a custom installation of openssl can be used like this
26#     - cmake -DCMAKE_PREFIX_PATH=</path/to/custom/openssl> -DWITH_SSL="system"
27#   or
28#     - cmake -DWITH_SSL=</path/to/custom/openssl>
29#
30# The default value for WITH_SSL is "system".
31#
32# WITH_SSL="system" means: use the SSL library that comes with the operating
33# system. This typically means you have to do 'yum install openssl-devel'
34# or something similar.
35#
36# For Windows or macOS, WITH_SSL="system" is handled a bit differently:
37# We assume you have installed
38#     https://slproweb.com/products/Win32OpenSSL.html
39#     We look for "C:/Program Files/OpenSSL-Win64/"
40#     The .dll files must be in your PATH.
41# or
42#     http://brewformulas.org/Openssl
43#     We look for "/usr/local/opt/openssl"
44#     We look for the static libraries, rather than the .dylib ones.
45# When the package has been located, we treat it as if cmake had been
46# invoked with  -DWITH_SSL=</path/to/custom/openssl>
47
48
49SET(WITH_SSL_DOC "\nsystem (use the OS openssl library)")
50SET(WITH_SSL_DOC
51  "${WITH_SSL_DOC}, \nyes (synonym for system)")
52SET(WITH_SSL_DOC
53  "${WITH_SSL_DOC}, \n</path/to/custom/openssl/installation>")
54
55STRING(REPLACE "\n" "| " WITH_SSL_DOC_STRING "${WITH_SSL_DOC}")
56
57MACRO(FATAL_SSL_NOT_FOUND_ERROR string)
58  MESSAGE(STATUS "\n${string}"
59    "\nMake sure you have specified a supported SSL version. "
60    "\nValid options are : ${WITH_SSL_DOC}\n"
61    )
62  IF(UNIX)
63    MESSAGE(FATAL_ERROR
64      "Please install the appropriate openssl developer package.\n")
65  ENDIF()
66  IF(WIN32)
67    MESSAGE(FATAL_ERROR
68      "Please see https://wiki.openssl.org/index.php/Binaries\n")
69  ENDIF()
70  IF(APPLE)
71    MESSAGE(FATAL_ERROR
72      "Please see http://brewformulas.org/Openssl\n")
73  ENDIF()
74ENDMACRO()
75
76MACRO(RESET_SSL_VARIABLES)
77  UNSET(WITH_SSL_PATH)
78  UNSET(WITH_SSL_PATH CACHE)
79  UNSET(OPENSSL_VERSION)
80  UNSET(OPENSSL_VERSION CACHE)
81  UNSET(OPENSSL_ROOT_DIR)
82  UNSET(OPENSSL_ROOT_DIR CACHE)
83  UNSET(OPENSSL_INCLUDE_DIR)
84  UNSET(OPENSSL_INCLUDE_DIR CACHE)
85  UNSET(OPENSSL_APPLINK_C)
86  UNSET(OPENSSL_APPLINK_C CACHE)
87  UNSET(OPENSSL_LIBRARY)
88  UNSET(OPENSSL_LIBRARY CACHE)
89  UNSET(CRYPTO_LIBRARY)
90  UNSET(CRYPTO_LIBRARY CACHE)
91  UNSET(HAVE_SHA512_DIGEST_LENGTH)
92  UNSET(HAVE_SHA512_DIGEST_LENGTH CACHE)
93ENDMACRO()
94
95# MYSQL_CHECK_SSL
96#
97# Provides the following configure options:
98# WITH_SSL=[yes|system|<path/to/custom/installation>]
99MACRO (MYSQL_CHECK_SSL)
100  IF(NOT WITH_SSL)
101    SET(WITH_SSL "system" CACHE STRING ${WITH_SSL_DOC_STRING} FORCE)
102  ENDIF()
103
104  # See if WITH_SSL is of the form </path/to/custom/installation>
105  FILE(GLOB WITH_SSL_HEADER ${WITH_SSL}/include/openssl/ssl.h)
106  IF (WITH_SSL_HEADER)
107    FILE(TO_CMAKE_PATH "${WITH_SSL}" WITH_SSL)
108    SET(WITH_SSL_PATH ${WITH_SSL} CACHE PATH "path to custom SSL installation")
109    SET(WITH_SSL_PATH ${WITH_SSL})
110  ENDIF()
111
112  IF(WITH_SSL STREQUAL "system" OR
113      WITH_SSL STREQUAL "yes" OR
114      WITH_SSL_PATH
115      )
116    # Treat "system" the same way as -DWITH_SSL=</path/to/custom/openssl>
117    # Note: we cannot use FIND_PACKAGE(OpenSSL), as older cmake versions
118    # have buggy implementations.
119    IF((APPLE OR WIN32) AND NOT WITH_SSL_PATH AND WITH_SSL STREQUAL "system")
120      IF(APPLE)
121        SET(WITH_SSL_PATH "/usr/local/opt/openssl")
122      ELSE()
123        SET(WITH_SSL_PATH "C:/Program Files/OpenSSL-Win64/")
124      ENDIF()
125    ENDIF()
126
127    # First search in WITH_SSL_PATH.
128    FIND_PATH(OPENSSL_ROOT_DIR
129      NAMES include/openssl/ssl.h
130      NO_CMAKE_PATH
131      NO_CMAKE_ENVIRONMENT_PATH
132      HINTS ${WITH_SSL_PATH}
133    )
134    # Then search in standard places (if not found above).
135    FIND_PATH(OPENSSL_ROOT_DIR
136      NAMES include/openssl/ssl.h
137    )
138
139    FIND_PATH(OPENSSL_INCLUDE_DIR
140      NAMES openssl/ssl.h
141      HINTS ${OPENSSL_ROOT_DIR}/include
142    )
143
144    IF (WIN32)
145      FIND_FILE(OPENSSL_APPLINK_C
146        NAMES openssl/applink.c
147        NO_DEFAULT_PATH
148        HINTS ${OPENSSL_ROOT_DIR}/include
149      )
150      MESSAGE(STATUS "OPENSSL_APPLINK_C ${OPENSSL_APPLINK_C}")
151    ENDIF()
152
153    # On mac this list is <.dylib;.so;.a>
154    # We prefer static libraries, so we reverse it here.
155    IF (WITH_SSL_PATH)
156      LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
157      MESSAGE(STATUS "suffixes <${CMAKE_FIND_LIBRARY_SUFFIXES}>")
158    ENDIF()
159
160    FIND_LIBRARY(OPENSSL_LIBRARY
161                 NAMES ssl libssl ssleay32 ssleay32MD
162                 HINTS ${OPENSSL_ROOT_DIR}/lib)
163    FIND_LIBRARY(CRYPTO_LIBRARY
164                 NAMES crypto libcrypto libeay32
165                 HINTS ${OPENSSL_ROOT_DIR}/lib)
166    IF (WITH_SSL_PATH)
167      LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
168    ENDIF()
169
170    IF(OPENSSL_INCLUDE_DIR)
171      # Verify version number. Version information looks like:
172      #   #define OPENSSL_VERSION_NUMBER 0x1000103fL
173      # Encoded as MNNFFPPS: major minor fix patch status
174      FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
175        OPENSSL_VERSION_NUMBER
176        REGEX "^#[ ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
177        )
178      STRING(REGEX REPLACE
179        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
180        OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
181        )
182      STRING(REGEX REPLACE
183        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x[0-9]([0-9][0-9]).*$" "\\1"
184        OPENSSL_MINOR_VERSION "${OPENSSL_VERSION_NUMBER}"
185        )
186      STRING(REGEX REPLACE
187        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x[0-9][0-9][0-9]([0-9][0-9]).*$" "\\1"
188        OPENSSL_FIX_VERSION "${OPENSSL_VERSION_NUMBER}"
189        )
190    ENDIF()
191    SET(OPENSSL_VERSION
192      "${OPENSSL_MAJOR_VERSION}.${OPENSSL_MINOR_VERSION}.${OPENSSL_FIX_VERSION}"
193      )
194    SET(OPENSSL_VERSION ${OPENSSL_VERSION} CACHE INTERNAL "")
195
196    CHECK_SYMBOL_EXISTS(TLS1_3_VERSION "openssl/tls1.h" HAVE_TLS1_3_VERSION)
197    IF(HAVE_TLS1_3_VERSION)
198       ADD_DEFINITIONS(-DHAVE_TLSv13)
199       SET(HAVE_TLSv13 1)
200       IF(SOLARIS)
201         SET(FORCE_SSL_SOLARIS "-Wl,--undefined,address_of_sk_new_null")
202       ENDIF()
203    ENDIF()
204    IF(OPENSSL_INCLUDE_DIR AND
205       OPENSSL_LIBRARY   AND
206       CRYPTO_LIBRARY
207      )
208      SET(OPENSSL_FOUND TRUE)
209    ELSE()
210      SET(OPENSSL_FOUND FALSE)
211    ENDIF()
212
213    # If we are invoked with -DWITH_SSL=/path/to/custom/openssl
214    # and we have found static libraries, then link them statically
215    # into our executables and libraries.
216    # Adding IMPORTED_LOCATION allows MERGE_STATIC_LIBS
217    # to merge imported libraries as well as our own libraries.
218    SET(MY_CRYPTO_LIBRARY "${CRYPTO_LIBRARY}")
219    SET(MY_OPENSSL_LIBRARY "${OPENSSL_LIBRARY}")
220    IF (WITH_SSL_PATH)
221      GET_FILENAME_COMPONENT(CRYPTO_EXT "${CRYPTO_LIBRARY}" EXT)
222      GET_FILENAME_COMPONENT(OPENSSL_EXT "${OPENSSL_LIBRARY}" EXT)
223      IF (CRYPTO_EXT STREQUAL ".a" OR CRYPTO_EXT STREQUAL ".lib")
224        SET(MY_CRYPTO_LIBRARY imported_crypto)
225        ADD_IMPORTED_LIBRARY(imported_crypto "${CRYPTO_LIBRARY}")
226      ENDIF()
227      IF (OPENSSL_EXT STREQUAL ".a" OR OPENSSL_EXT STREQUAL ".lib")
228        SET(MY_OPENSSL_LIBRARY imported_openssl)
229        ADD_IMPORTED_LIBRARY(imported_openssl "${OPENSSL_LIBRARY}")
230      ENDIF()
231      IF(CRYPTO_EXT STREQUAL ".a" OR OPENSSL_EXT STREQUAL ".a")
232        SET(STATIC_SSL_LIBRARY 1)
233      ENDIF()
234    ENDIF()
235
236    MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
237    MESSAGE(STATUS "OPENSSL_LIBRARY = ${OPENSSL_LIBRARY}")
238    MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
239    MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
240    MESSAGE(STATUS "OPENSSL_MINOR_VERSION = ${OPENSSL_MINOR_VERSION}")
241    MESSAGE(STATUS "OPENSSL_FIX_VERSION = ${OPENSSL_FIX_VERSION}")
242
243    # Static SSL libraries? we require at least 1.1.1
244    IF(STATIC_SSL_LIBRARY OR (WIN32 AND WITH_SSL_PATH))
245      IF(OPENSSL_VERSION VERSION_LESS "1.1.1")
246        RESET_SSL_VARIABLES()
247        MESSAGE(FATAL_ERROR "SSL version must be at least 1.1.1")
248      ENDIF()
249      SET(SSL_DEFINES "-DHAVE_STATIC_OPENSSL")
250    ENDIF()
251
252    INCLUDE(CheckSymbolExists)
253
254    CMAKE_PUSH_CHECK_STATE()
255    SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
256    CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
257                        HAVE_SHA512_DIGEST_LENGTH)
258    CMAKE_POP_CHECK_STATE()
259
260    IF(OPENSSL_FOUND AND HAVE_SHA512_DIGEST_LENGTH)
261      SET(SSL_SOURCES "")
262      SET(SSL_LIBRARIES ${MY_OPENSSL_LIBRARY} ${MY_CRYPTO_LIBRARY})
263      IF(SOLARIS)
264        SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBSOCKET})
265      ENDIF()
266      IF(LINUX)
267        SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBDL})
268      ENDIF()
269      MESSAGE(STATUS "SSL_LIBRARIES = ${SSL_LIBRARIES}")
270      IF(WIN32 AND WITH_SSL STREQUAL "system")
271        MESSAGE(STATUS "Please do\nPATH=\"${WITH_SSL_PATH}bin\":$PATH")
272        FILE(TO_NATIVE_PATH "${WITH_SSL_PATH}" WITH_SSL_PATH_XX)
273        MESSAGE(STATUS "or\nPATH=\"${WITH_SSL_PATH_XX}bin\":$PATH")
274      ENDIF()
275      SET(SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
276      SET(SSL_INTERNAL_INCLUDE_DIRS "")
277      STRING_APPEND(SSL_DEFINES " -DHAVE_OPENSSL")
278      INCLUDE(CMakePushCheckState)
279      cmake_push_check_state()
280      SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
281      SET(CMAKE_REQUIRED_LIBRARIES ${MY_OPENSSL_LIBRARY} ${MY_CRYPTO_LIBRARY})
282      CHECK_SYMBOL_EXISTS(X509_check_host "openssl/x509v3.h" HAVE_X509_CHECK_HOST)
283      CHECK_SYMBOL_EXISTS(X509_check_ip "openssl/x509v3.h" HAVE_X509_CHECK_IP)
284      cmake_pop_check_state()
285    ELSE()
286      RESET_SSL_VARIABLES()
287      FATAL_SSL_NOT_FOUND_ERROR(
288        "Cannot find appropriate system libraries for WITH_SSL=${WITH_SSL}.")
289    ENDIF()
290  ELSE()
291    RESET_SSL_VARIABLES()
292    FATAL_SSL_NOT_FOUND_ERROR(
293      "Wrong option or path for WITH_SSL=${WITH_SSL}.")
294  ENDIF()
295ENDMACRO()
296