Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
saml_auth_manager.inc
1 <?php
17 require_once SQ_PACKAGES_PATH.'/saml/lib/saml_sp.inc';
18 
31 class SAML_Auth_Manager extends SimpleSAML_Auth_Simple
32 {
33 
34 
40  protected $authSource;
41 
42 
48  public function __construct($authSource) {
49  $this->authSource = $authSource;
50  parent::__construct($authSource);
51  }
52 
73  public function login(array $params = array()) {
74 
75  if (array_key_exists('KeepPost', $params)) {
76  $keepPost = (bool)$params['KeepPost'];
77  } else {
78  $keepPost = TRUE;
79  }
80 
81  if (array_key_exists('ReturnTo', $params)) {
82  $returnTo = (string)$params['ReturnTo'];
83  } else if (array_key_exists('ReturnCallback', $params)) {
84  $returnTo = (array)$params['ReturnCallback'];
85  } else {
86  $returnTo = current_url();
87  }
88 
89  if (is_string($returnTo) && $keepPost && $_SERVER['REQUEST_METHOD'] === 'POST') {
90  $returnTo = SimpleSAML_Utilities::createPostRedirectLink($returnTo, $_POST);
91  }
92 
93  if (array_key_exists('ErrorURL', $params)) {
94  $errorURL = (string)$params['ErrorURL'];
95  } else {
96  $errorURL = NULL;
97  }
98 
99 
100  if (!isset($params[SimpleSAML_Auth_State::RESTART]) && is_string($returnTo)) {
101  /*
102  * An URL to restart the authentication, in case the user bookmarks
103  * something, e.g. the discovery service page.
104  */
105  $restartURL = $this->getLoginURL($returnTo);
106  $params[SimpleSAML_Auth_State::RESTART] = $restartURL;
107  }
108 
109  $authId = $this->authSource;
110 
111  $state = array_merge($params, array(
112  'SimpleSAML_Auth_Default.id' => $authId,
113  'SimpleSAML_Auth_Default.Return' => $returnTo,
114  'SimpleSAML_Auth_Default.ErrorURL' => $errorURL,
115  'LoginCompletedHandler' => array('SimpleSAML_Auth_Default', 'loginCompleted'),
116  'LogoutCallback' => array(get_class(), 'logoutCallback'),
117  'LogoutCallbackState' => array(
118  'SimpleSAML_Auth_Default.logoutSource' => $authId,
119  ),
120  ));
121 
122 
123  if ($errorURL !== NULL) {
124  $state[SimpleSAML_Auth_State::EXCEPTION_HANDLER_URL] = $errorURL;
125  }
126 
127  $config = SimpleSAML_Configuration::getConfig('authsources.php');
128  $authConfig = $config->getArray($authId, NULL);
129 
130  $as = new SAML_Service_Provider (Array('AuthId' => $authId), $authConfig);
131 
132  if ($as === NULL) {
133  throw new Exception('Invalid authentication source: ' . $authId);
134  }
135 
136  try {
137  $as->authenticate($state);
138  } catch (SimpleSAML_Error_Exception $e) {
139  SimpleSAML_Auth_State::throwException($state, $e);
140  } catch (Exception $e) {
141  $e = new SimpleSAML_Error_UnserializableException($e);
142  SimpleSAML_Auth_State::throwException($state, $e);
143  }
144 
145  SimpleSAML_Auth_Default::loginCompleted($state);
146 
147  assert('FALSE');
148  }
149 
150 
151 
170  public function logout($params = NULL) {
171  assert('is_array($params) || is_string($params) || is_null($params)');
172 
173  if (empty($params)) {
174  $params = current_url();
175  }
176 
177  if (is_string($params)) {
178  $params = array(
179  'ReturnTo' => $params,
180  );
181  }
182 
183 
184 
185  assert('is_array($params)');
186  assert('isset($params["ReturnTo"]) || isset($params["ReturnCallback"])');
187 
188  if (isset($params['ReturnStateParam']) || isset($params['ReturnStateStage'])) {
189  assert('isset($params["ReturnStateParam"]) && isset($params["ReturnStateStage"])');
190  }
191 
192  $session = SimpleSAML_Session::getInstance();
193  if ($session->isValid($this->authSource)) {
194  $state = $session->getAuthData($this->authSource, 'LogoutState');
195  if ($state !== NULL) {
196  $params = array_merge($state, $params);
197  }
198 
199  $session->doLogout($this->authSource);
200 
201  $params['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted');
202 
203  $authId = $this->authSource;
204  $config = SimpleSAML_Configuration::getConfig('authsources.php');
205  $authConfig = $config->getArray($authId, NULL);
206 
207  $as = new SAML_Service_Provider (Array('AuthId' => $authId), $authConfig);
208 
209 
210  if ($as !== NULL) {
211  $as->logout($params);
212  }
213  }
214 
215  self::logoutCompleted($params);
216  }
217 
218 
219 
220 
221 
230  public function printSPMetadataXML($acs_url, $sls_url)
231  {
232  $sourceId = $this->authSource;
233 
234  $config = SimpleSAML_Configuration::getInstance();
235 
236  $authConfig = SimpleSAML_Configuration::getConfig('authsources.php');
237  $authConfig = $authConfig->getArray($sourceId, NULL);
238  $source = new SAML_Service_Provider (Array('AuthId' => $sourceId), $authConfig);
239 
240  if ($source === NULL) {
241  throw new SimpleSAML_Error_NotFound('Could not find authentication source with id ' . $sourceId);
242  }
243 
244  if (!($source instanceof sspmod_saml_Auth_Source_SP)) {
245  throw new SimpleSAML_Error_NotFound('Source isn\'t a SAML SP: ' . var_export($sourceId, TRUE));
246  }
247 
248  $entityId = $source->getEntityId();
249  $spconfig = $source->getMetadata();
250 
251  $metaArray20 = array(
252  'AssertionConsumerService' => $acs_url,
253  'SingleLogoutService' => $sls_url,
254  );
255 
256  $ed = new SAML2_XML_md_EntityDescriptor();
257  $ed->entityID = $entityId;
258 
259  $sp = new SAML2_XML_md_SPSSODescriptor();
260  $ed->RoleDescriptor[] = $sp;
261  $sp->protocolSupportEnumeration = array(
262  'urn:oasis:names:tc:SAML:1.1:protocol',
263  'urn:oasis:names:tc:SAML:2.0:protocol'
264  );
265 
266  $slo = new SAML2_XML_md_EndpointType();
267  $slo->Binding = SAML2_Const::BINDING_HTTP_REDIRECT;
268  $slo->Location = $sls_url;
269  $sp->SingleLogoutService[] = $slo;
270 
271  $store = SimpleSAML_Store::getInstance();
272  if ($store instanceof SimpleSAML_Store_SQL) {
273  /* We can properly support SOAP logout. */
274  $slo = new SAML2_XML_md_EndpointType();
275  $slo->Binding = SAML2_Const::BINDING_SOAP;
276  $slo->Location = $sls_url;
277  $sp->SingleLogoutService[] = $slo;
278  }
279 
280  $assertionsconsumerservicesdefault = array(
281  'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
282  'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
283  'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
284  'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01',
285  'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
286  );
287 
288  $assertionsconsumerservices = $spconfig->getArray('acs.Bindings', $assertionsconsumerservicesdefault);
289 
290  $index = 0;
291  foreach ($assertionsconsumerservices as $services) {
292 
293  $acs = new SAML2_XML_md_IndexedEndpointType();
294  $acs->index = $index;
295  switch ($services) {
296  case 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST':
297  $acs->Binding = SAML2_Const::BINDING_HTTP_POST;
298  $acs->Location = $acs_url;
299  break;
300  case 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post':
301  $acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post';
302  $acs->Location = $acs_url;
303  break;
304  case 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact':
305  $acs->Binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact';
306  $acs->Location = $acs_url;
307  break;
308  case 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01':
309  $acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01';
310  $acs->Location = $acs_url;
311  break;
312  case 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser':
313  $acs->Binding = 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser';
314  $acs->ProtocolBinding = SAML2_Const::BINDING_HTTP_POST;
315  $acs->Location = $acs_url;
316  break;
317  }
318  $sp->AssertionConsumerService[] = $acs;
319  $index++;
320  }
321 
322 
323  $keys = array();
324  $certInfo = SimpleSAML_Utilities::loadPublicKey($spconfig, FALSE, 'new_');
325  if ($certInfo !== NULL && array_key_exists('certData', $certInfo)) {
326  $hasNewCert = TRUE;
327 
328  $certData = $certInfo['certData'];
329  $kd = SAML2_Utils::createKeyDescriptor($certData);
330  $kd->use = 'signing';
331  $sp->KeyDescriptor[] = $kd;
332 
333  $kd = SAML2_Utils::createKeyDescriptor($certData);
334  $kd->use = 'encryption';
335  $sp->KeyDescriptor[] = $kd;
336 
337  $keys[] = array(
338  'type' => 'X509Certificate',
339  'signing' => TRUE,
340  'encryption' => TRUE,
341  'X509Certificate' => $certInfo['certData'],
342  );
343  } else {
344  $hasNewCert = FALSE;
345  }
346 
347  $certInfo = SimpleSAML_Utilities::loadPublicKey($spconfig);
348  if ($certInfo !== NULL && array_key_exists('certData', $certInfo)) {
349  $certData = $certInfo['certData'];
350  $kd = SAML2_Utils::createKeyDescriptor($certData);
351  $kd->use = 'signing';
352  $sp->KeyDescriptor[] = $kd;
353 
354  if (!$hasNewCert) {
355  /* Don't include the old certificate for encryption when we have a newer certificate. */
356  $kd = SAML2_Utils::createKeyDescriptor($certData);
357  $kd->use = 'encryption';
358  $sp->KeyDescriptor[] = $kd;
359  }
360 
361  $keys[] = array(
362  'type' => 'X509Certificate',
363  'signing' => TRUE,
364  'encryption' => ($hasNewCert ? FALSE : TRUE),
365  'X509Certificate' => $certInfo['certData'],
366  );
367  } else {
368  $certData = NULL;
369  }
370 
371  $name = $spconfig->getLocalizedString('name', NULL);
372  $attributes = $spconfig->getArray('attributes', array());
373 
374  if ($name !== NULL && !empty($attributes)) {
375 
376  $attributesrequired = $spconfig->getArray('attributes.required', array());
377 
378  /* We have everything necessary to add an AttributeConsumingService. */
379  $acs = new SAML2_XML_md_AttributeConsumingService();
380  $sp->AttributeConsumingService[] = $acs;
381 
382  $acs->index = 0;
383  $acs->ServiceName = $name;
384 
385  $description = $spconfig->getLocalizedString('description', NULL);
386  if ($description !== NULL) {
387  $acs->ServiceDescription = $description;
388  }
389 
390  $nameFormat = $spconfig->getString('attributes.NameFormat', NULL);
391  foreach ($attributes as $attribute) {
392  $a = new SAML2_XML_md_RequestedAttribute();
393  $a->Name = $attribute;
394  $a->NameFormat = $nameFormat;
395  // Is the attribute required
396  if (in_array($attribute, $attributesrequired))
397  $a->isRequired = true;
398 
399  $acs->RequestedAttribute[] = $a;
400  }
401 
402  $metaArray20['name'] = $name;
403  if ($description !== NULL) {
404  $metaArray20['description'] = $description;
405  }
406 
407  $metaArray20['attributes'] = $attributes;
408  if ($nameFormat !== NULL) {
409  $metaArray20['attributes.NameFormat'] = $nameFormat;
410  }
411  }
412 
413 
414  $orgName = $spconfig->getLocalizedString('OrganizationName', NULL);
415  if ($orgName !== NULL) {
416  $o = new SAML2_XML_md_Organization();
417  $o->OrganizationName = $orgName;
418 
419  $o->OrganizationDisplayName = $spconfig->getLocalizedString('OrganizationDisplayName', NULL);
420  if ($o->OrganizationDisplayName === NULL) {
421  $o->OrganizationDisplayName = $orgName;
422  }
423 
424  $o->OrganizationURL = $spconfig->getLocalizedString('OrganizationURL', NULL);
425  if ($o->OrganizationURL === NULL) {
426  throw new SimpleSAML_Error_Exception('If OrganizationName is set, OrganizationURL must also be set.');
427  }
428 
429  $ed->Organization = $o;
430 
431  $metaArray20['OrganizationName'] = $orgName;
432  $metaArray20['OrganizationDisplayName'] = $o->OrganizationDisplayName;
433  $metaArray20['OrganizationURL'] = $o->OrganizationURL;
434  }
435 
436  $c = new SAML2_XML_md_ContactPerson();
437  $c->contactType = 'technical';
438 
439  $email = $config->getString('technicalcontact_email', NULL);
440  if ($email !== NULL) {
441  $c->EmailAddress = array($email);
442  }
443 
444  $name = $config->getString('technicalcontact_name', NULL);
445  if ($name === NULL) {
446  /* Nothing to do here... */
447  } elseif (preg_match('@^(.*?)\s*,\s*(.*)$@D', $name, $matches)) {
448  $c->SurName = $matches[1];
449  $c->GivenName = $matches[2];
450  } elseif (preg_match('@^(.*?)\s+(.*)$@D', $name, $matches)) {
451  $c->GivenName = $matches[1];
452  $c->SurName = $matches[2];
453  } else {
454  $c->GivenName = $name;
455  }
456  $ed->ContactPerson[] = $c;
457 
458  $xml = $ed->toXML();
459  SimpleSAML_Utilities::formatDOMElement($xml);
460  $xml = $xml->ownerDocument->saveXML($xml);
461 
462  if (count($keys) === 1) {
463  $metaArray20['certData'] = $keys[0]['X509Certificate'];
464  } elseif (count($keys) > 1) {
465  $metaArray20['keys'] = $keys;
466  }
467 
468  /* Sign the metadata if enabled. */
469  $xml = SimpleSAML_Metadata_Signer::sign($xml, $sp, 'SAML 2 SP');
470 
471  return $xml;
472  }//end printSPMetadataXML()
473 
474 
475 
476 }
477 
478 
479 ?>