From 94e5cf7540bec68bd8d9b299852907679f51a90e Mon Sep 17 00:00:00 2001 From: Stefano Bonicatti Date: Mon, 18 Mar 2024 19:35:01 +0100 Subject: [PATCH] temp --- osquery/core/init.cpp | 2 + osquery/remote/transports/tls.cpp | 261 ++++++++++++++++++------------ osquery/remote/transports/tls.h | 24 +-- 3 files changed, 169 insertions(+), 118 deletions(-) diff --git a/osquery/core/init.cpp b/osquery/core/init.cpp index 7fca23d3476..ef11605e08a 100644 --- a/osquery/core/init.cpp +++ b/osquery/core/init.cpp @@ -360,6 +360,8 @@ Initializer::Initializer(int& argc, // Let gflags parse the non-help options/flags. GFLAGS_NAMESPACE::ParseCommandLineFlags(argc_, argv_, isShell()); + std::cout << "Post parsing" << std::endl; + if (isShell()) { // Do not set these values before calling ParseCommandLineFlags. // These values are force-set and ignore the configuration and CLI. diff --git a/osquery/remote/transports/tls.cpp b/osquery/remote/transports/tls.cpp index 19687b010f8..bd3ea63d017 100644 --- a/osquery/remote/transports/tls.cpp +++ b/osquery/remote/transports/tls.cpp @@ -11,12 +11,15 @@ #include #include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -89,12 +92,17 @@ DECLARE_bool(verbose); namespace { enum class OpenSSLMode { Default, Native }; -constexpr bool isUnsafeTLSDisabled() { -#ifndef NDEBUG - return !FLAGS_tls_allow_unsafe; -#else - return true; -#endif +// This is used when parsing the certificate flags, +// to understand if the user is attempting to specify a mixed mode, +// which is not supported +static std::optional detectedOpenSSLMode; + +std::string extractTLSParams(std::string uri, OpenSSLMode mode) { + if (mode == OpenSSLMode::Default) { + return uri.substr(kFilePrefix.size()); + } else { + return uri.substr(kCertPrefix.size()); + } } std::optional detectOpenSSLMode(std::string_view uri) { @@ -109,6 +117,126 @@ std::optional detectOpenSSLMode(std::string_view uri) { return std::nullopt; } +bool validateClientCert(const char* flagname, const std::string& value) { + std::cout << "Attempting to validate tls_client_cert" << std::endl; + + if (value.empty()) { + return true; + } + + std::cout << "Client cert value is: " << value << std::endl; + + auto opt_openssl_mode = detectOpenSSLMode(value); + if (!opt_openssl_mode.has_value()) { + osquery::systemLog( + "The tls_client_cert value should either start with cert:// or " + "file://"); + std::cerr + << "The tls_client_cert value should either start with cert:// or " + "file://" + << std::endl; + return false; + } + + std::cerr << "OpenSSL mode: " << int(*opt_openssl_mode) << std::endl; + + if (detectedOpenSSLMode.has_value() && + detectedOpenSSLMode != opt_openssl_mode) { + osquery::systemLog( + "Cannot mix filesystem and native store mode in the client/server " + "certificates and private key options"); + std::cerr << "Cannot mix filesystem and native store mode in the " + "client/server certificates and private key options" + << std::endl; + return false; + } + + detectedOpenSSLMode = opt_openssl_mode; + + return true; +} + +bool validateClientKey(const char* flagname, const std::string& value) { + std::cout << "Attempting to validate tls_client_key" << std::endl; + + if (value.empty()) { + return true; + } + + std::cout << "Client cert key is: " << value << std::endl; + + auto opt_openssl_mode = detectOpenSSLMode(value); + if (!opt_openssl_mode.has_value() || + *opt_openssl_mode == OpenSSLMode::Native) { + osquery::systemLog("The tls_client_key value should start with file://"); + std::cerr << "The tls_client_key value should start with file://" + << std::endl; + return false; + } + + if (detectedOpenSSLMode.has_value() && + detectedOpenSSLMode != opt_openssl_mode) { + osquery::systemLog( + "Cannot mix filesystem and native store mode in the client/server " + "certificates and private key options"); + std::cerr << "Cannot mix filesystem and native store mode in the " + "client/server certificates and private key options" + << std::endl; + return false; + } + + detectedOpenSSLMode = opt_openssl_mode; + + return true; +} + +bool validateServerCerts(const char* flagname, const std::string& value) { + std::cout << "Attempting to validate tls_server_certs" << std::endl; + + if (value.empty()) { + return true; + } + + std::cout << "Server cert value is: " << value << std::endl; + + auto opt_openssl_mode = detectOpenSSLMode(value); + if (!opt_openssl_mode.has_value()) { + osquery::systemLog( + "The tls_server_certs value should either start with cert:// or " + "file://"); + std::cerr + << "The tls_server_certs value should either start with cert:// or " + "file://" + << std::endl; + return false; + } + + std::cerr << "OpenSSL mode: " << int(*opt_openssl_mode) << std::endl; + + if (detectedOpenSSLMode.has_value() && + detectedOpenSSLMode != opt_openssl_mode) { + osquery::systemLog( + "Cannot mix filesystem and native store mode in the client/server " + "certificates and private key options"); + std::cerr << "Cannot mix filesystem and native store mode in the " + "client/server certificates and private key options" + << std::endl; + return false; + } + + detectedOpenSSLMode = opt_openssl_mode; + + return true; +} + +constexpr bool isUnsafeTLSDisabled() { +#ifndef NDEBUG + return !FLAGS_tls_allow_unsafe; +#else + return true; +#endif +} + std::optional parseCertParams(std::string_view cert_params_string) { if (cert_params_string == "all") { @@ -177,94 +305,11 @@ http::Client::Options createCommonOptions(bool verify_peer) { } std::optional> -createOpenSSLParametersFrom(std::string client_certificate_uri, - std::string client_private_key_uri, - std::string server_certificate_uri) { - auto last_detected_openssl_mode = OpenSSLMode::Default; - std::string_view client_certificate_params; - std::string_view client_private_key_params; - std::string_view server_certificate_params; - - if (!server_certificate_uri.empty()) { - auto opt_openssl_mode = detectOpenSSLMode(server_certificate_uri); - - if (!opt_openssl_mode.has_value()) { - LOG(ERROR) << "Could not properly parse the tls_server_certs flag, " - "format was incorrect"; - return std::nullopt; - } - - last_detected_openssl_mode = *opt_openssl_mode; - - if (last_detected_openssl_mode == OpenSSLMode::Default) { - server_certificate_params = - std::string_view(server_certificate_uri.data() + kFilePrefix.size(), - server_certificate_uri.size() - kFilePrefix.size()); - } else { - server_certificate_params = - std::string_view(server_certificate_uri.data() + kCertPrefix.size(), - server_certificate_uri.size() - kCertPrefix.size()); - } - } - - if (!client_certificate_uri.empty()) { - auto opt_openssl_mode = detectOpenSSLMode(client_certificate_uri); - - if (!opt_openssl_mode.has_value()) { - LOG(ERROR) << "Could not properly parse the tls_client_cert flag, " - "format was incorrect"; - return std::nullopt; - } - - if (*opt_openssl_mode != last_detected_openssl_mode) { - LOG(ERROR) << "Cannot mix filesystem and native store mode in the " - "client/server certificates and private key options"; - return std::nullopt; - } - - last_detected_openssl_mode = *opt_openssl_mode; - - if (last_detected_openssl_mode == OpenSSLMode::Default) { - client_certificate_params = - std::string_view(client_certificate_uri.data() + kFilePrefix.size(), - client_certificate_uri.size() - kFilePrefix.size()); - } else { - client_certificate_params = - std::string_view(client_certificate_uri.data() + kCertPrefix.size(), - client_certificate_uri.size() - kCertPrefix.size()); - } - } - - // TODO: Cleanup, group this with the client cert check, since they need to be - // both present - if (!client_private_key_uri.empty()) { - auto opt_openssl_mode = detectOpenSSLMode(client_certificate_uri); - - if (!opt_openssl_mode.has_value()) { - LOG(ERROR) << "Could not properly parse the tls_client_cert flag, " - "format was incorrect"; - return std::nullopt; - } - - if (*opt_openssl_mode != last_detected_openssl_mode) { - LOG(ERROR) << "Cannot mix filesystem and native store mode in the " - "client/server certificates and private key options"; - return std::nullopt; - } - - if (last_detected_openssl_mode != OpenSSLMode::Default) { - LOG(WARNING) - << "The tls_client_key option must be of the format file://, it cannot be in native store form. " - "Value will be ignored."; - } - - client_private_key_params = - std::string_view(client_private_key_uri.data() + kFilePrefix.size(), - client_private_key_uri.size() - kFilePrefix.size()); - } - - if (last_detected_openssl_mode == OpenSSLMode::Default) { +createOpenSSLParametersFrom(std::string client_certificate_params, + std::string client_private_key_params, + std::string server_certificate_params, + OpenSSLMode openssl_mode) { + if (openssl_mode == OpenSSLMode::Default) { DefaultOpenSSLParameters openssl_parameters{}; if (!server_certificate_params.empty()) { @@ -334,8 +379,6 @@ createOpenSSLParametersFrom(std::string client_certificate_uri, return openssl_parameters; } - last_detected_openssl_mode = OpenSSLMode::Native; - openssl_parameters.server_search_parameters = std::get( *opt_cert_params); @@ -350,8 +393,6 @@ createOpenSSLParametersFrom(std::string client_certificate_uri, return openssl_parameters; } - last_detected_openssl_mode = OpenSSLMode::Native; - openssl_parameters.client_cert_search_parameters = *opt_cert_params; } @@ -362,10 +403,17 @@ createOpenSSLParametersFrom(std::string client_certificate_uri, } } // namespace +DEFINE_validator(tls_client_cert, &validateClientCert); +DEFINE_validator(tls_client_key, &validateClientKey); +DEFINE_validator(tls_server_certs, &validateServerCerts); + TLSTransport::TLSTransport() - : server_certificate_file_(FLAGS_tls_server_certs), - client_certificate_file_(FLAGS_tls_client_cert), - client_private_key_file_(FLAGS_tls_client_key) {} + : server_certificate_params_(extractTLSParams(FLAGS_tls_server_certs, + detectedOpenSSLMode.value())), + client_certificate_params_( + extractTLSParams(FLAGS_tls_client_cert, detectedOpenSSLMode.value())), + client_private_key_params_(extractTLSParams( + FLAGS_tls_client_key, detectedOpenSSLMode.value())) {} void TLSTransport::decorateRequest(http::Request& r) { r << http::Request::Header("Content-Type", serializer_->getContentType()); @@ -376,8 +424,8 @@ void TLSTransport::decorateRequest(http::Request& r) { http::Client::Options TLSTransport::getOptions() { http::Client::Options options = createCommonOptions(verify_peer_); - auto openssl_cert_parameters = - createOpenSSLParametersFrom({}, {}, server_certificate_file_); + auto openssl_cert_parameters = createOpenSSLParametersFrom( + {}, {}, server_certificate_params_, detectedOpenSSLMode.value()); options.openssl_set_cert_parameters(openssl_cert_parameters); @@ -391,9 +439,10 @@ http::Client::Options TLSTransport::getInternalOptions() { http::Client::Options options = createCommonOptions(verify_peer_); auto openssl_cert_parameters = - createOpenSSLParametersFrom(client_certificate_file_, - client_private_key_file_, - server_certificate_file_); + createOpenSSLParametersFrom(client_certificate_params_, + client_private_key_params_, + server_certificate_params_, + detectedOpenSSLMode.value()); options.openssl_set_cert_parameters(openssl_cert_parameters); diff --git a/osquery/remote/transports/tls.h b/osquery/remote/transports/tls.h index 275cd49cd30..555d18a8c5e 100644 --- a/osquery/remote/transports/tls.h +++ b/osquery/remote/transports/tls.h @@ -105,26 +105,26 @@ class TLSTransport : public Transport { } /// Set TLS-client authentication options. - void setClientCertificate(const std::string& certificate_file, - const std::string& private_key_file) { - client_certificate_file_ = certificate_file; - client_private_key_file_ = private_key_file; + void setClientCertificate(const std::string& certificate_params, + const std::string& private_key_params) { + client_certificate_params_ = certificate_params; + client_private_key_params_ = private_key_params; } /// Set TLS server/ca pinning options. - void setPeerCertificate(const std::string& server_certificate_file) { - server_certificate_file_ = server_certificate_file; + void setPeerCertificate(const std::string& server_certificate_params) { + server_certificate_params_ = server_certificate_params; } private: - /// Optional TLS client-auth client certificate filename. - std::string client_certificate_file_; + /// Optional TLS client-auth client certificate uri. + std::string client_certificate_params_; - /// Optional TLS client-auth client private key filename. - std::string client_private_key_file_; + /// Optional TLS client-auth client private key uri. + std::string client_private_key_params_; - /// Optional TLS server-pinning server certificate/bundle filename. - std::string server_certificate_file_; + /// Optional TLS server-pinning server certificate/bundle uri. + std::string server_certificate_params_; /// Testing-only, disable peer verification. bool verify_peer_{true};