C# get bound of ssl server certificate

2k Views Asked by At

I am running a self hosted web service. The communication is over https and I am using a self signed server certifivate. The Port is changeable. So on every application start I am looking for the certificate in the store and bind it to the specific port. This I am doing with netsh and delete/add.

Is there a way to find out if the command 'http add sslcert ipport=0.0.0.0:{port}' was already executed by an application start before? So I do not have to delete and add it on every app-start. My idea was to call 'http show sslcert ipport=0.0.0.0:{port}' and look into the output. But this is not so nice.. So is there a C# method that is doing this?

public static bool ActivateCertificate(int port, X509Certificate2 certificate, string appId)
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            bool certificateExists = false;

            store.Open(OpenFlags.ReadWrite);
            try
            {
            foreach (var cert in store.Certificates)
            {
                if (cert.Thumbprint != null && cert.Thumbprint.Equals(certificate.Thumbprint, StringComparison.InvariantCultureIgnoreCase))
                {
                    certificateExists = true;
                    break;
                }
            }
            if (!certificateExists)
            {
                store.Add(certificate);
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Could not activate certificate!");
            return false;
        }
        finally
        {
            store.Close();
        }
        StringBuilder str = new StringBuilder();
        ProcessStartInfo psi = new ProcessStartInfo() {CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true};
        psi.FileName = "netsh";

        psi.Arguments = $"http show sslcert ipport=0.0.0.0:{port}";
        Process procShow = Process.Start(psi);
        while (procShow != null && !procShow.StandardOutput.EndOfStream)
        {
            str.Append(procShow.StandardOutput.ReadLine());
        }
        Log.Warn(str.ToString);

        // delete IPV4.
        psi.Arguments = $"http delete sslcert ipport=0.0.0.0:{port}";
        Process procDel = Process.Start(psi);
        //exitCode = procDel.ExitCode;

        while (procDel != null && !procDel.StandardOutput.EndOfStream)
        {
            str.Append(procDel.StandardOutput.ReadLine());
        }
        Log.Warn(str.ToString);
        procDel?.WaitForExit(1000);
        // IPV4-Adresse hinzufügen.
        psi.Arguments = $"http add sslcert ipport=0.0.0.0:{port} certhash={certificate.Thumbprint.ToLower()} appid={{{appId}}}";
        Process proc = Process.Start(psi);
        //exitCode = proc.ExitCode;

        while (proc != null && !proc.StandardOutput.EndOfStream)
        {
            str.Append(proc.StandardOutput.ReadLine());
        }
        /*
        // delete IPV6
        Log.Warn(str.ToString);
        proc?.WaitForExit(1000);
        psi.Arguments = $"http delete sslcert ipport=[::]:{port}";
        Process procDelV6 = Process.Start(psi);

        while (procDelV6 != null && !procDelV6.StandardOutput.EndOfStream)
        {
            str.Append(procDelV6.StandardOutput.ReadLine());
        }
        Log.Warn(str.ToString);
        procDelV6?.WaitForExit(1000);
        // IPV6-Adresse hinzufügen.
        psi.Arguments = $"http add sslcert ipport=[::]:{port} certhash={certificate.Thumbprint.ToLower()} appid={{{appId}}}";
        Process procV6 = Process.Start(psi);

        while (procV6 != null && !procV6.StandardOutput.EndOfStream)
        {
            str.Append(procV6.StandardOutput.ReadLine());
        }
        Log.Warn(str.ToString);
        procV6?.WaitForExit();
        */
        return true;
    }
1

There are 1 best solutions below

0
On

Unfortunately, I think the generally accepted way to do this is by calling netsh the way you are. You could look into Microsoft.Web.Administration.Binding, but this depends on IIS being installed.

IMO it is perfectly valid to do netsh http delete sslcert... followed by netsh http add sslcert.... The delete will fail when the binding does not already exist, but that's okay.