self signed certificates in .net standard 2.0

0

My problem here is specifically in .net standard 2.0, since the same code seems to work on .net framework for reasons I'm not entirely certain.

The problem is that I want to make http requests to a server the uses self signed certificates. Now the way to get past this in .net framework (specifically 4.6.1) is to use:

ServicePointManager.ServerCertificateValidationCallback = CustomValidation;

public static bool CustomValidation
            (object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors policyErrors)
        {
            return true;
        }

And this solves the problem. However, doing this in .net standard seems to compile but the same error (WinHttpException - A security error occured) System.AggregateException occurred HResult=0x80131500 Message=One or more errors occurred. (An error occurred while sending the request.) Source= StackTrace: at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at matrix_tester.Program.Main(String[] args) in C:\Users\Nick\source\repos\matrix-tester\Program.cs:line 11

Inner Exception 1: HttpRequestException: An error occurred while sending the request.

Inner Exception 2: WinHttpException: A security error occurred

I'm at my wits end here. Does ServicePointManager not get used in .net standard?

c#
post
https
get
asked on Stack Overflow Nov 11, 2017 by Nick Buckner

1 Answer

0

ServicePointManager should be available in 2.0.

Disclaimer. I don't know why your code doesn't work. I have a hack I always use when I need to autoaccept certificates. It works in 2.0. But remember that this script accepts ALL self signed certificates which is a breach of security. Use at your own discretion. It is a singleton class. Just call it at beginning of your program like this:

Certificates.Instance.GetCertificatesAutomatically();

And it should work throughout your program. Hope it helps you advance.

using System;
using System.Collections.Generic;
using System.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Net.Security;

namespace test
{
    public sealed class Certificates
    {
        private static Certificates instance = null;
        private static readonly object padlock = new object();

        Certificates()
        {
        }

        public static Certificates Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Certificates();
                    }
                    return instance;
                }
            }
        }
        public void GetCertificatesAutomatically()
        {
            ServicePointManager.ServerCertificateValidationCallback +=
                new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors)
                    => { return true; });
        }

        private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            //Return true if the server certificate is ok
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            bool acceptCertificate = true;
            string msg = "The server could not be validated for the following reason(s):\r\n";

            //The server did not present a certificate
            if ((sslPolicyErrors &
                SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable)
            {
                msg = msg + "\r\n    -The server did not present a certificate.\r\n";
                acceptCertificate = false;
            }
            else
            {
                //The certificate does not match the server name
                if ((sslPolicyErrors &
                    SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
                {
                    msg = msg + "\r\n    -The certificate name does not match the authenticated name.\r\n";
                    acceptCertificate = false;
                }

                //There is some other problem with the certificate
                if ((sslPolicyErrors &
                    SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
                {
                    foreach (X509ChainStatus item in chain.ChainStatus)
                    {
                        if (item.Status != X509ChainStatusFlags.RevocationStatusUnknown &&
                            item.Status != X509ChainStatusFlags.OfflineRevocation)
                            break;

                        if (item.Status != X509ChainStatusFlags.NoError)
                        {
                            msg = msg + "\r\n    -" + item.StatusInformation;
                            acceptCertificate = false;
                        }
                    }
                }
            }

            //If Validation failed, present message box
            if (acceptCertificate == false)
            {
                msg = msg + "\r\nDo you wish to override the security check?";
                //          if (MessageBox.Show(msg, "Security Alert: Server could not be validated",
                //                       MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                acceptCertificate = true;
            }

            return acceptCertificate;
        }

    }
}
answered on Stack Overflow Nov 11, 2017 by Kent Kostelac • edited Nov 11, 2017 by Kent Kostelac

User contributions licensed under CC BY-SA 3.0