Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
saml2_sls.inc
1 <?php
21 require_once SQ_INCLUDE_PATH.'/asset.inc';
22 
36 class Saml2_SLS extends Asset
37 {
38 
39 
46  function __construct($assetid=0)
47  {
48  parent::__construct($assetid);
49 
50  }//end constructor
51 
52 
62  function _getName($short_name=FALSE)
63  {
64  return $this->attr('name');
65 
66  }//end _getName()
67 
68 
69 
80  protected function _createAdditional(Array &$link)
81  {
82  if (!parent::_createAdditional($link)) return FALSE;
83 
84  // NOTE: the main time we wont want to do this is if we are creating
85  // the root folder as it is not linked anywhere
86  if (empty($link)) return TRUE;
87 
88  return $this->makeAndSaveInitialWebPath(strtolower($this->attr('name')), $link);
89 
90  }//end _createAdditional()
91 
92 
99  function printBody()
100  {
101 
102  // get the source id from parent
103  $saml_account_manager_data = $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'saml_account_manager', TRUE, 'saml2_single_logout_service', 'minor');
104  $saml_account_manager = $GLOBALS['SQ_SYSTEM']->am->getAsset($saml_account_manager_data['majorid']);
105 
106  if(!$saml_account_manager->isSimplesamlphpInstalled()) {
107  echo('simplesamlphp library is not installed');
108  return FALSE;
109  }
110 
111  require_once SQ_TOOL_SIMPLESAMLPHP_PATH.'/lib/_autoload.php';
112  require_once SQ_PACKAGES_PATH.'/saml/lib/saml_auth_manager.inc';
113  require_once SQ_PACKAGES_PATH.'/saml/lib/saml_sp.inc';
114 
115  $sourceId = $saml_account_manager->attr('auth_source');
116 
117  $config = SimpleSAML_Configuration::getConfig('authsources.php');
118  $authConfig = $config->getArray($sourceId, NULL);
119  $source = new SAML_Service_Provider (Array('AuthId' => $sourceId), $authConfig);
120 
121  try {
122  $binding = SAML2_Binding::getCurrentBinding();
123  }
124  catch (Exception $e) {
125  echo($e->getMessage());
126  return FALSE;
127  }
128 
129  $binding = SAML2_Binding::getCurrentBinding();
130  $message = $binding->receive();
131 
132  $idpEntityId = $message->getIssuer();
133  if ($idpEntityId === NULL) {
134  /* Without an issuer we have no way to respond to the message. */
135  throw new SimpleSAML_Error_BadRequest('Received message on logout endpoint without issuer.');
136  }
137 
138  $spEntityId = $source->getEntityId();
139 
140  $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
141  $idpMetadata = $source->getIdPMetadata($idpEntityId);
142  $spMetadata = $source->getMetadata();
143 
144  sspmod_saml_Message::validateMessage($idpMetadata, $spMetadata, $message);
145 
146  $destination = $message->getDestination();
147  if ($destination !== NULL && $destination !== SimpleSAML_Utilities::selfURLNoQuery()) {
148  throw new SimpleSAML_Error_Exception('Destination in logout message is wrong.');
149  }
150 
151  if ($message instanceof SAML2_LogoutResponse) {
152 
153  $relayState = $message->getRelayState();
154  if ($relayState === NULL) {
155  /* Somehow, our RelayState has been lost. */
156  throw new SimpleSAML_Error_BadRequest('Missing RelayState in logout response.');
157  }
158 
159  if (!$message->isSuccess()) {
160  SimpleSAML_Logger::warning('Unsuccessful logout. Status was: ' . sspmod_saml_Message::getResponseError($message));
161  }
162 
163  $state = SimpleSAML_Auth_State::loadState($relayState, 'saml:slosent');
164  $state['saml:sp:LogoutStatus'] = $message->getStatus();
165  SimpleSAML_Auth_Source::completeLogout($state);
166 
167  } elseif ($message instanceof SAML2_LogoutRequest) {
168 
169  SimpleSAML_Logger::debug('SAML2 Single Logout Service: Request from ' . $idpEntityId);
170  SimpleSAML_Logger::stats('saml20-idp-SLO idpinit ' . $spEntityId . ' ' . $idpEntityId);
171 
172  if ($message->isNameIdEncrypted()) {
173  try {
174  $keys = sspmod_saml_Message::getDecryptionKeys($idpMetadata, $spMetadata);
175  } catch (Exception $e) {
176  throw new SimpleSAML_Error_Exception('Error decrypting NameID: ' . $e->getMessage());
177  }
178 
179  $lastException = NULL;
180  foreach ($keys as $i => $key) {
181  try {
182  $message->decryptNameId($key);
183  SimpleSAML_Logger::debug('Decryption with key #' . $i . ' succeeded.');
184  $lastException = NULL;
185  break;
186  } catch (Exception $e) {
187  SimpleSAML_Logger::debug('Decryption with key #' . $i . ' failed with exception: ' . $e->getMessage());
188  $lastException = $e;
189  }
190  }
191  if ($lastException !== NULL) {
192  throw $lastException;
193  }
194  }
195 
196  $nameId = $message->getNameId();
197  $sessionIndexes = $message->getSessionIndexes();
198 
199  $numLoggedOut = sspmod_saml_SP_LogoutStore::logoutSessions($sourceId, $nameId, $sessionIndexes);
200  if ($numLoggedOut === FALSE) {
201  /* This type of logout was unsupported. Use the old method. */
202  $source->handleLogout($idpEntityId);
203  $numLoggedOut = count($sessionIndexes);
204  }
205 
206  /* Create an send response. */
207  $lr = sspmod_saml_Message::buildLogoutResponse($spMetadata, $idpMetadata);
208  $lr->setRelayState($message->getRelayState());
209  $lr->setInResponseTo($message->getId());
210 
211  if ($numLoggedOut < count($sessionIndexes)) {
212  SimpleSAML_Logger::warning('Logged out of ' . $numLoggedOut . ' of ' . count($sessionIndexes) . ' sessions.');
213  }
214 
215  $binding->send($lr);
216  } else {
217  throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message));
218  }
219 
220 
221  }
222 
223 }//end class
224 ?>