-
/*
-
orginal script @ http://www.peej.co.uk/projects/phphttpdigest.html
-
Copyright (c) 2005 Paul James
-
All rights reserved.
-
Redistribution and use in source and binary forms, with or without
-
modification, are permitted provided that the following conditions
-
are met:
-
1. Redistributions of source code must retain the above copyright
-
notice, this list of conditions and the following disclaimer.
-
2. Redistributions in binary form must reproduce the above copyright
-
notice, this list of conditions and the following disclaimer in the
-
documentation and/or other materials provided with the distribution.
-
3. Neither the name of the Paul James nor the names of its contributors
-
may be used to endorse or promote products derived from this software
-
without specific prior written permission.
-
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-
SUCH DAMAGE.
-
*/
-
-
/** HTTP Digest authentication class modified by macosbrain*/
-
class HTTPDigest
-
{
-
/** The Digest opaque value (any string will do, never sent in plain text over the wire).
-
* @var str
-
*/
-
var $opaque = 'enter a random string';
-
/** The authentication realm name.
-
* @var str
-
*/
-
var $realm = 'please login';
-
/**
-
* flag to indicate the nonce was stale.
-
*
-
* @var bool
-
*/
-
var $stale = false;
-
/** The base URL of the application, auth data will be used for all resources under this URL.
-
* @var str
-
*/
-
var $baseURL = '/';
-
/** Are passwords stored as an a1 hash (username:realm:password) rather than plain text.
-
* @var str
-
*/
-
var $passwordsHashed = true;
-
/** The private key.
-
* @var str
-
*/
-
var $privateKey = 'please choose one';
-
/** The life of the nonce value in seconds
-
* @var int
-
*/
-
var $nonceLife = 30;// the $stale option allows us to set the $nonceLife very low
-
-
function HTTPDigest()
-
{
-
$this->unique = $_SERVER['SERVER_SOFTWARE'].$_SERVER['HTTP_HOST'].$_SERVER['SERVER_NAME'];//not a static value
-
}
-
-
function error()
-
{
-
header('HTTP/1.1 401 Unauthorized');
-
die('User authentication is required. You must enter a valid login ID and password to access this resource or have to disable your proxy-server.');
-
}
-
/** Send HTTP Auth header */
-
function send()
-
{
-
$str = 'WWW-Authenticate: Digest '.
-
'realm="'.$this->realm.'", '.
-
'domain="'.$this->baseURL.'", '.
-
'qop=auth, '.
-
'algorithm=MD5, '.
-
'nonce="'.$this->getNonce().'", '.
-
'opaque="'.$this->getOpaque().'"';
-
if ($this->stale) {
-
$str .= ', stale=true';
-
}
-
-
header('HTTP/1.0 401 Unauthorized');
-
-
}
-
/** Get the HTTP Auth header
-
* @return str
-
*/
-
function add_user($username,$password,$hash_it=false)
-
{
-
if ($hash_it==true)
-
$a1 = $this->crypt_pass($username,$password);
-
else
-
$a1 = $password;
-
$this->user[$username] = $a1;
-
}
-
-
function crypt_pass($user,$pass)
-
{
-
return md5($user.
':'.
$this->
getRealm().
':'.
$pass);
-
}
-
-
function getAuthHeader()
-
{
-
if (isset($_SERVER['Authorization']))
-
{
-
return $_SERVER['Authorization'];
-
}
-
-
{
-
-
if (isset($headers['Authorization']))
-
return $headers['Authorization'];
-
}
-
return NULL;
-
}
-
/** Authenticate the user and return username on success.
-
* @param str[] users Array of username/password pairs
-
* @return str
-
*/
-
function authenticate()
-
{
-
$authorization = $this->getAuthHeader();
-
if (!$authorization)
-
{
-
$this->send();
-
//die('HTTP Digest headers not being passed to PHP by the server, unable to authenticate user');
-
}
-
if (substr($authorization,
0,
5) ==
'Basic')
-
die('You are trying to use HTTP Basic authentication but I am expecting HTTP Digest');
-
if (preg_match('/username="([^"]+)"/',
$authorization,
$username) &&
preg_match('/nonce="([^"]+)"/',
$authorization,
$nonce) &&
preg_match('/response="([^"]+)"/',
$authorization,
$response) &&
preg_match('/opaque="([^"]+)"/',
$authorization,
$opaque) &&
preg_match('/uri="([^"]+)"/',
$authorization,
$uri))
-
{
-
$username = $username[1];
-
$requestURI = $_SERVER['REQUEST_URI'];
-
if (strpos($requestURI,
'?') !==
FALSE)
-
{ // hack for IE which does not pass querystring in URI element of Digest string or in response hash
-
-
}
-
if ( isset($this->
user[$username]) &&
$opaque[1] ==
$this->
getOpaque() &&
$uri[1] ==
$requestURI)
-
{
-
if($nonce[1] != $this->getNonce())
-
{
-
$this->stale = true;
-
$this->send();
-
}
-
$passphrase = $this->user[$username];
-
if ($this->passwordsHashed)
-
$a1 = $passphrase;
-
else
-
$a1 = $this->crypt_pass($username,$passphrase);
-
-
$a2 =
md5($_SERVER['REQUEST_METHOD'].
':'.
$requestURI);
-
if (preg_match('/qop="?([^,\s"]+)/',
$authorization,
$qop) &&
preg_match('/nc=([^,\s"]+)/',
$authorization,
$nc) &&
preg_match('/cnonce="([^"]+)"/',
$authorization,
$cnonce))
-
$expectedResponse =
md5($a1.
':'.
$nonce[1].
':'.
$nc[1].
':'.
$cnonce[1].
':'.
$qop[1].
':'.
$a2);
-
else
-
$expectedResponse =
md5($a1.
':'.
$nonce[1].
':'.
$a2);
-
if ($response[1] == $expectedResponse)
-
{
-
$this->logged_in_user = $username;
-
return TRUE;
-
}
-
}
-
else
-
$this->send();
-
}
-
return NULL;
-
}
-
/** Get nonce value for HTTP Digest.
-
* @return str
-
*/
-
function getNonce() {
-
$time =
ceil(time() /
$this->
nonceLife) *
$this->
nonceLife;
-
$nonce =
date('Y-m-d H:i',
$time).
':'.
$_SERVER['REMOTE_ADDR'].
':'.
$this->
privateKey.
':'.
$_SERVER['HTTP_USER_AGENT'].
$this->
unique;
-
-
}
-
/** Get opaque value for HTTP Digest.
-
* @return str
-
*/
-
function getOpaque()
-
{
-
return md5($this->
opaque.
$this->
unique);
-
}
-
/** Get realm for HTTP Digest taking PHP safe mode into account.
-
* @return str
-
*/
-
function getRealm()
-
{
-
-
-
} else {
-
return $this->realm;
-
}
-
}
-
}