From fb7adf2b1e9ffabf1572b78022391f8077b99fb6 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 8 Nov 2018 13:08:50 +0100 Subject: Update IdP Importer --- extras/import-idp.php | 98 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/extras/import-idp.php b/extras/import-idp.php index 0b9adf1..760783d 100644 --- a/extras/import-idp.php +++ b/extras/import-idp.php @@ -20,12 +20,7 @@ $db = new mysqli($settings['host'], $settings['user'], $settings['password'], $s if ($db->connect_errno) die("Could not connect to db: " . $db->connect_error . "\n"); $db->set_charset("utf8"); -if ($argc > 2) { - $url = $argv[2]; -} else { - $url = 'https://www.aai.dfn.de/fileadmin/metadata/DFN-AAI-metadata.xml'; -} -echo "Using $url...\n"; +$url = 'https://www.aai.dfn.de/fileadmin/metadata/DFN-AAI-metadata.xml'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @@ -36,24 +31,80 @@ if ($data === false) die("Could not download DFN-AAI meta data\n"); preg_match_all('##s', $data, $out); + + +function getAttributes($array, $path) +{ + if (!is_array($path)) { + // Convert '/path/syntax/foo/wanteditem' to array for further processing and recursive calls + $path = explode('/', $path); + } + do { + // Get next element from array, loop to ignore empty elements (so double slashes in the path are allowed) + $element = array_shift($path); + } while (empty($element) && !empty($path)); + if (!isset($array[$element])) { + // Current path element does not exist - error + return array(); + } + if (empty($path)) { + // Path is now empty which means we're at 'wanteditem' from out example above now + if (!is_array($array[$element]) || !isset($array[$element][0])) { + // If it's a leaf node of the array, wrap it in plain array, so the function will + // always return an array on success + return array($array[$element]); + } + // 'wanteditem' is not a unique leaf node, return as is + // This means it's either a plain array, in case there are multiple 'wanteditem' elements on the same level + // or it's an associative array if 'wanteditem' has any sub-nodes + return $array[$element]; + } + // Recurse + if (!is_array($array[$element])) { + // We're in the middle of the requested path, but the current element is already a leaf node with no + // children - error + return array(); + } + if (isset($array[$element][0])) { + // The currently handled element of the path exists multiple times on the current level, so it is + // wrapped in a plain array - recurse into each one of them and merge the results + $return = array(); + foreach ($array[$element] as $item) { + $return = array_merge($return, getAttributes($item, $path)); + } + return $return; + } + // Unique non-leaf node - simple recursion + return getAttributes($array[$element], $path); +} + +// Safety check: If XML module is missing, don't wipe DB +@simplexml_load_string(''); + +// Also, only wipe old URLs if we found at least one valid URL +function wipeDb() { + global $db; + static $wiped = false; + if ($wiped) + return; + $wiped = true; + $db->query("LOCK TABLES organization WRITE, organization_suffix WRITE"); + $db->query("UPDATE organization SET authmethod = '' WHERE authmethod LIKE 'http%'"); +} + foreach ($out[0] as $data) { $data = preg_replace('#<(/?)[a-zA-Z0-9]+:#', '<\1', $data); - $xml = json_decode(json_encode(simplexml_load_string('' . $data)), true); - //if (!isset($xml["Extensions"]["EntityAttributes"]["Attribute"]["AttributeValue"])) { - // echo "no EntityAttributes.Attribute.AttributeValue!\n"; - // continue; - //} - //if ($xml["Extensions"]["EntityAttributes"]["Attribute"]["AttributeValue"] !== 'http://aai.dfn.de/category/bwidm-member') continue; - if (!isset($xml["IDPSSODescriptor"]["Extensions"]["Scope"])) { - echo "No Extensions.Scope!\n"; - continue; - } - $scope = $xml["IDPSSODescriptor"]["Extensions"]["Scope"]; - if (!is_array($scope)) $scope = array($scope); - $name = $xml["IDPSSODescriptor"]["Extensions"]["UIInfo"]["DisplayName"]; + $data = preg_replace('# ([a-zA-Z0-9]+):([a-zA-Z0-9]+)=#', ' \1_\2=', $data); + $xml = json_decode(json_encode(simplexml_load_string('' + . $data + )), true); + if (!in_array('http://aai.dfn.de/category/bwidm-member', getAttributes($xml, 'Extensions/EntityAttributes/Attribute/AttributeValue'))) continue; + $scope = getAttributes($xml, "IDPSSODescriptor/Extensions/Scope"); + if (empty($scope)) continue; + $name = getAttributes($xml, "IDPSSODescriptor/Extensions/UIInfo/DisplayName"); $ecp = false; if (is_array($name)) $name = $name[0]; - foreach ($xml["IDPSSODescriptor"]['SingleSignOnService'] as $sso) { + foreach (getAttributes($xml, "IDPSSODescriptor/SingleSignOnService") as $sso) { if (isset($sso['@attributes']['Binding']) && $sso['@attributes']['Binding'] === 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP') { $ecp = $sso['@attributes']['Location']; break; @@ -61,15 +112,16 @@ foreach ($out[0] as $data) { } // Now usable: $scope (kind of, arrayize), $name, $ecp (if known, false otherwise) if ($ecp && !empty($scope)) { + wipeDb(); $eid = $db->escape_string($scope[0]); $ename = $db->escape_string($name); $eecp = $db->escape_string($ecp); - $db->query("INSERT INTO satellite (organizationid, address, name, authmethod, publickey) - VALUES ('$eid', '', '$ename', '$eecp', '') + $db->query("INSERT INTO organization (organizationid, name, authmethod, publickey) + VALUES ('$eid', '$ename', '$eecp', '') ON DUPLICATE KEY UPDATE authmethod = VALUES(authmethod), name = VALUES(name)"); foreach ($scope as $alias) { $ealias = $db->escape_string($alias); - $db->query("INSERT IGNORE INTO satellite_suffix (organizationid, suffix) VALUES ('$eid', '$ealias')"); + $db->query("INSERT IGNORE INTO organization_suffix (organizationid, suffix) VALUES ('$eid', '$ealias')"); } } } -- cgit v1.2.3-55-g7522