1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
<?php
error_reporting(E_ALL);
if ($argc < 2) die("To few arguments. Pass config file!\n");
$handle = fopen($argv[1], 'r') or die("Cannot open mysql config given on command line\n");
$settings = array();
while (($line = fgets($handle)) !== false) {
if (!preg_match('/^\s*(.*?)\s*=\s*(.*?)\s*$/', $line, $out)) continue;
$settings[$out[1]] = $out[2];
}
fclose($handle);
$ch = curl_init();
if ($ch === false) die("Could not init curl\n");
if (empty($settings['host']) || empty($settings['user']) || empty($settings['password']) || empty($settings['db'])) die("Missing fields in given mysql config\n");
$db = new mysqli($settings['host'], $settings['user'], $settings['password'], $settings['db']);
if ($db->connect_errno) die("Could not connect to db: " . $db->connect_error . "\n");
$db->set_charset("utf8");
$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);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
if ($data === false) die("Could not download DFN-AAI meta data\n");
preg_match_all('#<EntityDescriptor.*?</EntityDescriptor>#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('<?xml version="1.0" encoding="utf-8" standalone="yes" ?'.'><test></test>');
// 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);
$data = preg_replace('# ([a-zA-Z0-9]+):([a-zA-Z0-9]+)=#', ' \1_\2=', $data);
$xml = json_decode(json_encode(simplexml_load_string('<?xml version="1.0" encoding="utf-8" standalone="yes" ?'.'>'
. $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 (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;
}
}
// 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 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 organization_suffix (organizationid, suffix) VALUES ('$eid', '$ealias')");
}
}
}
|