-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CMake: Support for DarwinSSL and mbedTLS + cleanup #1228
Conversation
@ligfx, thanks for your PR! By analyzing the history of the files in this pull request, we identified @Lekensteyn, @jzakrzewski and @jgsogo to be potential reviewers. |
CMake/FindMbedTLS.cmake
Outdated
find_library(MBEDCRYPTO_LIBRARY mbedcrypto) | ||
|
||
set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) | ||
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a good idea to quote each of these variables (in case it contains spaces). E.g. "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" ...)
(same for previous include_dirs line)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good catch! The quoting rules always trip me up.
CMakeLists.txt
Outdated
if(SECURITY_FRAMEWORK) | ||
set(SSL_ENABLED ON) | ||
set(USE_DARWINSSL ON) | ||
list(APPEND CURL_LIBS "-framework CoreFoundation -framework Security") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work? Don't you have separate the two options like list(APPEND CURL_LIBS "-framework CoreFoundation" "-framework Security")
?
(Specifying -framework
should work according to cmake-commands manual (target_link_libraries
), hopefully it does (untested).)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any library that begins with -
gets passed straight through to the command-line, so it works as two options or as one option. After taking another look at this code, I replaced this with "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}"
, since it seems more correct (and it already goes to the trouble of finding Security.framework, so might as well...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, thanks for pushing macOS+cmake. I'll test this on a Mac soon. The current change does not break my custom OpenSSL configuration on Linux, so 👍
CMakeLists.txt
Outdated
|
||
if(CMAKE_USE_OPENSSL) | ||
option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON) | ||
if(CMAKE_USE_OPENSSL AND NOT SSL_ENABLED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This silently prioritizes Secure Channel over OpenSSL when configuring CMAKE_USE_WINSSL=1 CMAKE_USE_OPENSSL=1
on windows.
I think this priority should at least be written down as a comment about TLS at the top, But the safe thing would be to disallow setting multiple TLS providers.
When I apply this patch, I get a runtime error when setting |
Can you elaborate on exactly what you get when you do what? |
The call of |
Oh, that would imply that the |
I guess I cannot really tell what is included in the build. Since my application code fails when doing the above configuration, even my HTTP tests without SSL fail. Is the any useful debugging that I can perform on the .a file to answer your question? |
It is internal but it depends on one of the TLS enabled variables being set. See https://github.com/curl/curl/blob/master/lib/curl_setup.h#L618 |
I guess there is a |
CMakeLists.txt
Outdated
if(CMAKE_USE_DARWINSSL AND NOT SSL_ENABLED) | ||
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") | ||
find_library(SECURITY_FRAMEWORK "Security") | ||
if(SECURITY_FRAMEWORK) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this block does not properly handle the absense of required libraries. What about
find_library(COREFOUNDATION_FRAMEWORK CoreFoundation)
if (NOT COREFOUNDATION_FRAMEWORK)
message(FATAL ERROR "CoreFoundation framework not found")
endif()
find_library(SECURITY_FRAMEWORK Foundation)
if (NOT SECURITY_FRAMEWORK)
message(FATAL ERROR "Security framework not found")
endif()
set(SSL_ENABLED ON)
set(USE_DARWINSSL ON)
list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right (even though in practice they'll never be absent). I added the checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While testing this change, I found that there is DarwinSSL block missing in curl_config.cmake, see https://github.com/curl/curl/pull/1270/files
Thanks so much for testing this out and investigating that issue, @webmaster128. I've cherry-picked your commit from the other PR into this one. I also added another commit that checks that at most one SSL option is enabled. If multiple options are defined, it raises an error like this:
|
CMakeLists.txt
Outdated
string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) | ||
string(REPLACE "�!�" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) | ||
string(REPLACE "�!�" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you accidentally changed these lines. See #1271
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I responded on your PR.
CMakeLists.txt
Outdated
message(FATAL ERROR "Security framework not found") | ||
endif() | ||
|
||
if(SECURITY_FRAMEWORK) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now this check is obsolete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! This code looks much cleaner now, that was a great idea to disallow multiple SSL provider options.
CMakeLists.txt
Outdated
|
||
find_library(SECURITY_FRAMEWORK "Security") | ||
if(NOT SECURITY_FRAMEWORK) | ||
message(FATAL ERROR "Security framework not found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an underscore missing (my fault, I guess). It is FATAL_ERROR
, see https://cmake.org/cmake/help/v2.8.8/cmake.html#command%3amessage
Same for the block above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does the same thing regardless and aborts CMake, right? 👍 Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FATAL ERROR
was a typo that I copied from my own project where I wrote it the wrong way
Great! I found some minor other stuff. I'll test again soon |
CMakeLists.txt
Outdated
message(FATAL_ERROR "Security framework not found") | ||
endif() | ||
|
||
if(SECURITY_FRAMEWORK) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The obsolete check is still in here
CMakeLists.txt
Outdated
option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF) | ||
if(CMAKE_USE_MBEDTLS) | ||
find_package(MbedTLS) | ||
if(MBEDTLS_FOUND) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should fail hard and early when package MbedTLS was not found (like we discussed for CoreFoundation/Security)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I see the pattern now. I'll also do the same thing for OpenSSL.
CMakeLists.txt
Outdated
string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) | ||
string(REPLACE "�!�" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) | ||
string(REPLACE "�!�" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you replace to "" in 1075, line 1077 should be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand. I'm not changing line 1075/1077. These changes were accidental and I'll remove them from the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have a look at the full diff and you'll see that there is still a change that does not really make sense: https://github.com/curl/curl/pull/1228/files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... which is gone right now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CMakeLists.txt
Outdated
CMAKE_USE_OPENSSL | ||
CMAKE_USE_MBEDTLS | ||
) | ||
if(enabled_ssl_options MATCHES ";") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a way to get the length of a list for this check? Does this work in cmake 2.8? https://cmake.org/cmake/help/v3.0/command/list.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is, but that would add another command to call. I'll add a list length output parameter to collect_true
.
My runtime issue is gone now (just verified the current patch). What now happens is the following:
When you look at the cache, you see, that there are two CMAKE_USE_*SSL variables set:
This is because CMAKE_USE_OPENSSL is ON by default. It is not caugth in the first run because the option is set after the multiple ssl check is performed. I think the most sustainable way to fix this is to default CMAKE_USE_OPENSSL to OFF. |
@webmaster128 Thanks for the further testing! The Autoconf build defaults to enabling OpenSSL. I think enabling some form of SSL by default is a good idea since most users expect curl to be able to make secure connections. I can move the option definitions to the top of "check for SSL" block, before the multiple SSL check is performed. In some ways that's cleaner than before, and makes it easier to do things like different defaults per-OS (if that's ever wanted). That would look like this: option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON)
option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
if(APPLE)
option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
endif()
if(WIN32)
option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON
CMAKE_USE_WINSSL OFF)
endif()
collect_true(enabled_ssl_options enabled_ssl_options_count
CMAKE_USE_WINSSL
CMAKE_USE_DARWINSSL
CMAKE_USE_OPENSSL
CMAKE_USE_MBEDTLS
)
if(enabled_ssl_options_count GREATER 1)
message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.")
endif()
if(CMAKE_USE_WINSSL)
set(SSL_ENABLED ON)
set(USE_SCHANNEL ON) # Windows native SSL/TLS support
set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI
list(APPEND CURL_LIBS "crypt32")
endif()
if(CURL_WINDOWS_SSPI)
set(USE_WINDOWS_SSPI ON)
endif()
if(CMAKE_USE_DARWINSSL)
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") Would that work for you? |
This means everyone using a different TLS provider has to explicitly disable OpenSSL, right? Apart from that, the drafted version looks good to me. |
@webmaster128 Okay, I've updated the PR with that logic. |
All tests run green now :) The only question I have left is, if there is an equivalent of |
I suggest to take that in a separate PR, as that's rather independent of specific TLS backend. |
I didn't realize I changed that behavior. I've changed the PR so it acts the same way as before (doesn't default to OpenSSL on Windows). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good, but add REQUIRED to find_package
CMakeLists.txt
Outdated
set(CURL_WINDOWS_SSPI ON) | ||
if(NOT OPENSSL_FOUND) | ||
message(FATAL_ERROR "OpenSSL not found") | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These three lines can be removed if you add "REQUIRED" to find_package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Fixed both of these.
CMakeLists.txt
Outdated
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") | ||
if(NOT COREFOUNDATION_FRAMEWORK) | ||
message(FATAL_ERROR "CoreFoundation framework not found") | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These three lines can be removed if you add REQUIRED to find_library (see cmake-commands manpage)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is REQUIRED in find_library. At least it is not documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, there is no REQUIRED for find_library
CMakeLists.txt
Outdated
if(CMAKE_USE_MBEDTLS) | ||
find_package(MbedTLS) | ||
if(NOT MBEDTLS_FOUND) | ||
message(FATAL_ERROR "mbed TLS not found") | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
REQUIRED to find_package
Hmm strange, why is CI failing here: https://travis-ci.org/curl/curl/jobs/205374812#L3906 Maybe it is an intermittent error. Can you try to update the INSTALL.cmake file with the updated state for SSL library support and re-trigger CI? |
@Lekensteyn Yeah it must be, none of the files touched in this PR are involved in that build process. I've updated the INSTALL.cmake file and re-pushed. |
From what I understand pipelining there is a timing component in what order the data is received so occasionally they fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, still works on Arch Linux with OpenSSL.
@jay When merging these patches, should only the last commit message to include "Closes ..."? (Is something else needed?) |
Btw., is CMAKE_* really a naming convention that should be used for the public curl configuration API? As far as I can see, CMAKE_* variables usually come from the CMAKE system (CMAKE_SYSTEM_NAME, CMAKE_C_FLAGS and so on). The name CMAKE_USE_OPENSSL was introduced in 2009 probably just to avoid a conflict with USE_OPENSSL. Maybe those should better be prefixed with CURL_* |
@webmaster128 I totally agree. That's a good focus for another PR. |
Typically if it were me I would squash all commits or ask the reporter to do it. I see this is a few things in one PR and there are some distinct changes it may be useful leave separate, however this is more work. 'Closes' directive is never needed as a matter of protocol, it could be closed manually. What is important though is that we have some kind of a reference Closes/Fixes/Bug/Ref:, for example
Ideally something like that would near the end of each of these commit messages, so git blame nobody has to play detective. Off the top of my head I can't easily think of an automated way to append to all the commit messages at once. Right now there is:
At the very least the commit messages should be modified to meet the style format. That would involve changing the subjects to imperative present tense, adding missing area, ref, etc:
Then after rebase make sure to confirm that you're the committer on all of them, and the authors are left intact. If it were me I'd lose at least these squashable 2: Pick Squash
|
I can understand that you want this (excellent) piece of work to be done, but my concern is that this introduces two new public variables in a naming format that is at least confusing. As soon as this is in, we need to think about compatibility and I don't think it is worth carrying around compatibility code for a decade just because CMAKE_USE_DARWINSSL and CMAKE_USE_MBEDTLS have been used for one or two weeks, maybe including a release. |
I think we should do this once and good. The names for the options used in command line should be short and simple - without any prefix. After all the user is building curl and he/she and we know that so why should we force them to type those prefixes? So I'd say - make a separate PR, cleanup all names, break the compatibility once but do it the right way. |
@ligfx Can you squash the commits according to the suggestions from @jay? @webmaster128 @jzakrzewski There are more inconsistent names (CMAKE_USE_GSSAPI, CMAKE_USE_LIBSSH2), feel free to propose a patch tot rename them (and for backwards compat, the default for the renamed options could use the former). Maybe it would be even better to introduce a separate CMakeOptions.txt to keep all options in one place. See for example https://github.com/nghttp2/nghttp2/blob/master/CMakeOptions.txt |
@Lekensteyn done |
This is closer to how configure.ac does it Ref: #1228
Assisted-by: Simon Warta <simon@kullo.net> Ref: #1228
No description provided.