MatchHostnameToPattern() public static method

public static MatchHostnameToPattern ( string hostname, string pattern ) : bool
hostname string
pattern string
return bool
        public bool Check(string hostname, List <X509Certificate2> peerCertificates)
        {
            if (!HasPins(hostname))
            {
                Debug.WriteLine($"No certificate pin found for {hostname}");
                return(false);
            }

            hostname = Pins.FirstOrDefault(p => Utility.MatchHostnameToPattern(hostname, p.Key)).Key;

            // Get pins
            string[] pins = Pins[hostname];

            // Skip pinning with empty array
            if (pins == null || pins.Length == 0)
            {
                return(true);
            }

            foreach (var certificate in peerCertificates)
            {
                // Compute spki fingerprint
                var spkiFingerprint = SpkiFingerprint.Compute(certificate.RawData);

                // Check pin
                if (Array.IndexOf(pins, spkiFingerprint) > -1)
                {
                    Debug.WriteLine($"Certificate pin {spkiFingerprint} is ok for {hostname}");
                    return(true);
                }
            }

            Debug.WriteLine($"Certificate pinning failure! Peer certificate chain for {hostname}: {string.Join("|", pins)}");
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Verifies the server certificate by calling into ServicePointManager.ServerCertificateValidationCallback or,
        /// if the is no delegate attached to it by using the default hostname verifier.
        /// </summary>
        /// <returns><c>true</c>, if server certificate was verifyed, <c>false</c> otherwise.</returns>
        /// <param name="hostname"></param>
        /// <param name="session"></param>
        static bool verifyServerCertificate(string hostname, ISSLSession session)
        {
            var defaultVerifier = HttpsURLConnection.DefaultHostnameVerifier;

            if (ServicePointManager.ServerCertificateValidationCallback == null)
            {
                return(defaultVerifier.Verify(hostname, session));
            }

            // Convert java certificates to .NET certificates and build cert chain from root certificate
            var certificates = session.GetPeerCertificateChain();
            var chain        = new X509Chain();
            var errors       = System.Net.Security.SslPolicyErrors.None;

            // Build certificate chain and check for errors
            if (certificates == null || certificates.Length == 0)
            {            //no cert at all
                errors = System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable;
                return(ServicePointManager.ServerCertificateValidationCallback(hostname, null, chain, errors));
            }

            if (certificates.Length == 1)
            {            //no root?
                errors = System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors;
                return(ServicePointManager.ServerCertificateValidationCallback(hostname, null, chain, errors));
            }

            var netCerts = certificates.Select(x => new X509Certificate2(x.GetEncoded())).ToArray();

            for (int i = 1; i < netCerts.Length; i++)
            {
                chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
            }

            var root = netCerts[0];

            chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
            chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
            chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
            chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

            if (!chain.Build(root))
            {
                errors = System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors;
                return(ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors));
            }

            var subject   = root.Subject;
            var subjectCn = cnRegex.Match(subject).Groups[1].Value;

            if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn))
            {
                errors = System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch;
            }
            return(ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors));
        }
        public bool HasPins(string hostname)
        {
            foreach (var pin in Pins)
            {
                if (Utility.MatchHostnameToPattern(hostname, pin.Key))
                {
                    return(true);
                }
            }

            return(false);
        }
        public bool Check(string hostname, byte[] certificate)
        {
            if (!HasPins(hostname))
            {
                Debug.WriteLine($"No certificate pin found for {hostname}");
                return(false);
            }

            hostname = Pins.FirstOrDefault(p => Utility.MatchHostnameToPattern(hostname, p.Key)).Key;

            // Get pins
            string[] pins = Pins[hostname];

            // Skip pinning with empty array
            if (pins == null || pins.Length == 0)
            {
                return(true);
            }

            // Compute spki fingerprint
            var spkiFingerprint = SpkiFingerprint.Compute(certificate);

            // Check pin
            var match = Array.IndexOf(pins, spkiFingerprint) > -1;

            if (match)
            {
                Debug.WriteLine($"Certificate pin is ok for {hostname}");
            }
            else
            {
                Debug.WriteLine($"Certificate pinning failure! Peer certificate chain: {spkiFingerprint}, Pinned certificates for {hostname}: {string.Join("|", pins)}");
            }

            return(match);
        }
Beispiel #5
0
        public NativeMessageHandler(bool throwOnCaptiveNetwork, TLSConfig tLSConfig, NativeCookieHandler cookieHandler = null, IWebProxy proxy = null)
        {
            this.throwOnCaptiveNetwork = throwOnCaptiveNetwork;

            this.TLSConfig = tLSConfig;

            // Enforce TLS1.2
            SslProtocols = SslProtocols.Tls12;

            // Add Certificate Pins
            if (!TLSConfig.DangerousAcceptAnyServerCertificateValidator &&
                TLSConfig.Pins != null &&
                TLSConfig.Pins.Count > 0 &&
                TLSConfig.Pins.FirstOrDefault(p => p.PublicKeys.Count() > 0) != null)
            {
                this.PinningMode = "PublicKeysOnly";

                this.CertificatePinner = new CertificatePinner();

                foreach (var pin in TLSConfig.Pins)
                {
                    this.CertificatePinner.AddPins(pin.Hostname, pin.PublicKeys);
                }
            }

            // Set client credentials
            SetClientCertificate(TLSConfig.ClientCertificate);

            if (cookieHandler != null)
            {
                this.CookieContainer = cookieHandler;
            }

            // Adding proxy support
            if (proxy != null)
            {
                Proxy    = proxy;
                UseProxy = true;
            }

            this.ServerCertificateCustomValidationCallback = (request, root, chain, e) =>
            {
                var errors = SslPolicyErrors.None;

                if (TLSConfig.DangerousAcceptAnyServerCertificateValidator)
                {
                    goto sslErrorVerify;
                }

                var hostname = request.RequestUri.Host;

                var netCerts = new List <X509Certificate2>();

                foreach (var element in chain.ChainElements)
                {
                    netCerts.Add(element.Certificate);
                }

                switch (this.PinningMode)
                {
                case "CertificateOnly":

                    // Build certificate chain and check for errors
                    if (chain == null || chain.ChainElements.Count == 0)
                    {                            //no cert at all
                        errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                        goto sslErrorVerify;
                    }

                    if (chain.ChainElements.Count == 1)
                    {                            //no root?
                        errors = SslPolicyErrors.RemoteCertificateChainErrors;
                        goto sslErrorVerify;
                    }

                    if (!chain.Build(root))
                    {
                        errors = SslPolicyErrors.RemoteCertificateChainErrors;
                        goto sslErrorVerify;
                    }

                    var subject   = root.Subject;
                    var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                    if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn))
                    {
                        var subjectAn = root.ParseSubjectAlternativeName();

                        if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null)
                        {
                            errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                            goto sslErrorVerify;
                        }
                    }
                    break;

                case "PublicKeysOnly":

                    if (this.CertificatePinner != null)
                    {
                        if (!this.CertificatePinner.HasPins(hostname))
                        {
                            errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                            goto sslErrorVerify;
                        }

                        if (!this.CertificatePinner.Check(hostname, netCerts))
                        {
                            errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                        }
                    }
                    break;
                }

sslErrorVerify:
                return(errors == SslPolicyErrors.None);
            };
        }
            public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                if (!This.customSSLVerification)
                {
                    goto doDefault;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust")
                {
                    goto doDefault;
                }

                if (ServicePointManager.ServerCertificateValidationCallback == null)
                {
                    goto doDefault;
                }

                // Convert Mono Certificates to .NET certificates and build cert
                // chain from root certificate
                var serverCertChain   = challenge.ProtectionSpace.ServerSecTrust;
                var chain             = new X509Chain();
                X509Certificate2 root = null;
                var errors            = SslPolicyErrors.None;

                if (serverCertChain == null || serverCertChain.Count == 0)
                {
                    errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                    goto sslErrorVerify;
                }

                if (serverCertChain.Count == 1)
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var netCerts = Enumerable.Range(0, serverCertChain.Count)
                               .Select(x => serverCertChain[x].ToX509Certificate2())
                               .ToArray();

                for (int i = 1; i < netCerts.Length; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                }

                root = netCerts[0];

                chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                try {
                    if (!chain.Build(root))
                    {
                        errors = SslPolicyErrors.RemoteCertificateChainErrors;
                        goto sslErrorVerify;
                    }
                } catch (System.Security.Cryptography.CryptographicException) {
                    // As best we can tell, a XAMMIT (spurious).
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var subject   = root.Subject;
                var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn))
                {
                    errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                    goto sslErrorVerify;
                }

sslErrorVerify:
                // NachoCove: Add this to make it look like other HTTP client
                var url = task.CurrentRequest.Url.ToString();
                var request = new HttpWebRequest(new Uri(url));
                // End of NachoCove
                bool result = ServicePointManager.ServerCertificateValidationCallback(request, root, chain, errors);

                if (result)
                {
                    completionHandler(
                        NSUrlSessionAuthChallengeDisposition.UseCredential,
                        NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                }
                else
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null);
                }
                return;

doDefault:
                if (null != This.Credentials)
                {
                    var authenticationType = AuthenticationTypeFromAuthenticationMethod(challenge.ProtectionSpace.AuthenticationMethod);
                    var uri = UriFromNSUrlProtectionSpace(challenge.ProtectionSpace);
                    if (null != authenticationType && null != uri)
                    {
                        var specifedCredential = This.Credentials.GetCredential(uri, authenticationType);
                        var state = getResponseForTask(task);
                        if (null != specifedCredential &&
                            null != specifedCredential.UserName && null != specifedCredential.Password)
                        {
                            if (specifedCredential == state.PresentedCredential)
                            {
                                completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, null);
                            }
                            else
                            {
                                state.PresentedCredential = specifedCredential;
                                var credential = new NSUrlCredential(
                                    specifedCredential.UserName,
                                    specifedCredential.Password,
                                    NSUrlCredentialPersistence.ForSession);
                                completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                            }
                            return;
                        }
                    }
                }
                completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
                return;
            }
        /// <summary>
        /// Verifies the server certificate by calling into ServicePointManager.ServerCertificateValidationCallback or,
        /// if the is no delegate attached to it by using the default hostname verifier.
        /// </summary>
        /// <returns><c>true</c>, if server certificate was verifyed, <c>false</c> otherwise.</returns>
        /// <param name="hostname"></param>
        /// <param name="session"></param>
        public bool Verify(string hostname, ISSLSession session)
        {
            var errors = SslPolicyErrors.None;

            if (nativeHandler.TLSConfig.DangerousAcceptAnyServerCertificateValidator)
            {
                goto sslErrorVerify;
            }

            // Convert java certificates to .NET certificates and build cert chain from root certificate
            var serverCertChain = session.GetPeerCertificateChain();

            var netCerts = serverCertChain.Select(x => new X509Certificate2(x.GetEncoded())).ToList();

            switch (nativeHandler.PinningMode)
            {
            case "CertificateOnly":

                var chain             = new X509Chain();
                X509Certificate2 root = null;

                // Build certificate chain and check for errors
                if (serverCertChain == null || serverCertChain.Length == 0)
                {    //no cert at all
                    errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                    PinningFailureMessage = FailureMessages.NoCertAtAll;
                    goto sslErrorVerify;
                }

                if (serverCertChain.Length == 1)
                {    //no root?
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    PinningFailureMessage = FailureMessages.NoRoot;
                    goto sslErrorVerify;
                }

                for (int i = 1; i < netCerts.Count; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                }

                chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                root = netCerts[0];

                if (!chain.Build(root))
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    PinningFailureMessage = FailureMessages.ChainError;
                    goto sslErrorVerify;
                }

                var subject   = root.Subject;
                var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn))
                {
                    var subjectAn = root.ParseSubjectAlternativeName();

                    if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null)
                    {
                        errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                        PinningFailureMessage = FailureMessages.SubjectNameMismatch;
                        goto sslErrorVerify;
                    }
                }
                break;

            case "PublicKeysOnly":

                if (nativeHandler.CertificatePinner != null)
                {
                    if (!nativeHandler.CertificatePinner.HasPins(hostname))
                    {
                        errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                        PinningFailureMessage = FailureMessages.NoPinsProvided + " " + hostname;
                    }

                    // CertificatePinner.Check will be done by Square.OkHttp3.CertificatePinner
                }
                break;
            }

sslErrorVerify:
            return(errors == SslPolicyErrors.None);
        }
Beispiel #8
0
            public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM)
                {
                    NetworkCredential credentialsToUse;

                    if (This.Credentials != null)
                    {
                        if (This.Credentials is NetworkCredential)
                        {
                            credentialsToUse = (NetworkCredential)This.Credentials;
                        }
                        else
                        {
                            var uri = this.getResponseForTask(task).Request.RequestUri;
                            credentialsToUse = This.Credentials.GetCredential(uri, "NTLM");
                        }
                        var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession);
                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                    }
                    return;
                }

                if (!This.customSSLVerification)
                {
                    goto doDefault;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust")
                {
                    goto doDefault;
                }

                // Call custom ServicePointManager.ServerCertificateValidationCallback delegate
                // if customSSLVerification is true
                if (ServicePointManager.ServerCertificateValidationCallback == null)
                {
                    goto doDefault;
                }

                // Convert Mono Certificates to .NET certificates and build cert
                // chain from root certificate
                var serverCertChain   = challenge.ProtectionSpace.ServerSecTrust;
                var chain             = new X509Chain();
                X509Certificate2 root = null;
                var errors            = SslPolicyErrors.None;

                if (serverCertChain == null || serverCertChain.Count == 0)
                {
                    errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                    goto sslErrorVerify;
                }

                if (serverCertChain.Count == 1)
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var netCerts = Enumerable.Range(0, serverCertChain.Count)
                               .Select(x => serverCertChain[x].ToX509Certificate2())
                               .ToArray();

                for (int i = 1; i < netCerts.Length; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                }

                root = netCerts[0];

                chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                if (!chain.Build(root))
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var subject   = root.Subject;
                var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn))
                {
                    errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                    goto sslErrorVerify;
                }

sslErrorVerify:
                var hostname = task.CurrentRequest.Url.Host;
                bool result = ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors);

                if (result)
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                }
                else
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null);
                }
                return;

doDefault:
                // Support self-signed certificates
                if (This.EnableUntrustedCertificates)
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                }
                else
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
                }
                return;
            }
Beispiel #9
0
            public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                if (!This.customSSLVerification)
                {
                    goto doDefault;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust")
                {
                    goto doDefault;
                }

                if (ServicePointManager.ServerCertificateValidationCallback == null)
                {
                    goto doDefault;
                }

                // Convert Mono Certificates to .NET certificates and build cert
                // chain from root certificate
                var serverCertChain   = challenge.ProtectionSpace.ServerSecTrust;
                var chain             = new X509Chain();
                X509Certificate2 root = null;
                var errors            = SslPolicyErrors.None;

                if (serverCertChain == null || serverCertChain.Count == 0)
                {
                    errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                    goto sslErrorVerify;
                }

                if (serverCertChain.Count == 1)
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var netCerts = Enumerable.Range(0, serverCertChain.Count)
                               .Select(x => serverCertChain[x].ToX509Certificate2())
                               .ToArray();

                for (int i = 1; i < netCerts.Length; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                }

                root = netCerts[0];

                chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                if (!chain.Build(root))
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var subject   = root.Subject;
                var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn))
                {
                    errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                    goto sslErrorVerify;
                }

sslErrorVerify:
                bool result = ServicePointManager.ServerCertificateValidationCallback(this, root, chain, errors);

                if (result)
                {
                    completionHandler(
                        NSUrlSessionAuthChallengeDisposition.UseCredential,
                        NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                }
                else
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.RejectProtectionSpace, null);
                }
                return;

doDefault:
                completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
                return;
            }
            public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                // TODO: add NSUrlProtectionSpace.HTTPSProxy case

                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM)
                {
                    NetworkCredential credentialsToUse;

                    if (nativeHandler.Credentials != null)
                    {
                        if (nativeHandler.Credentials is NetworkCredential)
                        {
                            credentialsToUse = (NetworkCredential)nativeHandler.Credentials;
                        }
                        else
                        {
                            var uri = this.getResponseForTask(task).Request.RequestUri;
                            credentialsToUse = nativeHandler.Credentials.GetCredential(uri, "NTLM");
                        }
                        var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession);
                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                    }
                    return;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodServerTrust)
                {
                    var errors = SslPolicyErrors.None;

                    if (nativeHandler.TLSConfig.DangerousAcceptAnyServerCertificateValidator)
                    {
                        goto sslErrorVerify;
                    }

                    var hostname = task.CurrentRequest.Url.Host;

                    // Convert java certificates to .NET certificates and build cert chain from root certificate
                    var serverCertChain = challenge.ProtectionSpace.ServerSecTrust;

                    var netCerts = Enumerable.Range(0, serverCertChain.Count)
                                   .Select(x => serverCertChain[x].ToX509Certificate2())
                                   .ToList();

                    switch (nativeHandler.PinningMode)
                    {
                    case "CertificateOnly":

                        //Security.addProvider(new BouncyCastleProvider());
                        //CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

                        var chain             = new X509Chain();
                        X509Certificate2 root = null;

                        // Build certificate chain and check for errors
                        if (serverCertChain == null || serverCertChain.Count == 0)
                        {    //no cert at all
                            errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                            PinningFailureMessage = FailureMessages.NoCertAtAll;
                            goto sslErrorVerify;
                        }

                        if (serverCertChain.Count == 1)
                        {    //no root?
                            errors = SslPolicyErrors.RemoteCertificateChainErrors;
                            PinningFailureMessage = FailureMessages.NoRoot;
                            goto sslErrorVerify;
                        }

                        for (int i = 1; i < netCerts.Count; i++)
                        {
                            chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                        }

                        //chain.ChainPolicy.CertificatePolicy.Add(new Oid("1.2.840.10045.2.1"));
                        chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                        chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                        chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                        chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                        root = netCerts[0];

                        /*if (!chain.Build(root))
                         * {
                         *  errors = SslPolicyErrors.RemoteCertificateChainErrors;
                         *  PinningFailureMessage = FailureMessages.ChainError;
                         *  goto sslErrorVerify;
                         * }*/

                        var subject   = root.Subject;
                        var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                        if (string.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(hostname, subjectCn))
                        {
                            var subjectAn = root.ParseSubjectAlternativeName();

                            if (subjectAn.FirstOrDefault(s => Utility.MatchHostnameToPattern(hostname, s)) == null)
                            {
                                errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                                PinningFailureMessage = FailureMessages.SubjectNameMismatch;
                                goto sslErrorVerify;
                            }
                        }
                        break;

                    case "PublicKeysOnly":

                        if (nativeHandler.CertificatePinner != null)
                        {
                            if (!nativeHandler.CertificatePinner.HasPins(hostname))
                            {
                                errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                                PinningFailureMessage = FailureMessages.NoPinsProvided + " " + hostname;
                                goto sslErrorVerify;
                            }

                            if (!nativeHandler.CertificatePinner.Check(hostname, netCerts))
                            {
                                errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                                PinningFailureMessage = FailureMessages.PinMismatch;
                            }
                        }
                        break;
                    }

sslErrorVerify:
                    if (errors == SslPolicyErrors.None)
                    {
                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                    }
                    else
                    {
                        completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null);
                    }
                    return;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate)
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, nativeHandler.UrlCredential);

                    return;
                }

                completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
            }
Beispiel #11
0
            public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action <NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodNTLM)
                {
                    NetworkCredential credentialsToUse;

                    if (This.Credentials != null)
                    {
                        if (This.Credentials is NetworkCredential)
                        {
                            credentialsToUse = (NetworkCredential)This.Credentials;
                        }
                        else
                        {
                            var uri = this.getResponseForTask(task).Request.RequestUri;
                            credentialsToUse = This.Credentials.GetCredential(uri, "NTLM");
                        }
                        var credential = new NSUrlCredential(credentialsToUse.UserName, credentialsToUse.Password, NSUrlCredentialPersistence.ForSession);
                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                    }
                    return;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod == NSUrlProtectionSpace.AuthenticationMethodClientCertificate)
                {
                    Console.WriteLine("Client Cert!");

                    var password = "******";
                    var options  = NSDictionary.FromObjectAndKey(NSObject.FromObject(password), SecImportExport.Passphrase);

                    var path     = Path.Combine(NSBundle.MainBundle.BundlePath, "Content", "client.p12");
                    var certData = File.ReadAllBytes(path);

                    NSDictionary[] importResult;

                    X509Certificate cert = new X509Certificate(certData, password);

                    SecStatusCode statusCode     = SecImportExport.ImportPkcs12(certData, options, out importResult);
                    var           identityHandle = importResult[0][SecImportExport.Identity];
                    var           identity       = new SecIdentity(identityHandle.Handle);
                    var           certificate    = new SecCertificate(cert.GetRawCertData());

                    SecCertificate[] certificates = { certificate };
                    NSUrlCredential  credential   = NSUrlCredential.FromIdentityCertificatesPersistance(identity, certificates, NSUrlCredentialPersistence.ForSession);
                    completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);

                    return;
                }

                if (!This.customSSLVerification)
                {
                    goto doDefault;
                }

                if (challenge.ProtectionSpace.AuthenticationMethod != "NSURLAuthenticationMethodServerTrust")
                {
                    goto doDefault;
                }

                if (ServicePointManager.ServerCertificateValidationCallback == null)
                {
                    goto doDefault;
                }

                // Convert Mono Certificates to .NET certificates and build cert
                // chain from root certificate
                var serverCertChain   = challenge.ProtectionSpace.ServerSecTrust;
                var chain             = new X509Chain();
                X509Certificate2 root = null;
                var errors            = SslPolicyErrors.None;

                if (serverCertChain == null || serverCertChain.Count == 0)
                {
                    errors = SslPolicyErrors.RemoteCertificateNotAvailable;
                    goto sslErrorVerify;
                }

                if (serverCertChain.Count == 1)
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var netCerts = Enumerable.Range(0, serverCertChain.Count)
                               .Select(x => serverCertChain[x].ToX509Certificate2())
                               .ToArray();

                for (int i = 1; i < netCerts.Length; i++)
                {
                    chain.ChainPolicy.ExtraStore.Add(netCerts[i]);
                }

                root = netCerts[0];

                chain.ChainPolicy.RevocationFlag      = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;

                if (!chain.Build(root))
                {
                    errors = SslPolicyErrors.RemoteCertificateChainErrors;
                    goto sslErrorVerify;
                }

                var subject   = root.Subject;
                var subjectCn = cnRegex.Match(subject).Groups[1].Value;

                if (String.IsNullOrWhiteSpace(subjectCn) || !Utility.MatchHostnameToPattern(task.CurrentRequest.Url.Host, subjectCn))
                {
                    errors = SslPolicyErrors.RemoteCertificateNameMismatch;
                    goto sslErrorVerify;
                }

sslErrorVerify:
                var hostname = task.CurrentRequest.Url.Host;
                bool result = ServicePointManager.ServerCertificateValidationCallback(hostname, root, chain, errors);

                if (result)
                {
                    completionHandler(
                        NSUrlSessionAuthChallengeDisposition.UseCredential,
                        NSUrlCredential.FromTrust(challenge.ProtectionSpace.ServerSecTrust));
                }
                else
                {
                    completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null);
                }
                return;

doDefault:
                completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
                return;
            }