configFile = $configFile; $this->metadataDir = $metadataDir; } function init() { if( !is_readable($this->configFile) ) { echo "CRIT - " . $this->configFile . " didn't exists or isn't readable.\n"; return false; } $this->xml = new DOMDocument(); if( $this->xml->load($this->configFile) ) { return true; } else { echo "CRIT - Error while loading xml document: '" . $this->configFile . "'.\n"; return false; } } function getLocalMetadataFiles() { $DE = $this->xml->documentElement; if( $DE == NULL ) { echo "CRIT - No documentElement found in xml: '" . $this->configFile . "'.\n"; return false; } # alle MetadataProvider-Kinder des documentElement lesen und metadataFile-Attribute merken $MPs = $DE->getElementsByTagName("MetadataProvider"); if( $MPs->length == 0 ) { echo "WARN - No MetadataProvider found in xml: '" . $this->configFile . "'.\n"; return false; } $metadataFiles = array(); foreach( $MPs as $MP ) { if( $MP->getAttribute("xsi:type") == "FilesystemMetadataProvider" ) { $MPID = $MP->getAttribute("id"); if( $MP->hasAttribute("metadataFile") ) { $tmp = strrchr($MP->getAttribute("metadataFile"), "/"); if( $tmp !== false ) { $file = $this->metadataDir . $tmp; $metadataFiles[] = $file; } else { echo "WARN - Unknown path '" . $MP->getAttribute("metadataFile") . "' for file-attribute for MetadataProvider '" . $MPID . "'.\n"; return false; } } else { echo "WARN - No file-attribute found for MetadataProvider '" . $MPID . "'.\n"; return false; } } } return $metadataFiles; } # übergebene Datei parsen und gefundenen EntityDescriptor zurückgeben private function getEntityDescriptor($file) { if( !is_readable($file) ) { echo "WARN - " . $file . " didn't exists or isn't readable.\n"; return false; } $xml = new DOMDocument(); if( !$xml->load($file) ) { echo "WARN - Error while loading xml: '" . $file . "'.\n"; return false; } $top = $xml->documentElement; if( $top == NULL ) { echo "WARN - No documentElement found in xml: '" . $file . "'.\n"; return false; } if( in_array($top->tagName, array("EntityDescriptor", "md:EntityDescriptor")) ) { out("INFO - Found EntityDescriptor for SP:'" . $top->getAttribute("entityID") . "'.\n"); return $top; } else { echo "WARN - Unknown documentElement '" . $top->tagName . "' found in xml: '" . $file . "'.\n"; return false; } } # gibt alle hinterlegten Zertifikat der Metadaten-Datei zurück # (SPSSODescriptor => KeyDescriptor => KeyInfo => X509Data => X509Certificate => text) private function getCertificates($eD) { $SPSSOD = $eD->getElementsByTagName("SPSSODescriptor"); if( $SPSSOD->length < 1 ) { echo "WARN - Missing SPSSODescriptor in metadata.\n"; return false; } $kD = $SPSSOD->item(0)->getElementsByTagName("KeyDescriptor"); if( $kD->length < 1 ) { echo "WARN - Missing KeyDescriptor in metadata.\n"; return false; } $certs = array(); foreach( $kD as $t_kD ) { $kI = $t_kD->getElementsByTagName("KeyInfo"); if( $kI->length < 1 ) { echo "WARN - Missing KeyInfo in metadata.\n"; return false; } $data = $kI->item(0)->getElementsByTagName("X509Data"); if( $data->length < 1 ) { echo "WARN - Missing X509Data in metadata.\n"; return false; } $cert = $data->item(0)->getElementsByTagName("X509Certificate"); if( $cert->length < 1 ) { echo "WARN - Missing X509Certificate in metadata.\n"; return false; } $txt = $cert->item(0)->textContent; if( empty($txt) ) { echo "WARN - X509Certificate is empty.\n"; return false; } out("INFO - Found Certificate for SP:'" . $eD->getAttribute("entityID") . "'.\n"); if( $t_kD->hasAttribute("use") ) { $type = $t_kD->getAttribute("use"); if( $type == "signing" ) { $certs[] = array("sign", $txt); out("INFO - Cert-Type: sign.\n"); } elseif( $type == "encryption" ) { $certs[] = array("encr", $txt); out("INFO - Cert-Type: encr.\n"); } else { echo "WARN - Unknown KeyDescriptor-type:'" . $type . "'.\n"; return false; } } else { $certs[] = array("global", $txt); out("INFO - Cert-Type: global.\n"); } } return $certs; } # gibt alle Daten des Zertifikates zurück function getCertificateInfos($cert) { # alle whitespaces entfernen $cert = preg_replace('/\s+/', '', $cert); # nach 64 zeichen einen zeilenumbruch einfügen, da openssl bei zertifikaten keine längeren zeilen erlaubt $cert = chunk_split($cert, 64, "\n"); $tmp = "-----BEGIN CERTIFICATE-----\n!--[CERT]--!-----END CERTIFICATE-----"; $cert = str_replace("!--[CERT]--!", $cert, $tmp); $certInfo = openssl_x509_parse($cert); if( $certInfo == false ) { echo "WARN - Error while parsing cert.\n"; out($cert . "\n"); return false; } return $certInfo; } function getExpirationTimestamp($mf) { # liest den entityDescriptor einer Metadaten-Datei aus $descriptor = $this->getEntityDescriptor($mf); if( $descriptor === false ) { return false; } # gibt alle hinterlegten Zertifikate der Metadaten-Datei zurück $certs = $this->getCertificates($descriptor); if( $certs === false ) { return false; } if( empty($certs) ) { echo "CRIT - No certificates found in metadata: '" . $mf . "'.\n"; return false; } $sign_validTo = 0; $encr_validTo = 0; foreach( $certs as $c ) { # gibt alle Daten des Zertifikates zurück $certInfo = $this->getCertificateInfos($c[1]); if( $certInfo === false ) { return false; } # prüft ob Zertifikat überhaupt gültig out("INFO - Zertifikat gültig von:'" . $certInfo['validFrom_time_t'] . "' bis:'" . $certInfo['validTo_time_t'] . "'.\n"); if( $certInfo['validFrom_time_t'] > time() || $certInfo['validTo_time_t'] < time() ) { out("CRIT - Expired certificate found for '" . $mf . "'.\n"); continue; } else { out("OK - Valid certificate found for '" . $mf . "'.\n"); } # übernimmt höchsten Wert für Signieren und Verschlüsseln switch($c[0]) { case "global": if( $certInfo["validTo_time_t"] > $sign_validTo ) { $sign_validTo = $certInfo["validTo_time_t"]; } if( $certInfo["validTo_time_t"] > $encr_validTo ) { $encr_validTo = $certInfo["validTo_time_t"]; } break; case "sign": if( $certInfo["validTo_time_t"] > $sign_validTo ) { $sign_validTo = $certInfo["validTo_time_t"]; } break; case "encr": if( $certInfo["validTo_time_t"] > $encr_validTo ) { $encr_validTo = $certInfo["validTo_time_t"]; } break; } } # kleinster Wert von Sign und Encr gibt an, bis wann die Kommunikation zwischen SP und IdP gewährleistet ist return ($sign_validTo < $encr_validTo ? $sign_validTo : $encr_validTo); } }