From cc1ebbf3795356c45706fcdc7809ad77745d29d9 Mon Sep 17 00:00:00 2001 From: NotTsunami <4589807+NotTsunami@users.noreply.github.com> Date: Wed, 22 Apr 2020 15:50:13 -0400 Subject: [PATCH] Add HTTPS tracker certificate validation option This commit adds a new libtorrent setting to validate HTTPS tracker certificates. When enabled, libtorrent will validate the certificate of HTTPS trackers against the system's certificate store. This option is only enabled on libtorrent versions >= 1.2.6 and on non-Windows systems, as OpenSSL does not use the system's certificate store on Windows. --- src/base/bittorrent/session.cpp | 18 ++++++++++++++++++ src/base/bittorrent/session.h | 7 +++++++ src/gui/advancedsettings.cpp | 14 ++++++++++++++ src/gui/advancedsettings.h | 2 +- src/webui/api/appcontroller.cpp | 5 +++++ src/webui/www/private/views/preferences.html | 10 ++++++++++ 6 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 418b617cd..f584c1bc2 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -417,6 +417,7 @@ Session::Session(QObject *parent) , m_utpMixedMode(BITTORRENT_SESSION_KEY("uTPMixedMode"), MixedModeAlgorithm::TCP , clampValue(MixedModeAlgorithm::TCP, MixedModeAlgorithm::Proportional)) , m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false) + , m_validateHTTPSTrackerCertificate(BITTORRENT_SESSION_KEY("ValidateHTTPSTrackerCertificate"), false) , m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false) , m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers")) , m_globalMaxRatio(BITTORRENT_SESSION_KEY("GlobalMaxRatio"), -1, [](qreal r) { return r < 0 ? -1. : r;}) @@ -1416,6 +1417,10 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack) settingsPack.set_bool(lt::settings_pack::allow_multiple_connections_per_ip, multiConnectionsPerIpEnabled()); +#ifdef HAS_HTTPS_TRACKER_VALIDATION + settingsPack.set_bool(lt::settings_pack::validate_https_trackers, validateHTTPSTrackerCertificate()); +#endif + settingsPack.set_bool(lt::settings_pack::apply_ip_filter_to_trackers, isTrackerFilteringEnabled()); settingsPack.set_bool(lt::settings_pack::enable_dht, isDHTEnabled()); @@ -3703,6 +3708,19 @@ void Session::setMultiConnectionsPerIpEnabled(const bool enabled) configureDeferred(); } +bool Session::validateHTTPSTrackerCertificate() const +{ + return m_validateHTTPSTrackerCertificate; +} + +void Session::setValidateHTTPSTrackerCertificate(const bool enabled) +{ + if (enabled == m_validateHTTPSTrackerCertificate) return; + + m_validateHTTPSTrackerCertificate = enabled; + configureDeferred(); +} + bool Session::isTrackerFilteringEnabled() const { return m_isTrackerFilteringEnabled; diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index 892a8db28..a65de4cea 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -46,6 +46,10 @@ #include "sessionstatus.h" #include "torrentinfo.h" +#if ((LIBTORRENT_VERSION_NUM >= 10206) && !defined(Q_OS_WIN)) +#define HAS_HTTPS_TRACKER_VALIDATION +#endif + class QFile; class QNetworkConfiguration; class QNetworkConfigurationManager; @@ -399,6 +403,8 @@ namespace BitTorrent void setUtpMixedMode(MixedModeAlgorithm mode); bool multiConnectionsPerIpEnabled() const; void setMultiConnectionsPerIpEnabled(bool enabled); + bool validateHTTPSTrackerCertificate() const; + void setValidateHTTPSTrackerCertificate(bool enabled); bool isTrackerFilteringEnabled() const; void setTrackerFilteringEnabled(bool enabled); QStringList bannedIPs() const; @@ -660,6 +666,7 @@ namespace BitTorrent CachedSettingValue m_isUTPRateLimited; CachedSettingValue m_utpMixedMode; CachedSettingValue m_multiConnectionsPerIpEnabled; + CachedSettingValue m_validateHTTPSTrackerCertificate; CachedSettingValue m_isAddTrackersEnabled; CachedSettingValue m_additionalTrackers; CachedSettingValue m_globalMaxRatio; diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp index a6e91fa9f..186eb2851 100644 --- a/src/gui/advancedsettings.cpp +++ b/src/gui/advancedsettings.cpp @@ -105,6 +105,9 @@ enum AdvSettingsRows OUTGOING_PORT_MAX, UTP_MIX_MODE, MULTI_CONNECTIONS_PER_IP, +#ifdef HAS_HTTPS_TRACKER_VALIDATION + VALIDATE_HTTPS_TRACKER_CERTIFICATE, +#endif // embedded tracker TRACKER_STATUS, TRACKER_PORT, @@ -209,6 +212,10 @@ void AdvancedSettings::saveAdvancedSettings() session->setUtpMixedMode(static_cast(m_comboBoxUtpMixedMode.currentIndex())); // multiple connections per IP session->setMultiConnectionsPerIpEnabled(m_checkBoxMultiConnectionsPerIp.isChecked()); +#ifdef HAS_HTTPS_TRACKER_VALIDATION + // Validate HTTPS tracker certificate + session->setValidateHTTPSTrackerCertificate(m_checkBoxValidateHTTPSTrackerCertificate.isChecked()); +#endif // Recheck torrents on completion pref->recheckTorrentsOnCompletion(m_checkBoxRecheckCompleted.isChecked()); // Transfer list refresh interval @@ -485,6 +492,13 @@ void AdvancedSettings::loadAdvancedSettings() // multiple connections per IP m_checkBoxMultiConnectionsPerIp.setChecked(session->multiConnectionsPerIpEnabled()); addRow(MULTI_CONNECTIONS_PER_IP, tr("Allow multiple connections from the same IP address"), &m_checkBoxMultiConnectionsPerIp); +#ifdef HAS_HTTPS_TRACKER_VALIDATION + // Validate HTTPS tracker certificate + m_checkBoxValidateHTTPSTrackerCertificate.setChecked(session->validateHTTPSTrackerCertificate()); + addRow(VALIDATE_HTTPS_TRACKER_CERTIFICATE, (tr("Validate HTTPS tracker certificates") + + ' ' + makeLink("https://www.libtorrent.org/reference-Settings.html#validate_https_trackers", "(?)")) + , &m_checkBoxValidateHTTPSTrackerCertificate); +#endif // Recheck completed torrents m_checkBoxRecheckCompleted.setChecked(pref->recheckTorrentsOnCompletion()); addRow(RECHECK_COMPLETED, tr("Recheck torrents on completion"), &m_checkBoxRecheckCompleted); diff --git a/src/gui/advancedsettings.h b/src/gui/advancedsettings.h index 5e3beb192..934ff8426 100644 --- a/src/gui/advancedsettings.h +++ b/src/gui/advancedsettings.h @@ -64,7 +64,7 @@ private: QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts, m_checkBoxSuperSeeding, m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus, m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers, - m_checkBoxMultiConnectionsPerIp, m_checkBoxPieceExtentAffinity, m_checkBoxSuggestMode, m_checkBoxCoalesceRW, m_checkBoxSpeedWidgetEnabled; + m_checkBoxMultiConnectionsPerIp, m_checkBoxValidateHTTPSTrackerCertificate, m_checkBoxPieceExtentAffinity, m_checkBoxSuggestMode, m_checkBoxCoalesceRW, m_checkBoxSpeedWidgetEnabled; QComboBox m_comboBoxInterface, m_comboBoxInterfaceAddress, m_comboBoxUtpMixedMode, m_comboBoxChokingAlgorithm, m_comboBoxSeedChokingAlgorithm; QLineEdit m_lineEditAnnounceIP; diff --git a/src/webui/api/appcontroller.cpp b/src/webui/api/appcontroller.cpp index 49f5c5a72..1c28becfe 100644 --- a/src/webui/api/appcontroller.cpp +++ b/src/webui/api/appcontroller.cpp @@ -300,6 +300,8 @@ void AppController::preferencesAction() data["utp_tcp_mixed_mode"] = static_cast(session->utpMixedMode()); // Multiple connections per IP data["enable_multi_connections_from_same_ip"] = session->multiConnectionsPerIpEnabled(); + // Validate HTTPS tracker certificate + data["validate_https_tracker_certificate"] = session->validateHTTPSTrackerCertificate(); // Embedded tracker data["enable_embedded_tracker"] = session->isTrackerEnabled(); data["embedded_tracker_port"] = pref->getTrackerPort(); @@ -723,6 +725,9 @@ void AppController::setPreferencesAction() // Multiple connections per IP if (hasKey("enable_multi_connections_from_same_ip")) session->setMultiConnectionsPerIpEnabled(it.value().toBool()); + // Validate HTTPS tracker certificate + if (hasKey("validate_https_tracker_certificate")) + session->setValidateHTTPSTrackerCertificate(it.value().toBool()); // Embedded tracker if (hasKey("embedded_tracker_port")) pref->setTrackerPort(it.value().toInt()); diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index bafce04cb..ad0f91098 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -1018,6 +1018,14 @@ + + + + + + + + @@ -1777,6 +1785,7 @@ $('outgoingPortsMax').setProperty('value', pref.outgoing_ports_max); $('utpTCPMixedModeAlgorithm').setProperty('value', pref.utp_tcp_mixed_mode); $('allowMultipleConnectionsFromTheSameIPAddress').setProperty('checked', pref.enable_multi_connections_from_same_ip); + $('validateHTTPSTrackerCertificate').setProperty('checked', pref.validate_https_tracker_certificate); $('enableEmbeddedTracker').setProperty('checked', pref.enable_embedded_tracker); $('embeddedTrackerPort').setProperty('value', pref.embedded_tracker_port); $('uploadSlotsBehavior').setProperty('value', pref.upload_slots_behavior); @@ -2145,6 +2154,7 @@ settings.set('outgoing_ports_max', $('outgoingPortsMax').getProperty('value')); settings.set('utp_tcp_mixed_mode', $('utpTCPMixedModeAlgorithm').getProperty('value')); settings.set('enable_multi_connections_from_same_ip', $('allowMultipleConnectionsFromTheSameIPAddress').getProperty('checked')); + settings.set('validate_https_tracker_certificate', $('validateHTTPSTrackerCertificate').getProperty('checked')); settings.set('enable_embedded_tracker', $('enableEmbeddedTracker').getProperty('checked')); settings.set('embedded_tracker_port', $('embeddedTrackerPort').getProperty('value')); settings.set('upload_slots_behavior', $('uploadSlotsBehavior').getProperty('value'));