[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/auth/shibboleth/ -> logout.php (source)

   1  <?php
   2  
   3  // Implements logout for Shibboleth authenticated users according to:
   4  // - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
   5  // - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
   6  
   7  require_once("../../config.php");
   8  
   9  require_once($CFG->dirroot."/auth/shibboleth/auth.php");
  10  
  11  $action = optional_param('action', '', PARAM_ALPHA);
  12  $redirect = optional_param('return', '', PARAM_URL);
  13  
  14  // Find out whether host supports https
  15  $protocol = 'http://';
  16  if (is_https()) {
  17      $protocol = 'https://';
  18  }
  19  
  20  // If the shibboleth plugin is not enable, throw an exception.
  21  if (!is_enabled_auth('shibboleth')) {
  22      throw new moodle_exception(get_string('pluginnotenabled', 'auth', 'shibboleth'));
  23  }
  24  
  25  // Front channel logout.
  26  $inputstream = file_get_contents("php://input");
  27  if ($action == 'logout' && !empty($redirect)) {
  28  
  29      if ($USER->auth == 'shibboleth') {
  30          // Logout out user from application.
  31          require_logout();
  32           // Finally, send user to the return URL.
  33          redirect($redirect);
  34      }
  35  
  36  } else if (!empty($inputstream)) {
  37  
  38      // Back channel logout.
  39      // Set SOAP header.
  40      $server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
  41      $server->addFunction("LogoutNotification");
  42      $server->handle();
  43  
  44  } else {
  45  
  46      // Return WSDL.
  47      header('Content-Type: text/xml');
  48  
  49      echo <<<WSDL
  50  <?xml version ="1.0" encoding ="UTF-8" ?>
  51  <definitions name="LogoutNotification"
  52    targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
  53    xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
  54    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  55    xmlns="http://schemas.xmlsoap.org/wsdl/">
  56  
  57  <!--
  58  This page either has to be called with the GET arguments 'action' and 'return' via
  59  a redirect from the Shibboleth Service Provider logout handler (front-channel
  60  logout) or via a SOAP request by a Shibboleth Service Provider (back-channel
  61  logout).
  62  Because neither of these two variants seems to be the case, the WSDL file for
  63  the web service is returned.
  64  
  65  For more information see:
  66  - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
  67  - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
  68  -->
  69  
  70      <types>
  71         <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
  72             xmlns="http://www.w3.org/2000/10/XMLSchema"
  73             xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
  74  
  75              <simpleType name="string">
  76                  <restriction base="string">
  77                      <minLength value="1"/>
  78                  </restriction>
  79              </simpleType>
  80  
  81              <element name="OK" type="notify:OKType"/>
  82              <complexType name="OKType">
  83                  <sequence/>
  84              </complexType>
  85  
  86          </schema>
  87      </types>
  88  
  89      <message name="getLogoutNotificationRequest">
  90          <part name="SessionID" type="notify:string" />
  91      </message>
  92  
  93      <message name="getLogoutNotificationResponse" >
  94          <part name="OK"/>
  95      </message>
  96  
  97      <portType name="LogoutNotificationPortType">
  98          <operation name="LogoutNotification">
  99              <input message="getLogoutNotificationRequest"/>
 100              <output message="getLogoutNotificationResponse"/>
 101          </operation>
 102      </portType>
 103  
 104      <binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
 105          <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
 106          <operation name="LogoutNotification">
 107              <soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
 108          </operation>
 109      </binding>
 110  
 111      <service name="LogoutNotificationService">
 112            <port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
 113              <soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
 114            </port>
 115      </service>
 116  </definitions>
 117  WSDL;
 118      exit;
 119  }
 120  /******************************************************************************/
 121  
 122  function LogoutNotification($SessionID){
 123  
 124      global $CFG, $SESSION, $DB;
 125  
 126      // Delete session of user using $SessionID
 127      if(empty($CFG->dbsessions)) {
 128  
 129          // File session
 130          $dir = $CFG->dataroot .'/sessions';
 131          if (is_dir($dir)) {
 132              if ($dh = opendir($dir)) {
 133                  // Read all session files
 134                  while (($file = readdir($dh)) !== false) {
 135                      // Check if it is a file
 136                      if (is_file($dir.'/'.$file)){
 137                          $session_key = preg_replace('/sess_/', '', $file);
 138  
 139                          // Read session file data
 140                          $data = file($dir.'/'.$file);
 141                          if (isset($data[0])){
 142                              $user_session = unserializesession($data[0]);
 143  
 144                              // Check if we have found session that shall be deleted
 145                              if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
 146  
 147                                  // If there is a match, delete file
 148                                  if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
 149                                      // Delete session file
 150                                      if (!unlink($dir.'/'.$file)){
 151                                          return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
 152                                      }
 153                                  }
 154                              }
 155                          }
 156                      }
 157                  }
 158                  closedir($dh);
 159              }
 160          }
 161      } else {
 162          // DB Session
 163          //TODO: this needs to be rewritten to use new session stuff
 164          if (!empty($CFG->sessiontimeout)) {
 165              $ADODB_SESS_LIFE   = $CFG->sessiontimeout;
 166          }
 167  
 168              if ($user_session_data = $DB->get_records_sql('SELECT sesskey, sessdata FROM {sessions2} WHERE expiry > NOW()')) {
 169              foreach ($user_session_data as $session_data) {
 170  
 171                  // Get user session
 172                  $user_session = adodb_unserialize( urldecode($session_data->sessdata) );
 173  
 174                  if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
 175  
 176                      // If there is a match, delete file
 177                      if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
 178                          // Delete this session entry
 179                          if (ADODB_Session::destroy($session_data->sesskey) !== true){
 180                              return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
 181                          }
 182                      }
 183                  }
 184              }
 185          }
 186      }
 187  
 188      // If now SoapFault was thrown the function will return OK as the SP assumes
 189  
 190  }
 191  
 192  /*****************************************************************************/
 193  
 194  // Same function as in adodb, but cannot be used for file session for some reason...
 195  function unserializesession($serialized_string) {
 196      $variables = array();
 197      $a = preg_split("/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
 198      $counta = count($a);
 199      for ($i = 0; $i < $counta; $i = $i+2) {
 200              $variables[$a[$i]] = unserialize($a[$i+1]);
 201      }
 202      return $variables;
 203  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1