Subversion Repositories Applications.annuaire

Compare Revisions

Ignore whitespace Rev 435 → Rev 436

/tags/v1.2-autel/composants/openid/Auth/OpenID/Parse.php
New file
0,0 → 1,308
<?php
 
/**
* This module implements a VERY limited parser that finds <link> tags
* in the head of HTML or XHTML documents and parses out their
* attributes according to the OpenID spec. It is a liberal parser,
* but it requires these things from the data in order to work:
*
* - There must be an open <html> tag
*
* - There must be an open <head> tag inside of the <html> tag
*
* - Only <link>s that are found inside of the <head> tag are parsed
* (this is by design)
*
* - The parser follows the OpenID specification in resolving the
* attributes of the link tags. This means that the attributes DO
* NOT get resolved as they would by an XML or HTML parser. In
* particular, only certain entities get replaced, and href
* attributes do not get resolved relative to a base URL.
*
* From http://openid.net/specs.bml:
*
* - The openid.server URL MUST be an absolute URL. OpenID consumers
* MUST NOT attempt to resolve relative URLs.
*
* - The openid.server URL MUST NOT include entities other than &amp;,
* &lt;, &gt;, and &quot;.
*
* The parser ignores SGML comments and <![CDATA[blocks]]>. Both kinds
* of quoting are allowed for attributes.
*
* The parser deals with invalid markup in these ways:
*
* - Tag names are not case-sensitive
*
* - The <html> tag is accepted even when it is not at the top level
*
* - The <head> tag is accepted even when it is not a direct child of
* the <html> tag, but a <html> tag must be an ancestor of the
* <head> tag
*
* - <link> tags are accepted even when they are not direct children
* of the <head> tag, but a <head> tag must be an ancestor of the
* <link> tag
*
* - If there is no closing tag for an open <html> or <head> tag, the
* remainder of the document is viewed as being inside of the
* tag. If there is no closing tag for a <link> tag, the link tag is
* treated as a short tag. Exceptions to this rule are that <html>
* closes <html> and <body> or <head> closes <head>
*
* - Attributes of the <link> tag are not required to be quoted.
*
* - In the case of duplicated attribute names, the attribute coming
* last in the tag will be the value returned.
*
* - Any text that does not parse as an attribute within a link tag
* will be ignored. (e.g. <link pumpkin rel='openid.server' /> will
* ignore pumpkin)
*
* - If there are more than one <html> or <head> tag, the parser only
* looks inside of the first one.
*
* - The contents of <script> tags are ignored entirely, except
* unclosed <script> tags. Unclosed <script> tags are ignored.
*
* - Any other invalid markup is ignored, including unclosed SGML
* comments and unclosed <![CDATA[blocks.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Require Auth_OpenID::arrayGet().
*/
require_once "Auth/OpenID.php";
 
class Auth_OpenID_Parse {
 
/**
* Specify some flags for use with regex matching.
*/
var $_re_flags = "si";
 
/**
* Stuff to remove before we start looking for tags
*/
var $_removed_re =
"<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b(?!:)[^>]*>.*?<\/script>";
 
/**
* Starts with the tag name at a word boundary, where the tag name
* is not a namespace
*/
var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*?)(?:<\/?%s\s*>|\Z))";
 
var $_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)';
 
function Auth_OpenID_Parse()
{
$this->_link_find = sprintf("/<link\b(?!:)([^>]*)(?!<)>/%s",
$this->_re_flags);
 
$this->_entity_replacements = array(
'amp' => '&',
'lt' => '<',
'gt' => '>',
'quot' => '"'
);
 
$this->_attr_find = sprintf("/%s/%s",
$this->_attr_find,
$this->_re_flags);
 
$this->_removed_re = sprintf("/%s/%s",
$this->_removed_re,
$this->_re_flags);
 
$this->_ent_replace =
sprintf("&(%s);", implode("|",
$this->_entity_replacements));
}
 
/**
* Returns a regular expression that will match a given tag in an
* SGML string.
*/
function tagMatcher($tag_name, $close_tags = null)
{
if ($close_tags) {
$options = implode("|", array_merge(array($tag_name), $close_tags));
$closer = sprintf("(?:%s)", $options);
} else {
$closer = $tag_name;
}
 
$expr = sprintf($this->_tag_expr, $tag_name, $closer);
return sprintf("/%s/%s", $expr, $this->_re_flags);
}
 
function htmlFind()
{
return $this->tagMatcher('html');
}
 
function headFind()
{
return $this->tagMatcher('head', array('body'));
}
 
function replaceEntities($str)
{
foreach ($this->_entity_replacements as $old => $new) {
$str = preg_replace(sprintf("/&%s;/", $old), $new, $str);
}
return $str;
}
 
function removeQuotes($str)
{
$matches = array();
$double = '/^"(.*)"$/';
$single = "/^\'(.*)\'$/";
 
if (preg_match($double, $str, $matches)) {
return $matches[1];
} else if (preg_match($single, $str, $matches)) {
return $matches[1];
} else {
return $str;
}
}
 
/**
* Find all link tags in a string representing a HTML document and
* return a list of their attributes.
*
* @param string $html The text to parse
* @return array $list An array of arrays of attributes, one for each
* link tag
*/
function parseLinkAttrs($html)
{
$stripped = preg_replace($this->_removed_re,
"",
$html);
 
// Try to find the <HTML> tag.
$html_re = $this->htmlFind();
$html_matches = array();
if (!preg_match($html_re, $stripped, $html_matches)) {
return array();
}
 
// Try to find the <HEAD> tag.
$head_re = $this->headFind();
$head_matches = array();
if (!preg_match($head_re, $html_matches[0], $head_matches)) {
return array();
}
 
$link_data = array();
$link_matches = array();
 
if (!preg_match_all($this->_link_find, $head_matches[0],
$link_matches)) {
return array();
}
 
foreach ($link_matches[0] as $link) {
$attr_matches = array();
preg_match_all($this->_attr_find, $link, $attr_matches);
$link_attrs = array();
foreach ($attr_matches[0] as $index => $full_match) {
$name = $attr_matches[1][$index];
$value = $this->replaceEntities(
$this->removeQuotes($attr_matches[2][$index]));
 
$link_attrs[strtolower($name)] = $value;
}
$link_data[] = $link_attrs;
}
 
return $link_data;
}
 
function relMatches($rel_attr, $target_rel)
{
// Does this target_rel appear in the rel_str?
// XXX: TESTME
$rels = preg_split("/\s+/", trim($rel_attr));
foreach ($rels as $rel) {
$rel = strtolower($rel);
if ($rel == $target_rel) {
return 1;
}
}
 
return 0;
}
 
function linkHasRel($link_attrs, $target_rel)
{
// Does this link have target_rel as a relationship?
// XXX: TESTME
$rel_attr = Auth_OpeniD::arrayGet($link_attrs, 'rel', null);
return ($rel_attr && $this->relMatches($rel_attr,
$target_rel));
}
 
function findLinksRel($link_attrs_list, $target_rel)
{
// Filter the list of link attributes on whether it has
// target_rel as a relationship.
// XXX: TESTME
$result = array();
foreach ($link_attrs_list as $attr) {
if ($this->linkHasRel($attr, $target_rel)) {
$result[] = $attr;
}
}
 
return $result;
}
 
function findFirstHref($link_attrs_list, $target_rel)
{
// Return the value of the href attribute for the first link
// tag in the list that has target_rel as a relationship.
// XXX: TESTME
$matches = $this->findLinksRel($link_attrs_list,
$target_rel);
if (!$matches) {
return null;
}
$first = $matches[0];
return Auth_OpenID::arrayGet($first, 'href', null);
}
}
 
function Auth_OpenID_legacy_discover($html_text)
{
$p = new Auth_OpenID_Parse();
 
$link_attrs = $p->parseLinkAttrs($html_text);
 
$server_url = $p->findFirstHref($link_attrs,
'openid.server');
 
if ($server_url === null) {
return false;
} else {
$delegate_url = $p->findFirstHref($link_attrs,
'openid.delegate');
return array($delegate_url, $server_url);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/BigMath.php
New file
0,0 → 1,444
<?php
 
/**
* BigMath: A math library wrapper that abstracts out the underlying
* long integer library.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Needed for random number generation
*/
require_once 'Auth/OpenID/CryptUtil.php';
 
/**
* The superclass of all big-integer math implementations
* @access private
* @package OpenID
*/
class Auth_OpenID_MathLibrary {
/**
* Given a long integer, returns the number converted to a binary
* string. This function accepts long integer values of arbitrary
* magnitude and uses the local large-number math library when
* available.
*
* @param integer $long The long number (can be a normal PHP
* integer or a number created by one of the available long number
* libraries)
* @return string $binary The binary version of $long
*/
function longToBinary($long)
{
$cmp = $this->cmp($long, 0);
if ($cmp < 0) {
$msg = __FUNCTION__ . " takes only positive integers.";
trigger_error($msg, E_USER_ERROR);
return null;
}
 
if ($cmp == 0) {
return "\x00";
}
 
$bytes = array();
 
while ($this->cmp($long, 0) > 0) {
array_unshift($bytes, $this->mod($long, 256));
$long = $this->div($long, pow(2, 8));
}
 
if ($bytes && ($bytes[0] > 127)) {
array_unshift($bytes, 0);
}
 
$string = '';
foreach ($bytes as $byte) {
$string .= pack('C', $byte);
}
 
return $string;
}
 
/**
* Given a binary string, returns the binary string converted to a
* long number.
*
* @param string $binary The binary version of a long number,
* probably as a result of calling longToBinary
* @return integer $long The long number equivalent of the binary
* string $str
*/
function binaryToLong($str)
{
if ($str === null) {
return null;
}
 
// Use array_merge to return a zero-indexed array instead of a
// one-indexed array.
$bytes = array_merge(unpack('C*', $str));
 
$n = $this->init(0);
 
if ($bytes && ($bytes[0] > 127)) {
trigger_error("bytesToNum works only for positive integers.",
E_USER_WARNING);
return null;
}
 
foreach ($bytes as $byte) {
$n = $this->mul($n, pow(2, 8));
$n = $this->add($n, $byte);
}
 
return $n;
}
 
function base64ToLong($str)
{
$b64 = base64_decode($str);
 
if ($b64 === false) {
return false;
}
 
return $this->binaryToLong($b64);
}
 
function longToBase64($str)
{
return base64_encode($this->longToBinary($str));
}
 
/**
* Returns a random number in the specified range. This function
* accepts $start, $stop, and $step values of arbitrary magnitude
* and will utilize the local large-number math library when
* available.
*
* @param integer $start The start of the range, or the minimum
* random number to return
* @param integer $stop The end of the range, or the maximum
* random number to return
* @param integer $step The step size, such that $result - ($step
* * N) = $start for some N
* @return integer $result The resulting randomly-generated number
*/
function rand($stop)
{
static $duplicate_cache = array();
 
// Used as the key for the duplicate cache
$rbytes = $this->longToBinary($stop);
 
if (array_key_exists($rbytes, $duplicate_cache)) {
list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
} else {
if ($rbytes[0] == "\x00") {
$nbytes = strlen($rbytes) - 1;
} else {
$nbytes = strlen($rbytes);
}
 
$mxrand = $this->pow(256, $nbytes);
 
// If we get a number less than this, then it is in the
// duplicated range.
$duplicate = $this->mod($mxrand, $stop);
 
if (count($duplicate_cache) > 10) {
$duplicate_cache = array();
}
 
$duplicate_cache[$rbytes] = array($duplicate, $nbytes);
}
 
do {
$bytes = "\x00" . Auth_OpenID_CryptUtil::getBytes($nbytes);
$n = $this->binaryToLong($bytes);
// Keep looping if this value is in the low duplicated range
} while ($this->cmp($n, $duplicate) < 0);
 
return $this->mod($n, $stop);
}
}
 
/**
* Exposes BCmath math library functionality.
*
* {@link Auth_OpenID_BcMathWrapper} wraps the functionality provided
* by the BCMath extension.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_BcMathWrapper extends Auth_OpenID_MathLibrary{
var $type = 'bcmath';
 
function add($x, $y)
{
return bcadd($x, $y);
}
 
function sub($x, $y)
{
return bcsub($x, $y);
}
 
function pow($base, $exponent)
{
return bcpow($base, $exponent);
}
 
function cmp($x, $y)
{
return bccomp($x, $y);
}
 
function init($number, $base = 10)
{
return $number;
}
 
function mod($base, $modulus)
{
return bcmod($base, $modulus);
}
 
function mul($x, $y)
{
return bcmul($x, $y);
}
 
function div($x, $y)
{
return bcdiv($x, $y);
}
 
/**
* Same as bcpowmod when bcpowmod is missing
*
* @access private
*/
function _powmod($base, $exponent, $modulus)
{
$square = $this->mod($base, $modulus);
$result = 1;
while($this->cmp($exponent, 0) > 0) {
if ($this->mod($exponent, 2)) {
$result = $this->mod($this->mul($result, $square), $modulus);
}
$square = $this->mod($this->mul($square, $square), $modulus);
$exponent = $this->div($exponent, 2);
}
return $result;
}
 
function powmod($base, $exponent, $modulus)
{
if (function_exists('bcpowmod')) {
return bcpowmod($base, $exponent, $modulus);
} else {
return $this->_powmod($base, $exponent, $modulus);
}
}
 
function toString($num)
{
return $num;
}
}
 
/**
* Exposes GMP math library functionality.
*
* {@link Auth_OpenID_GmpMathWrapper} wraps the functionality provided
* by the GMP extension.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_GmpMathWrapper extends Auth_OpenID_MathLibrary{
var $type = 'gmp';
 
function add($x, $y)
{
return gmp_add($x, $y);
}
 
function sub($x, $y)
{
return gmp_sub($x, $y);
}
 
function pow($base, $exponent)
{
return gmp_pow($base, $exponent);
}
 
function cmp($x, $y)
{
return gmp_cmp($x, $y);
}
 
function init($number, $base = 10)
{
return gmp_init($number, $base);
}
 
function mod($base, $modulus)
{
return gmp_mod($base, $modulus);
}
 
function mul($x, $y)
{
return gmp_mul($x, $y);
}
 
function div($x, $y)
{
return gmp_div_q($x, $y);
}
 
function powmod($base, $exponent, $modulus)
{
return gmp_powm($base, $exponent, $modulus);
}
 
function toString($num)
{
return gmp_strval($num);
}
}
 
/**
* Define the supported extensions. An extension array has keys
* 'modules', 'extension', and 'class'. 'modules' is an array of PHP
* module names which the loading code will attempt to load. These
* values will be suffixed with a library file extension (e.g. ".so").
* 'extension' is the name of a PHP extension which will be tested
* before 'modules' are loaded. 'class' is the string name of a
* {@link Auth_OpenID_MathWrapper} subclass which should be
* instantiated if a given extension is present.
*
* You can define new math library implementations and add them to
* this array.
*/
global $_Auth_OpenID_math_extensions;
$_Auth_OpenID_math_extensions = array(
array('modules' => array('gmp', 'php_gmp'),
'extension' => 'gmp',
'class' => 'Auth_OpenID_GmpMathWrapper'),
array('modules' => array('bcmath', 'php_bcmath'),
'extension' => 'bcmath',
'class' => 'Auth_OpenID_BcMathWrapper')
);
 
/**
* Detect which (if any) math library is available
*/
function Auth_OpenID_detectMathLibrary($exts)
{
$loaded = false;
 
foreach ($exts as $extension) {
// See if the extension specified is already loaded.
if ($extension['extension'] &&
extension_loaded($extension['extension'])) {
$loaded = true;
}
 
// Try to load dynamic modules.
if (!$loaded) {
foreach ($extension['modules'] as $module) {
if (@dl($module . "." . PHP_SHLIB_SUFFIX)) {
$loaded = true;
break;
}
}
}
 
// If the load succeeded, supply an instance of
// Auth_OpenID_MathWrapper which wraps the specified
// module's functionality.
if ($loaded) {
return $extension;
}
}
 
return false;
}
 
/**
* {@link Auth_OpenID_getMathLib} checks for the presence of long
* number extension modules and returns an instance of
* {@link Auth_OpenID_MathWrapper} which exposes the module's
* functionality.
*
* Checks for the existence of an extension module described by the
* local {@link Auth_OpenID_math_extensions} array and returns an
* instance of a wrapper for that extension module. If no extension
* module is found, an instance of {@link Auth_OpenID_MathWrapper} is
* returned, which wraps the native PHP integer implementation. The
* proper calling convention for this method is $lib =&
* Auth_OpenID_getMathLib().
*
* This function checks for the existence of specific long number
* implementations in the following order: GMP followed by BCmath.
*
* @return Auth_OpenID_MathWrapper $instance An instance of
* {@link Auth_OpenID_MathWrapper} or one of its subclasses
*
* @package OpenID
*/
function &Auth_OpenID_getMathLib()
{
// The instance of Auth_OpenID_MathWrapper that we choose to
// supply will be stored here, so that subseqent calls to this
// method will return a reference to the same object.
static $lib = null;
 
if (isset($lib)) {
return $lib;
}
 
if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
$null = null;
return $null;
}
 
// If this method has not been called before, look at
// $Auth_OpenID_math_extensions and try to find an extension that
// works.
global $_Auth_OpenID_math_extensions;
$ext = Auth_OpenID_detectMathLibrary($_Auth_OpenID_math_extensions);
if ($ext === false) {
$tried = array();
foreach ($_Auth_OpenID_math_extensions as $extinfo) {
$tried[] = $extinfo['extension'];
}
$triedstr = implode(", ", $tried);
 
define('Auth_OpenID_NO_MATH_SUPPORT', true);
return null;
}
 
// Instantiate a new wrapper
$class = $ext['class'];
$lib = new $class();
 
return $lib;
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/Association.php
New file
0,0 → 1,308
<?php
 
/**
* This module contains code for dealing with associations between
* consumers and servers.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* @access private
*/
require_once 'Auth/OpenID/CryptUtil.php';
 
/**
* @access private
*/
require_once 'Auth/OpenID/KVForm.php';
 
/**
* This class represents an association between a server and a
* consumer. In general, users of this library will never see
* instances of this object. The only exception is if you implement a
* custom {@link Auth_OpenID_OpenIDStore}.
*
* If you do implement such a store, it will need to store the values
* of the handle, secret, issued, lifetime, and assoc_type instance
* variables.
*
* @package OpenID
*/
class Auth_OpenID_Association {
 
/**
* This is a HMAC-SHA1 specific value.
*
* @access private
*/
var $SIG_LENGTH = 20;
 
/**
* The ordering and name of keys as stored by serialize.
*
* @access private
*/
var $assoc_keys = array(
'version',
'handle',
'secret',
'issued',
'lifetime',
'assoc_type'
);
 
/**
* This is an alternate constructor (factory method) used by the
* OpenID consumer library to create associations. OpenID store
* implementations shouldn't use this constructor.
*
* @access private
*
* @param integer $expires_in This is the amount of time this
* association is good for, measured in seconds since the
* association was issued.
*
* @param string $handle This is the handle the server gave this
* association.
*
* @param string secret This is the shared secret the server
* generated for this association.
*
* @param assoc_type This is the type of association this
* instance represents. The only valid value of this field at
* this time is 'HMAC-SHA1', but new types may be defined in the
* future.
*
* @return association An {@link Auth_OpenID_Association}
* instance.
*/
function fromExpiresIn($expires_in, $handle, $secret, $assoc_type)
{
$issued = time();
$lifetime = $expires_in;
return new Auth_OpenID_Association($handle, $secret,
$issued, $lifetime, $assoc_type);
}
 
/**
* This is the standard constructor for creating an association.
* The library should create all of the necessary associations, so
* this constructor is not part of the external API.
*
* @access private
*
* @param string $handle This is the handle the server gave this
* association.
*
* @param string $secret This is the shared secret the server
* generated for this association.
*
* @param integer $issued This is the time this association was
* issued, in seconds since 00:00 GMT, January 1, 1970. (ie, a
* unix timestamp)
*
* @param integer $lifetime This is the amount of time this
* association is good for, measured in seconds since the
* association was issued.
*
* @param string $assoc_type This is the type of association this
* instance represents. The only valid value of this field at
* this time is 'HMAC-SHA1', but new types may be defined in the
* future.
*/
function Auth_OpenID_Association(
$handle, $secret, $issued, $lifetime, $assoc_type)
{
if ($assoc_type != 'HMAC-SHA1') {
$fmt = 'HMAC-SHA1 is the only supported association type (got %s)';
trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR);
}
 
$this->handle = $handle;
$this->secret = $secret;
$this->issued = $issued;
$this->lifetime = $lifetime;
$this->assoc_type = $assoc_type;
}
 
/**
* This returns the number of seconds this association is still
* valid for, or 0 if the association is no longer valid.
*
* @return integer $seconds The number of seconds this association
* is still valid for, or 0 if the association is no longer valid.
*/
function getExpiresIn($now = null)
{
if ($now == null) {
$now = time();
}
 
return max(0, $this->issued + $this->lifetime - $now);
}
 
/**
* This checks to see if two {@link Auth_OpenID_Association}
* instances represent the same association.
*
* @return bool $result true if the two instances represent the
* same association, false otherwise.
*/
function equal($other)
{
return ((gettype($this) == gettype($other))
&& ($this->handle == $other->handle)
&& ($this->secret == $other->secret)
&& ($this->issued == $other->issued)
&& ($this->lifetime == $other->lifetime)
&& ($this->assoc_type == $other->assoc_type));
}
 
/**
* Convert an association to KV form.
*
* @return string $result String in KV form suitable for
* deserialization by deserialize.
*/
function serialize()
{
$data = array(
'version' => '2',
'handle' => $this->handle,
'secret' => base64_encode($this->secret),
'issued' => strval(intval($this->issued)),
'lifetime' => strval(intval($this->lifetime)),
'assoc_type' => $this->assoc_type
);
 
assert(array_keys($data) == $this->assoc_keys);
 
return Auth_OpenID_KVForm::fromArray($data, $strict = true);
}
 
/**
* Parse an association as stored by serialize(). This is the
* inverse of serialize.
*
* @param string $assoc_s Association as serialized by serialize()
* @return Auth_OpenID_Association $result instance of this class
*/
function deserialize($class_name, $assoc_s)
{
$pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true);
$keys = array();
$values = array();
foreach ($pairs as $key => $value) {
if (is_array($value)) {
list($key, $value) = $value;
}
$keys[] = $key;
$values[] = $value;
}
 
$class_vars = get_class_vars($class_name);
$class_assoc_keys = $class_vars['assoc_keys'];
 
sort($keys);
sort($class_assoc_keys);
 
if ($keys != $class_assoc_keys) {
trigger_error('Unexpected key values: ' . strval($keys),
E_USER_WARNING);
return null;
}
 
$version = $pairs['version'];
$handle = $pairs['handle'];
$secret = $pairs['secret'];
$issued = $pairs['issued'];
$lifetime = $pairs['lifetime'];
$assoc_type = $pairs['assoc_type'];
 
if ($version != '2') {
trigger_error('Unknown version: ' . $version, E_USER_WARNING);
return null;
}
 
$issued = intval($issued);
$lifetime = intval($lifetime);
$secret = base64_decode($secret);
 
return new $class_name(
$handle, $secret, $issued, $lifetime, $assoc_type);
}
 
/**
* Generate a signature for a sequence of (key, value) pairs
*
* @access private
* @param array $pairs The pairs to sign, in order. This is an
* array of two-tuples.
* @return string $signature The binary signature of this sequence
* of pairs
*/
function sign($pairs)
{
$kv = Auth_OpenID_KVForm::fromArray($pairs);
return Auth_OpenID_HMACSHA1($this->secret, $kv);
}
 
/**
* Generate a signature for some fields in a dictionary
*
* @access private
* @param array $fields The fields to sign, in order; this is an
* array of strings.
* @param array $data Dictionary of values to sign (an array of
* string => string pairs).
* @return string $signature The signature, base64 encoded
*/
function signDict($fields, $data, $prefix = 'openid.')
{
$pairs = array();
foreach ($fields as $field) {
$pairs[] = array($field, $data[$prefix . $field]);
}
 
return base64_encode($this->sign($pairs));
}
 
/**
* Add a signature to an array of fields
*
* @access private
*/
function addSignature($fields, &$data, $prefix = 'openid.')
{
$sig = $this->signDict($fields, $data, $prefix);
$signed = implode(",", $fields);
$data[$prefix . 'sig'] = $sig;
$data[$prefix . 'signed'] = $signed;
}
 
/**
* Confirm that the signature of these fields matches the
* signature contained in the data
*
* @access private
*/
function checkSignature($data, $prefix = 'openid.')
{
$signed = $data[$prefix . 'signed'];
$fields = explode(",", $signed);
$expected_sig = $this->signDict($fields, $data, $prefix);
$request_sig = $data[$prefix . 'sig'];
 
return ($request_sig == $expected_sig);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/SQLStore.php
New file
0,0 → 1,658
<?php
 
/**
* SQL-backed OpenID stores.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Require the PEAR DB module because we'll need it for the SQL-based
* stores implemented here. We silence any errors from the inclusion
* because it might not be present, and a user of the SQL stores may
* supply an Auth_OpenID_DatabaseConnection instance that implements
* its own storage.
*/
global $__Auth_OpenID_PEAR_AVAILABLE;
$__Auth_OpenID_PEAR_AVAILABLE = @include_once 'DB.php';
 
/**
* @access private
*/
require_once 'Auth/OpenID/Interface.php';
 
/**
* This is the parent class for the SQL stores, which contains the
* logic common to all of the SQL stores.
*
* The table names used are determined by the class variables
* settings_table_name, associations_table_name, and
* nonces_table_name. To change the name of the tables used, pass new
* table names into the constructor.
*
* To create the tables with the proper schema, see the createTables
* method.
*
* This class shouldn't be used directly. Use one of its subclasses
* instead, as those contain the code necessary to use a specific
* database. If you're an OpenID integrator and you'd like to create
* an SQL-driven store that wraps an application's database
* abstraction, be sure to create a subclass of
* {@link Auth_OpenID_DatabaseConnection} that calls the application's
* database abstraction calls. Then, pass an instance of your new
* database connection class to your SQLStore subclass constructor.
*
* All methods other than the constructor and createTables should be
* considered implementation details.
*
* @package OpenID
*/
class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore {
 
/**
* This creates a new SQLStore instance. It requires an
* established database connection be given to it, and it allows
* overriding the default table names.
*
* @param connection $connection This must be an established
* connection to a database of the correct type for the SQLStore
* subclass you're using. This must either be an PEAR DB
* connection handle or an instance of a subclass of
* Auth_OpenID_DatabaseConnection.
*
* @param string $settings_table This is an optional parameter to
* specify the name of the table used for this store's settings.
* The default value is 'oid_settings'.
*
* @param associations_table: This is an optional parameter to
* specify the name of the table used for storing associations.
* The default value is 'oid_associations'.
*
* @param nonces_table: This is an optional parameter to specify
* the name of the table used for storing nonces. The default
* value is 'oid_nonces'.
*/
function Auth_OpenID_SQLStore($connection, $settings_table = null,
$associations_table = null,
$nonces_table = null)
{
global $__Auth_OpenID_PEAR_AVAILABLE;
 
$this->settings_table_name = "oid_settings";
$this->associations_table_name = "oid_associations";
$this->nonces_table_name = "oid_nonces";
 
// Check the connection object type to be sure it's a PEAR
// database connection.
if (!(is_object($connection) &&
(is_subclass_of($connection, 'db_common') ||
is_subclass_of($connection,
'auth_openid_databaseconnection')))) {
trigger_error("Auth_OpenID_SQLStore expected PEAR connection " .
"object (got ".get_class($connection).")",
E_USER_ERROR);
return;
}
 
$this->connection = $connection;
 
// Be sure to set the fetch mode so the results are keyed on
// column name instead of column index. This is a PEAR
// constant, so only try to use it if PEAR is present. Note
// that Auth_Openid_Databaseconnection instances need not
// implement ::setFetchMode for this reason.
if ($__Auth_OpenID_PEAR_AVAILABLE) {
$this->connection->setFetchMode(DB_FETCHMODE_ASSOC);
}
 
if ($settings_table) {
$this->settings_table_name = $settings_table;
}
 
if ($associations_table) {
$this->associations_table_name = $associations_table;
}
 
if ($nonces_table) {
$this->nonces_table_name = $nonces_table;
}
 
$this->max_nonce_age = 6 * 60 * 60;
 
// Be sure to run the database queries with auto-commit mode
// turned OFF, because we want every function to run in a
// transaction, implicitly. As a rule, methods named with a
// leading underscore will NOT control transaction behavior.
// Callers of these methods will worry about transactions.
$this->connection->autoCommit(false);
 
// Create an empty SQL strings array.
$this->sql = array();
 
// Call this method (which should be overridden by subclasses)
// to populate the $this->sql array with SQL strings.
$this->setSQL();
 
// Verify that all required SQL statements have been set, and
// raise an error if any expected SQL strings were either
// absent or empty.
list($missing, $empty) = $this->_verifySQL();
 
if ($missing) {
trigger_error("Expected keys in SQL query list: " .
implode(", ", $missing),
E_USER_ERROR);
return;
}
 
if ($empty) {
trigger_error("SQL list keys have no SQL strings: " .
implode(", ", $empty),
E_USER_ERROR);
return;
}
 
// Add table names to queries.
$this->_fixSQL();
}
 
function tableExists($table_name)
{
return !$this->isError(
$this->connection->query("SELECT * FROM %s LIMIT 0",
$table_name));
}
 
/**
* Returns true if $value constitutes a database error; returns
* false otherwise.
*/
function isError($value)
{
return PEAR::isError($value);
}
 
/**
* Converts a query result to a boolean. If the result is a
* database error according to $this->isError(), this returns
* false; otherwise, this returns true.
*/
function resultToBool($obj)
{
if ($this->isError($obj)) {
return false;
} else {
return true;
}
}
 
/**
* This method should be overridden by subclasses. This method is
* called by the constructor to set values in $this->sql, which is
* an array keyed on sql name.
*/
function setSQL()
{
}
 
/**
* Resets the store by removing all records from the store's
* tables.
*/
function reset()
{
$this->connection->query(sprintf("DELETE FROM %s",
$this->associations_table_name));
 
$this->connection->query(sprintf("DELETE FROM %s",
$this->nonces_table_name));
 
$this->connection->query(sprintf("DELETE FROM %s",
$this->settings_table_name));
}
 
/**
* @access private
*/
function _verifySQL()
{
$missing = array();
$empty = array();
 
$required_sql_keys = array(
'nonce_table',
'assoc_table',
'settings_table',
'get_auth',
'create_auth',
'set_assoc',
'get_assoc',
'get_assocs',
'remove_assoc',
'add_nonce',
'get_nonce',
'remove_nonce'
);
 
foreach ($required_sql_keys as $key) {
if (!array_key_exists($key, $this->sql)) {
$missing[] = $key;
} else if (!$this->sql[$key]) {
$empty[] = $key;
}
}
 
return array($missing, $empty);
}
 
/**
* @access private
*/
function _fixSQL()
{
$replacements = array(
array(
'value' => $this->nonces_table_name,
'keys' => array('nonce_table',
'add_nonce',
'get_nonce',
'remove_nonce')
),
array(
'value' => $this->associations_table_name,
'keys' => array('assoc_table',
'set_assoc',
'get_assoc',
'get_assocs',
'remove_assoc')
),
array(
'value' => $this->settings_table_name,
'keys' => array('settings_table',
'get_auth',
'create_auth')
)
);
 
foreach ($replacements as $item) {
$value = $item['value'];
$keys = $item['keys'];
 
foreach ($keys as $k) {
if (is_array($this->sql[$k])) {
foreach ($this->sql[$k] as $part_key => $part_value) {
$this->sql[$k][$part_key] = sprintf($part_value,
$value);
}
} else {
$this->sql[$k] = sprintf($this->sql[$k], $value);
}
}
}
}
 
function blobDecode($blob)
{
return $blob;
}
 
function blobEncode($str)
{
return $str;
}
 
function createTables()
{
$this->connection->autoCommit(true);
$n = $this->create_nonce_table();
$a = $this->create_assoc_table();
$s = $this->create_settings_table();
$this->connection->autoCommit(false);
 
if ($n && $a && $s) {
return true;
} else {
return false;
}
}
 
function create_nonce_table()
{
if (!$this->tableExists($this->nonces_table_name)) {
$r = $this->connection->query($this->sql['nonce_table']);
return $this->resultToBool($r);
}
return true;
}
 
function create_assoc_table()
{
if (!$this->tableExists($this->associations_table_name)) {
$r = $this->connection->query($this->sql['assoc_table']);
return $this->resultToBool($r);
}
return true;
}
 
function create_settings_table()
{
if (!$this->tableExists($this->settings_table_name)) {
$r = $this->connection->query($this->sql['settings_table']);
return $this->resultToBool($r);
}
return true;
}
 
/**
* @access private
*/
function _get_auth()
{
return $this->connection->getOne($this->sql['get_auth']);
}
 
/**
* @access private
*/
function _create_auth($str)
{
return $this->connection->query($this->sql['create_auth'],
array($str));
}
 
function getAuthKey()
{
$value = $this->_get_auth();
if (!$value) {
$auth_key =
Auth_OpenID_CryptUtil::randomString($this->AUTH_KEY_LEN);
 
$auth_key_s = $this->blobEncode($auth_key);
$this->_create_auth($auth_key_s);
} else {
$auth_key_s = $value;
$auth_key = $this->blobDecode($auth_key_s);
}
 
$this->connection->commit();
 
if (strlen($auth_key) != $this->AUTH_KEY_LEN) {
$fmt = "Expected %d-byte string for auth key. Got key of length %d";
trigger_error(sprintf($fmt, $this->AUTH_KEY_LEN, strlen($auth_key)),
E_USER_WARNING);
return null;
}
 
return $auth_key;
}
 
/**
* @access private
*/
function _set_assoc($server_url, $handle, $secret, $issued,
$lifetime, $assoc_type)
{
return $this->connection->query($this->sql['set_assoc'],
array(
$server_url,
$handle,
$secret,
$issued,
$lifetime,
$assoc_type));
}
 
function storeAssociation($server_url, $association)
{
if ($this->resultToBool($this->_set_assoc(
$server_url,
$association->handle,
$this->blobEncode(
$association->secret),
$association->issued,
$association->lifetime,
$association->assoc_type
))) {
$this->connection->commit();
} else {
$this->connection->rollback();
}
}
 
/**
* @access private
*/
function _get_assoc($server_url, $handle)
{
$result = $this->connection->getRow($this->sql['get_assoc'],
array($server_url, $handle));
if ($this->isError($result)) {
return null;
} else {
return $result;
}
}
 
/**
* @access private
*/
function _get_assocs($server_url)
{
$result = $this->connection->getAll($this->sql['get_assocs'],
array($server_url));
 
if ($this->isError($result)) {
return array();
} else {
return $result;
}
}
 
function removeAssociation($server_url, $handle)
{
if ($this->_get_assoc($server_url, $handle) == null) {
return false;
}
 
if ($this->resultToBool($this->connection->query(
$this->sql['remove_assoc'],
array($server_url, $handle)))) {
$this->connection->commit();
} else {
$this->connection->rollback();
}
 
return true;
}
 
function getAssociation($server_url, $handle = null)
{
if ($handle !== null) {
$assoc = $this->_get_assoc($server_url, $handle);
 
$assocs = array();
if ($assoc) {
$assocs[] = $assoc;
}
} else {
$assocs = $this->_get_assocs($server_url);
}
 
if (!$assocs || (count($assocs) == 0)) {
return null;
} else {
$associations = array();
 
foreach ($assocs as $assoc_row) {
$assoc = new Auth_OpenID_Association($assoc_row['handle'],
$assoc_row['secret'],
$assoc_row['issued'],
$assoc_row['lifetime'],
$assoc_row['assoc_type']);
 
$assoc->secret = $this->blobDecode($assoc->secret);
 
if ($assoc->getExpiresIn() == 0) {
$this->removeAssociation($server_url, $assoc->handle);
} else {
$associations[] = array($assoc->issued, $assoc);
}
}
 
if ($associations) {
$issued = array();
$assocs = array();
foreach ($associations as $key => $assoc) {
$issued[$key] = $assoc[0];
$assocs[$key] = $assoc[1];
}
 
array_multisort($issued, SORT_DESC, $assocs, SORT_DESC,
$associations);
 
// return the most recently issued one.
list($issued, $assoc) = $associations[0];
return $assoc;
} else {
return null;
}
}
}
 
/**
* @access private
*/
function _add_nonce($nonce, $expires)
{
$sql = $this->sql['add_nonce'];
$result = $this->connection->query($sql, array($nonce, $expires));
return $this->resultToBool($result);
}
 
/**
* @access private
*/
function storeNonce($nonce)
{
if ($this->_add_nonce($nonce, time())) {
$this->connection->commit();
} else {
$this->connection->rollback();
}
}
 
/**
* @access private
*/
function _get_nonce($nonce)
{
$result = $this->connection->getRow($this->sql['get_nonce'],
array($nonce));
 
if ($this->isError($result)) {
return null;
} else {
return $result;
}
}
 
/**
* @access private
*/
function _remove_nonce($nonce)
{
$this->connection->query($this->sql['remove_nonce'],
array($nonce));
}
 
function useNonce($nonce)
{
$row = $this->_get_nonce($nonce);
 
if ($row !== null) {
$nonce = $row['nonce'];
$timestamp = $row['expires'];
$nonce_age = time() - $timestamp;
 
if ($nonce_age > $this->max_nonce_age) {
$present = 0;
} else {
$present = 1;
}
 
$this->_remove_nonce($nonce);
} else {
$present = 0;
}
 
$this->connection->commit();
 
return $present;
}
 
/**
* "Octifies" a binary string by returning a string with escaped
* octal bytes. This is used for preparing binary data for
* PostgreSQL BYTEA fields.
*
* @access private
*/
function _octify($str)
{
$result = "";
for ($i = 0; $i < strlen($str); $i++) {
$ch = substr($str, $i, 1);
if ($ch == "\\") {
$result .= "\\\\\\\\";
} else if (ord($ch) == 0) {
$result .= "\\\\000";
} else {
$result .= "\\" . strval(decoct(ord($ch)));
}
}
return $result;
}
 
/**
* "Unoctifies" octal-escaped data from PostgreSQL and returns the
* resulting ASCII (possibly binary) string.
*
* @access private
*/
function _unoctify($str)
{
$result = "";
$i = 0;
while ($i < strlen($str)) {
$char = $str[$i];
if ($char == "\\") {
// Look to see if the next char is a backslash and
// append it.
if ($str[$i + 1] != "\\") {
$octal_digits = substr($str, $i + 1, 3);
$dec = octdec($octal_digits);
$char = chr($dec);
$i += 4;
} else {
$char = "\\";
$i += 2;
}
} else {
$i += 1;
}
 
$result .= $char;
}
 
return $result;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/SQLiteStore.php
New file
0,0 → 1,66
<?php
 
/**
* An SQLite store.
*
* @package OpenID
*/
 
/**
* Require the base class file.
*/
require_once "Auth/OpenID/SQLStore.php";
 
/**
* An SQL store that uses SQLite as its backend.
*
* @package OpenID
*/
class Auth_OpenID_SQLiteStore extends Auth_OpenID_SQLStore {
function setSQL()
{
$this->sql['nonce_table'] =
"CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
"expires INTEGER)";
 
$this->sql['assoc_table'] =
"CREATE TABLE %s (server_url VARCHAR(2047), handle VARCHAR(255), ".
"secret BLOB(128), issued INTEGER, lifetime INTEGER, ".
"assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle))";
 
$this->sql['settings_table'] =
"CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
"value BLOB(20))";
 
$this->sql['create_auth'] =
"INSERT INTO %s VALUES ('auth_key', ?)";
 
$this->sql['get_auth'] =
"SELECT value FROM %s WHERE setting = 'auth_key'";
 
$this->sql['set_assoc'] =
"INSERT OR REPLACE INTO %s VALUES (?, ?, ?, ?, ?, ?)";
 
$this->sql['get_assocs'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ?";
 
$this->sql['get_assoc'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ? AND handle = ?";
 
$this->sql['remove_assoc'] =
"DELETE FROM %s WHERE server_url = ? AND handle = ?";
 
$this->sql['add_nonce'] =
"INSERT OR REPLACE INTO %s (nonce, expires) VALUES (?, ?)";
 
$this->sql['get_nonce'] =
"SELECT * FROM %s WHERE nonce = ?";
 
$this->sql['remove_nonce'] =
"DELETE FROM %s WHERE nonce = ?";
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/Discover.php
New file
0,0 → 1,258
<?php
 
/**
* The OpenID and Yadis discovery implementation for OpenID 1.2.
*/
 
require_once "Auth/OpenID.php";
require_once "Auth/OpenID/Parse.php";
require_once "Services/Yadis/XRIRes.php";
require_once "Services/Yadis/Yadis.php";
 
define('_OPENID_1_0_NS', 'http://openid.net/xmlns/1.0');
define('_OPENID_1_2_TYPE', 'http://openid.net/signon/1.2');
define('_OPENID_1_1_TYPE', 'http://openid.net/signon/1.1');
define('_OPENID_1_0_TYPE', 'http://openid.net/signon/1.0');
 
/**
* Object representing an OpenID service endpoint.
*/
class Auth_OpenID_ServiceEndpoint {
function Auth_OpenID_ServiceEndpoint()
{
$this->identity_url = null;
$this->server_url = null;
$this->type_uris = array();
$this->delegate = null;
$this->canonicalID = null;
$this->used_yadis = false; // whether this came from an XRDS
}
 
function usesExtension($extension_uri)
{
return in_array($extension_uri, $this->type_uris);
}
 
function parseService($yadis_url, $uri, $type_uris, $service_element)
{
// Set the state of this object based on the contents of the
// service element.
$this->type_uris = $type_uris;
$this->identity_url = $yadis_url;
$this->server_url = $uri;
$this->delegate = Auth_OpenID_ServiceEndpoint::findDelegate(
$service_element);
$this->used_yadis = true;
}
 
function findDelegate($service)
{
// Extract a openid:Delegate value from a Yadis Service
// element. If no delegate is found, returns null.
 
// Try to register new namespace.
$service->parser->registerNamespace('openid',
'http://openid.net/xmlns/1.0');
 
// XXX: should this die if there is more than one delegate
// element?
$delegates = $service->getElements("openid:Delegate");
 
if ($delegates) {
return $service->parser->content($delegates[0]);
} else {
return null;
}
}
 
function getServerID()
{
// Return the identifier that should be sent as the
// openid.identity_url parameter to the server.
if ($this->delegate === null) {
if ($this->canonicalID) {
return $this->canonicalID;
} else {
return $this->identity_url;
}
} else {
return $this->delegate;
}
}
 
function fromHTML($uri, $html)
{
// Parse the given document as HTML looking for an OpenID <link
// rel=...>
$urls = Auth_OpenID_legacy_discover($html);
if ($urls === false) {
return null;
}
 
list($delegate_url, $server_url) = $urls;
 
$service = new Auth_OpenID_ServiceEndpoint();
$service->identity_url = $uri;
$service->delegate = $delegate_url;
$service->server_url = $server_url;
$service->type_uris = array(_OPENID_1_0_TYPE);
return $service;
}
}
 
function filter_MatchesAnyOpenIDType(&$service)
{
$uris = $service->getTypes();
 
foreach ($uris as $uri) {
if (in_array($uri,
array(_OPENID_1_0_TYPE,
_OPENID_1_1_TYPE,
_OPENID_1_2_TYPE))) {
return true;
}
}
 
return false;
}
 
function Auth_OpenID_makeOpenIDEndpoints($uri, $endpoints)
{
$s = array();
 
if (!$endpoints) {
return $s;
}
 
foreach ($endpoints as $service) {
$type_uris = $service->getTypes();
$uris = $service->getURIs();
 
// If any Type URIs match and there is an endpoint URI
// specified, then this is an OpenID endpoint
if ($type_uris &&
$uris) {
 
foreach ($uris as $service_uri) {
$openid_endpoint = new Auth_OpenID_ServiceEndpoint();
$openid_endpoint->parseService($uri,
$service_uri,
$type_uris,
$service);
 
$s[] = $openid_endpoint;
}
}
}
 
return $s;
}
 
function Auth_OpenID_discoverWithYadis($uri, &$fetcher)
{
// Discover OpenID services for a URI. Tries Yadis and falls back
// on old-style <link rel='...'> discovery if Yadis fails.
 
// Might raise a yadis.discover.DiscoveryFailure if no document
// came back for that URI at all. I don't think falling back to
// OpenID 1.0 discovery on the same URL will help, so don't bother
// to catch it.
$openid_services = array();
 
$http_response = null;
$response = Services_Yadis_Yadis::discover($uri, $http_response,
$fetcher);
 
if ($response) {
$identity_url = $response->uri;
$openid_services =
$response->xrds->services(array('filter_MatchesAnyOpenIDType'));
}
 
if (!$openid_services) {
return @Auth_OpenID_discoverWithoutYadis($uri,
$fetcher);
}
 
if (!$openid_services) {
$body = $response->body;
 
// Try to parse the response as HTML to get OpenID 1.0/1.1
// <link rel="...">
$service = Auth_OpenID_ServiceEndpoint::fromHTML($identity_url,
$body);
 
if ($service !== null) {
$openid_services = array($service);
}
} else {
$openid_services = Auth_OpenID_makeOpenIDEndpoints($response->uri,
$openid_services);
}
 
return array($identity_url, $openid_services, $http_response);
}
 
function _Auth_OpenID_discoverServiceList($uri, &$fetcher)
{
list($url, $services, $resp) = Auth_OpenID_discoverWithYadis($uri,
$fetcher);
 
return $services;
}
 
function _Auth_OpenID_discoverXRIServiceList($uri, &$fetcher)
{
list($url, $services, $resp) = _Auth_OpenID_discoverXRI($uri,
$fetcher);
return $services;
}
 
function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher)
{
$http_resp = @$fetcher->get($uri);
 
if ($http_resp->status != 200) {
return array(null, array(), $http_resp);
}
 
$identity_url = $http_resp->final_url;
 
// Try to parse the response as HTML to get OpenID 1.0/1.1 <link
// rel="...">
$endpoint =& new Auth_OpenID_ServiceEndpoint();
$service = $endpoint->fromHTML($identity_url, $http_resp->body);
if ($service === null) {
$openid_services = array();
} else {
$openid_services = array($service);
}
 
return array($identity_url, $openid_services, $http_resp);
}
 
function _Auth_OpenID_discoverXRI($iname, &$fetcher)
{
$services = new Services_Yadis_ProxyResolver($fetcher);
list($canonicalID, $service_list) = $services->query($iname,
array(_OPENID_1_0_TYPE,
_OPENID_1_1_TYPE,
_OPENID_1_2_TYPE),
array('filter_MatchesAnyOpenIDType'));
 
$endpoints = Auth_OpenID_makeOpenIDEndpoints($iname, $service_list);
 
for ($i = 0; $i < count($endpoints); $i++) {
$endpoints[$i]->canonicalID = $canonicalID;
}
 
// FIXME: returned xri should probably be in some normal form
return array($iname, $endpoints, null);
}
 
function Auth_OpenID_discover($uri, &$fetcher)
{
return @Auth_OpenID_discoverWithYadis($uri, $fetcher);
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/ServerRequest.php
New file
0,0 → 1,37
<?php
/**
* OpenID Server Request
*
* @see Auth_OpenID_Server
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Imports
*/
require_once "Auth/OpenID.php";
 
/**
* Object that holds the state of a request to the OpenID server
*
* With accessor functions to get at the internal request data.
*
* @see Auth_OpenID_Server
* @package OpenID
*/
class Auth_OpenID_ServerRequest {
function Auth_OpenID_ServerRequest()
{
$this->mode = null;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/PostgreSQLStore.php
New file
0,0 → 1,136
<?php
 
/**
* A PostgreSQL store.
*
* @package OpenID
*/
 
/**
* Require the base class file.
*/
require_once "Auth/OpenID/SQLStore.php";
 
/**
* An SQL store that uses PostgreSQL as its backend.
*
* @package OpenID
*/
class Auth_OpenID_PostgreSQLStore extends Auth_OpenID_SQLStore {
/**
* @access private
*/
function setSQL()
{
$this->sql['nonce_table'] =
"CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
"expires INTEGER)";
 
$this->sql['assoc_table'] =
"CREATE TABLE %s (server_url VARCHAR(2047), handle VARCHAR(255), ".
"secret BYTEA, issued INTEGER, lifetime INTEGER, ".
"assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle), ".
"CONSTRAINT secret_length_constraint CHECK ".
"(LENGTH(secret) <= 128))";
 
$this->sql['settings_table'] =
"CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
"value BYTEA, ".
"CONSTRAINT value_length_constraint CHECK (LENGTH(value) <= 20))";
 
$this->sql['create_auth'] =
"INSERT INTO %s VALUES ('auth_key', '!')";
 
$this->sql['get_auth'] =
"SELECT value FROM %s WHERE setting = 'auth_key'";
 
$this->sql['set_assoc'] =
array(
'insert_assoc' => "INSERT INTO %s (server_url, handle, ".
"secret, issued, lifetime, assoc_type) VALUES ".
"(?, ?, '!', ?, ?, ?)",
'update_assoc' => "UPDATE %s SET secret = '!', issued = ?, ".
"lifetime = ?, assoc_type = ? WHERE server_url = ? AND ".
"handle = ?"
);
 
$this->sql['get_assocs'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ?";
 
$this->sql['get_assoc'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ? AND handle = ?";
 
$this->sql['remove_assoc'] =
"DELETE FROM %s WHERE server_url = ? AND handle = ?";
 
$this->sql['add_nonce'] =
array(
'insert_nonce' => "INSERT INTO %s (nonce, expires) VALUES ".
"(?, ?)",
'update_nonce' => "UPDATE %s SET expires = ? WHERE nonce = ?"
);
 
$this->sql['get_nonce'] =
"SELECT * FROM %s WHERE nonce = ?";
 
$this->sql['remove_nonce'] =
"DELETE FROM %s WHERE nonce = ?";
}
 
/**
* @access private
*/
function _set_assoc($server_url, $handle, $secret, $issued, $lifetime,
$assoc_type)
{
$result = $this->_get_assoc($server_url, $handle);
if ($result) {
// Update the table since this associations already exists.
$this->connection->query($this->sql['set_assoc']['update_assoc'],
array($secret, $issued, $lifetime,
$assoc_type, $server_url, $handle));
} else {
// Insert a new record because this association wasn't
// found.
$this->connection->query($this->sql['set_assoc']['insert_assoc'],
array($server_url, $handle, $secret,
$issued, $lifetime, $assoc_type));
}
}
 
/**
* @access private
*/
function _add_nonce($nonce, $expires)
{
if ($this->_get_nonce($nonce)) {
return $this->resultToBool($this->connection->query(
$this->sql['add_nonce']['update_nonce'],
array($expires, $nonce)));
} else {
return $this->resultToBool($this->connection->query(
$this->sql['add_nonce']['insert_nonce'],
array($nonce, $expires)));
}
}
 
/**
* @access private
*/
function blobEncode($blob)
{
return $this->_octify($blob);
}
 
/**
* @access private
*/
function blobDecode($blob)
{
return $this->_unoctify($blob);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/MySQLStore.php
New file
0,0 → 1,78
<?php
 
/**
* A MySQL store.
*
* @package OpenID
*/
 
/**
* Require the base class file.
*/
require_once "Auth/OpenID/SQLStore.php";
 
/**
* An SQL store that uses MySQL as its backend.
*
* @package OpenID
*/
class Auth_OpenID_MySQLStore extends Auth_OpenID_SQLStore {
/**
* @access private
*/
function setSQL()
{
$this->sql['nonce_table'] =
"CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
"expires INTEGER) TYPE=InnoDB";
 
$this->sql['assoc_table'] =
"CREATE TABLE %s (server_url BLOB, handle VARCHAR(255), ".
"secret BLOB, issued INTEGER, lifetime INTEGER, ".
"assoc_type VARCHAR(64), PRIMARY KEY (server_url(255), handle)) ".
"TYPE=InnoDB";
 
$this->sql['settings_table'] =
"CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
"value BLOB) TYPE=InnoDB";
 
$this->sql['create_auth'] =
"INSERT INTO %s VALUES ('auth_key', !)";
 
$this->sql['get_auth'] =
"SELECT value FROM %s WHERE setting = 'auth_key'";
 
$this->sql['set_assoc'] =
"REPLACE INTO %s VALUES (?, ?, !, ?, ?, ?)";
 
$this->sql['get_assocs'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ?";
 
$this->sql['get_assoc'] =
"SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
"WHERE server_url = ? AND handle = ?";
 
$this->sql['remove_assoc'] =
"DELETE FROM %s WHERE server_url = ? AND handle = ?";
 
$this->sql['add_nonce'] =
"REPLACE INTO %s (nonce, expires) VALUES (?, ?)";
 
$this->sql['get_nonce'] =
"SELECT * FROM %s WHERE nonce = ?";
 
$this->sql['remove_nonce'] =
"DELETE FROM %s WHERE nonce = ?";
}
 
/**
* @access private
*/
function blobEncode($blob)
{
return "0x" . bin2hex($blob);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/DatabaseConnection.php
New file
0,0 → 1,131
<?php
 
/**
* The Auth_OpenID_DatabaseConnection class, which is used to emulate
* a PEAR database connection.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* An empty base class intended to emulate PEAR connection
* functionality in applications that supply their own database
* abstraction mechanisms. See {@link Auth_OpenID_SQLStore} for more
* information. You should subclass this class if you need to create
* an SQL store that needs to access its database using an
* application's database abstraction layer instead of a PEAR database
* connection. Any subclass of Auth_OpenID_DatabaseConnection MUST
* adhere to the interface specified here.
*
* @package OpenID
*/
class Auth_OpenID_DatabaseConnection {
/**
* Sets auto-commit mode on this database connection.
*
* @param bool $mode True if auto-commit is to be used; false if
* not.
*/
function autoCommit($mode)
{
}
 
/**
* Run an SQL query with the specified parameters, if any.
*
* @param string $sql An SQL string with placeholders. The
* placeholders are assumed to be specific to the database engine
* for this connection.
*
* @param array $params An array of parameters to insert into the
* SQL string using this connection's escaping mechanism.
*
* @return mixed $result The result of calling this connection's
* internal query function. The type of result depends on the
* underlying database engine. This method is usually used when
* the result of a query is not important, like a DDL query.
*/
function query($sql, $params = array())
{
}
 
/**
* Starts a transaction on this connection, if supported.
*/
function begin()
{
}
 
/**
* Commits a transaction on this connection, if supported.
*/
function commit()
{
}
 
/**
* Performs a rollback on this connection, if supported.
*/
function rollback()
{
}
 
/**
* Run an SQL query and return the first column of the first row
* of the result set, if any.
*
* @param string $sql An SQL string with placeholders. The
* placeholders are assumed to be specific to the database engine
* for this connection.
*
* @param array $params An array of parameters to insert into the
* SQL string using this connection's escaping mechanism.
*
* @return mixed $result The value of the first column of the
* first row of the result set. False if no such result was
* found.
*/
function getOne($sql, $params = array())
{
}
 
/**
* Run an SQL query and return the first row of the result set, if
* any.
*
* @param string $sql An SQL string with placeholders. The
* placeholders are assumed to be specific to the database engine
* for this connection.
*
* @param array $params An array of parameters to insert into the
* SQL string using this connection's escaping mechanism.
*
* @return array $result The first row of the result set, if any,
* keyed on column name. False if no such result was found.
*/
function getRow($sql, $params = array())
{
}
 
/**
* Run an SQL query with the specified parameters, if any.
*
* @param string $sql An SQL string with placeholders. The
* placeholders are assumed to be specific to the database engine
* for this connection.
*
* @param array $params An array of parameters to insert into the
* SQL string using this connection's escaping mechanism.
*
* @return array $result An array of arrays representing the
* result of the query; each array is keyed on column name.
*/
function getAll($sql, $params = array())
{
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/TrustRoot.php
New file
0,0 → 1,243
<?php
/**
* Functions for dealing with OpenID trust roots
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* A regular expression that matches a domain ending in a top-level domains.
* Used in checking trust roots for sanity.
*
* @access private
*/
define('Auth_OpenID___TLDs',
'/\.(com|edu|gov|int|mil|net|org|biz|info|name|museum|coop|aero|ac|' .
'ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|' .
'bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|' .
'cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|' .
'fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|' .
'gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|' .
'ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|' .
'ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|' .
'nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|' .
'ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|' .
'so|sr|st|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|' .
'ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)$/');
 
/**
* A wrapper for trust-root related functions
*/
class Auth_OpenID_TrustRoot {
/**
* Parse a URL into its trust_root parts.
*
* @static
*
* @access private
*
* @param string $trust_root The url to parse
*
* @return mixed $parsed Either an associative array of trust root
* parts or false if parsing failed.
*/
function _parse($trust_root)
{
$parts = @parse_url($trust_root);
if ($parts === false) {
return false;
}
$required_parts = array('scheme', 'host');
$forbidden_parts = array('user', 'pass', 'fragment');
$keys = array_keys($parts);
if (array_intersect($keys, $required_parts) != $required_parts) {
return false;
}
 
if (array_intersect($keys, $forbidden_parts) != array()) {
return false;
}
 
// Return false if the original trust root value has more than
// one port specification.
if (preg_match("/:\/\/[^:]+(:\d+){2,}(\/|$)/", $trust_root)) {
return false;
}
 
$scheme = strtolower($parts['scheme']);
$allowed_schemes = array('http', 'https');
if (!in_array($scheme, $allowed_schemes)) {
return false;
}
$parts['scheme'] = $scheme;
 
$host = strtolower($parts['host']);
$hostparts = explode('*', $host);
switch (count($hostparts)) {
case 1:
$parts['wildcard'] = false;
break;
case 2:
if ($hostparts[0] ||
($hostparts[1] && substr($hostparts[1], 0, 1) != '.')) {
return false;
}
$host = $hostparts[1];
$parts['wildcard'] = true;
break;
default:
return false;
}
if (strpos($host, ':') !== false) {
return false;
}
 
$parts['host'] = $host;
 
if (isset($parts['path'])) {
$path = strtolower($parts['path']);
if (substr($path, -1) != '/') {
$path .= '/';
}
} else {
$path = '/';
}
$parts['path'] = $path;
if (!isset($parts['port'])) {
$parts['port'] = false;
}
return $parts;
}
 
/**
* Is this trust root sane?
*
* A trust root is sane if it is syntactically valid and it has a
* reasonable domain name. Specifically, the domain name must be
* more than one level below a standard TLD or more than two
* levels below a two-letter tld.
*
* For example, '*.com' is not a sane trust root, but '*.foo.com'
* is. '*.co.uk' is not sane, but '*.bbc.co.uk' is.
*
* This check is not always correct, but it attempts to err on the
* side of marking sane trust roots insane instead of marking
* insane trust roots sane. For example, 'kink.fm' is marked as
* insane even though it "should" (for some meaning of should) be
* marked sane.
*
* This function should be used when creating OpenID servers to
* alert the users of the server when a consumer attempts to get
* the user to accept a suspicious trust root.
*
* @static
* @param string $trust_root The trust root to check
* @return bool $sanity Whether the trust root looks OK
*/
function isSane($trust_root)
{
$parts = Auth_OpenID_TrustRoot::_parse($trust_root);
if ($parts === false) {
return false;
}
 
// Localhost is a special case
if ($parts['host'] == 'localhost') {
return true;
}
 
// Get the top-level domain of the host. If it is not a valid TLD,
// it's not sane.
preg_match(Auth_OpenID___TLDs, $parts['host'], $matches);
if (!$matches) {
return false;
}
$tld = $matches[1];
 
// Require at least two levels of specificity for non-country
// tlds and three levels for country tlds.
$elements = explode('.', $parts['host']);
$n = count($elements);
if ($parts['wildcard']) {
$n -= 1;
}
if (strlen($tld) == 2) {
$n -= 1;
}
if ($n <= 1) {
return false;
}
return true;
}
 
/**
* Does this URL match the given trust root?
*
* Return whether the URL falls under the given trust root. This
* does not check whether the trust root is sane. If the URL or
* trust root do not parse, this function will return false.
*
* @param string $trust_root The trust root to match against
*
* @param string $url The URL to check
*
* @return bool $matches Whether the URL matches against the
* trust root
*/
function match($trust_root, $url)
{
$trust_root_parsed = Auth_OpenID_TrustRoot::_parse($trust_root);
$url_parsed = Auth_OpenID_TrustRoot::_parse($url);
if (!$trust_root_parsed || !$url_parsed) {
return false;
}
 
// Check hosts matching
if ($url_parsed['wildcard']) {
return false;
}
if ($trust_root_parsed['wildcard']) {
$host_tail = $trust_root_parsed['host'];
$host = $url_parsed['host'];
if ($host_tail &&
substr($host, -(strlen($host_tail))) != $host_tail &&
substr($host_tail, 1) != $host) {
return false;
}
} else {
if ($trust_root_parsed['host'] != $url_parsed['host']) {
return false;
}
}
 
// Check path and query matching
$base_path = $trust_root_parsed['path'];
$path = $url_parsed['path'];
if (!isset($trust_root_parsed['query'])) {
if (substr($path, 0, strlen($base_path)) != $base_path) {
return false;
}
} else {
$base_query = $trust_root_parsed['query'];
$query = @$url_parsed['query'];
$qplus = substr($query, 0, strlen($base_query) + 1);
$bqplus = $base_query . '&';
if ($base_path != $path ||
($base_query != $query && $qplus != $bqplus)) {
return false;
}
}
 
// The port and scheme need to match exactly
return ($trust_root_parsed['scheme'] == $url_parsed['scheme'] &&
$url_parsed['port'] === $trust_root_parsed['port']);
}
}
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/HMACSHA1.php
New file
0,0 → 1,72
<?php
 
/**
* This is the HMACSHA1 implementation for the OpenID library.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* SHA1_BLOCKSIZE is this module's SHA1 blocksize used by the fallback
* implementation.
*/
define('Auth_OpenID_SHA1_BLOCKSIZE', 64);
 
if (!function_exists('sha1')) {
/**
* Return a raw SHA1 hash of the given string
*
* XXX: include the SHA1 code from Dan Libby's OpenID library
*/
function Auth_OpenID_SHA1($text)
{
trigger_error('No SHA1 function found', E_USER_ERROR);
}
} else {
/**
* @ignore
*/
function Auth_OpenID_SHA1($text)
{
$hex = sha1($text);
$raw = '';
for ($i = 0; $i < 40; $i += 2) {
$hexcode = substr($hex, $i, 2);
$charcode = (int)base_convert($hexcode, 16, 10);
$raw .= chr($charcode);
}
return $raw;
}
}
 
/**
* Compute an HMAC/SHA1 hash.
*
* @access private
* @param string $key The HMAC key
* @param string $text The message text to hash
* @return string $mac The MAC
*/
function Auth_OpenID_HMACSHA1($key, $text)
{
if (strlen($key) > Auth_OpenID_SHA1_BLOCKSIZE) {
$key = Auth_OpenID_SHA1($key, true);
}
 
$key = str_pad($key, Auth_OpenID_SHA1_BLOCKSIZE, chr(0x00));
$ipad = str_repeat(chr(0x36), Auth_OpenID_SHA1_BLOCKSIZE);
$opad = str_repeat(chr(0x5c), Auth_OpenID_SHA1_BLOCKSIZE);
$hash1 = Auth_OpenID_SHA1(($key ^ $ipad) . $text, true);
$hmac = Auth_OpenID_SHA1(($key ^ $opad) . $hash1, true);
return $hmac;
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/DiffieHellman.php
New file
0,0 → 1,181
<?php
 
/**
* The OpenID library's Diffie-Hellman implementation.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
require_once 'Auth/OpenID/BigMath.php';
require_once 'Auth/OpenID/HMACSHA1.php';
 
function Auth_OpenID_getDefaultMod()
{
return '155172898181473697471232257763715539915724801'.
'966915404479707795314057629378541917580651227423'.
'698188993727816152646631438561595825688188889951'.
'272158842675419950341258706556549803580104870537'.
'681476726513255747040765857479291291572334510643'.
'245094715007229621094194349783925984760375594985'.
'848253359305585439638443';
}
 
function Auth_OpenID_getDefaultGen()
{
return '2';
}
 
/**
* The Diffie-Hellman key exchange class. This class relies on
* {@link Auth_OpenID_MathLibrary} to perform large number operations.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_DiffieHellman {
 
var $mod;
var $gen;
var $private;
var $lib = null;
 
function Auth_OpenID_DiffieHellman($mod = null, $gen = null,
$private = null, $lib = null)
{
if ($lib === null) {
$this->lib =& Auth_OpenID_getMathLib();
} else {
$this->lib =& $lib;
}
 
if ($mod === null) {
$this->mod = $this->lib->init(Auth_OpenID_getDefaultMod());
} else {
$this->mod = $mod;
}
 
if ($gen === null) {
$this->gen = $this->lib->init(Auth_OpenID_getDefaultGen());
} else {
$this->gen = $gen;
}
 
if ($private === null) {
$r = $this->lib->rand($this->mod);
$this->private = $this->lib->add($r, 1);
} else {
$this->private = $private;
}
 
$this->public = $this->lib->powmod($this->gen, $this->private,
$this->mod);
}
 
function getSharedSecret($composite)
{
return $this->lib->powmod($composite, $this->private, $this->mod);
}
 
function getPublicKey()
{
return $this->public;
}
 
/**
* Generate the arguments for an OpenID Diffie-Hellman association
* request
*/
function getAssocArgs()
{
$cpub = $this->lib->longToBase64($this->getPublicKey());
$args = array(
'openid.dh_consumer_public' => $cpub,
'openid.session_type' => 'DH-SHA1'
);
 
if ($this->lib->cmp($this->mod, Auth_OpenID_getDefaultMod()) ||
$this->lib->cmp($this->gen, Auth_OpenID_getDefaultGen())) {
$args['openid.dh_modulus'] = $this->lib->longToBase64($this->mod);
$args['openid.dh_gen'] = $this->lib->longToBase64($this->gen);
}
 
return $args;
}
 
function usingDefaultValues()
{
return ($this->mod == Auth_OpenID_getDefaultMod() &&
$this->gen == Auth_OpenID_getDefaultGen());
}
 
/**
* Perform the server side of the OpenID Diffie-Hellman association
*/
function serverAssociate($consumer_args, $assoc_secret)
{
$lib =& Auth_OpenID_getMathLib();
 
if (isset($consumer_args['openid.dh_modulus'])) {
$mod = $lib->base64ToLong($consumer_args['openid.dh_modulus']);
} else {
$mod = null;
}
 
if (isset($consumer_args['openid.dh_gen'])) {
$gen = $lib->base64ToLong($consumer_args['openid.dh_gen']);
} else {
$gen = null;
}
$cpub64 = @$consumer_args['openid.dh_consumer_public'];
if (!isset($cpub64)) {
return false;
}
 
$dh = new Auth_OpenID_DiffieHellman($mod, $gen);
$cpub = $lib->base64ToLong($cpub64);
$mac_key = $dh->xorSecret($cpub, $assoc_secret);
$enc_mac_key = base64_encode($mac_key);
$spub64 = $lib->longToBase64($dh->getPublicKey());
 
$server_args = array(
'session_type' => 'DH-SHA1',
'dh_server_public' => $spub64,
'enc_mac_key' => $enc_mac_key
);
 
return $server_args;
}
 
function consumerFinish($reply)
{
$spub = $this->lib->base64ToLong($reply['dh_server_public']);
if ($this->lib->cmp($spub, 0) <= 0) {
return false;
}
$enc_mac_key = base64_decode($reply['enc_mac_key']);
return $this->xorSecret($spub, $enc_mac_key);
}
 
function xorSecret($composite, $secret)
{
$dh_shared = $this->getSharedSecret($composite);
$dh_shared_str = $this->lib->longToBinary($dh_shared);
$sha1_dh_shared = Auth_OpenID_SHA1($dh_shared_str);
 
$xsecret = "";
for ($i = 0; $i < strlen($secret); $i++) {
$xsecret .= chr(ord($secret[$i]) ^ ord($sha1_dh_shared[$i]));
}
 
return $xsecret;
}
}
/tags/v1.2-autel/composants/openid/Auth/OpenID/URINorm.php
New file
0,0 → 1,231
<?php
 
/**
* URI normalization routines.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
require_once 'Services/Yadis/Misc.php';
 
// from appendix B of rfc 3986 (http://www.ietf.org/rfc/rfc3986.txt)
function Auth_OpenID_getURIPattern()
{
return '&^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?&';
}
 
function Auth_OpenID_getAuthorityPattern()
{
return '/^([^@]*@)?([^:]*)(:.*)?/';
}
 
function Auth_OpenID_getEncodedPattern()
{
return '/%([0-9A-Fa-f]{2})/';
}
 
function Auth_OpenID_getUnreserved()
{
$_unreserved = array();
for ($i = 0; $i < 256; $i++) {
$_unreserved[$i] = false;
}
 
for ($i = ord('A'); $i <= ord('Z'); $i++) {
$_unreserved[$i] = true;
}
 
for ($i = ord('0'); $i <= ord('9'); $i++) {
$_unreserved[$i] = true;
}
 
for ($i = ord('a'); $i <= ord('z'); $i++) {
$_unreserved[$i] = true;
}
 
$_unreserved[ord('-')] = true;
$_unreserved[ord('.')] = true;
$_unreserved[ord('_')] = true;
$_unreserved[ord('~')] = true;
 
return $_unreserved;
}
 
function Auth_OpenID_getEscapeRE()
{
$parts = array();
foreach (array_merge(Services_Yadis_getUCSChars(),
Services_Yadis_getIPrivateChars()) as $pair) {
list($m, $n) = $pair;
$parts[] = sprintf("%s-%s", chr($m), chr($n));
}
 
return sprintf('[%s]', implode('', $parts));
}
 
function Auth_OpenID_pct_encoded_replace_unreserved($mo)
{
$_unreserved = Auth_OpenID_getUnreserved();
 
$i = intval($mo[1], 16);
if ($_unreserved[$i]) {
return chr($i);
} else {
return strtoupper($mo[0]);
}
 
return $mo[0];
}
 
function Auth_OpenID_pct_encoded_replace($mo)
{
return chr(intval($mo[1], 16));
}
 
function Auth_OpenID_remove_dot_segments($path)
{
$result_segments = array();
while ($path) {
if (Services_Yadis_startswith($path, '../')) {
$path = substr($path, 3);
} else if (Services_Yadis_startswith($path, './')) {
$path = substr($path, 2);
} else if (Services_Yadis_startswith($path, '/./')) {
$path = substr($path, 2);
} else if ($path == '/.') {
$path = '/';
} else if (Services_Yadis_startswith($path, '/../')) {
$path = substr($path, 3);
if ($result_segments) {
array_pop($result_segments);
}
} else if ($path == '/..') {
$path = '/';
if ($result_segments) {
array_pop($result_segments);
}
} else if (($path == '..') ||
($path == '.')) {
$path = '';
} else {
$i = 0;
if ($path[0] == '/') {
$i = 1;
}
$i = strpos($path, '/', $i);
if ($i === false) {
$i = strlen($path);
}
$result_segments[] = substr($path, 0, $i);
$path = substr($path, $i);
}
}
 
return implode('', $result_segments);
}
 
function Auth_OpenID_urinorm($uri)
{
$uri_matches = array();
preg_match(Auth_OpenID_getURIPattern(), $uri, $uri_matches);
 
if (count($uri_matches) < 9) {
for ($i = count($uri_matches); $i <= 9; $i++) {
$uri_matches[] = '';
}
}
 
$scheme = $uri_matches[2];
if ($scheme) {
$scheme = strtolower($scheme);
}
 
$scheme = $uri_matches[2];
if ($scheme === '') {
// No scheme specified
return null;
}
 
$scheme = strtolower($scheme);
if (!in_array($scheme, array('http', 'https'))) {
// Not an absolute HTTP or HTTPS URI
return null;
}
 
$authority = $uri_matches[4];
if ($authority === '') {
// Not an absolute URI
return null;
}
 
$authority_matches = array();
preg_match(Auth_OpenID_getAuthorityPattern(),
$authority, $authority_matches);
if (count($authority_matches) === 0) {
// URI does not have a valid authority
return null;
}
 
if (count($authority_matches) < 4) {
for ($i = count($authority_matches); $i <= 4; $i++) {
$authority_matches[] = '';
}
}
 
list($_whole, $userinfo, $host, $port) = $authority_matches;
 
if ($userinfo === null) {
$userinfo = '';
}
 
if (strpos($host, '%') !== -1) {
$host = strtolower($host);
$host = preg_replace_callback(
Auth_OpenID_getEncodedPattern(),
'Auth_OpenID_pct_encoded_replace', $host);
// NO IDNA.
// $host = unicode($host, 'utf-8').encode('idna');
} else {
$host = strtolower($host);
}
 
if ($port) {
if (($port == ':') ||
($scheme == 'http' && $port == ':80') ||
($scheme == 'https' && $port == ':443')) {
$port = '';
}
} else {
$port = '';
}
 
$authority = $userinfo . $host . $port;
 
$path = $uri_matches[5];
$path = preg_replace_callback(
Auth_OpenID_getEncodedPattern(),
'Auth_OpenID_pct_encoded_replace_unreserved', $path);
 
$path = Auth_OpenID_remove_dot_segments($path);
if (!$path) {
$path = '/';
}
 
$query = $uri_matches[6];
if ($query === null) {
$query = '';
}
 
$fragment = $uri_matches[8];
if ($fragment === null) {
$fragment = '';
}
 
return $scheme . '://' . $authority . $path . $query . $fragment;
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/Consumer.php
New file
0,0 → 1,1186
<?php
 
/**
* This module documents the main interface with the OpenID consumer
* library. The only part of the library which has to be used and
* isn't documented in full here is the store required to create an
* Auth_OpenID_Consumer instance. More on the abstract store type and
* concrete implementations of it that are provided in the
* documentation for the Auth_OpenID_Consumer constructor.
*
* OVERVIEW
*
* The OpenID identity verification process most commonly uses the
* following steps, as visible to the user of this library:
*
* 1. The user enters their OpenID into a field on the consumer's
* site, and hits a login button.
* 2. The consumer site discovers the user's OpenID server using the
* YADIS protocol.
* 3. The consumer site sends the browser a redirect to the identity
* server. This is the authentication request as described in
* the OpenID specification.
* 4. The identity server's site sends the browser a redirect back
* to the consumer site. This redirect contains the server's
* response to the authentication request.
*
* The most important part of the flow to note is the consumer's site
* must handle two separate HTTP requests in order to perform the full
* identity check.
*
* LIBRARY DESIGN
*
* This consumer library is designed with that flow in mind. The goal
* is to make it as easy as possible to perform the above steps
* securely.
*
* At a high level, there are two important parts in the consumer
* library. The first important part is this module, which contains
* the interface to actually use this library. The second is the
* Auth_OpenID_Interface class, which describes the interface to use
* if you need to create a custom method for storing the state this
* library needs to maintain between requests.
*
* In general, the second part is less important for users of the
* library to know about, as several implementations are provided
* which cover a wide variety of situations in which consumers may use
* the library.
*
* This module contains a class, Auth_OpenID_Consumer, with methods
* corresponding to the actions necessary in each of steps 2, 3, and 4
* described in the overview. Use of this library should be as easy
* as creating an Auth_OpenID_Consumer instance and calling the
* methods appropriate for the action the site wants to take.
*
* STORES AND DUMB MODE
*
* OpenID is a protocol that works best when the consumer site is able
* to store some state. This is the normal mode of operation for the
* protocol, and is sometimes referred to as smart mode. There is
* also a fallback mode, known as dumb mode, which is available when
* the consumer site is not able to store state. This mode should be
* avoided when possible, as it leaves the implementation more
* vulnerable to replay attacks.
*
* The mode the library works in for normal operation is determined by
* the store that it is given. The store is an abstraction that
* handles the data that the consumer needs to manage between http
* requests in order to operate efficiently and securely.
*
* Several store implementation are provided, and the interface is
* fully documented so that custom stores can be used as well. See
* the documentation for the Auth_OpenID_Consumer class for more
* information on the interface for stores. The implementations that
* are provided allow the consumer site to store the necessary data in
* several different ways, including several SQL databases and normal
* files on disk.
*
* There is an additional concrete store provided that puts the system
* in dumb mode. This is not recommended, as it removes the library's
* ability to stop replay attacks reliably. It still uses time-based
* checking to make replay attacks only possible within a small
* window, but they remain possible within that window. This store
* should only be used if the consumer site has no way to retain data
* between requests at all.
*
* IMMEDIATE MODE
*
* In the flow described above, the user may need to confirm to the
* lidentity server that it's ok to authorize his or her identity.
* The server may draw pages asking for information from the user
* before it redirects the browser back to the consumer's site. This
* is generally transparent to the consumer site, so it is typically
* ignored as an implementation detail.
*
* There can be times, however, where the consumer site wants to get a
* response immediately. When this is the case, the consumer can put
* the library in immediate mode. In immediate mode, there is an
* extra response possible from the server, which is essentially the
* server reporting that it doesn't have enough information to answer
* the question yet. In addition to saying that, the identity server
* provides a URL to which the user can be sent to provide the needed
* information and let the server finish handling the original
* request.
*
* USING THIS LIBRARY
*
* Integrating this library into an application is usually a
* relatively straightforward process. The process should basically
* follow this plan:
*
* Add an OpenID login field somewhere on your site. When an OpenID
* is entered in that field and the form is submitted, it should make
* a request to the your site which includes that OpenID URL.
*
* First, the application should instantiate the Auth_OpenID_Consumer
* class using the store of choice (Auth_OpenID_FileStore or one of
* the SQL-based stores). If the application has any sort of session
* framework that provides per-client state management, a dict-like
* object to access the session should be passed as the optional
* second parameter. (The default behavior is to use PHP's standard
* session machinery.)
*
* Next, the application should call the Auth_OpenID_Consumer object's
* 'begin' method. This method takes the OpenID URL. The 'begin'
* method returns an Auth_OpenID_AuthRequest object.
*
* Next, the application should call the 'redirectURL' method of the
* Auth_OpenID_AuthRequest object. The 'return_to' URL parameter is
* the URL that the OpenID server will send the user back to after
* attempting to verify his or her identity. The 'trust_root' is the
* URL (or URL pattern) that identifies your web site to the user when
* he or she is authorizing it. Send a redirect to the resulting URL
* to the user's browser.
*
* That's the first half of the authentication process. The second
* half of the process is done after the user's ID server sends the
* user's browser a redirect back to your site to complete their
* login.
*
* When that happens, the user will contact your site at the URL given
* as the 'return_to' URL to the Auth_OpenID_AuthRequest::redirectURL
* call made above. The request will have several query parameters
* added to the URL by the identity server as the information
* necessary to finish the request.
*
* Lastly, instantiate an Auth_OpenID_Consumer instance as above and
* call its 'complete' method, passing in all the received query
* arguments.
*
* There are multiple possible return types possible from that
* method. These indicate the whether or not the login was successful,
* and include any additional information appropriate for their type.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Require utility classes and functions for the consumer.
*/
require_once "Auth/OpenID.php";
require_once "Auth/OpenID/HMACSHA1.php";
require_once "Auth/OpenID/Association.php";
require_once "Auth/OpenID/CryptUtil.php";
require_once "Auth/OpenID/DiffieHellman.php";
require_once "Auth/OpenID/KVForm.php";
require_once "Auth/OpenID/Discover.php";
require_once "Services/Yadis/Manager.php";
require_once "Services/Yadis/XRI.php";
 
/**
* This is the status code returned when the complete method returns
* successfully.
*/
define('Auth_OpenID_SUCCESS', 'success');
 
/**
* Status to indicate cancellation of OpenID authentication.
*/
define('Auth_OpenID_CANCEL', 'cancel');
 
/**
* This is the status code completeAuth returns when the value it
* received indicated an invalid login.
*/
define('Auth_OpenID_FAILURE', 'failure');
 
/**
* This is the status code completeAuth returns when the
* {@link Auth_OpenID_Consumer} instance is in immediate mode, and the
* identity server sends back a URL to send the user to to complete his
* or her login.
*/
define('Auth_OpenID_SETUP_NEEDED', 'setup needed');
 
/**
* This is the status code beginAuth returns when the page fetched
* from the entered OpenID URL doesn't contain the necessary link tags
* to function as an identity page.
*/
define('Auth_OpenID_PARSE_ERROR', 'parse error');
 
/**
* This is the characters that the nonces are made from.
*/
define('Auth_OpenID_DEFAULT_NONCE_CHRS',"abcdefghijklmnopqrstuvwxyz" .
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
 
/**
* An OpenID consumer implementation that performs discovery and does
* session management. See the Consumer.php file documentation for
* more information.
*
* @package OpenID
*/
class Auth_OpenID_Consumer {
 
/**
* @access private
*/
var $session_key_prefix = "_openid_consumer_";
 
/**
* @access private
*/
var $_token_suffix = "last_token";
 
/**
* Initialize a Consumer instance.
*
* You should create a new instance of the Consumer object with
* every HTTP request that handles OpenID transactions.
*
* @param Auth_OpenID_OpenIDStore $store This must be an object
* that implements the interface in {@link
* Auth_OpenID_OpenIDStore}. Several concrete implementations are
* provided, to cover most common use cases. For stores backed by
* MySQL, PostgreSQL, or SQLite, see the {@link
* Auth_OpenID_SQLStore} class and its sublcasses. For a
* filesystem-backed store, see the {@link Auth_OpenID_FileStore}
* module. As a last resort, if it isn't possible for the server
* to store state at all, an instance of {@link
* Auth_OpenID_DumbStore} can be used.
*
* @param mixed session An object which implements the interface
* of the Services_Yadis_Session class. Particularly, this object
* is expected to have these methods: get($key), set($key,
* $value), and del($key). This defaults to a session object
* which wraps PHP's native session machinery. You should only
* need to pass something here if you have your own sessioning
* implementation.
*/
function Auth_OpenID_Consumer(&$store, $session = null)
{
if ($session === null) {
$session = new Services_Yadis_PHPSession();
}
 
$this->session =& $session;
$this->consumer =& new Auth_OpenID_GenericConsumer($store);
$this->_token_key = $this->session_key_prefix . $this->_token_suffix;
}
 
/**
* Start the OpenID authentication process. See steps 1-2 in the
* overview at the top of this file.
*
* @param User_url: Identity URL given by the user. This method
* performs a textual transformation of the URL to try and make
* sure it is normalized. For example, a user_url of example.com
* will be normalized to http://example.com/ normalizing and
* resolving any redirects the server might issue.
*
* @return Auth_OpenID_AuthRequest $auth_request An object
* containing the discovered information will be returned, with a
* method for building a redirect URL to the server, as described
* in step 3 of the overview. This object may also be used to add
* extension arguments to the request, using its 'addExtensionArg'
* method.
*/
function begin($user_url)
{
$discoverMethod = '_Auth_OpenID_discoverServiceList';
$openid_url = $user_url;
 
if (Services_Yadis_identifierScheme($user_url) == 'XRI') {
$discoverMethod = '_Auth_OpenID_discoverXRIServiceList';
} else {
$openid_url = Auth_OpenID::normalizeUrl($user_url);
}
 
$disco =& new Services_Yadis_Discovery($this->session,
$openid_url,
$this->session_key_prefix);
 
// Set the 'stale' attribute of the manager. If discovery
// fails in a fatal way, the stale flag will cause the manager
// to be cleaned up next time discovery is attempted.
 
$m = $disco->getManager();
$loader = new Services_Yadis_ManagerLoader();
 
if ($m) {
if ($m->stale) {
$disco->destroyManager();
} else {
$m->stale = true;
$disco->session->set($disco->session_key,
serialize($loader->toSession($m)));
}
}
 
$endpoint = $disco->getNextService($discoverMethod,
$this->consumer->fetcher);
 
// Reset the 'stale' attribute of the manager.
$m =& $disco->getManager();
if ($m) {
$m->stale = false;
$disco->session->set($disco->session_key,
serialize($loader->toSession($m)));
}
 
if ($endpoint === null) {
return null;
} else {
return $this->beginWithoutDiscovery($endpoint);
}
}
 
/**
* Start OpenID verification without doing OpenID server
* discovery. This method is used internally by Consumer.begin
* after discovery is performed, and exists to provide an
* interface for library users needing to perform their own
* discovery.
*
* @param Auth_OpenID_ServiceEndpoint $endpoint an OpenID service
* endpoint descriptor.
*
* @return Auth_OpenID_AuthRequest $auth_request An OpenID
* authentication request object.
*/
function &beginWithoutDiscovery($endpoint)
{
$loader = new Auth_OpenID_ServiceEndpointLoader();
$auth_req = $this->consumer->begin($endpoint);
$this->session->set($this->_token_key,
$loader->toSession($auth_req->endpoint));
return $auth_req;
}
 
/**
* Called to interpret the server's response to an OpenID
* request. It is called in step 4 of the flow described in the
* consumer overview.
*
* @param array $query An array of the query parameters (key =>
* value pairs) for this HTTP request.
*
* @return Auth_OpenID_ConsumerResponse $response A instance of an
* Auth_OpenID_ConsumerResponse subclass. The type of response is
* indicated by the status attribute, which will be one of
* SUCCESS, CANCEL, FAILURE, or SETUP_NEEDED.
*/
function complete($query)
{
$query = Auth_OpenID::fixArgs($query);
 
$loader = new Auth_OpenID_ServiceEndpointLoader();
$endpoint_data = $this->session->get($this->_token_key);
$endpoint =
$loader->fromSession($endpoint_data);
 
if ($endpoint === null) {
$response = new Auth_OpenID_FailureResponse(null,
'No session state found');
} else {
$response = $this->consumer->complete($query, $endpoint);
$this->session->del($this->_token_key);
}
 
if (in_array($response->status, array(Auth_OpenID_SUCCESS,
Auth_OpenID_CANCEL))) {
if ($response->identity_url !== null) {
$disco = new Services_Yadis_Discovery($this->session,
$response->identity_url,
$this->session_key_prefix);
$disco->cleanup();
}
}
 
return $response;
}
}
 
class Auth_OpenID_DiffieHellmanConsumerSession {
var $session_type = 'DH-SHA1';
 
function Auth_OpenID_DiffieHellmanConsumerSession($dh = null)
{
if ($dh === null) {
$dh = new Auth_OpenID_DiffieHellman();
}
 
$this->dh = $dh;
}
 
function getRequest()
{
$math =& Auth_OpenID_getMathLib();
 
$cpub = $math->longToBase64($this->dh->public);
 
$args = array('openid.dh_consumer_public' => $cpub);
 
if (!$this->dh->usingDefaultValues()) {
$args = array_merge($args, array(
'openid.dh_modulus' =>
$math->longToBase64($this->dh->mod),
'openid.dh_gen' =>
$math->longToBase64($this->dh->gen)));
}
 
return $args;
}
 
function extractSecret($response)
{
if (!array_key_exists('dh_server_public', $response)) {
return null;
}
 
if (!array_key_exists('enc_mac_key', $response)) {
return null;
}
 
$math =& Auth_OpenID_getMathLib();
$spub = $math->base64ToLong($response['dh_server_public']);
$enc_mac_key = base64_decode($response['enc_mac_key']);
 
return $this->dh->xorSecret($spub, $enc_mac_key);
}
}
 
class Auth_OpenID_PlainTextConsumerSession {
var $session_type = null;
 
function getRequest()
{
return array();
}
 
function extractSecret($response)
{
if (!array_key_exists('mac_key', $response)) {
return null;
}
 
return base64_decode($response['mac_key']);
}
}
 
/**
* This class is the interface to the OpenID consumer logic.
* Instances of it maintain no per-request state, so they can be
* reused (or even used by multiple threads concurrently) as needed.
*
* @package OpenID
* @access private
*/
class Auth_OpenID_GenericConsumer {
/**
* This consumer's store object.
*/
var $store;
 
/**
* @access private
*/
var $_use_assocs;
 
/**
* This is the number of characters in the generated nonce for
* each transaction.
*/
var $nonce_len = 8;
 
/**
* What characters are allowed in nonces
*/
var $nonce_chrs = Auth_OpenID_DEFAULT_NONCE_CHRS;
 
/**
* This method initializes a new {@link Auth_OpenID_Consumer}
* instance to access the library.
*
* @param Auth_OpenID_OpenIDStore $store This must be an object
* that implements the interface in {@link Auth_OpenID_OpenIDStore}.
* Several concrete implementations are provided, to cover most common use
* cases. For stores backed by MySQL, PostgreSQL, or SQLite, see
* the {@link Auth_OpenID_SQLStore} class and its sublcasses. For a
* filesystem-backed store, see the {@link Auth_OpenID_FileStore} module.
* As a last resort, if it isn't possible for the server to store
* state at all, an instance of {@link Auth_OpenID_DumbStore} can be used.
*
* @param bool $immediate This is an optional boolean value. It
* controls whether the library uses immediate mode, as explained
* in the module description. The default value is False, which
* disables immediate mode.
*/
function Auth_OpenID_GenericConsumer(&$store)
{
$this->store =& $store;
$this->_use_assocs =
!(defined('Auth_OpenID_NO_MATH_SUPPORT') ||
($this->store && $this->store->isDumb()));
 
$this->fetcher = Services_Yadis_Yadis::getHTTPFetcher();
}
 
function begin($service_endpoint)
{
$nonce = $this->_createNonce();
$assoc = $this->_getAssociation($service_endpoint->server_url);
$r = new Auth_OpenID_AuthRequest($assoc, $service_endpoint);
$r->return_to_args['nonce'] = $nonce;
return $r;
}
 
function complete($query, $endpoint)
{
$mode = Auth_OpenID::arrayGet($query, 'openid.mode',
'<no mode specified>');
 
if ($mode == Auth_OpenID_CANCEL) {
return new Auth_OpenID_CancelResponse($endpoint);
} else if ($mode == 'error') {
$error = Auth_OpenID::arrayGet($query, 'openid.error');
return new Auth_OpenID_FailureResponse($endpoint, $error);
} else if ($mode == 'id_res') {
if ($endpoint->identity_url === null) {
return new Auth_OpenID_FailureResponse($identity_url,
"No session state found");
}
 
$response = $this->_doIdRes($query, $endpoint);
 
if ($response === null) {
return new Auth_OpenID_FailureResponse($endpoint,
"HTTP request failed");
}
if ($response->status == Auth_OpenID_SUCCESS) {
return $this->_checkNonce($response,
Auth_OpenID::arrayGet($query,
'nonce'));
} else {
return $response;
}
} else {
return new Auth_OpenID_FailureResponse($endpoint,
sprintf("Invalid openid.mode '%s'",
$mode));
}
}
 
/**
* @access private
*/
function _doIdRes($query, $endpoint)
{
$user_setup_url = Auth_OpenID::arrayGet($query,
'openid.user_setup_url');
 
if ($user_setup_url !== null) {
return new Auth_OpenID_SetupNeededResponse($endpoint,
$user_setup_url);
}
 
$return_to = Auth_OpenID::arrayGet($query, 'openid.return_to', null);
$server_id2 = Auth_OpenID::arrayGet($query, 'openid.identity', null);
$assoc_handle = Auth_OpenID::arrayGet($query,
'openid.assoc_handle', null);
 
if (($return_to === null) ||
($server_id2 === null) ||
($assoc_handle === null)) {
return new Auth_OpenID_FailureResponse($endpoint,
"Missing required field");
}
 
if ($endpoint->getServerID() != $server_id2) {
return new Auth_OpenID_FailureResponse($endpoint,
"Server ID (delegate) mismatch");
}
 
$signed = Auth_OpenID::arrayGet($query, 'openid.signed');
 
$assoc = $this->store->getAssociation($endpoint->server_url,
$assoc_handle);
 
if ($assoc === null) {
// It's not an association we know about. Dumb mode is
// our only possible path for recovery.
if ($this->_checkAuth($query, $endpoint->server_url)) {
return new Auth_OpenID_SuccessResponse($endpoint, $query,
$signed);
} else {
return new Auth_OpenID_FailureResponse($endpoint,
"Server denied check_authentication");
}
}
 
if ($assoc->getExpiresIn() <= 0) {
$msg = sprintf("Association with %s expired",
$endpoint->server_url);
return new Auth_OpenID_FailureResponse($endpoint, $msg);
}
 
// Check the signature
$sig = Auth_OpenID::arrayGet($query, 'openid.sig', null);
if (($sig === null) ||
($signed === null)) {
return new Auth_OpenID_FailureResponse($endpoint,
"Missing argument signature");
}
 
$signed_list = explode(",", $signed);
 
//Fail if the identity field is present but not signed
if (($endpoint->identity_url !== null) &&
(!in_array('identity', $signed_list))) {
$msg = '"openid.identity" not signed';
return new Auth_OpenID_FailureResponse($endpoint, $msg);
}
 
$v_sig = $assoc->signDict($signed_list, $query);
 
if ($v_sig != $sig) {
return new Auth_OpenID_FailureResponse($endpoint,
"Bad signature");
}
 
return Auth_OpenID_SuccessResponse::fromQuery($endpoint,
$query, $signed);
}
 
/**
* @access private
*/
function _checkAuth($query, $server_url)
{
$request = $this->_createCheckAuthRequest($query);
if ($request === null) {
return false;
}
 
$response = $this->_makeKVPost($request, $server_url);
if ($response == null) {
return false;
}
 
return $this->_processCheckAuthResponse($response, $server_url);
}
 
/**
* @access private
*/
function _createCheckAuthRequest($query)
{
$signed = Auth_OpenID::arrayGet($query, 'openid.signed', null);
if ($signed === null) {
return null;
}
 
$whitelist = array('assoc_handle', 'sig',
'signed', 'invalidate_handle');
 
$signed = array_merge(explode(",", $signed), $whitelist);
 
$check_args = array();
 
foreach ($query as $key => $value) {
if (in_array(substr($key, 7), $signed)) {
$check_args[$key] = $value;
}
}
 
$check_args['openid.mode'] = 'check_authentication';
return $check_args;
}
 
/**
* @access private
*/
function _processCheckAuthResponse($response, $server_url)
{
$is_valid = Auth_OpenID::arrayGet($response, 'is_valid', 'false');
 
$invalidate_handle = Auth_OpenID::arrayGet($response,
'invalidate_handle');
 
if ($invalidate_handle !== null) {
$this->store->removeAssociation($server_url,
$invalidate_handle);
}
 
if ($is_valid == 'true') {
return true;
}
 
return false;
}
 
/**
* @access private
*/
function _makeKVPost($args, $server_url)
{
$mode = $args['openid.mode'];
 
$pairs = array();
foreach ($args as $k => $v) {
$v = urlencode($v);
$pairs[] = "$k=$v";
}
 
$body = implode("&", $pairs);
 
$resp = $this->fetcher->post($server_url, $body);
 
if ($resp === null) {
return null;
}
 
$response = Auth_OpenID_KVForm::toArray($resp->body);
 
if ($resp->status == 400) {
return null;
} else if ($resp->status != 200) {
return null;
}
 
return $response;
}
 
/**
* @access private
*/
function _checkNonce($response, $nonce)
{
$parsed_url = parse_url($response->getReturnTo());
$query_str = @$parsed_url['query'];
$query = array();
parse_str($query_str, $query);
 
$found = false;
 
foreach ($query as $k => $v) {
if ($k == 'nonce') {
if ($v != $nonce) {
return new Auth_OpenID_FailureResponse($response,
"Nonce mismatch");
} else {
$found = true;
break;
}
}
}
 
if (!$found) {
return new Auth_OpenID_FailureResponse($response,
sprintf("Nonce missing from return_to: %s",
$response->getReturnTo()));
}
 
if (!$this->store->useNonce($nonce)) {
return new Auth_OpenID_FailureResponse($response,
"Nonce missing from store");
}
 
return $response;
}
 
/**
* @access private
*/
function _createNonce()
{
$nonce = Auth_OpenID_CryptUtil::randomString($this->nonce_len,
$this->nonce_chrs);
$this->store->storeNonce($nonce);
return $nonce;
}
 
/**
* @access protected
*/
function _createDiffieHellman()
{
return new Auth_OpenID_DiffieHellman();
}
 
/**
* @access private
*/
function _getAssociation($server_url)
{
if (!$this->_use_assocs) {
return null;
}
 
$assoc = $this->store->getAssociation($server_url);
 
if (($assoc === null) ||
($assoc->getExpiresIn() <= 0)) {
 
$parts = $this->_createAssociateRequest($server_url);
 
if ($parts === null) {
return null;
}
 
list($assoc_session, $args) = $parts;
 
$response = $this->_makeKVPost($args, $server_url);
 
if ($response === null) {
$assoc = null;
} else {
$assoc = $this->_parseAssociation($response, $assoc_session,
$server_url);
}
}
 
return $assoc;
}
 
function _createAssociateRequest($server_url)
{
$parts = parse_url($server_url);
 
if ($parts === false) {
return null;
}
 
if (array_key_exists('scheme', $parts)) {
$proto = $parts['scheme'];
} else {
$proto = 'http';
}
 
if ($proto == 'https') {
$assoc_session = new Auth_OpenID_PlainTextConsumerSession();
} else {
$assoc_session = new Auth_OpenID_DiffieHellmanConsumerSession();
}
 
$args = array(
'openid.mode' => 'associate',
'openid.assoc_type' => 'HMAC-SHA1');
 
if ($assoc_session->session_type !== null) {
$args['openid.session_type'] = $assoc_session->session_type;
}
 
$args = array_merge($args, $assoc_session->getRequest());
return array($assoc_session, $args);
}
 
/**
* @access private
*/
function _parseAssociation($results, $assoc_session, $server_url)
{
$required_keys = array('assoc_type', 'assoc_handle',
'expires_in');
 
foreach ($required_keys as $key) {
if (!array_key_exists($key, $results)) {
return null;
}
}
 
$assoc_type = $results['assoc_type'];
$assoc_handle = $results['assoc_handle'];
$expires_in_str = $results['expires_in'];
 
if ($assoc_type != 'HMAC-SHA1') {
return null;
}
 
$expires_in = intval($expires_in_str);
 
if ($expires_in <= 0) {
return null;
}
 
$session_type = Auth_OpenID::arrayGet($results, 'session_type');
if ($session_type != $assoc_session->session_type) {
if ($session_type === null) {
$assoc_session = new Auth_OpenID_PlainTextConsumerSession();
} else {
return null;
}
}
 
$secret = $assoc_session->extractSecret($results);
 
if (!$secret) {
return null;
}
 
$assoc = Auth_OpenID_Association::fromExpiresIn(
$expires_in, $assoc_handle, $secret, $assoc_type);
$this->store->storeAssociation($server_url, $assoc);
 
return $assoc;
}
}
 
/**
* This class represents an authentication request from a consumer to
* an OpenID server.
*
* @package OpenID
*/
class Auth_OpenID_AuthRequest {
 
/**
* Initialize an authentication request with the specified token,
* association, and endpoint.
*
* Users of this library should not create instances of this
* class. Instances of this class are created by the library when
* needed.
*/
function Auth_OpenID_AuthRequest($assoc, $endpoint)
{
$this->assoc = $assoc;
$this->endpoint = $endpoint;
$this->extra_args = array();
$this->return_to_args = array();
}
 
/**
* Add an extension argument to this OpenID authentication
* request.
*
* Use caution when adding arguments, because they will be
* URL-escaped and appended to the redirect URL, which can easily
* get quite long.
*
* @param string $namespace The namespace for the extension. For
* example, the simple registration extension uses the namespace
* 'sreg'.
*
* @param string $key The key within the extension namespace. For
* example, the nickname field in the simple registration
* extension's key is 'nickname'.
*
* @param string $value The value to provide to the server for
* this argument.
*/
function addExtensionArg($namespace, $key, $value)
{
$arg_name = implode('.', array('openid', $namespace, $key));
$this->extra_args[$arg_name] = $value;
}
 
/**
* Compute the appropriate redirection URL for this request based
* on a specified trust root and return-to.
*
* @param string $trust_root The trust root URI for your
* application.
*
* @param string$ $return_to The return-to URL to be used when the
* OpenID server redirects the user back to your site.
*
* @return string $redirect_url The resulting redirect URL that
* you should send to the user agent.
*/
function redirectURL($trust_root, $return_to, $immediate=false)
{
if ($immediate) {
$mode = 'checkid_immediate';
} else {
$mode = 'checkid_setup';
}
 
$return_to = Auth_OpenID::appendArgs($return_to, $this->return_to_args);
 
$redir_args = array(
'openid.mode' => $mode,
'openid.identity' => $this->endpoint->getServerID(),
'openid.return_to' => $return_to,
'openid.trust_root' => $trust_root);
 
if ($this->assoc) {
$redir_args['openid.assoc_handle'] = $this->assoc->handle;
}
 
$redir_args = array_merge($redir_args, $this->extra_args);
 
return Auth_OpenID::appendArgs($this->endpoint->server_url,
$redir_args);
}
}
 
/**
* The base class for responses from the Auth_OpenID_Consumer.
*
* @package OpenID
*/
class Auth_OpenID_ConsumerResponse {
var $status = null;
}
 
/**
* A response with a status of Auth_OpenID_SUCCESS. Indicates that
* this request is a successful acknowledgement from the OpenID server
* that the supplied URL is, indeed controlled by the requesting
* agent. This has three relevant attributes:
*
* identity_url - The identity URL that has been authenticated
*
* signed_args - The arguments in the server's response that were
* signed and verified.
*
* status - Auth_OpenID_SUCCESS.
*
* @package OpenID
*/
class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse {
var $status = Auth_OpenID_SUCCESS;
 
/**
* @access private
*/
function Auth_OpenID_SuccessResponse($endpoint, $signed_args)
{
$this->endpoint = $endpoint;
$this->identity_url = $endpoint->identity_url;
$this->signed_args = $signed_args;
}
 
/**
* @access private
*/
function fromQuery($endpoint, $query, $signed)
{
$signed_args = array();
foreach (explode(",", $signed) as $field_name) {
$field_name = 'openid.' . $field_name;
$signed_args[$field_name] = Auth_OpenID::arrayGet($query,
$field_name, '');
}
return new Auth_OpenID_SuccessResponse($endpoint, $signed_args);
}
 
/**
* Extract signed extension data from the server's response.
*
* @param string $prefix The extension namespace from which to
* extract the extension data.
*/
function extensionResponse($prefix)
{
$response = array();
$prefix = sprintf('openid.%s.', $prefix);
$prefix_len = strlen($prefix);
foreach ($this->signed_args as $k => $v) {
if (strpos($k, $prefix) === 0) {
$response_key = substr($k, $prefix_len);
$response[$response_key] = $v;
}
}
 
return $response;
}
 
/**
* Get the openid.return_to argument from this response.
*
* This is useful for verifying that this request was initiated by
* this consumer.
*
* @return string $return_to The return_to URL supplied to the
* server on the initial request, or null if the response did not
* contain an 'openid.return_to' argument.
*/
function getReturnTo()
{
return Auth_OpenID::arrayGet($this->signed_args, 'openid.return_to');
}
}
 
/**
* A response with a status of Auth_OpenID_FAILURE. Indicates that the
* OpenID protocol has failed. This could be locally or remotely
* triggered. This has three relevant attributes:
*
* identity_url - The identity URL for which authentication was
* attempted, if it can be determined. Otherwise, null.
*
* message - A message indicating why the request failed, if one is
* supplied. Otherwise, null.
*
* status - Auth_OpenID_FAILURE.
*
* @package OpenID
*/
class Auth_OpenID_FailureResponse extends Auth_OpenID_ConsumerResponse {
var $status = Auth_OpenID_FAILURE;
 
function Auth_OpenID_FailureResponse($endpoint, $message = null)
{
$this->endpoint = $endpoint;
if ($endpoint !== null) {
$this->identity_url = $endpoint->identity_url;
} else {
$this->identity_url = null;
}
$this->message = $message;
}
}
 
/**
* A response with a status of Auth_OpenID_CANCEL. Indicates that the
* user cancelled the OpenID authentication request. This has two
* relevant attributes:
*
* identity_url - The identity URL for which authentication was
* attempted, if it can be determined. Otherwise, null.
*
* status - Auth_OpenID_SUCCESS.
*
* @package OpenID
*/
class Auth_OpenID_CancelResponse extends Auth_OpenID_ConsumerResponse {
var $status = Auth_OpenID_CANCEL;
 
function Auth_OpenID_CancelResponse($endpoint)
{
$this->endpoint = $endpoint;
$this->identity_url = $endpoint->identity_url;
}
}
 
/**
* A response with a status of Auth_OpenID_SETUP_NEEDED. Indicates
* that the request was in immediate mode, and the server is unable to
* authenticate the user without further interaction.
*
* identity_url - The identity URL for which authentication was
* attempted.
*
* setup_url - A URL that can be used to send the user to the server
* to set up for authentication. The user should be redirected in to
* the setup_url, either in the current window or in a new browser
* window.
*
* status - Auth_OpenID_SETUP_NEEDED.
*
* @package OpenID
*/
class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse {
var $status = Auth_OpenID_SETUP_NEEDED;
 
function Auth_OpenID_SetupNeededResponse($endpoint,
$setup_url = null)
{
$this->endpoint = $endpoint;
$this->identity_url = $endpoint->identity_url;
$this->setup_url = $setup_url;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/FileStore.php
New file
0,0 → 1,674
<?php
 
/**
* This file supplies a Memcached store backend for OpenID servers and
* consumers.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
*/
 
/**
* Require base class for creating a new interface.
*/
require_once 'Auth/OpenID.php';
require_once 'Auth/OpenID/Interface.php';
require_once 'Auth/OpenID/HMACSHA1.php';
 
/**
* This is a filesystem-based store for OpenID associations and
* nonces. This store should be safe for use in concurrent systems on
* both windows and unix (excluding NFS filesystems). There are a
* couple race conditions in the system, but those failure cases have
* been set up in such a way that the worst-case behavior is someone
* having to try to log in a second time.
*
* Most of the methods of this class are implementation details.
* People wishing to just use this store need only pay attention to
* the constructor.
*
* @package OpenID
*/
class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore {
 
/**
* Initializes a new {@link Auth_OpenID_FileStore}. This
* initializes the nonce and association directories, which are
* subdirectories of the directory passed in.
*
* @param string $directory This is the directory to put the store
* directories in.
*/
function Auth_OpenID_FileStore($directory)
{
if (!Auth_OpenID::ensureDir($directory)) {
trigger_error('Not a directory and failed to create: '
. $directory, E_USER_ERROR);
}
$directory = realpath($directory);
 
$this->directory = $directory;
$this->active = true;
 
$this->nonce_dir = $directory . DIRECTORY_SEPARATOR . 'nonces';
 
$this->association_dir = $directory . DIRECTORY_SEPARATOR .
'associations';
 
// Temp dir must be on the same filesystem as the assciations
// $directory and the $directory containing the auth key file.
$this->temp_dir = $directory . DIRECTORY_SEPARATOR . 'temp';
 
$this->auth_key_name = $directory . DIRECTORY_SEPARATOR . 'auth_key';
 
$this->max_nonce_age = 6 * 60 * 60; // Six hours, in seconds
 
if (!$this->_setup()) {
trigger_error('Failed to initialize OpenID file store in ' .
$directory, E_USER_ERROR);
}
}
 
function destroy()
{
Auth_OpenID_FileStore::_rmtree($this->directory);
$this->active = false;
}
 
/**
* Make sure that the directories in which we store our data
* exist.
*
* @access private
*/
function _setup()
{
return (Auth_OpenID::ensureDir(dirname($this->auth_key_name)) &&
Auth_OpenID::ensureDir($this->nonce_dir) &&
Auth_OpenID::ensureDir($this->association_dir) &&
Auth_OpenID::ensureDir($this->temp_dir));
}
 
/**
* Create a temporary file on the same filesystem as
* $this->auth_key_name and $this->association_dir.
*
* The temporary directory should not be cleaned if there are any
* processes using the store. If there is no active process using
* the store, it is safe to remove all of the files in the
* temporary directory.
*
* @return array ($fd, $filename)
* @access private
*/
function _mktemp()
{
$name = Auth_OpenID_FileStore::_mkstemp($dir = $this->temp_dir);
$file_obj = @fopen($name, 'wb');
if ($file_obj !== false) {
return array($file_obj, $name);
} else {
Auth_OpenID_FileStore::_removeIfPresent($name);
}
}
 
/**
* Read the auth key from the auth key file. Will return None if
* there is currently no key.
*
* @return mixed
*/
function readAuthKey()
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$auth_key_file = @fopen($this->auth_key_name, 'rb');
if ($auth_key_file === false) {
return null;
}
 
$key = fread($auth_key_file, filesize($this->auth_key_name));
fclose($auth_key_file);
 
return $key;
}
 
/**
* Generate a new random auth key and safely store it in the
* location specified by $this->auth_key_name.
*
* @return string $key
*/
function createAuthKey()
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$auth_key = Auth_OpenID_CryptUtil::randomString($this->AUTH_KEY_LEN);
 
list($file_obj, $tmp) = $this->_mktemp();
 
fwrite($file_obj, $auth_key);
fflush($file_obj);
fclose($file_obj);
 
if (function_exists('link')) {
// Posix filesystem
$saved = link($tmp, $this->auth_key_name);
Auth_OpenID_FileStore::_removeIfPresent($tmp);
} else {
// Windows filesystem
$saved = rename($tmp, $this->auth_key_name);
}
 
if (!$saved) {
// The link failed, either because we lack the permission,
// or because the file already exists; try to read the key
// in case the file already existed.
$auth_key = $this->readAuthKey();
}
 
return $auth_key;
}
 
/**
* Retrieve the auth key from the file specified by
* $this->auth_key_name, creating it if it does not exist.
*
* @return string $key
*/
function getAuthKey()
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$auth_key = $this->readAuthKey();
if ($auth_key === null) {
$auth_key = $this->createAuthKey();
 
if (strlen($auth_key) != $this->AUTH_KEY_LEN) {
$fmt = 'Got an invalid auth key from %s. Expected '.
'%d-byte string. Got: %s';
$msg = sprintf($fmt, $this->auth_key_name, $this->AUTH_KEY_LEN,
$auth_key);
trigger_error($msg, E_USER_WARNING);
return null;
}
}
return $auth_key;
}
 
/**
* Create a unique filename for a given server url and
* handle. This implementation does not assume anything about the
* format of the handle. The filename that is returned will
* contain the domain name from the server URL for ease of human
* inspection of the data directory.
*
* @return string $filename
*/
function getAssociationFilename($server_url, $handle)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
if (strpos($server_url, '://') === false) {
trigger_error(sprintf("Bad server URL: %s", $server_url),
E_USER_WARNING);
return null;
}
 
list($proto, $rest) = explode('://', $server_url, 2);
$parts = explode('/', $rest);
$domain = Auth_OpenID_FileStore::_filenameEscape($parts[0]);
$url_hash = Auth_OpenID_FileStore::_safe64($server_url);
if ($handle) {
$handle_hash = Auth_OpenID_FileStore::_safe64($handle);
} else {
$handle_hash = '';
}
 
$filename = sprintf('%s-%s-%s-%s', $proto, $domain, $url_hash,
$handle_hash);
 
return $this->association_dir. DIRECTORY_SEPARATOR . $filename;
}
 
/**
* Store an association in the association directory.
*/
function storeAssociation($server_url, $association)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return false;
}
 
$association_s = $association->serialize();
$filename = $this->getAssociationFilename($server_url,
$association->handle);
list($tmp_file, $tmp) = $this->_mktemp();
 
if (!$tmp_file) {
trigger_error("_mktemp didn't return a valid file descriptor",
E_USER_WARNING);
return false;
}
 
fwrite($tmp_file, $association_s);
 
fflush($tmp_file);
 
fclose($tmp_file);
 
if (@rename($tmp, $filename)) {
return true;
} else {
// In case we are running on Windows, try unlinking the
// file in case it exists.
@unlink($filename);
 
// Now the target should not exist. Try renaming again,
// giving up if it fails.
if (@rename($tmp, $filename)) {
return true;
}
}
 
// If there was an error, don't leave the temporary file
// around.
Auth_OpenID_FileStore::_removeIfPresent($tmp);
return false;
}
 
/**
* Retrieve an association. If no handle is specified, return the
* association with the most recent issue time.
*
* @return mixed $association
*/
function getAssociation($server_url, $handle = null)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
if ($handle === null) {
$handle = '';
}
 
// The filename with the empty handle is a prefix of all other
// associations for the given server URL.
$filename = $this->getAssociationFilename($server_url, $handle);
 
if ($handle) {
return $this->_getAssociation($filename);
} else {
$association_files =
Auth_OpenID_FileStore::_listdir($this->association_dir);
$matching_files = array();
 
// strip off the path to do the comparison
$name = basename($filename);
foreach ($association_files as $association_file) {
if (strpos($association_file, $name) === 0) {
$matching_files[] = $association_file;
}
}
 
$matching_associations = array();
// read the matching files and sort by time issued
foreach ($matching_files as $name) {
$full_name = $this->association_dir . DIRECTORY_SEPARATOR .
$name;
$association = $this->_getAssociation($full_name);
if ($association !== null) {
$matching_associations[] = array($association->issued,
$association);
}
}
 
$issued = array();
$assocs = array();
foreach ($matching_associations as $key => $assoc) {
$issued[$key] = $assoc[0];
$assocs[$key] = $assoc[1];
}
 
array_multisort($issued, SORT_DESC, $assocs, SORT_DESC,
$matching_associations);
 
// return the most recently issued one.
if ($matching_associations) {
list($issued, $assoc) = $matching_associations[0];
return $assoc;
} else {
return null;
}
}
}
 
/**
* @access private
*/
function _getAssociation($filename)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$assoc_file = @fopen($filename, 'rb');
 
if ($assoc_file === false) {
return null;
}
 
$assoc_s = fread($assoc_file, filesize($filename));
fclose($assoc_file);
 
if (!$assoc_s) {
return null;
}
 
$association =
Auth_OpenID_Association::deserialize('Auth_OpenID_Association',
$assoc_s);
 
if (!$association) {
Auth_OpenID_FileStore::_removeIfPresent($filename);
return null;
}
 
if ($association->getExpiresIn() == 0) {
Auth_OpenID_FileStore::_removeIfPresent($filename);
return null;
} else {
return $association;
}
}
 
/**
* Remove an association if it exists. Do nothing if it does not.
*
* @return bool $success
*/
function removeAssociation($server_url, $handle)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$assoc = $this->getAssociation($server_url, $handle);
if ($assoc === null) {
return false;
} else {
$filename = $this->getAssociationFilename($server_url, $handle);
return Auth_OpenID_FileStore::_removeIfPresent($filename);
}
}
 
/**
* Mark this nonce as present.
*/
function storeNonce($nonce)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$filename = $this->nonce_dir . DIRECTORY_SEPARATOR . $nonce;
$nonce_file = fopen($filename, 'w');
if ($nonce_file === false) {
return false;
}
fclose($nonce_file);
return true;
}
 
/**
* Return whether this nonce is present. As a side effect, mark it
* as no longer present.
*
* @return bool $present
*/
function useNonce($nonce)
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$filename = $this->nonce_dir . DIRECTORY_SEPARATOR . $nonce;
$st = @stat($filename);
 
if ($st === false) {
return false;
}
 
// Either it is too old or we are using it. Either way, we
// must remove the file.
if (!unlink($filename)) {
return false;
}
 
$now = time();
$nonce_age = $now - $st[9];
 
// We can us it if the age of the file is less than the
// expiration time.
return $nonce_age <= $this->max_nonce_age;
}
 
/**
* Remove expired entries from the database. This is potentially
* expensive, so only run when it is acceptable to take time.
*/
function clean()
{
if (!$this->active) {
trigger_error("FileStore no longer active", E_USER_ERROR);
return null;
}
 
$nonces = Auth_OpenID_FileStore::_listdir($this->nonce_dir);
$now = time();
 
// Check all nonces for expiry
foreach ($nonces as $nonce) {
$filename = $this->nonce_dir . DIRECTORY_SEPARATOR . $nonce;
$st = @stat($filename);
 
if ($st !== false) {
// Remove the nonce if it has expired
$nonce_age = $now - $st[9];
if ($nonce_age > $this->max_nonce_age) {
Auth_OpenID_FileStore::_removeIfPresent($filename);
}
}
}
 
$association_filenames =
Auth_OpenID_FileStore::_listdir($this->association_dir);
 
foreach ($association_filenames as $association_filename) {
$association_file = fopen($association_filename, 'rb');
 
if ($association_file !== false) {
$assoc_s = fread($association_file,
filesize($association_filename));
fclose($association_file);
 
// Remove expired or corrupted associations
$association =
Auth_OpenID_Association::deserialize(
'Auth_OpenID_Association', $assoc_s);
 
if ($association === null) {
Auth_OpenID_FileStore::_removeIfPresent(
$association_filename);
} else {
if ($association->getExpiresIn() == 0) {
Auth_OpenID_FileStore::_removeIfPresent(
$association_filename);
}
}
}
}
}
 
/**
* @access private
*/
function _rmtree($dir)
{
if ($dir[strlen($dir) - 1] != DIRECTORY_SEPARATOR) {
$dir .= DIRECTORY_SEPARATOR;
}
 
if ($handle = opendir($dir)) {
while ($item = readdir($handle)) {
if (!in_array($item, array('.', '..'))) {
if (is_dir($dir . $item)) {
 
if (!Auth_OpenID_FileStore::_rmtree($dir . $item)) {
return false;
}
} else if (is_file($dir . $item)) {
if (!unlink($dir . $item)) {
return false;
}
}
}
}
 
closedir($handle);
 
if (!@rmdir($dir)) {
return false;
}
 
return true;
} else {
// Couldn't open directory.
return false;
}
}
 
/**
* @access private
*/
function _mkstemp($dir)
{
foreach (range(0, 4) as $i) {
$name = tempnam($dir, "php_openid_filestore_");
 
if ($name !== false) {
return $name;
}
}
return false;
}
 
/**
* @access private
*/
function _mkdtemp($dir)
{
foreach (range(0, 4) as $i) {
$name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) .
"-" . strval(rand(1, time()));
if (!mkdir($name, 0700)) {
return false;
} else {
return $name;
}
}
return false;
}
 
/**
* @access private
*/
function _listdir($dir)
{
$handle = opendir($dir);
$files = array();
while (false !== ($filename = readdir($handle))) {
$files[] = $filename;
}
return $files;
}
 
/**
* @access private
*/
function _isFilenameSafe($char)
{
$_Auth_OpenID_filename_allowed = Auth_OpenID_letters .
Auth_OpenID_digits . ".";
return (strpos($_Auth_OpenID_filename_allowed, $char) !== false);
}
 
/**
* @access private
*/
function _safe64($str)
{
$h64 = base64_encode(Auth_OpenID_SHA1($str));
$h64 = str_replace('+', '_', $h64);
$h64 = str_replace('/', '.', $h64);
$h64 = str_replace('=', '', $h64);
return $h64;
}
 
/**
* @access private
*/
function _filenameEscape($str)
{
$filename = "";
for ($i = 0; $i < strlen($str); $i++) {
$c = $str[$i];
if (Auth_OpenID_FileStore::_isFilenameSafe($c)) {
$filename .= $c;
} else {
$filename .= sprintf("_%02X", ord($c));
}
}
return $filename;
}
 
/**
* Attempt to remove a file, returning whether the file existed at
* the time of the call.
*
* @access private
* @return bool $result True if the file was present, false if not.
*/
function _removeIfPresent($filename)
{
return @unlink($filename);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/CryptUtil.php
New file
0,0 → 1,109
<?php
 
/**
* CryptUtil: A suite of wrapper utility functions for the OpenID
* library.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
if (!defined('Auth_OpenID_RAND_SOURCE')) {
/**
* The filename for a source of random bytes. Define this yourself
* if you have a different source of randomness.
*/
define('Auth_OpenID_RAND_SOURCE', '/dev/urandom');
}
 
class Auth_OpenID_CryptUtil {
/**
* Get the specified number of random bytes.
*
* Attempts to use a cryptographically secure (not predictable)
* source of randomness if available. If there is no high-entropy
* randomness source available, it will fail. As a last resort,
* for non-critical systems, define
* <code>Auth_OpenID_RAND_SOURCE</code> as <code>null</code>, and
* the code will fall back on a pseudo-random number generator.
*
* @param int $num_bytes The length of the return value
* @return string $bytes random bytes
*/
function getBytes($num_bytes)
{
static $f = null;
$bytes = '';
if ($f === null) {
if (Auth_OpenID_RAND_SOURCE === null) {
$f = false;
} else {
$f = @fopen(Auth_OpenID_RAND_SOURCE, "r");
if ($f === false) {
$msg = 'Define Auth_OpenID_RAND_SOURCE as null to ' .
' continue with an insecure random number generator.';
trigger_error($msg, E_USER_ERROR);
}
}
}
if ($f === false) {
// pseudorandom used
$bytes = '';
for ($i = 0; $i < $num_bytes; $i += 4) {
$bytes .= pack('L', mt_rand());
}
$bytes = substr($bytes, 0, $num_bytes);
} else {
$bytes = fread($f, $num_bytes);
}
return $bytes;
}
 
/**
* Produce a string of length random bytes, chosen from chrs. If
* $chrs is null, the resulting string may contain any characters.
*
* @param integer $length The length of the resulting
* randomly-generated string
* @param string $chrs A string of characters from which to choose
* to build the new string
* @return string $result A string of randomly-chosen characters
* from $chrs
*/
function randomString($length, $population = null)
{
if ($population === null) {
return Auth_OpenID_CryptUtil::getBytes($length);
}
 
$popsize = strlen($population);
 
if ($popsize > 256) {
$msg = 'More than 256 characters supplied to ' . __FUNCTION__;
trigger_error($msg, E_USER_ERROR);
}
 
$duplicate = 256 % $popsize;
 
$str = "";
for ($i = 0; $i < $length; $i++) {
do {
$n = ord(Auth_OpenID_CryptUtil::getBytes(1));
} while ($n < $duplicate);
 
$n %= $popsize;
$str .= $population[$n];
}
 
return $str;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/Interface.php
New file
0,0 → 1,188
<?php
 
/**
* This file specifies the interface for PHP OpenID store implementations.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* This is the interface for the store objects the OpenID library
* uses. It is a single class that provides all of the persistence
* mechanisms that the OpenID library needs, for both servers and
* consumers. If you want to create an SQL-driven store, please see
* then {@link Auth_OpenID_SQLStore} class.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
*/
class Auth_OpenID_OpenIDStore {
/**
* @var integer The length of the auth key that should be returned
* by the getAuthKey method.
*/
var $AUTH_KEY_LEN = 20;
 
/**
* This method puts an Association object into storage,
* retrievable by server URL and handle.
*
* @param string $server_url The URL of the identity server that
* this association is with. Because of the way the server portion
* of the library uses this interface, don't assume there are any
* limitations on the character set of the input string. In
* particular, expect to see unescaped non-url-safe characters in
* the server_url field.
*
* @param Association $association The Association to store.
*/
function storeAssociation($server_url, $association)
{
trigger_error("Auth_OpenID_OpenIDStore::storeAssociation ".
"not implemented", E_USER_ERROR);
}
 
/**
* This method returns an Association object from storage that
* matches the server URL and, if specified, handle. It returns
* null if no such association is found or if the matching
* association is expired.
*
* If no handle is specified, the store may return any association
* which matches the server URL. If multiple associations are
* valid, the recommended return value for this method is the one
* that will remain valid for the longest duration.
*
* This method is allowed (and encouraged) to garbage collect
* expired associations when found. This method must not return
* expired associations.
*
* @param string $server_url The URL of the identity server to get
* the association for. Because of the way the server portion of
* the library uses this interface, don't assume there are any
* limitations on the character set of the input string. In
* particular, expect to see unescaped non-url-safe characters in
* the server_url field.
*
* @param mixed $handle This optional parameter is the handle of
* the specific association to get. If no specific handle is
* provided, any valid association matching the server URL is
* returned.
*
* @return Association The Association for the given identity
* server.
*/
function getAssociation($server_url, $handle = null)
{
trigger_error("Auth_OpenID_OpenIDStore::getAssociation ".
"not implemented", E_USER_ERROR);
}
 
/**
* This method removes the matching association if it's found, and
* returns whether the association was removed or not.
*
* @param string $server_url The URL of the identity server the
* association to remove belongs to. Because of the way the server
* portion of the library uses this interface, don't assume there
* are any limitations on the character set of the input
* string. In particular, expect to see unescaped non-url-safe
* characters in the server_url field.
*
* @param string $handle This is the handle of the association to
* remove. If there isn't an association found that matches both
* the given URL and handle, then there was no matching handle
* found.
*
* @return mixed Returns whether or not the given association existed.
*/
function removeAssociation($server_url, $handle)
{
trigger_error("Auth_OpenID_OpenIDStore::removeAssociation ".
"not implemented", E_USER_ERROR);
}
 
/**
* Stores a nonce. This is used by the consumer to prevent replay
* attacks.
*
* @param string $nonce The nonce to store.
*
* @return null
*/
function storeNonce($nonce)
{
trigger_error("Auth_OpenID_OpenIDStore::storeNonce ".
"not implemented", E_USER_ERROR);
}
 
/**
* This method is called when the library is attempting to use a
* nonce. If the nonce is in the store, this method removes it and
* returns a value which evaluates as true. Otherwise it returns a
* value which evaluates as false.
*
* This method is allowed and encouraged to treat nonces older
* than some period (a very conservative window would be 6 hours,
* for example) as no longer existing, and return False and remove
* them.
*
* @param string $nonce The nonce to use.
*
* @return bool Whether or not the nonce was valid.
*/
function useNonce($nonce)
{
trigger_error("Auth_OpenID_OpenIDStore::useNonce ".
"not implemented", E_USER_ERROR);
}
 
/**
* This method returns a key used to sign the tokens, to ensure
* that they haven't been tampered with in transit. It should
* return the same key every time it is called. The key returned
* should be {@link AUTH_KEY_LEN} bytes long.
*
* @return string The key. It should be {@link AUTH_KEY_LEN} bytes in
* length, and use the full range of byte values. That is, it
* should be treated as a lump of binary data stored in a string.
*/
function getAuthKey()
{
trigger_error("Auth_OpenID_OpenIDStore::getAuthKey ".
"not implemented", E_USER_ERROR);
}
 
/**
* This method must return true if the store is a dumb-mode-style
* store. Unlike all other methods in this class, this one
* provides a default implementation, which returns false.
*
* In general, any custom subclass of {@link Auth_OpenID_OpenIDStore}
* won't override this method, as custom subclasses are only likely to
* be created when the store is fully functional.
*
* @return bool true if the store works fully, false if the
* consumer will have to use dumb mode to use this store.
*/
function isDumb()
{
return false;
}
 
/**
* Removes all entries from the store; implementation is optional.
*/
function reset()
{
}
 
}
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/KVForm.php
New file
0,0 → 1,112
<?php
 
/**
* OpenID protocol key-value/comma-newline format parsing and
* serialization
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @access private
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Container for key-value/comma-newline OpenID format and parsing
*/
class Auth_OpenID_KVForm {
/**
* Convert an OpenID colon/newline separated string into an
* associative array
*
* @static
* @access private
*/
function toArray($kvs, $strict=false)
{
$lines = explode("\n", $kvs);
 
$last = array_pop($lines);
if ($last !== '') {
array_push($lines, $last);
if ($strict) {
return false;
}
}
 
$values = array();
 
for ($lineno = 0; $lineno < count($lines); $lineno++) {
$line = $lines[$lineno];
$kv = explode(':', $line, 2);
if (count($kv) != 2) {
if ($strict) {
return false;
}
continue;
}
 
$key = $kv[0];
$tkey = trim($key);
if ($tkey != $key) {
if ($strict) {
return false;
}
}
 
$value = $kv[1];
$tval = trim($value);
if ($tval != $value) {
if ($strict) {
return false;
}
}
 
$values[$tkey] = $tval;
}
 
return $values;
}
 
/**
* Convert an array into an OpenID colon/newline separated string
*
* @static
* @access private
*/
function fromArray($values)
{
if ($values === null) {
return null;
}
 
ksort($values);
 
$serialized = '';
foreach ($values as $key => $value) {
if (is_array($value)) {
list($key, $value) = array($value[0], $value[1]);
}
 
if (strpos($key, ':') !== false) {
return null;
}
 
if (strpos($key, "\n") !== false) {
return null;
}
 
if (strpos($value, "\n") !== false) {
return null;
}
$serialized .= "$key:$value\n";
}
return $serialized;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/DumbStore.php
New file
0,0 → 1,116
<?php
 
/**
* This file supplies a dumb store backend for OpenID servers and
* consumers.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Import the interface for creating a new store class.
*/
require_once 'Auth/OpenID/Interface.php';
require_once 'Auth/OpenID/HMACSHA1.php';
 
/**
* This is a store for use in the worst case, when you have no way of
* saving state on the consumer site. Using this store makes the
* consumer vulnerable to replay attacks, as it's unable to use
* nonces. Avoid using this store if it is at all possible.
*
* Most of the methods of this class are implementation details.
* Users of this class need to worry only about the constructor.
*
* @package OpenID
*/
class Auth_OpenID_DumbStore extends Auth_OpenID_OpenIDStore {
 
/**
* Creates a new {@link Auth_OpenID_DumbStore} instance. For the security
* of the tokens generated by the library, this class attempts to
* at least have a secure implementation of getAuthKey.
*
* When you create an instance of this class, pass in a secret
* phrase. The phrase is hashed with sha1 to make it the correct
* length and form for an auth key. That allows you to use a long
* string as the secret phrase, which means you can make it very
* difficult to guess.
*
* Each {@link Auth_OpenID_DumbStore} instance that is created for use by
* your consumer site needs to use the same $secret_phrase.
*
* @param string secret_phrase The phrase used to create the auth
* key returned by getAuthKey
*/
function Auth_OpenID_DumbStore($secret_phrase)
{
$this->auth_key = Auth_OpenID_SHA1($secret_phrase);
}
 
/**
* This implementation does nothing.
*/
function storeAssociation($server_url, $association)
{
}
 
/**
* This implementation always returns null.
*/
function getAssociation($server_url, $handle = null)
{
return null;
}
 
/**
* This implementation always returns false.
*/
function removeAssociation($server_url, $handle)
{
return false;
}
 
/**
* This implementation does nothing.
*/
function storeNonce($nonce)
{
}
 
/**
* In a system truly limited to dumb mode, nonces must all be
* accepted. This therefore always returns true, which makes
* replay attacks feasible.
*/
function useNonce($nonce)
{
return true;
}
 
/**
* This method returns the auth key generated by the constructor.
*/
function getAuthKey()
{
return $this->auth_key;
}
 
/**
* This store is a dumb mode store, so this method is overridden
* to return true.
*/
function isDumb()
{
return true;
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID/Server.php
New file
0,0 → 1,1307
<?php
 
/**
* OpenID server protocol and logic.
*
* Overview
*
* An OpenID server must perform three tasks:
*
* 1. Examine the incoming request to determine its nature and validity.
* 2. Make a decision about how to respond to this request.
* 3. Format the response according to the protocol.
*
* The first and last of these tasks may performed by the
* 'decodeRequest' and 'encodeResponse' methods of the
* Auth_OpenID_Server object. Who gets to do the intermediate task --
* deciding how to respond to the request -- will depend on what type
* of request it is.
*
* If it's a request to authenticate a user (a 'checkid_setup' or
* 'checkid_immediate' request), you need to decide if you will assert
* that this user may claim the identity in question. Exactly how you
* do that is a matter of application policy, but it generally
* involves making sure the user has an account with your system and
* is logged in, checking to see if that identity is hers to claim,
* and verifying with the user that she does consent to releasing that
* information to the party making the request.
*
* Examine the properties of the Auth_OpenID_CheckIDRequest object,
* and if and when you've come to a decision, form a response by
* calling Auth_OpenID_CheckIDRequest::answer.
*
* Other types of requests relate to establishing associations between
* client and server and verifing the authenticity of previous
* communications. Auth_OpenID_Server contains all the logic and data
* necessary to respond to such requests; just pass it to
* Auth_OpenID_Server::handleRequest.
*
* OpenID Extensions
*
* Do you want to provide other information for your users in addition
* to authentication? Version 1.2 of the OpenID protocol allows
* consumers to add extensions to their requests. For example, with
* sites using the Simple Registration
* Extension
* (http://www.openidenabled.com/openid/simple-registration-extension/),
* a user can agree to have their nickname and e-mail address sent to
* a site when they sign up.
*
* Since extensions do not change the way OpenID authentication works,
* code to handle extension requests may be completely separate from
* the Auth_OpenID_Request class here. But you'll likely want data
* sent back by your extension to be signed. Auth_OpenID_Response
* provides methods with which you can add data to it which can be
* signed with the other data in the OpenID signature.
*
* For example:
*
* // when request is a checkid_* request
* response = request.answer(True)
* // this will a signed 'openid.sreg.timezone' parameter to the response
* response.addField('sreg', 'timezone', 'America/Los_Angeles')
*
* Stores
*
* The OpenID server needs to maintain state between requests in order
* to function. Its mechanism for doing this is called a store. The
* store interface is defined in Interface.php. Additionally, several
* concrete store implementations are provided, so that most sites
* won't need to implement a custom store. For a store backed by flat
* files on disk, see Auth_OpenID_FileStore. For stores based on
* MySQL, SQLite, or PostgreSQL, see the Auth_OpenID_SQLStore
* subclasses.
*
* Upgrading
*
* The keys by which a server looks up associations in its store have
* changed in version 1.2 of this library. If your store has entries
* created from version 1.0 code, you should empty it.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Required imports
*/
require_once "Auth/OpenID.php";
require_once "Auth/OpenID/Association.php";
require_once "Auth/OpenID/CryptUtil.php";
require_once "Auth/OpenID/BigMath.php";
require_once "Auth/OpenID/DiffieHellman.php";
require_once "Auth/OpenID/KVForm.php";
require_once "Auth/OpenID/TrustRoot.php";
require_once "Auth/OpenID/ServerRequest.php";
 
define('AUTH_OPENID_HTTP_OK', 200);
define('AUTH_OPENID_HTTP_REDIRECT', 302);
define('AUTH_OPENID_HTTP_ERROR', 400);
 
global $_Auth_OpenID_Request_Modes,
$_Auth_OpenID_OpenID_Prefix,
$_Auth_OpenID_Encode_Kvform,
$_Auth_OpenID_Encode_Url;
 
/**
* @access private
*/
$_Auth_OpenID_Request_Modes = array('checkid_setup',
'checkid_immediate');
 
/**
* @access private
*/
$_Auth_OpenID_OpenID_Prefix = "openid.";
 
/**
* @access private
*/
$_Auth_OpenID_Encode_Kvform = array('kfvorm');
 
/**
* @access private
*/
$_Auth_OpenID_Encode_Url = array('URL/redirect');
 
/**
* @access private
*/
function _isError($obj, $cls = 'Auth_OpenID_ServerError')
{
return is_a($obj, $cls);
}
 
/**
* An error class which gets instantiated and returned whenever an
* OpenID protocol error occurs. Be prepared to use this in place of
* an ordinary server response.
*
* @package OpenID
*/
class Auth_OpenID_ServerError {
/**
* @access private
*/
function Auth_OpenID_ServerError($query = null, $message = null)
{
$this->message = $message;
$this->query = $query;
}
 
/**
* Returns the return_to URL for the request which caused this
* error.
*/
function hasReturnTo()
{
global $_Auth_OpenID_OpenID_Prefix;
if ($this->query) {
return array_key_exists($_Auth_OpenID_OpenID_Prefix .
'return_to', $this->query);
} else {
return false;
}
}
 
/**
* Encodes this error's response as a URL suitable for
* redirection. If the response has no return_to, another
* Auth_OpenID_ServerError is returned.
*/
function encodeToURL()
{
global $_Auth_OpenID_OpenID_Prefix;
$return_to = Auth_OpenID::arrayGet($this->query,
$_Auth_OpenID_OpenID_Prefix .
'return_to');
if (!$return_to) {
return new Auth_OpenID_ServerError(null, "no return_to URL");
}
 
return Auth_OpenID::appendArgs($return_to,
array('openid.mode' => 'error',
'openid.error' => $this->toString()));
}
 
/**
* Encodes the response to key-value form. This is a
* machine-readable format used to respond to messages which came
* directly from the consumer and not through the user-agent. See
* the OpenID specification.
*/
function encodeToKVForm()
{
return Auth_OpenID_KVForm::fromArray(
array('mode' => 'error',
'error' => $this->toString()));
}
 
/**
* Returns one of $_Auth_OpenID_Encode_Url,
* $_Auth_OpenID_Encode_Kvform, or null, depending on the type of
* encoding expected for this error's payload.
*/
function whichEncoding()
{
global $_Auth_OpenID_Encode_Url,
$_Auth_OpenID_Encode_Kvform,
$_Auth_OpenID_Request_Modes;
 
if ($this->hasReturnTo()) {
return $_Auth_OpenID_Encode_Url;
}
 
$mode = Auth_OpenID::arrayGet($this->query, 'openid.mode');
 
if ($mode) {
if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
return $_Auth_OpenID_Encode_Kvform;
}
}
return null;
}
 
/**
* Returns this error message.
*/
function toString()
{
if ($this->message) {
return $this->message;
} else {
return get_class($this) . " error";
}
}
}
 
/**
* An error indicating that the return_to URL is malformed.
*
* @package OpenID
*/
class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
function Auth_OpenID_MalformedReturnURL($query, $return_to)
{
$this->return_to = $return_to;
parent::Auth_OpenID_ServerError($query, "malformed return_to URL");
}
}
 
/**
* This error is returned when the trust_root value is malformed.
*
* @package OpenID
*/
class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
function toString()
{
return "Malformed trust root";
}
}
 
/**
* The base class for all server request classes.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_Request {
var $mode = null;
}
 
/**
* A request to verify the validity of a previous response.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
var $mode = "check_authentication";
var $invalidate_handle = null;
 
function Auth_OpenID_CheckAuthRequest($assoc_handle, $sig, $signed,
$invalidate_handle = null)
{
$this->assoc_handle = $assoc_handle;
$this->sig = $sig;
$this->signed = $signed;
if ($invalidate_handle !== null) {
$this->invalidate_handle = $invalidate_handle;
}
}
 
function fromQuery($query)
{
global $_Auth_OpenID_OpenID_Prefix;
 
$required_keys = array('assoc_handle', 'sig', 'signed');
 
foreach ($required_keys as $k) {
if (!array_key_exists($_Auth_OpenID_OpenID_Prefix . $k,
$query)) {
return new Auth_OpenID_ServerError($query,
sprintf("%s request missing required parameter %s from \
query", "check_authentication", $k));
}
}
 
$assoc_handle = $query[$_Auth_OpenID_OpenID_Prefix . 'assoc_handle'];
$sig = $query[$_Auth_OpenID_OpenID_Prefix . 'sig'];
$signed_list = $query[$_Auth_OpenID_OpenID_Prefix . 'signed'];
 
$signed_list = explode(",", $signed_list);
$signed_pairs = array();
 
foreach ($signed_list as $field) {
if ($field == 'mode') {
// XXX KLUDGE HAX WEB PROTOCoL BR0KENNN
//
// openid.mode is currently check_authentication
// because that's the mode of this request. But the
// signature was made on something with a different
// openid.mode.
$value = "id_res";
} else {
if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
$query)) {
$value = $query[$_Auth_OpenID_OpenID_Prefix . $field];
} else {
return new Auth_OpenID_ServerError($query,
sprintf("Couldn't find signed field %r in query %s",
$field, var_export($query, true)));
}
}
$signed_pairs[] = array($field, $value);
}
 
$result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $sig,
$signed_pairs);
$result->invalidate_handle = Auth_OpenID::arrayGet($query,
$_Auth_OpenID_OpenID_Prefix . 'invalidate_handle');
return $result;
}
 
function answer(&$signatory)
{
$is_valid = $signatory->verify($this->assoc_handle, $this->sig,
$this->signed);
 
// Now invalidate that assoc_handle so it this checkAuth
// message cannot be replayed.
$signatory->invalidate($this->assoc_handle, true);
$response = new Auth_OpenID_ServerResponse($this);
$response->fields['is_valid'] = $is_valid ? "true" : "false";
 
if ($this->invalidate_handle) {
$assoc = $signatory->getAssociation($this->invalidate_handle,
false);
if (!$assoc) {
$response->fields['invalidate_handle'] =
$this->invalidate_handle;
}
}
return $response;
}
}
 
class Auth_OpenID_PlainTextServerSession {
/**
* An object that knows how to handle association requests with no
* session type.
*/
var $session_type = 'plaintext';
 
function fromQuery($unused_request)
{
return new Auth_OpenID_PlainTextServerSession();
}
 
function answer($secret)
{
return array('mac_key' => base64_encode($secret));
}
}
 
class Auth_OpenID_DiffieHellmanServerSession {
/**
* An object that knows how to handle association requests with
* the Diffie-Hellman session type.
*/
 
var $session_type = 'DH-SHA1';
 
function Auth_OpenID_DiffieHellmanServerSession($dh, $consumer_pubkey)
{
$this->dh = $dh;
$this->consumer_pubkey = $consumer_pubkey;
}
 
function fromQuery($query)
{
$dh_modulus = Auth_OpenID::arrayGet($query, 'openid.dh_modulus');
$dh_gen = Auth_OpenID::arrayGet($query, 'openid.dh_gen');
 
if ((($dh_modulus === null) && ($dh_gen !== null)) ||
(($dh_gen === null) && ($dh_modulus !== null))) {
 
if ($dh_modulus === null) {
$missing = 'modulus';
} else {
$missing = 'generator';
}
 
return new Auth_OpenID_ServerError(
'If non-default modulus or generator is '.
'supplied, both must be supplied. Missing '.
$missing);
}
 
$lib =& Auth_OpenID_getMathLib();
 
if ($dh_modulus || $dh_gen) {
$dh_modulus = $lib->base64ToLong($dh_modulus);
$dh_gen = $lib->base64ToLong($dh_gen);
if ($lib->cmp($dh_modulus, 0) == 0 ||
$lib->cmp($dh_gen, 0) == 0) {
return new Auth_OpenID_ServerError(
$query, "Failed to parse dh_mod or dh_gen");
}
$dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
} else {
$dh = new Auth_OpenID_DiffieHellman();
}
 
$consumer_pubkey = Auth_OpenID::arrayGet($query,
'openid.dh_consumer_public');
if ($consumer_pubkey === null) {
return new Auth_OpenID_ServerError(
'Public key for DH-SHA1 session '.
'not found in query');
}
 
$consumer_pubkey =
$lib->base64ToLong($consumer_pubkey);
 
if ($consumer_pubkey === false) {
return new Auth_OpenID_ServerError($query,
"dh_consumer_public is not base64");
}
 
return new Auth_OpenID_DiffieHellmanServerSession($dh,
$consumer_pubkey);
}
 
function answer($secret)
{
$lib =& Auth_OpenID_getMathLib();
$mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret);
return array(
'dh_server_public' =>
$lib->longToBase64($this->dh->public),
'enc_mac_key' => base64_encode($mac_key));
}
}
 
/**
* A request to associate with the server.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
var $mode = "associate";
var $assoc_type = 'HMAC-SHA1';
 
function Auth_OpenID_AssociateRequest(&$session)
{
$this->session =& $session;
}
 
function fromQuery($query)
{
global $_Auth_OpenID_OpenID_Prefix;
 
$session_classes = array(
'DH-SHA1' => 'Auth_OpenID_DiffieHellmanServerSession',
null => 'Auth_OpenID_PlainTextServerSession');
 
$session_type = null;
 
if (array_key_exists($_Auth_OpenID_OpenID_Prefix . 'session_type',
$query)) {
$session_type = $query[$_Auth_OpenID_OpenID_Prefix .
'session_type'];
}
 
if (!array_key_exists($session_type, $session_classes)) {
return new Auth_OpenID_ServerError($query,
"Unknown session type $session_type");
}
 
$session_cls = $session_classes[$session_type];
$session = call_user_func_array(array($session_cls, 'fromQuery'),
array($query));
 
if (($session === null) || (_isError($session))) {
return new Auth_OpenID_ServerError($query,
"Error parsing $session_type session");
}
 
return new Auth_OpenID_AssociateRequest($session);
}
 
function answer($assoc)
{
$ml =& Auth_OpenID_getMathLib();
$response = new Auth_OpenID_ServerResponse($this);
 
$response->fields = array('expires_in' => $assoc->getExpiresIn(),
'assoc_type' => 'HMAC-SHA1',
'assoc_handle' => $assoc->handle);
 
$r = $this->session->answer($assoc->secret);
foreach ($r as $k => $v) {
$response->fields[$k] = $v;
}
 
if ($this->session->session_type != 'plaintext') {
$response->fields['session_type'] = $this->session->session_type;
}
 
return $response;
}
}
 
/**
* A request to confirm the identity of a user.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
var $mode = "checkid_setup"; // or "checkid_immediate"
var $immediate = false;
var $trust_root = null;
 
function make($query, $identity, $return_to, $trust_root = null,
$immediate = false, $assoc_handle = null)
{
if (!Auth_OpenID_TrustRoot::_parse($return_to)) {
return new Auth_OpenID_MalformedReturnURL($query, $return_to);
}
 
$r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
$trust_root, $immediate,
$assoc_handle);
 
if (!$r->trustRootValid()) {
return new Auth_OpenID_UntrustedReturnURL($return_to,
$trust_root);
} else {
return $r;
}
}
 
function Auth_OpenID_CheckIDRequest($identity, $return_to,
$trust_root = null, $immediate = false,
$assoc_handle = null)
{
$this->identity = $identity;
$this->return_to = $return_to;
$this->trust_root = $trust_root;
$this->assoc_handle = $assoc_handle;
 
if ($immediate) {
$this->immediate = true;
$this->mode = "checkid_immediate";
} else {
$this->immediate = false;
$this->mode = "checkid_setup";
}
}
 
function fromQuery($query)
{
global $_Auth_OpenID_OpenID_Prefix;
 
$mode = $query[$_Auth_OpenID_OpenID_Prefix . 'mode'];
$immediate = null;
 
if ($mode == "checkid_immediate") {
$immediate = true;
$mode = "checkid_immediate";
} else {
$immediate = false;
$mode = "checkid_setup";
}
 
$required = array('identity',
'return_to');
 
$optional = array('trust_root',
'assoc_handle');
 
$values = array();
 
foreach ($required as $field) {
if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
$query)) {
$value = $query[$_Auth_OpenID_OpenID_Prefix . $field];
} else {
return new Auth_OpenID_ServerError($query,
sprintf("Missing required field %s from request",
$field));
}
$values[$field] = $value;
}
 
foreach ($optional as $field) {
$value = null;
if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field,
$query)) {
$value = $query[$_Auth_OpenID_OpenID_Prefix. $field];
}
if ($value) {
$values[$field] = $value;
}
}
 
if (!Auth_OpenID_TrustRoot::_parse($values['return_to'])) {
return new Auth_OpenID_MalformedReturnURL($query,
$values['return_to']);
}
 
$obj = Auth_OpenID_CheckIDRequest::make($query,
$values['identity'],
$values['return_to'],
Auth_OpenID::arrayGet($values,
'trust_root', null),
$immediate);
 
if (is_a($obj, 'Auth_OpenID_ServerError')) {
return $obj;
}
 
if (Auth_OpenID::arrayGet($values, 'assoc_handle')) {
$obj->assoc_handle = $values['assoc_handle'];
}
 
return $obj;
}
 
function trustRootValid()
{
if (!$this->trust_root) {
return true;
}
 
$tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
if ($tr === false) {
return new Auth_OpenID_MalformedTrustRoot(null, $this->trust_root);
}
 
return Auth_OpenID_TrustRoot::match($this->trust_root,
$this->return_to);
}
 
function answer($allow, $server_url = null)
{
if ($allow || $this->immediate) {
$mode = 'id_res';
} else {
$mode = 'cancel';
}
 
$response = new Auth_OpenID_CheckIDResponse($this, $mode);
 
if ($allow) {
$response->fields['identity'] = $this->identity;
$response->fields['return_to'] = $this->return_to;
if (!$this->trustRootValid()) {
return new Auth_OpenID_UntrustedReturnURL($this->return_to,
$this->trust_root);
}
} else {
$response->signed = array();
if ($this->immediate) {
if (!$server_url) {
return new Auth_OpenID_ServerError(null,
'setup_url is required for $allow=false \
in immediate mode.');
}
 
$setup_request =& new Auth_OpenID_CheckIDRequest(
$this->identity,
$this->return_to,
$this->trust_root,
false,
$this->assoc_handle);
 
$setup_url = $setup_request->encodeToURL($server_url);
 
$response->fields['user_setup_url'] = $setup_url;
}
}
 
return $response;
}
 
function encodeToURL($server_url)
{
global $_Auth_OpenID_OpenID_Prefix;
 
// Imported from the alternate reality where these classes are
// used in both the client and server code, so Requests are
// Encodable too. That's right, code imported from alternate
// realities all for the love of you, id_res/user_setup_url.
 
$q = array('mode' => $this->mode,
'identity' => $this->identity,
'return_to' => $this->return_to);
 
if ($this->trust_root) {
$q['trust_root'] = $this->trust_root;
}
 
if ($this->assoc_handle) {
$q['assoc_handle'] = $this->assoc_handle;
}
 
$_q = array();
 
foreach ($q as $k => $v) {
$_q[$_Auth_OpenID_OpenID_Prefix . $k] = $v;
}
 
return Auth_OpenID::appendArgs($server_url, $_q);
}
 
function getCancelURL()
{
global $_Auth_OpenID_OpenID_Prefix;
 
if ($this->immediate) {
return new Auth_OpenID_ServerError(null,
"Cancel is not an appropriate \
response to immediate mode \
requests.");
}
 
return Auth_OpenID::appendArgs($this->return_to,
array($_Auth_OpenID_OpenID_Prefix . 'mode' =>
'cancel'));
}
}
 
/**
* This class encapsulates the response to an OpenID server request.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_ServerResponse {
 
function Auth_OpenID_ServerResponse($request)
{
$this->request = $request;
$this->fields = array();
}
 
function whichEncoding()
{
global $_Auth_OpenID_Encode_Kvform,
$_Auth_OpenID_Request_Modes,
$_Auth_OpenID_Encode_Url;
 
if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
return $_Auth_OpenID_Encode_Url;
} else {
return $_Auth_OpenID_Encode_Kvform;
}
}
 
function encodeToURL()
{
global $_Auth_OpenID_OpenID_Prefix;
 
$fields = array();
 
foreach ($this->fields as $k => $v) {
$fields[$_Auth_OpenID_OpenID_Prefix . $k] = $v;
}
 
return Auth_OpenID::appendArgs($this->request->return_to, $fields);
}
 
function encodeToKVForm()
{
return Auth_OpenID_KVForm::fromArray($this->fields);
}
}
 
/**
* A response to a checkid request.
*
* @access private
* @package OpenID
*/
class Auth_OpenID_CheckIDResponse extends Auth_OpenID_ServerResponse {
 
function Auth_OpenID_CheckIDResponse(&$request, $mode = 'id_res')
{
parent::Auth_OpenID_ServerResponse($request);
$this->fields['mode'] = $mode;
$this->signed = array();
 
if ($mode == 'id_res') {
array_push($this->signed, 'mode', 'identity', 'return_to');
}
}
 
function addField($namespace, $key, $value, $signed = true)
{
if ($namespace) {
$key = sprintf('%s.%s', $namespace, $key);
}
$this->fields[$key] = $value;
if ($signed && !in_array($key, $this->signed)) {
$this->signed[] = $key;
}
}
 
function addFields($namespace, $fields, $signed = true)
{
foreach ($fields as $k => $v) {
$this->addField($namespace, $k, $v, $signed);
}
}
 
function update($namespace, $other)
{
$namespaced_fields = array();
 
foreach ($other->fields as $k => $v) {
$name = sprintf('%s.%s', $namespace, $k);
 
$namespaced_fields[$name] = $v;
}
 
$this->fields = array_merge($this->fields, $namespaced_fields);
$this->signed = array_merge($this->signed, $other->signed);
}
}
 
/**
* A web-capable response object which you can use to generate a
* user-agent response.
*
* @package OpenID
*/
class Auth_OpenID_WebResponse {
var $code = AUTH_OPENID_HTTP_OK;
var $body = "";
 
function Auth_OpenID_WebResponse($code = null, $headers = null,
$body = null)
{
if ($code) {
$this->code = $code;
}
 
if ($headers !== null) {
$this->headers = $headers;
} else {
$this->headers = array();
}
 
if ($body !== null) {
$this->body = $body;
}
}
}
 
/**
* Responsible for the signature of query data and the verification of
* OpenID signature values.
*
* @package OpenID
*/
class Auth_OpenID_Signatory {
 
// = 14 * 24 * 60 * 60; # 14 days, in seconds
var $SECRET_LIFETIME = 1209600;
 
// keys have a bogus server URL in them because the filestore
// really does expect that key to be a URL. This seems a little
// silly for the server store, since I expect there to be only one
// server URL.
var $normal_key = 'http://localhost/|normal';
var $dumb_key = 'http://localhost/|dumb';
 
/**
* Create a new signatory using a given store.
*/
function Auth_OpenID_Signatory(&$store)
{
// assert store is not None
$this->store =& $store;
}
 
/**
* Verify, using a given association handle, a signature with
* signed key-value pairs from an HTTP request.
*/
function verify($assoc_handle, $sig, $signed_pairs)
{
$assoc = $this->getAssociation($assoc_handle, true);
if (!$assoc) {
// oidutil.log("failed to get assoc with handle %r to verify sig %r"
// % (assoc_handle, sig))
return false;
}
 
$expected_sig = base64_encode($assoc->sign($signed_pairs));
 
return $sig == $expected_sig;
}
 
/**
* Given a response, sign the fields in the response's 'signed'
* list, and insert the signature into the response.
*/
function sign($response)
{
$signed_response = $response;
$assoc_handle = $response->request->assoc_handle;
 
if ($assoc_handle) {
// normal mode
$assoc = $this->getAssociation($assoc_handle, false);
if (!$assoc) {
// fall back to dumb mode
$signed_response->fields['invalidate_handle'] = $assoc_handle;
$assoc = $this->createAssociation(true);
}
} else {
// dumb mode.
$assoc = $this->createAssociation(true);
}
 
$signed_response->fields['assoc_handle'] = $assoc->handle;
$assoc->addSignature($signed_response->signed,
$signed_response->fields, '');
return $signed_response;
}
 
/**
* Make a new association.
*/
function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
{
$secret = Auth_OpenID_CryptUtil::getBytes(20);
$uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
$handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
 
$assoc = Auth_OpenID_Association::fromExpiresIn(
$this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
 
if ($dumb) {
$key = $this->dumb_key;
} else {
$key = $this->normal_key;
}
 
$this->store->storeAssociation($key, $assoc);
return $assoc;
}
 
/**
* Given an association handle, get the association from the
* store, or return a ServerError or null if something goes wrong.
*/
function getAssociation($assoc_handle, $dumb)
{
if ($assoc_handle === null) {
return new Auth_OpenID_ServerError(null,
"assoc_handle must not be null");
}
 
if ($dumb) {
$key = $this->dumb_key;
} else {
$key = $this->normal_key;
}
 
$assoc = $this->store->getAssociation($key, $assoc_handle);
 
if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
$this->store->removeAssociation($key, $assoc_handle);
$assoc = null;
}
 
return $assoc;
}
 
/**
* Invalidate a given association handle.
*/
function invalidate($assoc_handle, $dumb)
{
if ($dumb) {
$key = $this->dumb_key;
} else {
$key = $this->normal_key;
}
$this->store->removeAssociation($key, $assoc_handle);
}
}
 
/**
* Encode an Auth_OpenID_Response to an Auth_OpenID_WebResponse.
*
* @package OpenID
*/
class Auth_OpenID_Encoder {
 
var $responseFactory = 'Auth_OpenID_WebResponse';
 
/**
* Encode an Auth_OpenID_Response and return an
* Auth_OpenID_WebResponse.
*/
function encode(&$response)
{
global $_Auth_OpenID_Encode_Kvform,
$_Auth_OpenID_Encode_Url;
 
$cls = $this->responseFactory;
 
$encode_as = $response->whichEncoding();
if ($encode_as == $_Auth_OpenID_Encode_Kvform) {
$wr = new $cls(null, null, $response->encodeToKVForm());
if (is_a($response, 'Auth_OpenID_ServerError')) {
$wr->code = AUTH_OPENID_HTTP_ERROR;
}
} else if ($encode_as == $_Auth_OpenID_Encode_Url) {
$location = $response->encodeToURL();
$wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
array('location' => $location));
} else {
return new Auth_OpenID_EncodingError($response);
}
return $wr;
}
}
 
/**
* Returns true if the given response needs a signature.
*
* @access private
*/
function needsSigning($response)
{
return (in_array($response->request->mode, array('checkid_setup',
'checkid_immediate')) &&
$response->signed);
}
 
/**
* An encoder which also takes care of signing fields when required.
*
* @package OpenID
*/
class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
 
function Auth_OpenID_SigningEncoder(&$signatory)
{
$this->signatory =& $signatory;
}
 
/**
* Sign an Auth_OpenID_Response and return an
* Auth_OpenID_WebResponse.
*/
function encode(&$response)
{
// the isinstance is a bit of a kludge... it means there isn't
// really an adapter to make the interfaces quite match.
if (!is_a($response, 'Auth_OpenID_ServerError') &&
needsSigning($response)) {
 
if (!$this->signatory) {
return new Auth_OpenID_ServerError(null,
"Must have a store to sign request");
}
if (array_key_exists('sig', $response->fields)) {
return new Auth_OpenID_AlreadySigned($response);
}
$response = $this->signatory->sign($response);
}
return parent::encode($response);
}
}
 
/**
* Decode an incoming Auth_OpenID_WebResponse into an
* Auth_OpenID_Request.
*
* @package OpenID
*/
class Auth_OpenID_Decoder {
 
function Auth_OpenID_Decoder()
{
global $_Auth_OpenID_OpenID_Prefix;
$this->prefix = $_Auth_OpenID_OpenID_Prefix;
 
$this->handlers = array(
'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
'associate' => 'Auth_OpenID_AssociateRequest'
);
}
 
/**
* Given an HTTP query in an array (key-value pairs), decode it
* into an Auth_OpenID_Request object.
*/
function decode($query)
{
if (!$query) {
return null;
}
 
$myquery = array();
 
foreach ($query as $k => $v) {
if (strpos($k, $this->prefix) === 0) {
$myquery[$k] = $v;
}
}
 
if (!$myquery) {
return null;
}
 
$mode = Auth_OpenID::arrayGet($myquery, $this->prefix . 'mode');
if (!$mode) {
return new Auth_OpenID_ServerError($query,
sprintf("No %s mode found in query", $this->prefix));
}
 
$handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
$this->defaultDecoder($query));
 
if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) {
return call_user_func_array(array($handlerCls, 'fromQuery'),
array($query));
} else {
return $handlerCls;
}
}
 
function defaultDecoder($query)
{
$mode = $query[$this->prefix . 'mode'];
return new Auth_OpenID_ServerError($query,
sprintf("No decoder for mode %s", $mode));
}
}
 
/**
* An error that indicates an encoding problem occurred.
*
* @package OpenID
*/
class Auth_OpenID_EncodingError {
function Auth_OpenID_EncodingError(&$response)
{
$this->response =& $response;
}
}
 
/**
* An error that indicates that a response was already signed.
*
* @package OpenID
*/
class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
// This response is already signed.
}
 
/**
* An error that indicates that the given return_to is not under the
* given trust_root.
*
* @package OpenID
*/
class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
function Auth_OpenID_UntrustedReturnURL($return_to, $trust_root)
{
global $_Auth_OpenID_OpenID_Prefix;
 
$query = array(
$_Auth_OpenID_OpenID_Prefix . 'return_to' => $return_to,
$_Auth_OpenID_OpenID_Prefix . 'trust_root' => $trust_root);
 
parent::Auth_OpenID_ServerError($query);
}
 
function toString()
{
global $_Auth_OpenID_OpenID_Prefix;
 
$return_to = $this->query[$_Auth_OpenID_OpenID_Prefix . 'return_to'];
$trust_root = $this->query[$_Auth_OpenID_OpenID_Prefix . 'trust_root'];
 
return sprintf("return_to %s not under trust_root %s",
$return_to, $trust_root);
}
}
 
/**
* An object that implements the OpenID protocol for a single URL.
*
* Use this object by calling getOpenIDResponse when you get any
* request for the server URL.
*
* @package OpenID
*/
class Auth_OpenID_Server {
function Auth_OpenID_Server(&$store)
{
$this->store =& $store;
$this->signatory =& new Auth_OpenID_Signatory($this->store);
$this->encoder =& new Auth_OpenID_SigningEncoder($this->signatory);
$this->decoder =& new Auth_OpenID_Decoder();
}
 
/**
* Handle a request. Given an Auth_OpenID_Request object, call
* the appropriate Auth_OpenID_Server method to process the
* request and generate a response.
*
* @param Auth_OpenID_Request $request An Auth_OpenID_Request
* returned by Auth_OpenID_Server::decodeRequest.
*
* @return Auth_OpenID_Response $response A response object
* capable of generating a user-agent reply.
*/
function handleRequest($request)
{
if (method_exists($this, "openid_" . $request->mode)) {
$handler = array($this, "openid_" . $request->mode);
return call_user_func($handler, $request);
}
return null;
}
 
/**
* The callback for 'check_authentication' messages.
*
* @access private
*/
function openid_check_authentication(&$request)
{
return $request->answer($this->signatory);
}
 
/**
* The callback for 'associate' messages.
*
* @access private
*/
function openid_associate(&$request)
{
$assoc = $this->signatory->createAssociation(false);
return $request->answer($assoc);
}
 
/**
* Encodes as response in the appropriate format suitable for
* sending to the user agent.
*/
function encodeResponse(&$response)
{
return $this->encoder->encode($response);
}
 
/**
* Decodes a query args array into the appropriate
* Auth_OpenID_Request object.
*/
function decodeRequest(&$query)
{
return $this->decoder->decode($query);
}
}
 
?>
/tags/v1.2-autel/composants/openid/Auth/OpenID.php
New file
0,0 → 1,412
<?php
 
/**
* This is the PHP OpenID library by JanRain, Inc.
*
* This module contains core utility functionality used by the
* library. See Consumer.php and Server.php for the consumer and
* server implementations.
*
* PHP versions 4 and 5
*
* LICENSE: See the COPYING file included in this distribution.
*
* @package OpenID
* @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005 Janrain, Inc.
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*/
 
/**
* Require the fetcher code.
*/
require_once "Services/Yadis/PlainHTTPFetcher.php";
require_once "Services/Yadis/ParanoidHTTPFetcher.php";
require_once "Auth/OpenID/BigMath.php";
 
/**
* Status code returned by the server when the only option is to show
* an error page, since we do not have enough information to redirect
* back to the consumer. The associated value is an error message that
* should be displayed on an HTML error page.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_LOCAL_ERROR', 'local_error');
 
/**
* Status code returned when there is an error to return in key-value
* form to the consumer. The caller should return a 400 Bad Request
* response with content-type text/plain and the value as the body.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_REMOTE_ERROR', 'remote_error');
 
/**
* Status code returned when there is a key-value form OK response to
* the consumer. The value associated with this code is the
* response. The caller should return a 200 OK response with
* content-type text/plain and the value as the body.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_REMOTE_OK', 'remote_ok');
 
/**
* Status code returned when there is a redirect back to the
* consumer. The value is the URL to redirect back to. The caller
* should return a 302 Found redirect with a Location: header
* containing the URL.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_REDIRECT', 'redirect');
 
/**
* Status code returned when the caller needs to authenticate the
* user. The associated value is a {@link Auth_OpenID_ServerRequest}
* object that can be used to complete the authentication. If the user
* has taken some authentication action, use the retry() method of the
* {@link Auth_OpenID_ServerRequest} object to complete the request.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_DO_AUTH', 'do_auth');
 
/**
* Status code returned when there were no OpenID arguments
* passed. This code indicates that the caller should return a 200 OK
* response and display an HTML page that says that this is an OpenID
* server endpoint.
*
* @see Auth_OpenID_Server
*/
define('Auth_OpenID_DO_ABOUT', 'do_about');
 
/**
* Defines for regexes and format checking.
*/
define('Auth_OpenID_letters',
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
 
define('Auth_OpenID_digits',
"0123456789");
 
define('Auth_OpenID_punct',
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
 
if (Auth_OpenID_getMathLib() === null) {
define('Auth_OpenID_NO_MATH_SUPPORT', true);
}
 
/**
* The OpenID utility function class.
*
* @package OpenID
* @access private
*/
class Auth_OpenID {
 
/**
* These namespaces are automatically fixed in query arguments by
* Auth_OpenID::fixArgs.
*/
function getOpenIDNamespaces()
{
return array('openid',
'sreg');
}
 
/**
* Rename query arguments back to 'openid.' from 'openid_'
*
* @access private
* @param array $args An associative array of URL query arguments
*/
function fixArgs($args)
{
foreach (array_keys($args) as $key) {
$fixed = $key;
if (preg_match('/^openid/', $key)) {
foreach (Auth_OpenID::getOpenIDNamespaces() as $ns) {
if (preg_match('/'.$ns.'_/', $key)) {
$fixed = preg_replace('/'.$ns.'_/', $ns.'.', $fixed);
}
}
 
if ($fixed != $key) {
$val = $args[$key];
unset($args[$key]);
$args[$fixed] = $val;
}
}
}
 
return $args;
}
 
/**
* Create dir_name as a directory if it does not exist. If it
* exists, make sure that it is, in fact, a directory. Returns
* true if the operation succeeded; false if not.
*
* @access private
*/
function ensureDir($dir_name)
{
if (is_dir($dir_name) || @mkdir($dir_name)) {
return true;
} else {
if (Auth_OpenID::ensureDir(dirname($dir_name))) {
return is_dir($dir_name) || @mkdir($dir_name);
} else {
return false;
}
}
}
 
/**
* Convenience function for getting array values.
*
* @access private
*/
function arrayGet($arr, $key, $fallback = null)
{
if (is_array($arr)) {
if (array_key_exists($key, $arr)) {
return $arr[$key];
} else {
return $fallback;
}
} else {
trigger_error("Auth_OpenID::arrayGet expected " .
"array as first parameter", E_USER_WARNING);
return false;
}
}
 
/**
* Implements the PHP 5 'http_build_query' functionality.
*
* @access private
* @param array $data Either an array key/value pairs or an array
* of arrays, each of which holding two values: a key and a value,
* sequentially.
* @return string $result The result of url-encoding the key/value
* pairs from $data into a URL query string
* (e.g. "username=bob&id=56").
*/
function httpBuildQuery($data)
{
$pairs = array();
foreach ($data as $key => $value) {
if (is_array($value)) {
$pairs[] = urlencode($value[0])."=".urlencode($value[1]);
} else {
$pairs[] = urlencode($key)."=".urlencode($value);
}
}
return implode("&", $pairs);
}
 
/**
* "Appends" query arguments onto a URL. The URL may or may not
* already have arguments (following a question mark).
*
* @param string $url A URL, which may or may not already have
* arguments.
* @param array $args Either an array key/value pairs or an array of
* arrays, each of which holding two values: a key and a value,
* sequentially. If $args is an ordinary key/value array, the
* parameters will be added to the URL in sorted alphabetical order;
* if $args is an array of arrays, their order will be preserved.
* @return string $url The original URL with the new parameters added.
*
*/
function appendArgs($url, $args)
{
if (count($args) == 0) {
return $url;
}
 
// Non-empty array; if it is an array of arrays, use
// multisort; otherwise use sort.
if (array_key_exists(0, $args) &&
is_array($args[0])) {
// Do nothing here.
} else {
$keys = array_keys($args);
sort($keys);
$new_args = array();
foreach ($keys as $key) {
$new_args[] = array($key, $args[$key]);
}
$args = $new_args;
}
 
$sep = '?';
if (strpos($url, '?') !== false) {
$sep = '&';
}
 
return $url . $sep . Auth_OpenID::httpBuildQuery($args);
}
 
/**
* Turn a string into an ASCII string.
*
* Replace non-ascii characters with a %-encoded, UTF-8
* encoding. This function will fail if the input is a string and
* there are non-7-bit-safe characters. It is assumed that the
* caller will have already translated the input into a Unicode
* character sequence, according to the encoding of the HTTP POST
* or GET.
*
* Do not escape anything that is already 7-bit safe, so we do the
* minimal transform on the identity URL
*
* @access private
*/
function quoteMinimal($s)
{
$res = array();
for ($i = 0; $i < strlen($s); $i++) {
$c = $s[$i];
if ($c >= "\x80") {
for ($j = 0; $j < count(utf8_encode($c)); $j++) {
array_push($res, sprintf("%02X", ord($c[$j])));
}
} else {
array_push($res, $c);
}
}
return implode('', $res);
}
 
/**
* Implements python's urlunparse, which is not available in PHP.
* Given the specified components of a URL, this function rebuilds
* and returns the URL.
*
* @access private
* @param string $scheme The scheme (e.g. 'http'). Defaults to 'http'.
* @param string $host The host. Required.
* @param string $port The port.
* @param string $path The path.
* @param string $query The query.
* @param string $fragment The fragment.
* @return string $url The URL resulting from assembling the
* specified components.
*/
function urlunparse($scheme, $host, $port = null, $path = '/',
$query = '', $fragment = '')
{
 
if (!$scheme) {
$scheme = 'http';
}
 
if (!$host) {
return false;
}
 
if (!$path) {
$path = '/';
}
 
$result = $scheme . "://" . $host;
 
if ($port) {
$result .= ":" . $port;
}
 
$result .= $path;
 
if ($query) {
$result .= "?" . $query;
}
 
if ($fragment) {
$result .= "#" . $fragment;
}
 
return $result;
}
 
/**
* Given a URL, this "normalizes" it by adding a trailing slash
* and / or a leading http:// scheme where necessary. Returns
* null if the original URL is malformed and cannot be normalized.
*
* @access private
* @param string $url The URL to be normalized.
* @return mixed $new_url The URL after normalization, or null if
* $url was malformed.
*/
function normalizeUrl($url)
{
if ($url === null) {
return null;
}
 
assert(is_string($url));
 
$old_url = $url;
$url = trim($url);
 
if (strpos($url, "://") === false) {
$url = "http://" . $url;
}
 
$parsed = @parse_url($url);
 
if ($parsed === false) {
return null;
}
 
$defaults = array(
'scheme' => '',
'host' => '',
'path' => '',
'query' => '',
'fragment' => '',
'port' => ''
);
 
$parsed = array_merge($defaults, $parsed);
 
if (($parsed['scheme'] == '') ||
($parsed['host'] == '')) {
if ($parsed['path'] == '' &&
$parsed['query'] == '' &&
$parsed['fragment'] == '') {
return null;
}
 
$url = 'http://' + $url;
$parsed = parse_url($url);
 
$parsed = array_merge($defaults, $parsed);
}
 
$tail = array_map(array('Auth_OpenID', 'quoteMinimal'),
array($parsed['path'],
$parsed['query'],
$parsed['fragment']));
if ($tail[0] == '') {
$tail[0] = '/';
}
 
$url = Auth_OpenID::urlunparse($parsed['scheme'], $parsed['host'],
$parsed['port'], $tail[0], $tail[1],
$tail[2]);
 
assert(is_string($url));
 
return $url;
}
}
 
?>