MDL-59495 lang_hub: deprecate all unused strings
[moodle.git] / auth / shibboleth / logout.php
blob7bb0bec61959d5659ca5aa12eaba59b0801e62ec
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 (isloggedin($USER) && $USER->auth == 'shibboleth') {
30 // Logout user from application.
31 require_logout();
34 // Finally, send user to the return URL.
35 redirect($redirect);
37 } else if (!empty($inputstream)) {
39 // Back channel logout.
40 // Set SOAP header.
41 $server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
42 $server->addFunction("LogoutNotification");
43 $server->handle();
45 } else {
47 // Return WSDL.
48 header('Content-Type: text/xml');
50 echo <<<WSDL
51 <?xml version ="1.0" encoding ="UTF-8" ?>
52 <definitions name="LogoutNotification"
53 targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
54 xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
55 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
56 xmlns="http://schemas.xmlsoap.org/wsdl/">
58 <!--
59 This page either has to be called with the GET arguments 'action' and 'return' via
60 a redirect from the Shibboleth Service Provider logout handler (front-channel
61 logout) or via a SOAP request by a Shibboleth Service Provider (back-channel
62 logout).
63 Because neither of these two variants seems to be the case, the WSDL file for
64 the web service is returned.
66 For more information see:
67 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
68 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
69 -->
71 <types>
72 <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
73 xmlns="http://www.w3.org/2000/10/XMLSchema"
74 xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
76 <simpleType name="string">
77 <restriction base="string">
78 <minLength value="1"/>
79 </restriction>
80 </simpleType>
82 <element name="OK" type="notify:OKType"/>
83 <complexType name="OKType">
84 <sequence/>
85 </complexType>
87 </schema>
88 </types>
90 <message name="getLogoutNotificationRequest">
91 <part name="SessionID" type="notify:string" />
92 </message>
94 <message name="getLogoutNotificationResponse" >
95 <part name="OK"/>
96 </message>
98 <portType name="LogoutNotificationPortType">
99 <operation name="LogoutNotification">
100 <input message="getLogoutNotificationRequest"/>
101 <output message="getLogoutNotificationResponse"/>
102 </operation>
103 </portType>
105 <binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
106 <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
107 <operation name="LogoutNotification">
108 <soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
109 </operation>
110 </binding>
112 <service name="LogoutNotificationService">
113 <port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
114 <soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
115 </port>
116 </service>
117 </definitions>
118 WSDL;
119 exit;
121 /******************************************************************************/
123 function LogoutNotification($SessionID){
125 global $CFG, $SESSION, $DB;
127 // Delete session of user using $SessionID
128 if(empty($CFG->dbsessions)) {
130 // File session
131 $dir = $CFG->dataroot .'/sessions';
132 if (is_dir($dir)) {
133 if ($dh = opendir($dir)) {
134 // Read all session files
135 while (($file = readdir($dh)) !== false) {
136 // Check if it is a file
137 if (is_file($dir.'/'.$file)){
138 $session_key = preg_replace('/sess_/', '', $file);
140 // Read session file data
141 $data = file($dir.'/'.$file);
142 if (isset($data[0])){
143 $user_session = unserializesession($data[0]);
145 // Check if we have found session that shall be deleted
146 if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
148 // If there is a match, delete file
149 if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
150 // Delete session file
151 if (!unlink($dir.'/'.$file)){
152 return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
159 closedir($dh);
162 } else {
163 // DB Session
164 //TODO: this needs to be rewritten to use new session stuff
165 if (!empty($CFG->sessiontimeout)) {
166 $ADODB_SESS_LIFE = $CFG->sessiontimeout;
169 if ($user_session_data = $DB->get_records_sql('SELECT sesskey, sessdata FROM {sessions2} WHERE expiry > NOW()')) {
170 foreach ($user_session_data as $session_data) {
172 // Get user session
173 $user_session = adodb_unserialize( urldecode($session_data->sessdata) );
175 if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
177 // If there is a match, delete file
178 if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
179 // Delete this session entry
180 if (ADODB_Session::destroy($session_data->sesskey) !== true){
181 return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
189 // If now SoapFault was thrown the function will return OK as the SP assumes
193 /*****************************************************************************/
195 // Same function as in adodb, but cannot be used for file session for some reason...
196 function unserializesession($serialized_string) {
197 $variables = array();
198 $a = preg_split("/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
199 $counta = count($a);
200 for ($i = 0; $i < $counta; $i = $i+2) {
201 $variables[$a[$i]] = unserialize($a[$i+1]);
203 return $variables;