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 
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 }
$params
Definition: disable.php:11
idplistStructured($list)
Structure the list of IdPs in a hierarchy based upon the tags.
Add rich text string
setPreviousIdP($idp)
Save the current IdP choice to a cookie.
$_COOKIE['client_id']
Definition: server.php:9
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41
$slist
Definition: registry.php:43
start()
Check if an IdP is set or if the request is passive, and redirect accordingly.
Definition: IdPDisco.php:512
handleRequest()
Handles a request to this discovery service.
getCDC()
Get the IdP entities saved in the common domain cookie.
Attribute-related utility methods.
static info($string)
Definition: Logger.php:201
catch(Exception $e) $message
static setCookie($name, $value, $params=null, $throw=true)
Set a cookie.
Definition: HTTP.php:1107
__construct(array $metadataSets, $instance)
Initializes this discovery service.
getIdPList()
Retrieve the list of IdPs which are stored in the metadata.
Definition: IdPDisco.php:459
log($message)
Log a message.
$tags
Definition: croninfo.php:19
filterList($list)
Filter a list of entities according to any filters defined in the parent class, plus discopower confi...
static getConfig($filename='config.php', $configSet='simplesaml')
Load a configuration file from a configuration set.
Create styles array
The data for the language used.
getPreviousIdP()
Retrieve the previous IdP the user used.
getRecommendedIdP()
Try to determine which IdP the user should most likely use.
Definition: IdPDisco.php:365
$idp
Definition: prp.php:13
$ret
Definition: parser.php:6
processFilter($filter, $entry, $default=true)
Do the actual filtering according the rules defined.
static mcmp(array $a, array $b)
Compare two entities.
$key
Definition: croninfo.php:18
validateIdP($idp)
Validates the given IdP entity id.
Definition: IdPDisco.php:238
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35