Exchange Zertifikate Rechte

Wieder einmal stand eine einfache Verlängerung eines Exchange SMTP-Transport-Zertifikats an. Der Weg war aber steinig und hat mir viele Details zu Exchange und Zertifikate geliefert.

Auslöser

Wer Exchange Hybrid betreibt ist gut damit beraten, für den SMTP-Transport ein eigenes Zertifikat zu nutzen und nicht ein Wildcard, welches z.B. auch der reguläre Mailserver zum Versand verwendet. Es muss aber ein öffentliches Zertifikat sein, damit Exchange Online den OnPremises-Server eingehend akzeptiert und als "OnPremises-Connector" über die "Org-Connector Attribution" erkennt oder Sie nutzen eine separate Source-IP ihrer OnPremises Umgebung als Kriterium. In die Gegenrichtung von Exchange Online zu Exchange OnPremises können Sie TLS auch mit beliebigen Zertifikaten zulassen.

Wir haben ein Zertifikats-Request erstellt und von der öffentlichen PKI signieren lassen und wieder eingespielt. Natürlich haben wir an die Pflege der SAN-Namen, die Installation der Intermediate-CAs und die Auswahl des richtigen Keyproviders (Nicht CNG!) geachtet. In der MMC war das alte und das neue Zertifikat nebeneinander sichtbar und beide hatten auch einen privaten Schlüssel.

Dennoch war schon nach der Installation des Zertifikats samt privatem Key auf dem Exchange Server keine Mailkommunikation mehr möglich. Ich nutze zum Test dazu mein Skript Get-TCPCert.

PS C:\Script> .\get-tcpcert.ps1 -remotehost localhost -port 25 -sniname hybrid.msxfaq.com -starttls

datetime                       : 2024-10-13 08:37:26Z
remotehost                     : localhost
sniname                        : hybrid.msxfaq.com
dnsanswer                      : localhost
remoteip                       : 127.0.0.1
Port                           : 25
TCPStatus                      :
TLSStatus                      : TLSHandshakeFail
SslProtocol                    : Fail
CipherAlgorithm                :
HashAlgorithm                  :
KeyExchangeAlgorithm           :
CN                             :
DnsNameList                    :
Subject                        :
NotAfter                       :
NotBefore                      :
validdays                      :
Issuer                         :
Thumbprint                     :
SerialNumber                   :
SignatureAlgorithmFriendlyName :
RawData                        :
Extensions                     :
ExtensionSANName               :
ExtensionKeyUsages             :
dnstimems                      : 1
connecttimems                  : 1
tlstimems                      : 4
totaltimems                    : 7

Sobald ich das neue Zertifikat aus dem Computerstore entfernt habe, hat der Exchange Transport Service sofort und ohne Neustart wieder das alte noch gültige Zertifikat verwendet. Das hat natürlich meine Neugier geweckt aber vor allem hatte ich nur noch ein paar Tage Zeit das Zertifikat zu tauschen.

Wir haben das Problem letztlich durch eine neuen Zertifikats-Request gelöst. Die Ursache für das komische Verhalten von Exchange haben wir noch nicht final ermittelt. Die Seite und die Schritte der Fehlersuche sind aber vielleicht doch für den ein oder anderen Administrator interessant.

Private Key Rechte

Nachdem ich das Zertifikat auf dem Produktionssystem erst mal wieder entfernt habe, habe ich auf einem Testsystem das Zertifikat importiert und mir die Details angeschaut. Es gibt z.B. einen Unterschied, ob ich ein Zertifikat als PFX-Datei per MMC oder Exchange Powershell importiere:

Schritt PowerShell MMC

Zertifikat einspielen

Import-ExchangeCertificate `
   -FileData ([System.IO.File]::ReadAllBytes('C:\Certificates\Transport2024.pfx')) `
   -Password (Read-Host "Enter password" -AsSecureString) `
   -PrivateKeyExportable $true

Die Anforderung über ECP oder PowerShell mit und Installation ergibt identische Ergebnisse

Doppelklick auf die PFX-Datei und Import in den Zertifikatspeicher des Computers.

Exchange Status

Nach dem Import des Zertifikats ist es in allen drei Fällen in Exchange noch nicht aktiviert.

[PS] C:\>Get-ExchangeCertificate

Thumbprint                                Services   Subject
----------                                --------   -------
BBDD09730D0264FF7FA4AFD8FE078AC3E42DF14B  .......    CN=hybrid.msxfaq.com, O=MSFAQ, L=Paderborn, S=Nor...
7BCD045D32EA19AC93C932D8E3C2F06E4EFA14CD  ....SF.    CN=Federation
6FC282ED7DD5A9409F29765319038E9AABE77F47  IP.WS..    CN=outlook.msxfaq.com, C=DE
FD3714B3BF5C9B62FF2080DAF82A204F4F4B52A1  .......    CN=CLIUSR
0C11E52AB42DACBB7626C698BC4CEA203AEDF8AC  ....S..    CN=hybrid.msxfaq.com, O=MSXFAQ, L=Paderborn, S=Nor...
6DAD3D03D52E69CF18FEAF7C20E325B74E4F3B57  ....S..    CN=EX1
3F593F7D40A31EB5306D542845FB5627D92BAD0A  .......    CN=WMSvc-SHA2-EX1
8EABEC8EB8F4D14083BFE000BB2B544ADBAF74F4  ....S..    CN=Microsoft Exchange Server Auth Certificate

Das erste Exchange Zertifikat hat noch kein "S" in den Services und die Ausgabe war bei beiden Import-Wegen identisch.

Achtung:
Exchange nutzt das Zertifikat direkt auch ohne vorheriges Enable-ExchangeCertificate. In meinem Fall war "irgendetwas" mit dem Zertifikat defekt und der Transport-Dienst hat zwar noch STARTLS angeboten aber die TS-Verbindung kam nicht zustande. Da stellt sich dann die Frage, was ein Enable-ExchangeCertificate noch macht.

Rechte auf privaten Schlüssel

Ich habe mir über die MMC die Berechtigungen auf den privaten Key angeschaut. Das geht sehr einfach über die MMC:

Und hier gibt es tatsächlich Unterschiede je nach Importweg.

Private Key Permission

Beim Import über die PowerShell bekommt "SYSTEM" das Recht "Full Control", während Administrators nur "Read" bekommt.

Beim Import über die MMC bekommt "SYSTEM" ebenfalls das Recht "Full Control". Die Gruppe der Administrators bekommt nun aber auch ein "Full Control" und zusätzlich wird noch eine unbekannte "LogonSessionID" mit "Read" addiert.

Rechte nach Enable-ExchangeCertificate

Wenn ich dann einen "Enable-ExchangeCertificate" ausführe, dann werden die Rechte um "NETWORK SERVICE" mit READ erweitert.

Wenn ich dann einen "Enable-ExchangeCertificate" ausführe, dann werden die Rechte um "NETWORK SERVICE" mit READ erweitert.

Das erscheint mir logisch, da die TransportDienste nicht mit "SYSTEM" sondern nur mit "Network Service" laufen:

Daher dürfte ein "Enable-ExchangeCertificate" schon sinnvoll und für viele andere Dienste auch erforderlich sein. Warum aber der Transport-Dienst auch ohne diese Recht zumindest eingehende Verbindungen mit dem neuen Zertifikat anbietet, bleibt mir ein Rätsel.

Certutil

Auch wenn das Problem durch ein ganz neues Zertifikat letztlich gelöst wurde, habe ich da alte Zertifikat noch weiter analysiert und mit CERTUTIL kann ich mir sowohl die PFX-Datei als auch ein installiertes Zertifikat anschauen.

Wichtig: Alle Befehle in einer administrativen Shell starten.

Direkt nach dem Request funktioniert ein "-VerifyKeys" ohne Probleme.

C:\>certutil -store my BBDD09730D0264FF7FA4AFD8FE078AC3E42DF14B -verifykeys
my "Personal"
================ Certificate 2 ================
Serial Number: 06a89933175402e5d7fbe485f9c9623b
Issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1, O=DigiCert Inc, C=US
 NotBefore: 18.10.2024 02:00
 NotAfter: 18.10.2025 01:59
Subject: CN=hybrid.msxfaq.com, MSXFAQ, L=Paderborn, S=Nordrhein-Westfalen, C=DE
Non-root Certificate
Cert Hash(sha1): bbdd09730d0264ff7fa4afd8fe078ac3e42df14b
  Key Container = 6b6eaec653c539a3fff39ce5c34b39a3_784b76a9-b2fd-4090-ba30-bfcf8a033039
  Simple container name: te-47c80fad-6df8-452c-9ae1-3a9a4064e407
  Provider = Microsoft RSA SChannel Cryptographic Provider
Encryption test passed
CertUtil: -store command completed successfully.

Kaum habe ich aber einen "Enable-ExchangeCertificate" gemacht, funktioniert die Prüfung nicht mehr.

# Das neue Zertifikat

C:\>certutil -store my BBDD09730D0264FF7FA4AFD8FE078AC3E42DF14B -verifykeys
my "Personal"
================ Certificate 2 ================
Serial Number: 06a89933175402e5d7fbe485f9c9623b
Issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1, O=DigiCert Inc, C=US
 NotBefore: 18.10.2024 02:00
 NotAfter: 18.10.2025 01:59
Subject: CN=hybrid.msxfaq.com, MSXFAQ, L=Paderborn, S=Nordrhein-Westfalen, C=DE
Non-root Certificate
Cert Hash(sha1): bbdd09730d0264ff7fa4afd8fe078ac3e42df14b
  Key Container = 6b6eaec653c539a3fff39ce5c34b39a3_784b76a9-b2fd-4090-ba30-bfcf8a033039
  Simple container name: te-47c80fad-6df8-452c-9ae1-3a9a4064e407
  Provider = Microsoft RSA SChannel Cryptographic Provider
Encryption test passed
CertUtil: -store command FAILED: 0x80070050 (WIN32: 80 ERROR_FILE_EXISTS)
CertUtil: The file exists.
# Problematisches Zertifikat

C:\> certutil -store my CF8E46E1682273FBC901A752E47C837F8FB00E11 -verifykeys
my "Personal"
================ Certificate 1 ================
Serial Number: 0ae57ddbb755f07a62922a82c40c2263
Issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1, O=DigiCert Inc, C=US
 NotBefore: 14.10.2024 02:00
 NotAfter: 15.10.2025 01:59
Subject: CN=hybrid.msxfaq.com, O=MSXFAQ, L=Paderborn, S=Nordrhein-Westfalen, C=DE
Non-root Certificate
Cert Hash(sha1): cf8e46e1682273fbc901a752e47c837f8fb00e11
  Key Container = {19B15E64-E7E6-4273-8F62-65718173EBC4}
  Unique container name: d8e888d203ca20b86c23f8ba8546da56_f1a5d978-e239-405a-b311-95efaebc0482
  Provider = Microsoft RSA SChannel Cryptographic Provider
Private key is NOT exportable
Encryption test passed
CertUtil: -store command FAILED: 0x80070050 (WIN32: 80 ERROR_FILE_EXISTS)
CertUtil: The file exists.

Der Fehler kommt aber sowohl beim funktionierenden als auch beim problematischen Zertifikat aber beide liefern auch einen "Encryption test passed".

Wenn ich den Aufruf ohne Admin-Rechte mache, dann erhalte ich einen "Access is Denied" und ein "Missing stored keyset". Das ist aber erwartet.

C:\> certutil -store my CF8E46E1682273FBC901A752E47C837F8FB00E11 -verifykeys
my "Personal"
================ Certificate 1 ================
Serial Number: 0ae57ddbb755f07a62922a82c40c2263
Issuer: CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1, O=DigiCert Inc, C=US
 NotBefore: 14.10.2024 02:00
 NotAfter: 15.10.2025 01:59
Subject: CN=hybrid.msxfaq.com, O=MSXFAQ, L=Paderborn, S=Nordrhein-Westfalen, C=DE
Non-root Certificate
Cert Hash(sha1): cf8e46e1682273fbc901a752e47c837f8fb00e11
  Key Container = {19B15E64-E7E6-4273-8F62-65718173EBC4}
  Unique container name: d8e888d203ca20b86c23f8ba8546da56_f1a5d978-e239-405a-b311-95efaebc0482
  Provider = Microsoft RSA SChannel Cryptographic Provider
Missing stored keyset
CertUtil: -store command FAILED: 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED)
CertUtil: Access is denied.

Mit CERTUTIL kann ich daher ein installiertes Zertifikat prüfen aber weiter bin ich damit nicht gekommen.

Irritierend war dabei, dass ich das problematische Zertifikat auf dem Server problemlos an eine IIS-Instanz binden und nutzen konnte. Der private und öffentliche Schlüssel in der PFX-Datei passen zueinander.

Zwischenstand

Der Import der PFX-Datei in zwei anderen Test-Umgebungen war problemlos möglich und das Zertifikat wurde vom Exchange Transport klaglos angenommen.

Da ich den Fehler nur auf diesen Servern nachstellen konnte aber das Zertifikat ansonsten überall sonst funktioniert, habe ich das Thema bislang nicht weiter verfolgt

Es hat mich aber schon gefuchst, dass ich die Ursache nicht ermitteln konnte. Weder im Application- noch Security-Eventlog oder mit aktiviertem CAPI2-Debugging war etwas zu finden. Auch das Hochsetzen des EventlogLevel der verschiedenen Exchange Transport Komponenten hat keine weiteren Eventlogs generiert. Ich wüsste wirklich gerne genauer, was den Exchange Transport dazu gebracht hat, das Zertifikat beim STARTTLS nicht auszuliefern. Der SMTP-Dienst hat nämlich schon STARTTLS angeboten und auf eine entsprechende Anforderung auch umgeschaltet. Allerdings auf das "CLIENT HELLO" nicht weiter reagiert. Das konnte ich mit WireShark noch sehen.

Weitere Links