ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
Association.php
Go to the documentation of this file.
1 <?php
2 
20 require_once 'Auth/OpenID/CryptUtil.php';
21 
25 require_once 'Auth/OpenID/KVForm.php';
26 
30 require_once 'Auth/OpenID/HMAC.php';
31 
45 
51  var $SIG_LENGTH = 20;
52 
58  var $assoc_keys = array(
59  'version',
60  'handle',
61  'secret',
62  'issued',
63  'lifetime',
64  'assoc_type'
65  );
66 
67  var $_macs = array(
68  'HMAC-SHA1' => 'Auth_OpenID_HMACSHA1',
69  'HMAC-SHA256' => 'Auth_OpenID_HMACSHA256'
70  );
71 
97  static function fromExpiresIn($expires_in, $handle, $secret, $assoc_type)
98  {
99  $issued = time();
100  $lifetime = $expires_in;
101  return new Auth_OpenID_Association($handle, $secret,
102  $issued, $lifetime, $assoc_type);
103  }
104 
132  $handle, $secret, $issued, $lifetime, $assoc_type)
133  {
134  if (!in_array($assoc_type,
136  $fmt = 'Unsupported association type (%s)';
137  trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR);
138  }
139 
140  $this->handle = $handle;
141  $this->secret = $secret;
142  $this->issued = $issued;
143  $this->lifetime = $lifetime;
144  $this->assoc_type = $assoc_type;
145  }
146 
154  function getExpiresIn($now = null)
155  {
156  if ($now == null) {
157  $now = time();
158  }
159 
160  return max(0, $this->issued + $this->lifetime - $now);
161  }
162 
170  function equal($other)
171  {
172  return ((gettype($this) == gettype($other))
173  && ($this->handle == $other->handle)
174  && ($this->secret == $other->secret)
175  && ($this->issued == $other->issued)
176  && ($this->lifetime == $other->lifetime)
177  && ($this->assoc_type == $other->assoc_type));
178  }
179 
186  function serialize()
187  {
188  $data = array(
189  'version' => '2',
190  'handle' => $this->handle,
191  'secret' => base64_encode($this->secret),
192  'issued' => strval(intval($this->issued)),
193  'lifetime' => strval(intval($this->lifetime)),
194  'assoc_type' => $this->assoc_type
195  );
196 
197  assert(array_keys($data) == $this->assoc_keys);
198 
199  return Auth_OpenID_KVForm::fromArray($data, $strict = true);
200  }
201 
209  static function deserialize($class_name, $assoc_s)
210  {
211  $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true);
212  $keys = array();
213  $values = array();
214  foreach ($pairs as $key => $value) {
215  if (is_array($value)) {
216  list($key, $value) = $value;
217  }
218  $keys[] = $key;
219  $values[] = $value;
220  }
221 
222  $class_vars = get_class_vars($class_name);
223  $class_assoc_keys = $class_vars['assoc_keys'];
224 
225  sort($keys);
226  sort($class_assoc_keys);
227 
228  if ($keys != $class_assoc_keys) {
229  trigger_error('Unexpected key values: ' . var_export($keys, true),
230  E_USER_WARNING);
231  return null;
232  }
233 
234  $version = $pairs['version'];
235  $handle = $pairs['handle'];
236  $secret = $pairs['secret'];
237  $issued = $pairs['issued'];
238  $lifetime = $pairs['lifetime'];
239  $assoc_type = $pairs['assoc_type'];
240 
241  if ($version != '2') {
242  trigger_error('Unknown version: ' . $version, E_USER_WARNING);
243  return null;
244  }
245 
246  $issued = intval($issued);
247  $lifetime = intval($lifetime);
248  $secret = base64_decode($secret);
249 
250  return new $class_name(
251  $handle, $secret, $issued, $lifetime, $assoc_type);
252  }
253 
263  function sign($pairs)
264  {
265  $kv = Auth_OpenID_KVForm::fromArray($pairs);
266 
267  /* Invalid association types should be caught at constructor */
268  $callback = $this->_macs[$this->assoc_type];
269 
270  return call_user_func_array($callback, array($this->secret, $kv));
271  }
272 
283  function signMessage($message)
284  {
285  if ($message->hasKey(Auth_OpenID_OPENID_NS, 'sig') ||
286  $message->hasKey(Auth_OpenID_OPENID_NS, 'signed')) {
287  // Already has a sig
288  return null;
289  }
290 
291  $extant_handle = $message->getArg(Auth_OpenID_OPENID_NS,
292  'assoc_handle');
293 
294  if ($extant_handle && ($extant_handle != $this->handle)) {
295  // raise ValueError("Message has a different association handle")
296  return null;
297  }
298 
299  $signed_message = $message;
300  $signed_message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle',
301  $this->handle);
302 
303  $message_keys = array_keys($signed_message->toPostArgs());
304  $signed_list = array();
305  $signed_prefix = 'openid.';
306 
307  foreach ($message_keys as $k) {
308  if (strpos($k, $signed_prefix) === 0) {
309  $signed_list[] = substr($k, strlen($signed_prefix));
310  }
311  }
312 
313  $signed_list[] = 'signed';
314  sort($signed_list);
315 
316  $signed_message->setArg(Auth_OpenID_OPENID_NS, 'signed',
317  implode(',', $signed_list));
318  $sig = $this->getMessageSignature($signed_message);
319  $signed_message->setArg(Auth_OpenID_OPENID_NS, 'sig', $sig);
320  return $signed_message;
321  }
322 
330  function _makePairs($message)
331  {
332  $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
333  if (!$signed || Auth_OpenID::isFailure($signed)) {
334  // raise ValueError('Message has no signed list: %s' % (message,))
335  return null;
336  }
337 
338  $signed_list = explode(',', $signed);
339  $pairs = array();
340  $data = $message->toPostArgs();
341  foreach ($signed_list as $field) {
342  $pairs[] = array($field, Auth_OpenID::arrayGet($data,
343  'openid.' .
344  $field, ''));
345  }
346  return $pairs;
347  }
348 
355  function getMessageSignature($message)
356  {
357  $pairs = $this->_makePairs($message);
358  return base64_encode($this->sign($pairs));
359  }
360 
367  function checkMessageSignature($message)
368  {
369  $sig = $message->getArg(Auth_OpenID_OPENID_NS,
370  'sig');
371 
372  if (!$sig || Auth_OpenID::isFailure($sig)) {
373  return false;
374  }
375 
376  $calculated_sig = $this->getMessageSignature($message);
377  return $calculated_sig == $sig;
378  }
379 }
380 
381 function Auth_OpenID_getSecretSize($assoc_type)
382 {
383  if ($assoc_type == 'HMAC-SHA1') {
384  return 20;
385  } else if ($assoc_type == 'HMAC-SHA256') {
386  return 32;
387  } else {
388  return null;
389  }
390 }
391 
393 {
394  return array('HMAC-SHA1', 'HMAC-SHA256');
395 }
396 
398 {
399  $a = array('HMAC-SHA1');
400 
401  if (Auth_OpenID_HMACSHA256_SUPPORTED) {
402  $a[] = 'HMAC-SHA256';
403  }
404 
405  return $a;
406 }
407 
408 function Auth_OpenID_getSessionTypes($assoc_type)
409 {
410  $assoc_to_session = array(
411  'HMAC-SHA1' => array('DH-SHA1', 'no-encryption'));
412 
413  if (Auth_OpenID_HMACSHA256_SUPPORTED) {
414  $assoc_to_session['HMAC-SHA256'] =
415  array('DH-SHA256', 'no-encryption');
416  }
417 
418  return Auth_OpenID::arrayGet($assoc_to_session, $assoc_type, array());
419 }
420 
421 function Auth_OpenID_checkSessionType($assoc_type, $session_type)
422 {
423  if (!in_array($session_type,
424  Auth_OpenID_getSessionTypes($assoc_type))) {
425  return false;
426  }
427 
428  return true;
429 }
430 
432 {
433  $order = array();
434 
435  if (!Auth_OpenID_noMathSupport()) {
436  $order[] = array('HMAC-SHA1', 'DH-SHA1');
437 
438  if (Auth_OpenID_HMACSHA256_SUPPORTED) {
439  $order[] = array('HMAC-SHA256', 'DH-SHA256');
440  }
441  }
442 
443  $order[] = array('HMAC-SHA1', 'no-encryption');
444 
445  if (Auth_OpenID_HMACSHA256_SUPPORTED) {
446  $order[] = array('HMAC-SHA256', 'no-encryption');
447  }
448 
449  return $order;
450 }
451 
453 {
454  $result = array();
455 
456  foreach (Auth_OpenID_getDefaultAssociationOrder() as $pair) {
457  list($assoc, $session) = $pair;
458 
459  if ($session != 'no-encryption') {
460  if (Auth_OpenID_HMACSHA256_SUPPORTED &&
461  ($assoc == 'HMAC-SHA256')) {
462  $result[] = $pair;
463  } else if ($assoc != 'HMAC-SHA256') {
464  $result[] = $pair;
465  }
466  }
467  }
468 
469  return $result;
470 }
471 
473 {
476 }
477 
479 {
482 }
483 
526  function Auth_OpenID_SessionNegotiator($allowed_types)
527  {
528  $this->allowed_types = array();
529  $this->setAllowedTypes($allowed_types);
530  }
531 
538  function setAllowedTypes($allowed_types)
539  {
540  foreach ($allowed_types as $pair) {
541  list($assoc_type, $session_type) = $pair;
542  if (!Auth_OpenID_checkSessionType($assoc_type, $session_type)) {
543  return false;
544  }
545  }
546 
547  $this->allowed_types = $allowed_types;
548  return true;
549  }
550 
558  function addAllowedType($assoc_type, $session_type = null)
559  {
560  if ($this->allowed_types === null) {
561  $this->allowed_types = array();
562  }
563 
564  if ($session_type === null) {
565  $available = Auth_OpenID_getSessionTypes($assoc_type);
566 
567  if (!$available) {
568  return false;
569  }
570 
571  foreach ($available as $session_type) {
572  $this->addAllowedType($assoc_type, $session_type);
573  }
574  } else {
575  if (Auth_OpenID_checkSessionType($assoc_type, $session_type)) {
576  $this->allowed_types[] = array($assoc_type, $session_type);
577  } else {
578  return false;
579  }
580  }
581 
582  return true;
583  }
584 
585  // Is this combination of association type and session type allowed?
586  function isAllowed($assoc_type, $session_type)
587  {
588  $assoc_good = in_array(array($assoc_type, $session_type),
589  $this->allowed_types);
590 
591  $matches = in_array($session_type,
592  Auth_OpenID_getSessionTypes($assoc_type));
593 
594  return ($assoc_good && $matches);
595  }
596 
601  function getAllowedType()
602  {
603  if (!$this->allowed_types) {
604  return array(null, null);
605  }
606 
607  return $this->allowed_types[0];
608  }
609 }
610