summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AppleTLSContext.cc4
-rw-r--r--src/AppleTLSContext.h10
-rw-r--r--src/AppleTLSSession.cc32
-rw-r--r--src/LibgnutlsTLSContext.cc7
-rw-r--r--src/LibgnutlsTLSContext.h8
-rw-r--r--src/LibgnutlsTLSSession.cc15
-rw-r--r--src/LibsslTLSContext.cc25
-rw-r--r--src/LibsslTLSContext.h2
-rw-r--r--src/MultiUrlRequestInfo.cc8
-rw-r--r--src/OptionHandlerFactory.cc11
-rw-r--r--src/TLSContext.h9
-rw-r--r--src/WinTLSContext.cc40
-rw-r--r--src/WinTLSContext.h2
-rw-r--r--src/prefs.cc6
-rw-r--r--src/prefs.h6
-rw-r--r--src/usage_text.h2
-rw-r--r--src/util.cc17
-rw-r--r--src/util.h6
18 files changed, 177 insertions, 33 deletions
diff --git a/src/AppleTLSContext.cc b/src/AppleTLSContext.cc
index 10e034fd..ae72b5b7 100644
--- a/src/AppleTLSContext.cc
+++ b/src/AppleTLSContext.cc
@@ -195,9 +195,9 @@ bool checkIdentity(const SecIdentityRef id,
namespace aria2 {
-TLSContext* TLSContext::make(TLSSessionSide side)
+TLSContext* TLSContext::make(TLSSessionSide side, TLSVersion ver)
{
- return new AppleTLSContext(side);
+ return new AppleTLSContext(side, ver);
}
AppleTLSContext::~AppleTLSContext()
diff --git a/src/AppleTLSContext.h b/src/AppleTLSContext.h
index b1d24154..6c72e5e9 100644
--- a/src/AppleTLSContext.h
+++ b/src/AppleTLSContext.h
@@ -49,8 +49,8 @@ namespace aria2 {
class AppleTLSContext : public TLSContext
{
public:
- AppleTLSContext(TLSSessionSide side)
- : side_(side), verifyPeer_(true), credentials_(nullptr)
+ AppleTLSContext(TLSSessionSide side, TLSVersion ver)
+ : side_(side), minTLSVer_(ver), verifyPeer_(true), credentials_(nullptr)
{}
virtual ~AppleTLSContext();
@@ -89,8 +89,14 @@ public:
SecIdentityRef getCredentials();
+ TLSVersion getMinTLSVersion() const
+ {
+ return minTLSVer_;
+ }
+
private:
TLSSessionSide side_;
+ TLSVersion minTLSVer_;
bool verifyPeer_;
SecIdentityRef credentials_;
diff --git a/src/AppleTLSSession.cc b/src/AppleTLSSession.cc
index 00c662c5..0633583f 100644
--- a/src/AppleTLSSession.cc
+++ b/src/AppleTLSSession.cc
@@ -362,14 +362,36 @@ AppleTLSSession::AppleTLSSession(AppleTLSContext* ctx)
return;
}
#if defined(__MAC_10_8)
- (void)SSLSetProtocolVersionMin(sslCtx_, kSSLProtocol3);
+ switch (ctx->getMinTLSVersion()) {
+ case TLS_PROTO_SSL3:
+ (void)SSLSetProtocolVersionMin(sslCtx_, kSSLProtocol3);
+ break;
+ case TLS_PROTO_TLS10:
+ (void)SSLSetProtocolVersionMin(sslCtx_, kSSLProtocol1);
+ break;
+ case TLS_PROTO_TLS11:
+ (void)SSLSetProtocolVersionMin(sslCtx_, kSSLProtocol11);
+ break;
+ case TLS_PROTO_TLS12:
+ (void)SSLSetProtocolVersionMin(sslCtx_, kSSLProtocol12);
+ break;
+ }
(void)SSLSetProtocolVersionMax(sslCtx_, kTLSProtocol12);
#else
(void)SSLSetProtocolVersionEnabled(sslCtx_, kSSLProtocolAll, false);
- (void)SSLSetProtocolVersionEnabled(sslCtx_, kSSLProtocol3, true);
- (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol1, true);
- (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol11, true);
- (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol12, true);
+ switch (ctx->getMinTLSVersion()) {
+ case TLS_PROTO_SSL3:
+ (void)SSLSetProtocolVersionEnabled(sslCtx_, kSSLProtocol3, true);
+ // fall through
+ case TLS_PROTO_TLS10:
+ (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol1, true);
+ // fall through
+ case TLS_PROTO_TLS11:
+ (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol11, true);
+ // fall through
+ case TLS_PROTO_TLS12:
+ (void)SSLSetProtocolVersionEnabled(sslCtx_, kTLSProtocol12, true);
+ }
#endif
// BEAST
diff --git a/src/LibgnutlsTLSContext.cc b/src/LibgnutlsTLSContext.cc
index e62f0691..df9ef6fb 100644
--- a/src/LibgnutlsTLSContext.cc
+++ b/src/LibgnutlsTLSContext.cc
@@ -49,14 +49,15 @@
namespace aria2 {
-TLSContext* TLSContext::make(TLSSessionSide side)
+TLSContext* TLSContext::make(TLSSessionSide side, TLSVersion ver)
{
- return new GnuTLSContext(side);
+ return new GnuTLSContext(side, ver);
}
-GnuTLSContext::GnuTLSContext(TLSSessionSide side)
+GnuTLSContext::GnuTLSContext(TLSSessionSide side, TLSVersion ver)
: certCred_(0),
side_(side),
+ minTLSVer_(ver),
verifyPeer_(true)
{
int r = gnutls_certificate_allocate_credentials(&certCred_);
diff --git a/src/LibgnutlsTLSContext.h b/src/LibgnutlsTLSContext.h
index ef2b005c..d31aa6d5 100644
--- a/src/LibgnutlsTLSContext.h
+++ b/src/LibgnutlsTLSContext.h
@@ -46,7 +46,7 @@ namespace aria2 {
class GnuTLSContext : public TLSContext {
public:
- GnuTLSContext(TLSSessionSide side);
+ GnuTLSContext(TLSSessionSide side, TLSVersion ver);
virtual ~GnuTLSContext();
@@ -79,9 +79,15 @@ public:
gnutls_certificate_credentials_t getCertCred() const;
+ TLSVersion getMinTLSVersion() const
+ {
+ return minTLSVer_;
+ }
+
private:
gnutls_certificate_credentials_t certCred_;
TLSSessionSide side_;
+ TLSVersion minTLSVer_;
bool good_;
bool verifyPeer_;
};
diff --git a/src/LibgnutlsTLSSession.cc b/src/LibgnutlsTLSSession.cc
index bbb8d100..deda15a3 100644
--- a/src/LibgnutlsTLSSession.cc
+++ b/src/LibgnutlsTLSSession.cc
@@ -107,7 +107,20 @@ int GnuTLSSession::init(sock_t sockfd)
// It seems err is not error message, but the argument string
// which causes syntax error.
const char* err;
- rv_ = gnutls_priority_set_direct(sslSession_, "SECURE128:-VERS-SSL3.0", &err);
+ std::string pri = "SECURE128";
+ switch(tlsContext_->getMinTLSVersion()) {
+ case TLS_PROTO_TLS12:
+ pri += ":-VERS-TLS1.1";
+ // fall through
+ case TLS_PROTO_TLS11:
+ pri += ":-VERS-TLS1.0";
+ // fall through
+ case TLS_PROTO_TLS10:
+ pri += ":-VERS-SSL3.0";
+ default:
+ break;
+ };
+ rv_ = gnutls_priority_set_direct(sslSession_, pri.c_str(), &err);
if(rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
diff --git a/src/LibsslTLSContext.cc b/src/LibsslTLSContext.cc
index 3ecac860..70c13a60 100644
--- a/src/LibsslTLSContext.cc
+++ b/src/LibsslTLSContext.cc
@@ -81,12 +81,12 @@ namespace {
namespace aria2 {
-TLSContext* TLSContext::make(TLSSessionSide side)
+TLSContext* TLSContext::make(TLSSessionSide side, TLSVersion minVer)
{
- return new OpenSSLTLSContext(side);
+ return new OpenSSLTLSContext(side, minVer);
}
-OpenSSLTLSContext::OpenSSLTLSContext(TLSSessionSide side)
+OpenSSLTLSContext::OpenSSLTLSContext(TLSSessionSide side, TLSVersion minVer)
: sslCtx_(nullptr),
side_(side),
verifyPeer_(true)
@@ -100,8 +100,23 @@ OpenSSLTLSContext::OpenSSLTLSContext(TLSSessionSide side)
ERR_error_string(ERR_get_error(), nullptr)));
return;
}
- // Disable SSLv2/3 and enable all workarounds for buggy servers
- SSL_CTX_set_options(sslCtx_, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
+
+ long ver_opts = 0;
+ switch(minVer) {
+ case TLS_PROTO_TLS12:
+ ver_opts |= SSL_OP_NO_TLSv1_1;
+ // fall through
+ case TLS_PROTO_TLS11:
+ ver_opts |= SSL_OP_NO_TLSv1;
+ // fall through
+ case TLS_PROTO_TLS10:
+ ver_opts |= SSL_OP_NO_SSLv3;
+ default:
+ break;
+ };
+
+ // Disable SSLv2 and enable all workarounds for buggy servers
+ SSL_CTX_set_options(sslCtx_, SSL_OP_ALL | SSL_OP_NO_SSLv2 | ver_opts
#ifdef SSL_OP_SINGLE_ECDH_USE
| SSL_OP_SINGLE_ECDH_USE
#endif // SSL_OP_SINGLE_ECDH_USE
diff --git a/src/LibsslTLSContext.h b/src/LibsslTLSContext.h
index 65582366..ea37e6b2 100644
--- a/src/LibsslTLSContext.h
+++ b/src/LibsslTLSContext.h
@@ -48,7 +48,7 @@ namespace aria2 {
class OpenSSLTLSContext : public TLSContext {
public:
- OpenSSLTLSContext(TLSSessionSide side);
+ OpenSSLTLSContext(TLSSessionSide side, TLSVersion minVer);
~OpenSSLTLSContext();
diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc
index 7ce24b63..e8239309 100644
--- a/src/MultiUrlRequestInfo.cc
+++ b/src/MultiUrlRequestInfo.cc
@@ -188,7 +188,9 @@ int MultiUrlRequestInfo::prepare()
}
// We set server TLS context to the SocketCore before creating
// DownloadEngine instance.
- std::shared_ptr<TLSContext> svTlsContext(TLSContext::make(TLS_SERVER));
+ auto minTLSVer = util::toTLSVersion(option_->get(PREF_MIN_TLS_VERSION));
+ std::shared_ptr<TLSContext> svTlsContext
+ (TLSContext::make(TLS_SERVER, minTLSVer));
if(!svTlsContext->addCredentialFile
(option_->get(PREF_RPC_CERTIFICATE),
option_->get(PREF_RPC_PRIVATE_KEY))) {
@@ -245,7 +247,9 @@ int MultiUrlRequestInfo::prepare()
e_->setAuthConfigFactory(std::move(authConfigFactory));
#ifdef ENABLE_SSL
- std::shared_ptr<TLSContext> clTlsContext(TLSContext::make(TLS_CLIENT));
+ auto minTLSVer = util::toTLSVersion(option_->get(PREF_MIN_TLS_VERSION));
+ std::shared_ptr<TLSContext> clTlsContext
+ (TLSContext::make(TLS_CLIENT, minTLSVer));
if(!option_->blank(PREF_CERTIFICATE)) {
clTlsContext->addCredentialFile(option_->get(PREF_CERTIFICATE),
option_->get(PREF_PRIVATE_KEY));
diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc
index dec0624a..f2f4eec9 100644
--- a/src/OptionHandlerFactory.cc
+++ b/src/OptionHandlerFactory.cc
@@ -584,6 +584,17 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
op->setChangeOptionForReserved(true);
handlers.push_back(op);
}
+#ifdef ENABLE_SSL
+ {
+ OptionHandler* op(new ParameterOptionHandler
+ (PREF_MIN_TLS_VERSION,
+ TEXT_MIN_TLS_VERSION,
+ A2_V_TLS10,
+ { A2_V_SSL3, A2_V_TLS10, A2_V_TLS11, A2_V_TLS12 }));
+ op->addTag(TAG_ADVANCED);
+ handlers.push_back(op);
+ }
+#endif // ENABLE_SSL
{
OptionHandler* op(new BooleanOptionHandler
(PREF_NO_CONF,
diff --git a/src/TLSContext.h b/src/TLSContext.h
index 64223ada..91b20965 100644
--- a/src/TLSContext.h
+++ b/src/TLSContext.h
@@ -46,9 +46,16 @@ enum TLSSessionSide {
TLS_SERVER
};
+enum TLSVersion {
+ TLS_PROTO_SSL3,
+ TLS_PROTO_TLS10,
+ TLS_PROTO_TLS11,
+ TLS_PROTO_TLS12,
+};
+
class TLSContext {
public:
- static TLSContext* make(TLSSessionSide side);
+ static TLSContext* make(TLSSessionSide side, TLSVersion minVer);
virtual ~TLSContext() {}
// private key `keyfile' must be decrypted.
diff --git a/src/WinTLSContext.cc b/src/WinTLSContext.cc
index ee67cfd0..d30aea52 100644
--- a/src/WinTLSContext.cc
+++ b/src/WinTLSContext.cc
@@ -63,28 +63,50 @@
namespace aria2 {
-WinTLSContext::WinTLSContext(TLSSessionSide side) : side_(side), store_(0)
+WinTLSContext::WinTLSContext(TLSSessionSide side, TLSVersion ver)
+ : side_(side), store_(0)
{
memset(&credentials_, 0, sizeof(credentials_));
credentials_.dwVersion = SCHANNEL_CRED_VERSION;
+ credentials_.grbitEnabledProtocols = 0;
if (side_ == TLS_CLIENT) {
- credentials_.grbitEnabledProtocols =
- SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT |
- SP_PROT_TLS1_2_CLIENT;
+ switch (ver) {
+ case TLS_PROTO_SSL3:
+ credentials_.grbitEnabledProtocols |= SP_PROT_SSL3_CLIENT;
+ // fall through
+ case TLS_PROTO_TLS10:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_CLIENT;
+ // fall through
+ case TLS_PROTO_TLS11:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ // fall through
+ case TLS_PROTO_TLS12:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ }
}
else {
- credentials_.grbitEnabledProtocols =
- SP_PROT_SSL3_SERVER | SP_PROT_TLS1_SERVER | SP_PROT_TLS1_1_SERVER |
- SP_PROT_TLS1_2_SERVER;
+ switch (ver) {
+ case TLS_PROTO_SSL3:
+ credentials_.grbitEnabledProtocols |= SP_PROT_SSL3_SERVER;
+ // fall through
+ case TLS_PROTO_TLS10:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_SERVER;
+ // fall through
+ case TLS_PROTO_TLS11:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_1_SERVER;
+ // fall through
+ case TLS_PROTO_TLS12:
+ credentials_.grbitEnabledProtocols |= SP_PROT_TLS1_2_SERVER;
+ }
}
credentials_.dwMinimumCipherStrength = 128; // bit
setVerifyPeer(side_ == TLS_CLIENT);
}
-TLSContext* TLSContext::make(TLSSessionSide side)
+TLSContext* TLSContext::make(TLSSessionSide side, TLSVersion ver)
{
- return new WinTLSContext(side);
+ return new WinTLSContext(side, ver);
}
WinTLSContext::~WinTLSContext()
diff --git a/src/WinTLSContext.h b/src/WinTLSContext.h
index 7b182c6f..8ca9e3a8 100644
--- a/src/WinTLSContext.h
+++ b/src/WinTLSContext.h
@@ -67,7 +67,7 @@ typedef std::unique_ptr<CredHandle, cred_deleter> CredPtr;
class WinTLSContext : public TLSContext
{
public:
- WinTLSContext(TLSSessionSide side);
+ WinTLSContext(TLSSessionSide side, TLSVersion ver);
virtual ~WinTLSContext();
diff --git a/src/prefs.cc b/src/prefs.cc
index a6de66ef..2332bd57 100644
--- a/src/prefs.cc
+++ b/src/prefs.cc
@@ -169,6 +169,10 @@ const std::string V_ARC4("arc4");
const std::string V_HTTP("http");
const std::string V_HTTPS("https");
const std::string V_FTP("ftp");
+const std::string A2_V_SSL3("SSLv3");
+const std::string A2_V_TLS10("TLSv1");
+const std::string A2_V_TLS11("TLSv1.1");
+const std::string A2_V_TLS12("TLSv1.2");
PrefPtr PREF_VERSION = makePref("version");
PrefPtr PREF_HELP = makePref("help");
@@ -367,6 +371,8 @@ PrefPtr PREF_DSCP = makePref("dscp");
PrefPtr PREF_PAUSE_METADATA = makePref("pause-metadata");
// values: 1*digit
PrefPtr PREF_RLIMIT_NOFILE = makePref("rlimit-nofile");
+// vlaues: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
+PrefPtr PREF_MIN_TLS_VERSION = makePref("min-tls-version");
/**
* FTP related preferences
diff --git a/src/prefs.h b/src/prefs.h
index 33ab67ac..a4b5bfdf 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -105,6 +105,10 @@ extern const std::string V_ARC4;
extern const std::string V_HTTP;
extern const std::string V_HTTPS;
extern const std::string V_FTP;
+extern const std::string A2_V_SSL3;
+extern const std::string A2_V_TLS10;
+extern const std::string A2_V_TLS11;
+extern const std::string A2_V_TLS12;
extern PrefPtr PREF_VERSION;
extern PrefPtr PREF_HELP;
@@ -304,6 +308,8 @@ extern PrefPtr PREF_DSCP;
extern PrefPtr PREF_PAUSE_METADATA;
// values: 1*digit
extern PrefPtr PREF_RLIMIT_NOFILE;
+// vlaues: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
+extern PrefPtr PREF_MIN_TLS_VERSION;
/**
* FTP related preferences
diff --git a/src/usage_text.h b/src/usage_text.h
index 2831b48e..1b139b13 100644
--- a/src/usage_text.h
+++ b/src/usage_text.h
@@ -1011,3 +1011,5 @@
" and the next download waiting in queue gets\n" \
" started. But be aware that seeding item is still\n" \
" recognized as active download in RPC method.")
+#define TEXT_MIN_TLS_VERSION \
+ _(" --min-tls-version=VERSION Specify minimum SSL/TLS version to enable.")
diff --git a/src/util.cc b/src/util.cc
index 0a0f3901..9332ae47 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -2009,6 +2009,23 @@ bool strless(const char* a, const char* b)
return strcmp(a, b) < 0;
}
+TLSVersion toTLSVersion(const std::string& ver)
+{
+ if(ver == A2_V_SSL3) {
+ return TLS_PROTO_SSL3;
+ }
+ if(ver == A2_V_TLS10) {
+ return TLS_PROTO_TLS10;
+ }
+ if(ver == A2_V_TLS11) {
+ return TLS_PROTO_TLS11;
+ }
+ if(ver == A2_V_TLS12) {
+ return TLS_PROTO_TLS12;
+ }
+ return TLS_PROTO_TLS10;
+}
+
} // namespace util
} // namespace aria2
diff --git a/src/util.h b/src/util.h
index d14d8fc9..ff24c279 100644
--- a/src/util.h
+++ b/src/util.h
@@ -64,6 +64,10 @@
#include "fmt.h"
#include "prefs.h"
+#ifdef ENABLE_SSL
+#include "TLSContext.h"
+#endif // ENABLE_SSL
+
#ifndef HAVE_SIGACTION
# define sigset_t int
#endif // HAVE_SIGACTION
@@ -880,6 +884,8 @@ bool noProxyDomainMatch(const std::string& hostname, const std::string& domain);
// Checks hostname matches pattern as described in RFC 6125.
bool tlsHostnameMatch(const std::string& pattern, const std::string& hostname);
+TLSVersion toTLSVersion(const std::string& ver);
+
} // namespace util
} // namespace aria2