From cdd9411d5d539bfba735e4a973eec35b15112b65 Mon Sep 17 00:00:00 2001 From: kaso17 Date: Tue, 28 Feb 2017 20:05:57 +0100 Subject: [PATCH] Add support for self signed certificates --- src/Jackett/Definitions/rapidetracker.yml | 2 ++ src/Jackett/Indexers/BaseIndexer.cs | 2 +- src/Jackett/Indexers/CardigannIndexer.cs | 13 ++++++++ src/Jackett/Indexers/TorrentHeaven.cs | 12 +++++-- src/Jackett/Utils/Clients/HttpWebClient.cs | 37 +++++++++++++++++++++ src/Jackett/Utils/Clients/HttpWebClient2.cs | 24 +++++++++++++ src/Jackett/Utils/Clients/IWebClient.cs | 5 +++ 7 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/Jackett/Definitions/rapidetracker.yml b/src/Jackett/Definitions/rapidetracker.yml index d8865cb7a..d24edb638 100644 --- a/src/Jackett/Definitions/rapidetracker.yml +++ b/src/Jackett/Definitions/rapidetracker.yml @@ -6,6 +6,8 @@ encoding: UTF-8 links: - https://rapidetracker.net + certificates: + - B0238C547A905BFA119C4E8BACCAEACF36491FF6 caps: categories: diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index 1d25c2c3c..636c9cb3e 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -321,7 +321,7 @@ namespace Jackett.Indexers } } - public void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false) + virtual public void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false) { IProtectionService ps = null; if (useProtectionService) diff --git a/src/Jackett/Indexers/CardigannIndexer.cs b/src/Jackett/Indexers/CardigannIndexer.cs index cb4d340c8..de06d254f 100644 --- a/src/Jackett/Indexers/CardigannIndexer.cs +++ b/src/Jackett/Indexers/CardigannIndexer.cs @@ -47,6 +47,7 @@ namespace Jackett.Indexers public string Language { get; set; } public string Encoding { get; set; } public List Links { get; set; } + public List Certificates { get; set; } public capabilitiesBlock Caps { get; set; } public loginBlock Login { get; set; } public ratioBlock Ratio { get; set; } @@ -296,6 +297,18 @@ namespace Jackett.Indexers LoadValuesFromJson(null); } + public override void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false) + { + base.LoadValuesFromJson(jsonConfig, useProtectionService); + + // add self signed cert to trusted certs + if (Definition.Certificates != null) + { + foreach (var certificateHash in Definition.Certificates) + webclient.AddTrustedCertificate(new Uri(SiteLink).Host, certificateHash); + } + } + protected Dictionary getTemplateVariablesFromConfigData() { Dictionary variables = new Dictionary(); diff --git a/src/Jackett/Indexers/TorrentHeaven.cs b/src/Jackett/Indexers/TorrentHeaven.cs index 045909821..6057f58ef 100644 --- a/src/Jackett/Indexers/TorrentHeaven.cs +++ b/src/Jackett/Indexers/TorrentHeaven.cs @@ -13,7 +13,6 @@ using Jackett.Models.IndexerConfig; using System.Collections.Specialized; using System.Text; using System.Linq; -using System.Threading; using System.Text.RegularExpressions; namespace Jackett.Indexers @@ -22,6 +21,7 @@ namespace Jackett.Indexers { string IndexUrl { get { return SiteLink + "index.php"; } } string LoginCompleteUrl { get { return SiteLink + "index.php?strWebValue=account&strWebAction=login_complete&ancestry=verify"; } } + static readonly string certificateHash = "6F5CE30D578C2A7AECFB919D0D013976D395055F"; new ConfigurationDataCaptchaLogin configData { @@ -39,7 +39,7 @@ namespace Jackett.Indexers logger: l, p: ps, configData: new ConfigurationDataCaptchaLogin()) - { + { Encoding = Encoding.GetEncoding("iso-8859-1"); Language = "de-de"; Type = "private"; @@ -92,6 +92,14 @@ namespace Jackett.Indexers AddCategoryMapping(71, TorznabCatType.PCMac); // APPLICATIONS/Mac } + public override void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false) + { + base.LoadValuesFromJson(jsonConfig, useProtectionService); + + // add self signed cert to trusted certs + webclient.AddTrustedCertificate(new Uri(SiteLink).Host, certificateHash); + } + public override async Task GetConfigurationForSetup() { var loginPage = await RequestStringWithCookies(IndexUrl, string.Empty); diff --git a/src/Jackett/Utils/Clients/HttpWebClient.cs b/src/Jackett/Utils/Clients/HttpWebClient.cs index 178eb9f25..4e3ac47a7 100644 --- a/src/Jackett/Utils/Clients/HttpWebClient.cs +++ b/src/Jackett/Utils/Clients/HttpWebClient.cs @@ -8,6 +8,8 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -16,6 +18,8 @@ namespace Jackett.Utils.Clients { public class HttpWebClient : IWebClient { + static protected Dictionary> trustedCertificates = new Dictionary>(); + public HttpWebClient(IProcessService p, Logger l, IConfigurationService c) : base(p: p, l: l, @@ -30,6 +34,26 @@ namespace Jackett.Utils.Clients logger.Info(string.Format("HttpWebClient: Disabling certificate validation")); ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; } + + // custom handler for our own internal certificates + ServicePointManager.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + if (sender.GetType() != typeof(HttpWebRequest)) + return sslPolicyErrors == SslPolicyErrors.None; + + var request = (HttpWebRequest)sender; + var hash = certificate.GetCertHashString(); + + ICollection hosts; + + trustedCertificates.TryGetValue(hash, out hosts); + if (hosts != null) + { + if (hosts.Contains(request.Host)) + return true; + } + return sslPolicyErrors == SslPolicyErrors.None; + }; } override protected async Task Run(WebRequest webRequest) @@ -203,5 +227,18 @@ namespace Jackett.Utils.Clients } } } + + override public void AddTrustedCertificate(string host, string hash) + { + hash = hash.ToUpper(); + ICollection hosts; + trustedCertificates.TryGetValue(hash.ToUpper(), out hosts); + if (hosts == null) + { + hosts = new HashSet(); + trustedCertificates[hash] = hosts; + } + hosts.Add(host); + } } } diff --git a/src/Jackett/Utils/Clients/HttpWebClient2.cs b/src/Jackett/Utils/Clients/HttpWebClient2.cs index 4ca07922b..060b229a1 100644 --- a/src/Jackett/Utils/Clients/HttpWebClient2.cs +++ b/src/Jackett/Utils/Clients/HttpWebClient2.cs @@ -9,6 +9,8 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -24,6 +26,8 @@ namespace Jackett.Utils.Clients HttpClientHandler clientHandlr; HttpClient client; + static protected Dictionary> trustedCertificates = new Dictionary>(); + public HttpWebClient2(IProcessService p, Logger l, IConfigurationService c) : base(p: p, l: l, @@ -62,6 +66,26 @@ namespace Jackett.Utils.Clients } ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 | (SecurityProtocolType)768 | (SecurityProtocolType)3072; + + // custom handler for our own internal certificates + ServicePointManager.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + if (sender.GetType() != typeof(HttpWebRequest)) + return sslPolicyErrors == SslPolicyErrors.None; + + var request = (HttpWebRequest)sender; + var hash = certificate.GetCertHashString(); + + ICollection hosts; + + trustedCertificates.TryGetValue(hash, out hosts); + if (hosts != null) + { + if (hosts.Contains(request.Host)) + return true; + } + return sslPolicyErrors == SslPolicyErrors.None; + }; } override protected async Task Run(WebRequest webRequest) diff --git a/src/Jackett/Utils/Clients/IWebClient.cs b/src/Jackett/Utils/Clients/IWebClient.cs index 81ce96bd2..2689a7547 100644 --- a/src/Jackett/Utils/Clients/IWebClient.cs +++ b/src/Jackett/Utils/Clients/IWebClient.cs @@ -17,6 +17,11 @@ namespace Jackett.Utils.Clients protected IConfigurationService configService; protected IProcessService processService; + virtual public void AddTrustedCertificate(string host, string hash) + { + // not implemented by default + } + public IWebClient(IProcessService p, Logger l, IConfigurationService c) { processService = p;