MDL-51853 calendar: Whitespace fix
[moodle.git] / auth / shibboleth / logout.php
blob997f757234aebd3c03c681961be6604c02c11012
1 <?php
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
7 require_once("../../config.php");
9 require_once($CFG->dirroot."/auth/shibboleth/auth.php");
11 $action = optional_param('action', '', PARAM_ALPHA);
12 $redirect = optional_param('return', '', PARAM_URL);
14 // Find out whether host supports https
15 $protocol = 'http://';
16 if (is_https()) {
17 $protocol = 'https://';
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'));
25 // Front channel logout.
26 $inputstream = file_get_contents("php://input");
27 if ($action == 'logout' && !empty($redirect)) {
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);
36 } else if (!empty($inputstream)) {
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();
44 } else {
46 // Return WSDL.
47 header('Content-Type: text/xml');
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/">
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.
65 For more information see:
66 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
67 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
68 -->
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">
75 <simpleType name="string">
76 <restriction base="string">
77 <minLength value="1"/>
78 </restriction>
79 </simpleType>
81 <element name="OK" type="notify:OKType"/>
82 <complexType name="OKType">
83 <sequence/>
84 </complexType>
86 </schema>
87 </types>
89 <message name="getLogoutNotificationRequest">
90 <part name="SessionID" type="notify:string" />
91 </message>
93 <message name="getLogoutNotificationResponse" >
94 <part name="OK"/>
95 </message>
97 <portType name="LogoutNotificationPortType">
98 <operation name="LogoutNotification">
99 <input message="getLogoutNotificationRequest"/>
100 <output message="getLogoutNotificationResponse"/>
101 </operation>
102 </portType>
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>
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;
120 /******************************************************************************/
122 function LogoutNotification($SessionID){
124 global $CFG, $SESSION, $DB;
126 // Delete session of user using $SessionID
127 if(empty($CFG->dbsessions)) {
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);
139 // Read session file data
140 $data = file($dir.'/'.$file);
141 if (isset($data[0])){
142 $user_session = unserializesession($data[0]);
144 // Check if we have found session that shall be deleted
145 if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
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.');
158 closedir($dh);
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;
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) {
171 // Get user session
172 $user_session = adodb_unserialize( urldecode($session_data->sessdata) );
174 if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
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.');
188 // If now SoapFault was thrown the function will return OK as the SP assumes
192 /*****************************************************************************/
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]);
202 return $variables;