ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Server.php
Go to the documentation of this file.
1<?php
2
9{
15 private $domain;
16
17
23 private $server;
24
25
31 private $key;
32
33
42
43
49 public function __construct($domain)
50 {
51 assert(is_string($domain));
52
53 $cdcConfig = SimpleSAML_Configuration::getConfig('module_cdc.php');
54 $config = $cdcConfig->getConfigItem($domain, null);
55
56 if ($config === null) {
57 throw new SimpleSAML_Error_Exception('Unknown CDC domain: ' . var_export($domain, true));
58 }
59
60 $this->domain = $domain;
61 $this->server = $config->getString('server');
62 $this->key = $config->getString('key');
63 $this->cookieLifetime = $config->getInteger('cookie.lifetime', 0);
64
65 if ($this->key === 'ExampleSharedKey') {
66 throw new SimpleSAML_Error_Exception('Key for CDC domain ' . var_export($domain, true) . ' not changed from default.');
67 }
68 }
69
70
76 public function sendRequest(array $request)
77 {
78 assert(isset($request['return']));
79 assert(isset($request['op']));
80
81 $request['domain'] = $this->domain;
82 $this->send($this->server, 'CDCRequest', $request);
83 }
84
85
91 public function getResponse()
92 {
93 $response = self::get('CDCResponse');
94 if ($response === null) {
95 return null;
96 }
97
98 if ($response['domain'] !== $this->domain) {
99 throw new SimpleSAML_Error_Exception('Response received from wrong domain.');
100 }
101
102 $this->validate('CDCResponse');
103
104 return $response;
105 }
106
107
111 public static function processRequest()
112 {
113 $request = self::get('CDCRequest');
114 if ($request === null) {
115 throw new SimpleSAML_Error_BadRequest('Missing "CDCRequest" parameter.');
116 }
117
118 $domain = $request['domain'];
120
121 $server->validate('CDCRequest');
122 $server->handleRequest($request);
123 }
124
125
131 private function handleRequest(array $request)
132 {
133 if (!isset($request['op'])) {
134 throw new SimpleSAML_Error_BadRequest('Missing "op" in CDC request.');
135 }
136 $op = (string)$request['op'];
137
138 SimpleSAML\Logger::info('Received CDC request with "op": ' . var_export($op, true));
139
140 if (!isset($request['return'])) {
141 throw new SimpleSAML_Error_BadRequest('Missing "return" in CDC request.');
142 }
143 $return = (string)$request['return'];
144
145 switch ($op) {
146 case 'append':
147 $response = $this->handleAppend($request);
148 break;
149 case 'delete':
150 $response = $this->handleDelete($request);
151 break;
152 case 'read':
153 $response = $this->handleRead($request);
154 break;
155 default:
156 $response = 'unknown-op';
157 }
158
159 if (is_string($response)) {
160 $response = array(
161 'status' => $response,
162 );
163 }
164
165 $response['op'] = $op;
166 if (isset($request['id'])) {
167 $response['id'] = (string)$request['id'];
168 }
169 $response['domain'] = $this->domain;
170
171 $this->send($return, 'CDCResponse', $response);
172 }
173
174
181 private function handleAppend(array $request)
182 {
183 if (!isset($request['entityID'])) {
184 throw new SimpleSAML_Error_BadRequest('Missing entityID in append request.');
185 }
186 $entityID = (string)$request['entityID'];
187
188 $list = $this->getCDC();
189
190 $prevIndex = array_search($entityID, $list, true);
191 if ($prevIndex !== false) {
192 unset($list[$prevIndex]);
193 }
194 $list[] = $entityID;
195
196 $this->setCDC($list);
197
198 return 'ok';
199 }
200
201
208 private function handleDelete(array $request)
209 {
210 $params = array(
211 'path' => '/',
212 'domain' => '.' . $this->domain,
213 'secure' => true,
214 'httponly' => false,
215 );
216
217 \SimpleSAML\Utils\HTTP::setCookie('_saml_idp', null, $params, false);
218 return 'ok';
219 }
220
221
228 private function handleRead(array $request)
229 {
230 $list = $this->getCDC();
231
232 return array(
233 'status' => 'ok',
234 'cdc' => $list,
235 );
236 }
237
238
245 private static function get($parameter)
246 {
247 assert(is_string($parameter));
248
249 if (!isset($_REQUEST[$parameter])) {
250 return null;
251 }
252 $message = (string)$_REQUEST[$parameter];
253
254 $message = @base64_decode($message);
255 if ($message === false) {
256 throw new SimpleSAML_Error_BadRequest('Error base64-decoding CDC message.');
257 }
258
259 $message = @json_decode($message, true);
260 if ($message === false) {
261 throw new SimpleSAML_Error_BadRequest('Error json-decoding CDC message.');
262 }
263
264 if (!isset($message['timestamp'])) {
265 throw new SimpleSAML_Error_BadRequest('Missing timestamp in CDC message.');
266 }
267 $timestamp = (int)$message['timestamp'];
268
269 if ($timestamp + 60 < time()) {
270 throw new SimpleSAML_Error_BadRequest('CDC signature has expired.');
271 }
272 if ($timestamp - 60 > time()) {
273 throw new SimpleSAML_Error_BadRequest('CDC signature from the future.');
274 }
275
276 if (!isset($message['domain'])) {
277 throw new SimpleSAML_Error_BadRequest('Missing domain in CDC message.');
278 }
279
280 return $message;
281 }
282
283
291 private function validate($parameter)
292 {
293 assert(is_string($parameter));
294 assert(isset($_REQUEST[$parameter]));
295
296 $message = (string)$_REQUEST[$parameter];
297
298 if (!isset($_REQUEST['Signature'])) {
299 throw new SimpleSAML_Error_BadRequest('Missing Signature on CDC message.');
300 }
301 $signature = (string)$_REQUEST['Signature'];
302
303 $cSignature = $this->calcSignature($message);
304 if ($signature !== $cSignature) {
305 throw new SimpleSAML_Error_BadRequest('Invalid signature on CDC message.');
306 }
307 }
308
309
317 private function send($to, $parameter, array $message)
318 {
319 assert(is_string($to));
320 assert(is_string($parameter));
321
322 $message['timestamp'] = time();
323 $message = json_encode($message);
324 $message = base64_encode($message);
325
326 $signature = $this->calcSignature($message);
327
328 $params = array(
329 $parameter => $message,
330 'Signature' => $signature,
331 );
332
333 $url = \SimpleSAML\Utils\HTTP::addURLParameters($to, $params);
334 if (strlen($url) < 2048) {
336 } else {
338 }
339 }
340
341
348 private function calcSignature($rawMessage)
349 {
350 assert(is_string($rawMessage));
351
352 return sha1($this->key . $rawMessage . $this->key);
353 }
354
355
361 private function getCDC()
362 {
363 if (!isset($_COOKIE['_saml_idp'])) {
364 return array();
365 }
366
367 $ret = (string)$_COOKIE['_saml_idp'];
368 $ret = explode(' ', $ret);
369 foreach ($ret as &$idp) {
370 $idp = base64_decode($idp);
371 if ($idp === false) {
372 // Not properly base64 encoded
373 SimpleSAML\Logger::warning('CDC - Invalid base64-encoding of CDC entry.');
374 return array();
375 }
376 }
377
378 return $ret;
379 }
380
381
388 private function setCDC(array $list)
389 {
390 foreach ($list as &$value) {
391 $value = base64_encode($value);
392 }
393
394 $cookie = implode(' ', $list);
395
396 while (strlen($cookie) > 4000) {
397 // The cookie is too long. Remove the oldest elements until it is short enough
398 $tmp = explode(' ', $cookie, 2);
399 if (count($tmp) === 1) {
400 /*
401 * We are left with a single entityID whose base64
402 * representation is too long to fit in a cookie.
403 */
404 break;
405 }
406 $cookie = $tmp[1];
407 }
408
409 $params = array(
410 'lifetime' => $this->cookieLifetime,
411 'path' => '/',
412 'domain' => '.' . $this->domain,
413 'secure' => true,
414 'httponly' => false,
415 );
416
417 \SimpleSAML\Utils\HTTP::setCookie('_saml_idp', $cookie, $params, false);
418 }
419}
$_COOKIE['client_id']
Definition: server.php:9
foreach($paths as $path) $request
Definition: asyncclient.php:32
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
An exception for terminatinating execution or to throw for unit testing.
static info($string)
Definition: Logger.php:199
static warning($string)
Definition: Logger.php:177
static submitPOSTData($destination, $data)
Submit a POST form to a specific destination.
Definition: HTTP.php:1202
static setCookie($name, $value, $params=null, $throw=true)
Set a cookie.
Definition: HTTP.php:1104
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:959
static getConfig($filename='config.php', $configSet='simplesaml')
Load a configuration file from a configuration set.
getCDC()
Get the IdP entities saved in the common domain cookie.
Definition: Server.php:361
__construct($domain)
Initialize a CDC server.
Definition: Server.php:49
getResponse()
Parse and validate response received from a CDC server.
Definition: Server.php:91
static get($parameter)
Helper function for parsing and validating a CDC message.
Definition: Server.php:245
handleAppend(array $request)
Handle an append request.
Definition: Server.php:181
send($to, $parameter, array $message)
Helper function for sending CDC messages.
Definition: Server.php:317
$cookieLifetime
The lifetime of our cookie, in seconds.
Definition: Server.php:41
sendRequest(array $request)
Send a request to this CDC server.
Definition: Server.php:76
validate($parameter)
Helper function for validating the signature on a CDC message.
Definition: Server.php:291
handleRequest(array $request)
Handle a parsed CDC requst.
Definition: Server.php:131
setCDC(array $list)
Build a CDC cookie string.
Definition: Server.php:388
calcSignature($rawMessage)
Calculate the signature on the given message.
Definition: Server.php:348
static processRequest()
Parse and process a CDC request.
Definition: Server.php:111
handleRead(array $request)
Handle a read request.
Definition: Server.php:228
handleDelete(array $request)
Handle a delete request.
Definition: Server.php:208
$config
Definition: bootstrap.php:15
catch(Exception $e) $message
$ret
Definition: parser.php:6
$url
$response
$idp
Definition: prp.php:13
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41