1# Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
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}")
56MACRO (CHANGE_SSL_SETTINGS string)
57  SET(WITH_SSL ${string} CACHE STRING ${WITH_SSL_DOC_STRING} FORCE)
58ENDMACRO()
59
60MACRO(FATAL_SSL_NOT_FOUND_ERROR string)
61  MESSAGE(STATUS "\n${string}"
62    "\nMake sure you have specified a supported SSL version. "
63    "\nValid options are : ${WITH_SSL_DOC}\n"
64    )
65  IF(UNIX)
66    MESSAGE(FATAL_ERROR
67      "Please install the appropriate openssl developer package.\n")
68  ENDIF()
69  IF(WIN32)
70    MESSAGE(FATAL_ERROR
71      "Please see https://wiki.openssl.org/index.php/Binaries\n")
72  ENDIF()
73  IF(APPLE)
74    MESSAGE(FATAL_ERROR
75      "Please see http://brewformulas.org/Openssl\n")
76  ENDIF()
77ENDMACRO()
78
79MACRO(RESET_SSL_VARIABLES)
80  UNSET(WITH_SSL_PATH)
81  UNSET(WITH_SSL_PATH CACHE)
82  UNSET(OPENSSL_ROOT_DIR)
83  UNSET(OPENSSL_ROOT_DIR CACHE)
84  UNSET(OPENSSL_INCLUDE_DIR)
85  UNSET(OPENSSL_INCLUDE_DIR CACHE)
86  UNSET(OPENSSL_APPLINK_C)
87  UNSET(OPENSSL_APPLINK_C CACHE)
88  UNSET(OPENSSL_LIBRARY)
89  UNSET(OPENSSL_LIBRARY CACHE)
90  UNSET(CRYPTO_LIBRARY)
91  UNSET(CRYPTO_LIBRARY CACHE)
92  UNSET(HAVE_SHA512_DIGEST_LENGTH)
93  UNSET(HAVE_SHA512_DIGEST_LENGTH CACHE)
94ENDMACRO()
95
96# MYSQL_CHECK_SSL
97#
98# Provides the following configure options:
99# WITH_SSL=[yes|system|<path/to/custom/installation>]
100MACRO (MYSQL_CHECK_SSL)
101  IF(NOT WITH_SSL)
102    CHANGE_SSL_SETTINGS("system")
103  ENDIF()
104
105  # See if WITH_SSL is of the form </path/to/custom/installation>
106  FILE(GLOB WITH_SSL_HEADER ${WITH_SSL}/include/openssl/ssl.h)
107  IF (WITH_SSL_HEADER)
108    FILE(TO_CMAKE_PATH "${WITH_SSL}" WITH_SSL)
109    SET(WITH_SSL_PATH ${WITH_SSL} CACHE PATH "path to custom SSL installation")
110    SET(WITH_SSL_PATH ${WITH_SSL})
111  ENDIF()
112
113  IF(WITH_SSL STREQUAL "system" OR
114      WITH_SSL STREQUAL "yes" OR
115      WITH_SSL_PATH
116      )
117    # Treat "system" the same way as -DWITH_SSL=</path/to/custom/openssl>
118    # Note: we cannot use FIND_PACKAGE(OpenSSL), as older cmake versions
119    # have buggy implementations.
120    IF((APPLE OR WIN32) AND NOT WITH_SSL_PATH AND WITH_SSL STREQUAL "system")
121      IF(APPLE)
122        SET(WITH_SSL_PATH "/usr/local/opt/openssl")
123      ELSE()
124        SET(WITH_SSL_PATH "C:/Program Files/OpenSSL-Win64/")
125      ENDIF()
126    ENDIF()
127
128    # First search in WITH_SSL_PATH.
129    FIND_PATH(OPENSSL_ROOT_DIR
130      NAMES include/openssl/ssl.h
131      NO_CMAKE_PATH
132      NO_CMAKE_ENVIRONMENT_PATH
133      HINTS ${WITH_SSL_PATH}
134    )
135    # Then search in standard places (if not found above).
136    FIND_PATH(OPENSSL_ROOT_DIR
137      NAMES include/openssl/ssl.h
138    )
139
140    FIND_PATH(OPENSSL_INCLUDE_DIR
141      NAMES openssl/ssl.h
142      HINTS ${OPENSSL_ROOT_DIR}/include
143    )
144
145    IF (WIN32)
146      FIND_FILE(OPENSSL_APPLINK_C
147        NAMES openssl/applink.c
148        NO_DEFAULT_PATH
149        HINTS ${OPENSSL_ROOT_DIR}/include
150      )
151      MESSAGE(STATUS "OPENSSL_APPLINK_C ${OPENSSL_APPLINK_C}")
152    ENDIF()
153
154    # On mac this list is <.dylib;.so;.a>
155    # We prefer static libraries, so we revert it here.
156    IF (WITH_SSL_PATH)
157      LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
158      MESSAGE(STATUS "suffixes <${CMAKE_FIND_LIBRARY_SUFFIXES}>")
159    ENDIF()
160
161    FIND_LIBRARY(OPENSSL_LIBRARY
162                 NAMES ssl libssl ssleay32 ssleay32MD
163                 HINTS ${OPENSSL_ROOT_DIR}/lib)
164    FIND_LIBRARY(CRYPTO_LIBRARY
165                 NAMES crypto libcrypto libeay32
166                 HINTS ${OPENSSL_ROOT_DIR}/lib)
167    IF (WITH_SSL_PATH)
168      LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
169    ENDIF()
170
171    IF(OPENSSL_INCLUDE_DIR)
172      # Verify version number. Version information looks like:
173      #   #define OPENSSL_VERSION_NUMBER 0x1000103fL
174      # Encoded as MNNFFPPS: major minor fix patch status
175      FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
176        OPENSSL_VERSION_NUMBER
177        REGEX "^#[ ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
178        )
179      STRING(REGEX REPLACE
180        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
181        OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
182        )
183      STRING(REGEX REPLACE
184        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x[0-9]([0-9][0-9]).*$" "\\1"
185        OPENSSL_MINOR_VERSION "${OPENSSL_VERSION_NUMBER}"
186        )
187      STRING(REGEX REPLACE
188        "^.*OPENSSL_VERSION_NUMBER[\t ]+0x[0-9][0-9][0-9]([0-9][0-9]).*$" "\\1"
189        OPENSSL_FIX_VERSION "${OPENSSL_VERSION_NUMBER}"
190        )
191    ENDIF()
192    IF("${OPENSSL_MAJOR_VERSION}.${OPENSSL_MINOR_VERSION}.${OPENSSL_FIX_VERSION}" VERSION_GREATER "1.1.0")
193       ADD_DEFINITIONS(-DHAVE_TLSv13)
194    ENDIF()
195    IF(OPENSSL_INCLUDE_DIR AND
196       OPENSSL_LIBRARY   AND
197       CRYPTO_LIBRARY
198      )
199      SET(OPENSSL_FOUND TRUE)
200    ELSE()
201      SET(OPENSSL_FOUND FALSE)
202    ENDIF()
203
204    # If we are invoked with -DWITH_SSL=/path/to/custom/openssl
205    # and we have found static libraries, then link them statically
206    # into our executables and libraries.
207    # Adding IMPORTED_LOCATION allows MERGE_STATIC_LIBS
208    # to get LOCATION and do correct dependency analysis.
209    SET(MY_CRYPTO_LIBRARY "${CRYPTO_LIBRARY}")
210    SET(MY_OPENSSL_LIBRARY "${OPENSSL_LIBRARY}")
211    IF (WITH_SSL_PATH)
212      GET_FILENAME_COMPONENT(CRYPTO_EXT "${CRYPTO_LIBRARY}" EXT)
213      GET_FILENAME_COMPONENT(OPENSSL_EXT "${OPENSSL_LIBRARY}" EXT)
214      IF (CRYPTO_EXT STREQUAL ".a" OR CRYPTO_EXT STREQUAL ".lib")
215        SET(MY_CRYPTO_LIBRARY imported_crypto)
216        ADD_LIBRARY(imported_crypto STATIC IMPORTED)
217        SET_TARGET_PROPERTIES(imported_crypto
218          PROPERTIES IMPORTED_LOCATION "${CRYPTO_LIBRARY}")
219      ENDIF()
220      IF (OPENSSL_EXT STREQUAL ".a" OR OPENSSL_EXT STREQUAL ".lib")
221        SET(MY_OPENSSL_LIBRARY imported_openssl)
222        ADD_LIBRARY(imported_openssl STATIC IMPORTED)
223        SET_TARGET_PROPERTIES(imported_openssl
224          PROPERTIES IMPORTED_LOCATION "${OPENSSL_LIBRARY}")
225      ENDIF()
226    ENDIF()
227
228    MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
229    MESSAGE(STATUS "OPENSSL_LIBRARY = ${OPENSSL_LIBRARY}")
230    MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
231    MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
232    MESSAGE(STATUS "OPENSSL_MINOR_VERSION = ${OPENSSL_MINOR_VERSION}")
233    MESSAGE(STATUS "OPENSSL_FIX_VERSION = ${OPENSSL_FIX_VERSION}")
234
235    INCLUDE(CheckSymbolExists)
236    SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
237    CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
238                        HAVE_SHA512_DIGEST_LENGTH)
239    IF(OPENSSL_FOUND AND HAVE_SHA512_DIGEST_LENGTH)
240      SET(SSL_SOURCES "")
241      SET(SSL_LIBRARIES ${MY_OPENSSL_LIBRARY} ${MY_CRYPTO_LIBRARY})
242      IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
243        SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBSOCKET})
244      ENDIF()
245      IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
246        SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBDL})
247      ENDIF()
248      MESSAGE(STATUS "SSL_LIBRARIES = ${SSL_LIBRARIES}")
249      IF(WIN32 AND WITH_SSL STREQUAL "system")
250        MESSAGE(STATUS "Please do\nPATH=\"${WITH_SSL_PATH}bin\":$PATH")
251        FILE(TO_NATIVE_PATH "${WITH_SSL_PATH}" WITH_SSL_PATH_XX)
252        MESSAGE(STATUS "or\nPATH=\"${WITH_SSL_PATH_XX}bin\":$PATH")
253      ENDIF()
254      SET(SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
255      SET(SSL_INTERNAL_INCLUDE_DIRS "")
256      SET(SSL_DEFINES "-DHAVE_OPENSSL")
257      INCLUDE(CMakePushCheckState)
258      cmake_push_check_state()
259      SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
260      SET(CMAKE_REQUIRED_LIBRARIES ${MY_OPENSSL_LIBRARY} ${MY_CRYPTO_LIBRARY})
261      CHECK_SYMBOL_EXISTS(X509_check_host "openssl/x509v3.h" HAVE_X509_CHECK_HOST)
262      CHECK_SYMBOL_EXISTS(X509_check_ip "openssl/x509v3.h" HAVE_X509_CHECK_IP)
263      cmake_pop_check_state()
264    ELSE()
265      RESET_SSL_VARIABLES()
266      FATAL_SSL_NOT_FOUND_ERROR(
267        "Cannot find appropriate system libraries for WITH_SSL=${WITH_SSL}.")
268    ENDIF()
269  ELSE()
270    RESET_SSL_VARIABLES()
271    FATAL_SSL_NOT_FOUND_ERROR(
272      "Wrong option or path for WITH_SSL=${WITH_SSL}.")
273  ENDIF()
274ENDMACRO()
275