Problem:

PHP hat keinen direkten Zugriff auf den Windows-Zertifikatsspeicher, um eine Überprüfung der Vertrauenswürdigkeit vornehmen zu können.

Ansatz zur Lösung:

Es besteht die Möglichkeit, mit Hilfe der PHP-Direktive

php.ini: Auszug
openssl.cafile = <absolter-Pfad-zur-Zertifikatsdatei>

auf Zertifikate, denen vertraut werden soll, zuzugreifen.

Es ist also erforderlich, alle vertrauenswürdigen Zertifikate aus dem Windows Zertifikatsspeicher in eine monolitische Datei exportieren und über die o.g. Direktive verfügbar zu machen.

Methode:

Mit Hilfe des nachfolgenden Powershell Skriptes werden standardmäßig die Windows Zertifikatsspeicher

  • Root
  • AuthRoot
  • CA

in die Datei exportiert.

Voraussetzung:

Es muss sichergestellt werden, dass sich die öffentlichen Zertifikate der Zertifizierungsstellen in einem der o.g. Verzeichnisse des Windows Zertifikatsspeichers befinden.

Alternativ kann ein abweichend verwendetes Verzeichnis in der Konfigurationsdatei ergänzt werden.

Verwendung:

Zunächst ist die Konfigurationsdatei an die individuelle Laufzeitumgebung anzupassen.

Variable

Relevanz

Beschreibung

$exportPath

erforderlich

Es muss sichergestellt werden, dass

  1. der Pfad zur Exportdatei korrekt ist
  2. die Dateiberechtigungen den Export nicht verhindern
  3. die Dateiberechtigungen das Auslesen der Exportdatei durch die PHP Laufzeitumgebung erlauben
  4. der Pfad zur Exportdatei in der PHP Laufzeitkonfiguration (Direktive openssl.cafile) hinterlegt wird

$arrExportedCertificateStores

erforderlich

Ferner muss überprüft werden, ob die gültigen Zeritifikate einer ggf. genutzten unternehmensinternen Zertifizierungsstelle in einer der standardmäßig vorkonfigurierten Windows Zertifikatsspeicher

  • Root
  • Auth
  • CA

hinterlegt werden. Abweichende Zertifikatsspeicher sind ggf. zu ergänzen. Weitere Informationen s. https://technet.microsoft.com/de-de/library/cc725751%28v=ws.11%29.aspx

$rfrAppPoolName

optional

Wenn der IIS Application Pool der zugehörigen Website hinterlegt wird, wird der Application Pool am Ende des Exportvorgangs wiederverwendet und die exportierten Zertifikate sofort von der PHP Laufzeit ausgewertet.

Der Export kann mit Hilfe der Powershell Konsole getestet werden.

Soll der Export regelmäßig ausgeführt werden, kann beispielsweise eine Aufgabe in der Windows Aufgabenplanung erstellt werden und der Aufruf über eine Batchdatei erfolgen.


Konfigurationsdatei: exportWindowsCertificateStore.conf
# Datei: exportWindowsCertificateStore.conf
 
# Konfigurationsvariablen
# -----------------------
 
# Die hier benannte Exportdatei wird von PHP benötigt, um ein von einer
# Gegenstellen empfangenes Zertifikat auf seine Vertrauenswürdigkeit
# zu überprüfen
# PHP Konfigurationsdirektive: openssl.cafile
$exportPath = "C:\inetpub\wwwroot\ExportedWindowsCertificates.crt"
 
# Liste mit Powershell konformen Zertifikatsspeichern, die Stamm- und
# Zwischenzertifikate enthalten, welche zur Überprüfung der Identität
# bei HTTPS gesicherten Verbindungen herangezogen werden.
#
# Weitere Infos unter https://wiki.mediadialog.de/x/XIAMBg
# sowie https://technet.microsoft.com/de-de/library/cc725751%28v=ws.11%29.aspx
$arrExportedCertifiacteStores = "Root","AuthRoot","CA"
 
# Optionale Angabe des IIS AplicationPool Namens
# Falls Variable nicht leer, wird der ApplicationPool recycled und somit die
# zuvor exportierten Zertifikate direkt in PHP verfügbar - Natürlich unter der
# Voraussetzung, dass die PHP Direktive openssl.cafile den Pfad zur
# exportierten Zertifikatsdatei enthält
$rfrAppPoolName = "arbeitsplanung";
Anwendung: exportWindowsCertificateStore.ps1
# Datei: exportWindowsCertificateStore.ps1
 
# Importiert Variablen der Laufzeitumgebung in Powershell Notation aus dieser Konfigurationsdatei
. .\exportWindowsCertificateStore.conf
 
# Programm
# --------
 
# Existiert das Verzeichnis, in das die Zertifikate exportiert werden sollen?
#if (-Not (Test-Path -PathType Container $exportPath)){
# Write-Output 'Das in der Variable $exportPath angegebene Verzeichnis existiert nicht !!!'
# Write-Output "exportPath: $exportPath"
# Exit
#}
 
# Entferne Exportdatei, falls eine alte Version bereits existiert
If (Test-Path $exportPath){
Remove-Item $exportPath
}
 
# Exportiere alle Zertifikate der in $arrExportedCertifiacteStores aufgeführten
# Zertifikatsspeicher
get-childitem -path cert:\LocalMachine | ForEach-Object {
$currentCertificateStore = $_
if ($arrExportedCertifiacteStores -contains $currentCertificateStore.Name) {
get-childitem -path cert:\LocalMachine\$($currentCertificateStore.Name) | ForEach-Object {
$currentCertificate = $_
$hash = $currentCertificate.GetCertHashString()
$out = New-Object String[] -ArgumentList 3
$out[0] = "-----BEGIN CERTIFICATE-----"
$out[1] = [System.Convert]::ToBase64String($currentCertificate.RawData, "InsertLineBreaks")
$out[2] = "-----END CERTIFICATE-----"
Add-Content -Path $exportPath -Value $out
}
}
}
# Prüfe, ob der IIS ApplicationPool recycled werden soll
if ($rfrAppPoolName.length -gt 0) {
 
$appCmdPath = "C:\Windows\System32\inetsrv\appcmd.exe"
if (Test-Path $appCmdPath){
# Suche nach ApplicationPool Name
$cmd = "$appCmdPath list apppool | findstr $rfrAppPoolName >nul 2>&1"
Invoke-Expression $cmd
if ($? -eq "True"){
# appcmd recycle apppool /apppool.name: string
$cmd = "$appCmdPath recycle apppool /apppool.name: $rfrAppPoolName"
Invoke-Expression $cmd
} else {
Write-Output "AppPool '$rfrAppPoolName' existiert nicht !"
}
 
} else {
Write-Output 'Das in der Variable $exportPath angegebene Verzeichnis existiert nicht !!!'
Write-Output "exportPath: $exportPath"
Exit
}
}
Batchdatei: exportWindowsCertificateStore.bat
powershell.exe -noprofile -executionpolicy bypass -file .\exportWindowsCertificateStore.ps1