1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/vendor/CPR/include/cpr/ssl_options.h
Sandu Liviu Catalin 4a6bfc086c Major plugin refactor and cleanup.
Switched to POCO library for unified platform/library interface.
Deprecated the external module API. It was creating more problems than solving.
Removed most built-in libraries in favor of system libraries for easier maintenance.
Cleaned and secured code with help from static analyzers.
2021-01-30 08:51:39 +02:00

517 lines
13 KiB
C++

#ifndef CPR_SSLOPTIONS_H
#define CPR_SSLOPTIONS_H
#include <string>
#include <curl/curl.h>
#include <utility>
#define __LIBCURL_VERSION_GTE(major, minor) \
((LIBCURL_VERSION_MAJOR > (major)) || \
((LIBCURL_VERSION_MAJOR == (major)) && (LIBCURL_VERSION_MINOR >= (minor))))
#define __LIBCURL_VERSION_LT(major, minor) \
((LIBCURL_VERSION_MAJOR < (major)) || \
((LIBCURL_VERSION_MAJOR == (major)) && (LIBCURL_VERSION_MINOR < (minor))))
#ifndef SUPPORT_ALPN
#define SUPPORT_ALPN __LIBCURL_VERSION_GTE(7, 36)
#endif
#ifndef SUPPORT_NPN
#define SUPPORT_NPN __LIBCURL_VERSION_GTE(7, 36)
#endif
#ifndef SUPPORT_SSLv2
#define SUPPORT_SSLv2 __LIBCURL_VERSION_LT(7, 19)
#endif
#ifndef SUPPORT_SSLv3
#define SUPPORT_SSLv3 __LIBCURL_VERSION_LT(7, 39)
#endif
#ifndef SUPPORT_TLSv1_0
#define SUPPORT_TLSv1_0 __LIBCURL_VERSION_GTE(7, 34)
#endif
#ifndef SUPPORT_TLSv1_1
#define SUPPORT_TLSv1_1 __LIBCURL_VERSION_GTE(7, 34)
#endif
#ifndef SUPPORT_TLSv1_2
#define SUPPORT_TLSv1_2 __LIBCURL_VERSION_GTE(7, 34)
#endif
#ifndef SUPPORT_TLSv1_3
#define SUPPORT_TLSv1_3 __LIBCURL_VERSION_GTE(7, 52)
#endif
#ifndef SUPPORT_MAX_TLS_VERSION
#define SUPPORT_MAX_TLS_VERSION __LIBCURL_VERSION_GTE(7, 54)
#endif
#ifndef SUPPORT_MAX_TLSv1_1
#define SUPPORT_MAX_TLSv1_1 __LIBCURL_VERSION_GTE(7, 54)
#endif
#ifndef SUPPORT_MAX_TLSv1_2
#define SUPPORT_MAX_TLSv1_2 __LIBCURL_VERSION_GTE(7, 54)
#endif
#ifndef SUPPORT_MAX_TLSv1_3
#define SUPPORT_MAX_TLSv1_3 __LIBCURL_VERSION_GTE(7, 54)
#endif
#ifndef SUPPORT_TLSv13_CIPHERS
#define SUPPORT_TLSv13_CIPHERS __LIBCURL_VERSION_GTE(7, 61)
#endif
#ifndef SUPPORT_SESSIONID_CACHE
#define SUPPORT_SESSIONID_CACHE __LIBCURL_VERSION_GTE(7, 16)
#endif
#ifndef SUPPORT_SSL_FALSESTART
#define SUPPORT_SSL_FALSESTART __LIBCURL_VERSION_GTE(7, 42)
#endif
namespace cpr {
class VerifySsl {
public:
VerifySsl() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
VerifySsl(bool verify) : verify(verify) {}
explicit operator bool() const {
return verify;
}
bool verify = true;
};
namespace ssl {
// set SSL client certificate
class CertFile {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
CertFile(std::string&& p_filename) : filename(std::move(p_filename)) {}
const std::string filename;
virtual const char* GetCertType() const {
return "PEM";
}
};
using PemCert = CertFile;
class DerCert : public CertFile {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
DerCert(std::string&& p_filename) : CertFile(std::move(p_filename)) {}
const char* GetCertType() const override {
return "DER";
}
};
// specify private keyfile for TLS and SSL client cert
class KeyFile {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
KeyFile(std::string&& p_filename) : filename(std::move(p_filename)) {}
template <typename FileType, typename PassType>
KeyFile(FileType&& p_filename, PassType p_password)
: filename(std::forward<FileType>(p_filename)), password(std::move(p_password)) {}
std::string filename;
std::string password;
virtual const char* GetKeyType() const {
return "PEM";
}
};
using PemKey = KeyFile;
class DerKey : public KeyFile {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
DerKey(std::string&& p_filename) : KeyFile(std::move(p_filename)) {}
template <typename FileType, typename PassType>
DerKey(FileType&& p_filename, PassType p_password)
: KeyFile(std::forward<FileType>(p_filename), std::move(p_password)) {}
const char* GetKeyType() const override {
return "DER";
}
};
#if SUPPORT_ALPN
// This option enables/disables ALPN in the SSL handshake (if the SSL backend libcurl is built to
// use supports it), which can be used to negotiate http2.
class ALPN {
public:
ALPN() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
ALPN(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = true;
};
#endif // SUPPORT_ALPN
#if SUPPORT_NPN
// This option enables/disables NPN in the SSL handshake (if the SSL backend libcurl is built to
// use supports it), which can be used to negotiate http2.
class NPN {
public:
NPN() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
NPN(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = true;
};
#endif // SUPPORT_NPN
// This option determines whether libcurl verifies that the server cert is for the server it is
// known as.
class VerifyHost {
public:
VerifyHost() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
VerifyHost(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = true;
};
// This option determines whether libcurl verifies the authenticity of the peer's certificate.
class VerifyPeer {
public:
VerifyPeer() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
VerifyPeer(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = true;
};
// This option determines whether libcurl verifies the status of the server cert using the
// "Certificate Status Request" TLS extension (aka. OCSP stapling).
class VerifyStatus {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
VerifyStatus(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = false;
};
// TLS v1.0 or later
struct TLSv1 {};
#if SUPPORT_SSLv2
// SSL v2 (but not SSLv3)
struct SSLv2 {};
#endif
#if SUPPORT_SSLv3
// SSL v3 (but not SSLv2)
struct SSLv3 {};
#endif
#if SUPPORT_TLSv1_0
// TLS v1.0 or later (Added in 7.34.0)
struct TLSv1_0 {};
#endif
#if SUPPORT_TLSv1_1
// TLS v1.1 or later (Added in 7.34.0)
struct TLSv1_1 {};
#endif
#if SUPPORT_TLSv1_2
// TLS v1.2 or later (Added in 7.34.0)
struct TLSv1_2 {};
#endif
#if SUPPORT_TLSv1_3
// TLS v1.3 or later (Added in 7.52.0)
struct TLSv1_3 {};
#endif
#if SUPPORT_MAX_TLS_VERSION
// The flag defines the maximum supported TLS version by libcurl, or the default value from the SSL
// library is used.
struct MaxTLSVersion {};
#endif
#if SUPPORT_MAX_TLSv1_0
// The flag defines maximum supported TLS version as TLSv1.0. (Added in 7.54.0)
struct MaxTLSv1_0 {};
#endif
#if SUPPORT_MAX_TLSv1_1
// The flag defines maximum supported TLS version as TLSv1.1. (Added in 7.54.0)
struct MaxTLSv1_1 {};
#endif
#if SUPPORT_MAX_TLSv1_2
// The flag defines maximum supported TLS version as TLSv1.2. (Added in 7.54.0)
struct MaxTLSv1_2 {};
#endif
#if SUPPORT_MAX_TLSv1_3
// The flag defines maximum supported TLS version as TLSv1.3. (Added in 7.54.0)
struct MaxTLSv1_3 {};
#endif
// path to Certificate Authority (CA) bundle
class CaInfo {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
CaInfo(std::string&& p_filename) : filename(std::move(p_filename)) {}
std::string filename;
};
// specify directory holding CA certificates
class CaPath {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
CaPath(std::string&& p_filename) : filename(std::move(p_filename)) {}
std::string filename;
};
// specify a Certificate Revocation List file
class Crl {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
Crl(std::string&& p_filename) : filename(std::move(p_filename)) {}
std::string filename;
};
// specify ciphers to use for TLS
class Ciphers {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
Ciphers(std::string&& p_ciphers) : ciphers(std::move(p_ciphers)) {}
std::string ciphers;
};
#if SUPPORT_TLSv13_CIPHERS
// specify ciphers suites to use for TLS 1.3
class TLS13_Ciphers {
public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
TLS13_Ciphers(std::string&& p_ciphers) : ciphers(std::move(p_ciphers)) {}
std::string ciphers;
};
#endif
#if SUPPORT_SESSIONID_CACHE
// enable/disable use of the SSL session-ID cache
class SessionIdCache {
public:
SessionIdCache() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
SessionIdCache(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = true;
};
#endif
#if SUPPORT_SSL_FALSESTART
class SslFastStart {
public:
SslFastStart() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
SslFastStart(bool enabled) : enabled(enabled) {}
explicit operator bool() const {
return enabled;
}
bool enabled = false;
};
#endif
} // namespace ssl
struct SslOptions {
std::string cert_file{};
std::string cert_type{};
std::string key_file{};
std::string key_type{};
std::string key_pass{};
#if SUPPORT_ALPN
bool enable_alpn = true;
#endif // SUPPORT_ALPN
#if SUPPORT_NPN
bool enable_npn = true;
#endif // SUPPORT_ALPN
bool verify_host = true;
bool verify_peer = true;
bool verify_status = false;
int ssl_version = CURL_SSLVERSION_DEFAULT;
#if SUPPORT_MAX_TLS_VERSION
int max_version = CURL_SSLVERSION_MAX_DEFAULT;
#endif
std::string ca_info{};
std::string ca_path{};
std::string crl_file{};
std::string ciphers{};
#if SUPPORT_TLSv13_CIPHERS
std::string tls13_ciphers{};
#endif
#if SUPPORT_SESSIONID_CACHE
bool session_id_cache = true;
#endif
SslOptions() = default;
SslOptions(const SslOptions &) = default;
SslOptions(SslOptions &&) noexcept = default;
~SslOptions() = default;
SslOptions & operator = (const SslOptions &) = default;
SslOptions & operator = (SslOptions &&) noexcept = default;
void SetOption(const ssl::CertFile& opt) {
cert_file = opt.filename;
cert_type = opt.GetCertType();
}
void SetOption(const ssl::KeyFile& opt) {
key_file = opt.filename;
key_type = opt.GetKeyType();
key_pass = opt.password;
}
#if SUPPORT_ALPN
void SetOption(const ssl::ALPN& opt) {
enable_alpn = opt.enabled;
}
#endif // SUPPORT_ALPN
#if SUPPORT_NPN
void SetOption(const ssl::NPN& opt) {
enable_npn = opt.enabled;
}
#endif // SUPPORT_NPN
void SetOption(const ssl::VerifyHost& opt) {
verify_host = opt.enabled;
}
void SetOption(const ssl::VerifyPeer& opt) {
verify_peer = opt.enabled;
}
void SetOption(const ssl::VerifyStatus& opt) {
verify_status = opt.enabled;
}
void SetOption(const ssl::TLSv1& /*opt*/) {
ssl_version = CURL_SSLVERSION_TLSv1;
}
#if SUPPORT_SSLv2
void SetOption(const ssl::SSLv2& /*opt*/) {
ssl_version = CURL_SSLVERSION_SSLv2;
}
#endif
#if SUPPORT_SSLv3
void SetOption(const ssl::SSLv3& /*opt*/) {
ssl_version = CURL_SSLVERSION_SSLv3;
}
#endif
#if SUPPORT_TLSv1_0
void SetOption(const ssl::TLSv1_0& /*opt*/) {
ssl_version = CURL_SSLVERSION_TLSv1_0;
}
#endif
#if SUPPORT_TLSv1_1
void SetOption(const ssl::TLSv1_1& /*opt*/) {
ssl_version = CURL_SSLVERSION_TLSv1_1;
}
#endif
#if SUPPORT_TLSv1_2
void SetOption(const ssl::TLSv1_2& /*opt*/) {
ssl_version = CURL_SSLVERSION_TLSv1_2;
}
#endif
#if SUPPORT_TLSv1_3
void SetOption(const ssl::TLSv1_3& /*opt*/) {
ssl_version = CURL_SSLVERSION_TLSv1_3;
}
#endif
#if SUPPORT_MAX_TLS_VERSION
void SetOption(const ssl::MaxTLSVersion& /*opt*/) {
max_version = CURL_SSLVERSION_DEFAULT;
}
#endif
#if SUPPORT_MAX_TLSv1_0
void SetOption(const ssl::MaxTLSv1_0& opt) {
max_version = CURL_SSLVERSION_MAX_TLSv1_0;
}
#endif
#if SUPPORT_MAX_TLSv1_1
void SetOption(const ssl::MaxTLSv1_1& /*opt*/) {
max_version = CURL_SSLVERSION_MAX_TLSv1_1;
}
#endif
#if SUPPORT_MAX_TLSv1_2
void SetOption(const ssl::MaxTLSv1_2& /*opt*/) {
max_version = CURL_SSLVERSION_MAX_TLSv1_2;
}
#endif
#if SUPPORT_MAX_TLSv1_3
void SetOption(const ssl::MaxTLSv1_3& /*opt*/) {
max_version = CURL_SSLVERSION_MAX_TLSv1_3;
}
#endif
void SetOption(const ssl::CaInfo& opt) {
ca_info = opt.filename;
}
void SetOption(const ssl::CaPath& opt) {
ca_path = opt.filename;
}
void SetOption(const ssl::Crl& opt) {
crl_file = opt.filename;
}
void SetOption(const ssl::Ciphers& opt) {
ciphers = opt.ciphers;
}
#if SUPPORT_TLSv13_CIPHERS
void SetOption(const ssl::TLS13_Ciphers& opt) {
tls13_ciphers = opt.ciphers;
}
#endif
#if SUPPORT_SESSIONID_CACHE
void SetOption(const ssl::SessionIdCache& opt) {
session_id_cache = opt.enabled;
}
#endif
};
namespace priv {
template <typename T>
void set_ssl_option(SslOptions& opts, T&& t) {
opts.SetOption(std::forward<T>(t));
}
template <typename T, typename... Ts>
void set_ssl_option(SslOptions& opts, T&& t, Ts&&... ts) {
set_ssl_option(opts, std::forward<T>(t));
set_ssl_option(opts, std::move(ts)...);
}
} // namespace priv
template <typename... Ts>
SslOptions Ssl(Ts&&... ts) {
SslOptions opts;
priv::set_ssl_option(opts, std::move(ts)...);
return opts;
}
} // namespace cpr
#endif