ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
PowerIdPDisco.php
Go to the documentation of this file.
1<?php
2
3
14{
15
16
22 private $discoconfig;
23
24
31 private $cdcDomain;
32
33
39 private $cdcLifetime;
40
41
50 public function __construct(array $metadataSets, $instance)
51 {
52 parent::__construct($metadataSets, $instance);
53
54 $this->discoconfig = SimpleSAML_Configuration::getConfig('module_discopower.php');
55
56 $this->cdcDomain = $this->discoconfig->getString('cdc.domain', null);
57 if ($this->cdcDomain !== null && $this->cdcDomain[0] !== '.') {
58 // ensure that the CDC domain starts with a dot ('.') as required by the spec
59 $this->cdcDomain = '.'.$this->cdcDomain;
60 }
61
62 $this->cdcLifetime = $this->discoconfig->getInteger('cdc.lifetime', null);
63 }
64
65
73 protected function log($message)
74 {
75 SimpleSAML\Logger::info('PowerIdPDisco.'.$this->instance.': '.$message);
76 }
77
78
90 public static function mcmp(array $a, array $b)
91 {
92 if (isset($a['name']['en']) && isset($b['name']['en'])) {
93 return strcasecmp($a['name']['en'], $b['name']['en']);
94 } elseif (isset($a['name']['en'])) {
95 return -1; // place name before entity ID
96 } elseif (isset($b['name']['en'])) {
97 return 1; // Place entity ID after name
98 } else {
99 return strcasecmp($a['entityid'], $b['entityid']);
100 }
101 }
102
103
111 protected function idplistStructured($list)
112 {
113 $slist = array();
114
115 $order = $this->discoconfig->getValue('taborder');
116 if (is_array($order)) {
117 foreach ($order as $oe) {
118 $slist[$oe] = array();
119 }
120 }
121
122 $enableTabs = $this->discoconfig->getValue('tabs', null);
123
124 foreach ($list as $key => $val) {
125 $tags = array('misc');
126 if (array_key_exists('tags', $val)) {
127 $tags = $val['tags'];
128 }
129 foreach ($tags as $tag) {
130 if (!empty($enableTabs) && !in_array($tag, $enableTabs, true)) {
131 continue;
132 }
133 $slist[$tag][$key] = $val;
134 }
135 }
136
137 foreach ($slist as $tab => $tbslist) {
138 uasort($slist[$tab], array('sspmod_discopower_PowerIdPDisco', 'mcmp'));
139 }
140
141 return $slist;
142 }
143
144
154 private function processFilter($filter, $entry, $default = true)
155 {
156 if (in_array($entry['entityid'], $filter['entities.include'], true)) {
157 return true;
158 }
159 if (in_array($entry['entityid'], $filter['entities.exclude'], true)) {
160 return false;
161 }
162
163 if (array_key_exists('tags', $entry)) {
164 foreach ($filter['tags.include'] as $fe) {
165 if (in_array($fe, $entry['tags'], true)) {
166 return true;
167 }
168 }
169 foreach ($filter['tags.exclude'] as $fe) {
170 if (in_array($fe, $entry['tags'], true)) {
171 return false;
172 }
173 }
174 }
175 return $default;
176 }
177
178
187 protected function filterList($list)
188 {
189 $list = parent::filterList($list);
190
191 try {
192 $spmd = $this->metadata->getMetaData($this->spEntityId, 'saml20-sp-remote');
193 } catch (Exception $e) {
194 return $list;
195 }
196
197 if (!isset($spmd)) {
198 return $list;
199 }
200 if (!array_key_exists('discopower.filter', $spmd)) {
201 return $list;
202 }
203 $filter = $spmd['discopower.filter'];
204
205 if (!array_key_exists('entities.include', $filter)) {
206 $filter['entities.include'] = array();
207 }
208 if (!array_key_exists('entities.exclude', $filter)) {
209 $filter['entities.exclude'] = array();
210 }
211 if (!array_key_exists('tags.include', $filter)) {
212 $filter['tags.include'] = array();
213 }
214 if (!array_key_exists('tags.exclude', $filter)) {
215 $filter['tags.exclude'] = array();
216 }
217
218 $defaultrule = true;
219 if (array_key_exists('entities.include', $spmd['discopower.filter']) ||
220 array_key_exists('tags.include', $spmd['discopower.filter'])
221 ) {
222
223 $defaultrule = false;
224 }
225
226 $returnlist = array();
227 foreach ($list as $key => $entry) {
228 if ($this->processFilter($filter, $entry, $defaultrule)) {
229 $returnlist[$key] = $entry;
230 }
231 }
232 return $returnlist;
233 }
234
235
241 public function handleRequest()
242 {
243 $this->start();
244
245 // no choice made. Show discovery service page
246 $idpList = $this->getIdPList();
247 $idpList = $this->idplistStructured($this->filterList($idpList));
248 $preferredIdP = $this->getRecommendedIdP();
249 $faventry = NULL;
250 foreach ($idpList AS $tab => $slist) {
251 if (!empty($preferredIdP) && array_key_exists($preferredIdP, $slist)) {
252 $faventry = $slist[$preferredIdP];
253 }
254 }
255
256 $t = new SimpleSAML_XHTML_Template($this->config, 'discopower:disco.tpl.php', 'disco');
257 $discoPowerTabs = array(
258 'denmark' => $t->noop('{discopower:tabs:denmark}'),
259 'edugain' => $t->noop('{discopower:tabs:edugain}'),
260 'finland' => $t->noop('{discopower:tabs:finland}'),
261 'greece' => $t->noop('{discopower:tabs:greece}'),
262 'southafrica' => $t->noop('{discopower:tabs:southafrica}'),
263 'iceland' => $t->noop('{discopower:tabs:iceland}'),
264 'incommon' => $t->noop('{discopower:tabs:incommon}'),
265 'kalmar' => $t->noop('{discopower:tabs:kalmar}'),
266 'misc' => $t->noop('{discopower:tabs:misc}'),
267 'norway' => $t->noop('{discopower:tabs:norway}'),
268 'sweden' => $t->noop('{discopower:tabs:sweden}'),
269 'switzerland' => $t->noop('{discopower:tabs:switzerland}'),
270 'ukacessfederation' => $t->noop('{discopower:tabs:ukacessfederation}'),
271 );
272 $t->data['faventry'] = $faventry;
273 $t->data['tabNames'] = $discoPowerTabs;
274 $t->data['idplist'] = $idpList;
275 $t->data['preferredidp'] = $preferredIdP;
276 $t->data['return'] = $this->returnURL;
277 $t->data['returnIDParam'] = $this->returnIdParam;
278 $t->data['entityID'] = $this->spEntityId;
279 $t->data['urlpattern'] = htmlspecialchars(\SimpleSAML\Utils\HTTP::getSelfURLNoQuery());
280 $t->data['rememberenabled'] = $this->config->getBoolean('idpdisco.enableremember', false);
281 $t->data['rememberchecked'] = $this->config->getBoolean('idpdisco.rememberchecked', false);
282 $t->data['defaulttab'] = $this->discoconfig->getValue('defaulttab', 0);
283 $t->data['score'] = $this->discoconfig->getValue('score', 'quicksilver');
284 $t->show();
285 }
286
287
293 private function getCDC()
294 {
295 if (!isset($_COOKIE['_saml_idp'])) {
296 return array();
297 }
298
299 $ret = (string) $_COOKIE['_saml_idp'];
300 $ret = explode(' ', $ret);
301 foreach ($ret as &$idp) {
302 $idp = base64_decode($idp);
303 if ($idp === false) {
304 // not properly base64 encoded
305 return array();
306 }
307 }
308
309 return $ret;
310 }
311
312
320 protected function setPreviousIdP($idp)
321 {
322 assert('is_string($idp)');
323
324 if ($this->cdcDomain === null) {
325 parent::setPreviousIdP($idp);
326 return;
327 }
328
329 $list = $this->getCDC();
330
331 $prevIndex = array_search($idp, $list, true);
332 if ($prevIndex !== false) {
333 unset($list[$prevIndex]);
334 }
335 $list[] = $idp;
336
337 foreach ($list as &$value) {
338 $value = base64_encode($value);
339 }
340 $newCookie = implode(' ', $list);
341
342 while (strlen($newCookie) > 4000) {
343 // the cookie is too long. Remove the oldest elements until it is short enough
344 $tmp = explode(' ', $newCookie, 2);
345 if (count($tmp) === 1) {
346 // we are left with a single entityID whose base64 representation is too long to fit in a cookie
347 break;
348 }
349 $newCookie = $tmp[1];
350 }
351
352 $params = array(
353 'lifetime' => $this->cdcLifetime,
354 'domain' => $this->cdcDomain,
355 'secure' => true,
356 'httponly' => false,
357 );
358 \SimpleSAML\Utils\HTTP::setCookie('_saml_idp', $newCookie, $params, false);
359 }
360
361
369 protected function getPreviousIdP()
370 {
371 if ($this->cdcDomain === null) {
372 return parent::getPreviousIdP();
373 }
374
375 $prevIdPs = $this->getCDC();
376 while (count($prevIdPs) > 0) {
377 $idp = array_pop($prevIdPs);
378 $idp = $this->validateIdP($idp);
379 if ($idp !== null) {
380 return $idp;
381 }
382 }
383
384 return null;
385 }
386}
$_COOKIE['client_id']
Definition: server.php:9
An exception for terminatinating execution or to throw for unit testing.
static info($string)
Definition: Logger.php:201
static setCookie($name, $value, $params=null, $throw=true)
Set a cookie.
Definition: HTTP.php:1107
static getConfig($filename='config.php', $configSet='simplesaml')
Load a configuration file from a configuration set.
getIdPList()
Retrieve the list of IdPs which are stored in the metadata.
Definition: IdPDisco.php:459
start()
Check if an IdP is set or if the request is passive, and redirect accordingly.
Definition: IdPDisco.php:512
validateIdP($idp)
Validates the given IdP entity id.
Definition: IdPDisco.php:238
getRecommendedIdP()
Try to determine which IdP the user should most likely use.
Definition: IdPDisco.php:365
setPreviousIdP($idp)
Save the current IdP choice to a cookie.
static mcmp(array $a, array $b)
Compare two entities.
idplistStructured($list)
Structure the list of IdPs in a hierarchy based upon the tags.
processFilter($filter, $entry, $default=true)
Do the actual filtering according the rules defined.
filterList($list)
Filter a list of entities according to any filters defined in the parent class, plus discopower confi...
handleRequest()
Handles a request to this discovery service.
log($message)
Log a message.
getPreviousIdP()
Retrieve the previous IdP the user used.
getCDC()
Get the IdP entities saved in the common domain cookie.
__construct(array $metadataSets, $instance)
Initializes this discovery service.
$tags
Definition: croninfo.php:19
$key
Definition: croninfo.php:18
if(function_exists( 'posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
catch(Exception $e) $message
Attribute-related utility methods.
$ret
Definition: parser.php:6
$idp
Definition: prp.php:13
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41
$slist
Definition: registry.php:43
$params
Definition: disable.php:11