SSL einstellen für IIS mit C# und DirectoryEntry


Es gibt die unterschiedlichsten Wege um für eine Webseite SSL einzustellen, wie .z.B. das manuelle Hinzufügen einer https Verbindung mit dem IIS-Manager hier.

Dann kann man noch für den IIS 6 mit Hilfe von C# und DirectoryEntry SSL setzten. Im Folgenden erläutere ich welche Einstellungen im DirectoryEntry gesetzt werden müssen. Da ich leider keine “genaue” Anleitung gefunden habe, sondern alles mit Hilfe von Probieren und einem guten Metabase Explorer aus dem Resource Toolkit für den IIS 6 “herausgefunden” habe, kann es gut sein das es auch andere und evtl. einfachere Wege gibt das ganze einzustellen, wenn ja würde ich mich über einen Kommentar sehr freuen.

Als erstes müssen wir uns einen passenden DirectoryEntry heraussuchen für den wir SSL setzten wollen. Da man SSL für eine komplette Site setzt, suchen wir uns in meinem Beispiel die “Default Web Site” heraus und setzten hier den Standard SSL Port 443.

Ich setzte voraus das man im ISS bereits ein SSL Zertifikat angelegt hat, wie z.B. hier am Anfang erläutert wird, das Zertifikat mit dem Namen “squadwuschelscert”.

Eine Liste der installierten Zertifikate auf dem lokalen Rechner erhält man z.B. mit der folgenden Funktion:

/// <summary>
/// Gibt eine Liste mit den installierten Zertifikaten zurück
/// </summary>
public static SortedList<string, string> GetInstalledCertifcates()
{
    //SortedList(HashAlsString,CertificateFileName)
    SortedList<string, string> certificates = new SortedList<string, string>();
    bool edoCertIsInstalled = false;

    //Den lokalen Zertifikatsstore auf dem Rechner öffnen.
    X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

    //alle Zertifikate auf dem lokalen Rechner durchgehen.
    foreach (X509Certificate2 eCertificate in store.Certificates)
    {
        //Die Zertifikate unserer Liste hinzufügen, der Hash wird als Key verwendet, 
        //da dieser im Regelfall nur einmal im lokalen Store installiert sein sollte.
        if (!certificates.ContainsKey(eCertificate.GetCertHashString()))
        {
            if (eCertificate.FriendlyName.Trim().Length == 0)
            {
                certificates.Add(eCertificate.GetCertHashString(), eCertificate.SubjectName.Name);
            }
            else
            {
                certificates.Add(eCertificate.GetCertHashString(), eCertificate.FriendlyName);
            }
        }
    }

    return certificates;
}

Wir benötigen den passenden Zertifikatshash, den wir dann im DirectoryEntry eintragen (das Zertifikat muss auf dem Lokalen System installiert sein zu dem der Hash gehört!).

Der Normale HashString der vom Store für die einzelnen Zertifikate zurück gegeben wird, kann nicht im DirectoryEntry hinzugefügt werden, daher muss dieser “modifiziert” werden mit der folgenden Funktion, wird ein Hash der z.B: “61a669c54ab30b5e72209ff88b3c0785df927228” aussieht an die Funktion übergeben.

/// <summary>
/// Der normale HashString, der vom Zertifikat zurück gegeben wird, kann so nicht verwendet werden um ihn
/// dem directoryEntry hinzufügen zu können. Dieser wird hier bearbeitet und e
/// </summary>
/// <param name="certHashString">der HashString der in ein object array umgewandelt werden soll.</param>
public static object[] ConvertCertHashString(string certHashString)
{
    //Der String vom Certifikathash muss speziell "aufgearbeitet" werden, damit dieser unserem SSLCertHash im IIS hinzugefügt werden kann.
    string newHash = string.Empty;
    string tmp = string.Empty;
    for (int i = 1; i <= certHashString.Length; i++)
    {
        //BeispielString der erzeugt wird: "a7 1f db 98 92 7e 71 c0 7b 1e f7 0d 74 1d c4 5a 39 a8 22 f5"
        //damit eine Split methode ausgeführt werden kann.
        tmp += certHashString[i - 1];

        if (i % 2 == 0)
        {
            tmp += ' ';
            newHash += tmp.ToLower();
            tmp = string.Empty;
        }
    }

    //Damit der Eintrag dann dem DirectoryEntry hinzugefügt werden kann wird ein Object Array benötigt.
    string[] newValueSplit = newHash.Trim().Split(new Char[] { ' ' });
    object[] newObj = new object[newValueSplit.Length];
    newValueSplit.CopyTo(newObj, 0);

    return newObj;
}

Die Funktion gibt dann ein Object Array zurück, welches dem DirectoryEntry erfolgreich hinzugefügt werden kann.

Mit dem folgenden Code Ausschnitt suchen wir unsere Website heraus und setzten die DirectoryEntries. Wir müssen hier nur zwei Einträge setzten. Dazu gehört “SSLCertHash” und “SecureBindings”.

Der “SSLCertHash” Eintrag wird benötigt, damit der IIS weiß welches Zertifikat verwendet werden soll und mit Hilfe von “SecureBindings” wird der Port angegeben für den SSL Zugang. Wenn wir diese Werte dem DirectoryEntry hinzugefügt haben, dann werden automatisch noch weitere Werte angelegt, was man sehr gut in einem Metabase Explorer sehen kann wie z.B. “SLLCertStoreName”.

//Die Basiswebseite (ROOT) ermitteln.
DirectoryEntry w3svc = new DirectoryEntry("IIS://localhost/W3SVC/1");

//Der Hash kann immer wieder neu gesetzt werden, 
//d.h. wenn jmd ein anderes Zertifikat möchte muss man das alte erst entfernen
PropertyValueCollection propValues = w3svc.Properties["SSLCertHash"];
propValues.Clear();
w3svc.CommitChanges();

//Einen passenden SSL Cert Hash heraussuchen
propValues.Add(CertificateFunctions.ConvertCertHashString("61a669c54ab30b5e72209ff88b3c0785df927228"));
w3svc.CommitChanges();

//Wenn noch keine Bindings für SSL gemacht wurden, wird hier ein Standard Binding für SSL angelegt, sonst
//wird das bereits gesetzte Binding verwendet, 
//um keine Änderungen an der bestehenden Basiswebseite zu machen die nicht notwendig sind.
if (w3svc.Properties["SecureBindings"].Count == 0)
{
    propValues = w3svc.Properties["SecureBindings"];
    //Den neuen Ports für SSL - Wenn dieser Eintrag hinzugefügt wird, werden automatisch weitere Einträge vom 
    //System erstellt wie SLLCertStoreName = "MY" muss nicht von uns erstellt werden.
    //Gut zu sehen mit einem Metabase explorer
    propValues.Add("*:443:");
    w3svc.CommitChanges();
}

Wenn man jetzt die Bindings der Default Web Site anschaut, ist dort auch ein Binding für SSL und dem Port 443 angegeben.

Das ganze geht auch noch einfacher, aber nur für den IIS größer Version 7 mit dem ServerManager.

Advertisements

Ein Gedanke zu „SSL einstellen für IIS mit C# und DirectoryEntry

  1. Pingback: SSL einstellen für IIS 7 mit C# und dem ServerManager « SquadWuschel's Blog

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s