Auth_HTTP-2.1.8/000075500000000000000000000000001220715273400132635ustar00rootroot00000000000000Auth_HTTP-2.1.8/Auth/000075500000000000000000000000001220715273400141645ustar00rootroot00000000000000Auth_HTTP-2.1.8/Auth/HTTP.php000064400000000000000000000576021220715273400154660ustar00rootroot00000000000000 | // | Rui Hirokawa | // | David Costa | // +----------------------------------------------------------------------+ // // $Id$ // require_once "Auth/Auth.php"; define('AUTH_HTTP_NONCE_TIME_LEN', 16); define('AUTH_HTTP_NONCE_HASH_LEN', 32); // {{{ class Auth_HTTP /** * PEAR::Auth_HTTP * * The PEAR::Auth_HTTP class provides methods for creating an * HTTP authentication system based on RFC-2617 using PHP. * * Instead of generating an HTML driven form like PEAR::Auth * does, this class sends header commands to the clients which * cause them to present a login box like they are e.g. used * in Apache's .htaccess mechanism. * * This class requires the PEAR::Auth package. * * @notes The HTTP Digest Authentication part is based on * authentication class written by Tom Pike * * @author Martin Jansen * @author Rui Hirokawa * @author David Costa * @package Auth_HTTP * @extends Auth * @version $Revision$ */ class Auth_HTTP extends Auth { // {{{ properties /** * Authorization method: 'basic' or 'digest' * * @access public * @var string */ var $authType = 'basic'; /** * Name of the realm for Basic Authentication * * @access public * @var string * @see drawLogin() */ var $realm = "protected area"; /** * Text to send if user hits cancel button * * @access public * @var string * @see drawLogin() */ var $CancelText = "Error 401 - Access denied"; /** * option array * * @access public * @var array */ var $options = array(); /** * flag to indicate the nonce was stale. * * @access public * @var bool */ var $stale = false; /** * opaque string for digest authentication * * @access public * @var string */ var $opaque = 'dummy'; /** * digest URI * * @access public * @var string */ var $uri = ''; /** * authorization info returned by the client * * @access public * @var array */ var $auth = array(); /** * next nonce value * * @access public * @var string */ var $nextNonce = ''; /** * nonce value * * @access public * @var string */ var $nonce = ''; /** * Holds a reference to the global server variable * @var array */ var $server; /** * Holds a reference to the global post variable * @var array */ var $post; /** * Holds a reference to the global cookie variable * @var array */ var $cookie; // }}} // {{{ Constructor /** * Constructor * * @param string Type of the storage driver * @param mixed Additional options for the storage driver * (example: if you are using DB as the storage * driver, you have to pass the dsn string here) * * @return void */ function Auth_HTTP($storageDriver, $options = '') { /* set default values for options */ $this->options = array('cryptType' => 'md5', 'algorithm' => 'MD5', 'qop' => 'auth-int,auth', 'opaquekey' => 'moo', 'noncekey' => 'moo', 'digestRealm' => 'protected area', 'forceDigestOnly' => false, 'nonceLife' => 300, 'sessionSharing' => false, ); if (!empty($options['authType'])) { $this->authType = strtolower($options['authType']); } if (is_array($options)) { foreach($options as $key => $value) { if (array_key_exists( $key, $this->options)) { $this->options[$key] = $value; } } if (!empty($this->options['opaquekey'])) { $this->opaque = md5($this->options['opaquekey']); } } $this->Auth($storageDriver, $options); } // }}} // {{{ assignData() /** * Assign values from $PHP_AUTH_USER and $PHP_AUTH_PW or 'Authorization' header * to internal variables and sets the session id based * on them * * @access public * @return void */ function assignData() { if (method_exists($this, '_importGlobalVariable')) { $this->server = &$this->_importGlobalVariable('server'); } if ($this->authType == 'basic') { if (!empty($this->server['PHP_AUTH_USER'])) { $this->username = $this->server['PHP_AUTH_USER']; } if (!empty($this->server['PHP_AUTH_PW'])) { $this->password = $this->server['PHP_AUTH_PW']; } /** * Try to get authentication information from IIS */ if (empty($this->username) && empty($this->password)) { if (!empty($this->server['HTTP_AUTHORIZATION'])) { list($this->username, $this->password) = explode(':', base64_decode(substr($this->server['HTTP_AUTHORIZATION'], 6))); } } } elseif ($this->authType == 'digest') { $this->username = ''; $this->password = ''; $this->digest_header = null; if (!empty($this->server['PHP_AUTH_DIGEST'])) { $this->digest_header = $this->server['PHP_AUTH_DIGEST']; $headers = getallheaders(); } else { $headers = getallheaders(); if(isset($headers['Authorization']) && !empty($headers['Authorization'])) { $this->digest_header = substr($headers['Authorization'], strpos($headers['Authorization'],' ')+1); } } if($this->digest_header) { $authtemp = explode(',', $this->digest_header); $auth = array(); foreach($authtemp as $key => $value) { $value = trim($value); if(strpos($value,'=') !== false) { $lhs = substr($value,0,strpos($value,'=')); $rhs = substr($value,strpos($value,'=')+1); if(substr($rhs,0,1) == '"' && substr($rhs,-1,1) == '"') { $rhs = substr($rhs,1,-1); } $auth[$lhs] = $rhs; } } } if (!isset($auth['uri']) || !isset($auth['realm'])) { return; } if ($this->selfURI() == $auth['uri']) { $this->uri = $auth['uri']; if (substr($headers['Authorization'],0,7) == 'Digest ') { $this->authType = 'digest'; if (!isset($auth['nonce']) || !isset($auth['username']) || !isset($auth['response']) || !isset($auth['qop']) || !isset($auth['nc']) || !isset($auth['cnonce'])){ return; } if ($auth['qop'] != 'auth' && $auth['qop'] != 'auth-int') { return; } $this->stale = $this->_judgeStale($auth['nonce']); if ($this->nextNonce == false) { return; } $this->username = $auth['username']; $this->password = $auth['response']; $this->auth['nonce'] = $auth['nonce']; $this->auth['qop'] = $auth['qop']; $this->auth['nc'] = $auth['nc']; $this->auth['cnonce'] = $auth['cnonce']; if (isset($auth['opaque'])) { $this->auth['opaque'] = $auth['opaque']; } } elseif (substr($headers['Authorization'],0,6) == 'Basic ') { if ($this->options['forceDigestOnly']) { return; // Basic authentication is not allowed. } $this->authType = 'basic'; list($username, $password) = explode(':',base64_decode(substr($headers['Authorization'],6))); $this->username = $username; $this->password = $password; } } } else { include_once 'PEAR.php'; return PEAR::throwError('authType is invalid.'); } if ($this->options['sessionSharing'] && isset($this->username) && isset($this->password)) { session_id(md5('Auth_HTTP' . $this->username . $this->password)); } /** * set sessionName for AUTH, so that the sessionName is different * for distinct realms */ $this->_sessionName = "_authhttp".md5($this->realm); } // }}} // {{{ login() /** * Login function * * @access private * @return void */ function login() { $login_ok = false; if (method_exists($this, '_loadStorage')) { $this->_loadStorage(); } $this->storage->_auth_obj->_sessionName =& $this->_sessionName; /** * When the user has already entered a username, * we have to validate it. */ if (!empty($this->username) && !empty($this->password)) { if ($this->authType == 'basic' && !$this->options['forceDigestOnly']) { if (true === $this->storage->fetchData($this->username, $this->password)) { $login_ok = true; } } else { /* digest authentication */ if (!$this->getAuth() || $this->getAuthData('a1') == null) { /* * note: * - only PEAR::DB is supported as container. * - password should be stored in container as plain-text * (if $options['cryptType'] == 'none') or * A1 hashed form (md5('username:realm:password')) * (if $options['cryptType'] == 'md5') */ $dbs = $this->storage; if (!DB::isConnection($dbs->db)) { $dbs->_connect($dbs->options['dsn']); } $query = 'SELECT '.$dbs->options['passwordcol']." FROM ".$dbs->options['table']. ' WHERE '.$dbs->options['usernamecol']." = '". $dbs->db->quoteString($this->username)."' "; $pwd = $dbs->db->getOne($query); // password stored in container. if (DB::isError($pwd)) { include_once 'PEAR.php'; return PEAR::throwError($pwd->getMessage(), $pwd->getCode()); } if ($this->options['cryptType'] == 'none') { $a1 = md5($this->username.':'.$this->options['digestRealm'].':'.$pwd); } else { $a1 = $pwd; } $this->setAuthData('a1', $a1, true); } else { $a1 = $this->getAuthData('a1'); } $login_ok = $this->validateDigest($this->password, $a1); if ($this->nextNonce == false) { $login_ok = false; } } if (!$login_ok && is_callable($this->loginFailedCallback)) { call_user_func($this->loginFailedCallback,$this->username, $this); } } if (!empty($this->username) && $login_ok) { $this->setAuth($this->username); if (is_callable($this->loginCallback)) { call_user_func($this->loginCallback,$this->username, $this); } } /** * If the login failed or the user entered no username, * output the login screen again. */ if (!empty($this->username) && !$login_ok) { $this->status = AUTH_WRONG_LOGIN; } if ((empty($this->username) || !$login_ok) && $this->showLogin) { $this->drawLogin($this->storage->activeUser); return; } if (!empty($this->username) && $login_ok && $this->authType == 'digest' && $this->auth['qop'] == 'auth') { $this->authenticationInfo(); } } // }}} // {{{ drawLogin() /** * Launch the login box * * @param string $username Username * @return void * @access private */ function drawLogin($username = "") { /** * Send the header commands */ if ($this->authType == 'basic') { header("WWW-Authenticate: Basic realm=\"".$this->realm."\""); header('HTTP/1.0 401 Unauthorized'); } else if ($this->authType == 'digest') { $this->nonce = $this->_getNonce(); $wwwauth = 'WWW-Authenticate: Digest '; $wwwauth .= 'qop="'.$this->options['qop'].'", '; $wwwauth .= 'algorithm='.$this->options['algorithm'].', '; $wwwauth .= 'realm="'.$this->options['digestRealm'].'", '; $wwwauth .= 'nonce="'.$this->nonce.'", '; if ($this->stale) { $wwwauth .= 'stale=true, '; } if (!empty($this->opaque)) { $wwwauth .= 'opaque="'.$this->opaque.'"' ; } $wwwauth .= "\r\n"; if (!$this->options['forceDigestOnly']) { $wwwauth .= 'WWW-Authenticate: Basic realm="'.$this->realm.'"'; } header($wwwauth); header('HTTP/1.0 401 Unauthorized'); } /** * This code is only executed if the user hits the cancel * button or if he enters wrong data 3 times. */ if ($this->stale) { echo 'Stale nonce value, please re-authenticate.'; } else { echo $this->CancelText; } exit; } // }}} // {{{ setRealm() /** * Set name of the current realm * * @access public * @param string $realm Name of the realm * @param string $digestRealm Name of the realm for digest authentication * @return void */ function setRealm($realm, $digestRealm = '') { $this->realm = $realm; if (!empty($digestRealm)) { $this->options['digestRealm'] = $digestRealm; } } // }}} // {{{ setCancelText() /** * Set the text to send if user hits the cancel button * * @access public * @param string $text Text to send * @return void */ function setCancelText($text) { $this->CancelText = $text; } // }}} // {{{ validateDigest() /** * judge if the client response is valid. * * @access private * @param string $response client response * @param string $a1 password or hashed password stored in container * @return bool true if success, false otherwise */ function validateDigest($response, $a1) { if (method_exists($this, '_importGlobalVariable')) { $this->server = &$this->_importGlobalVariable('server'); } $a2unhashed = $this->server['REQUEST_METHOD'].":".$this->selfURI(); if($this->auth['qop'] == 'auth-int') { if(isset($GLOBALS["HTTP_RAW_POST_DATA"])) { // In PHP < 4.3 get raw POST data from this variable $body = $GLOBALS["HTTP_RAW_POST_DATA"]; } else if($lines = @file('php://input')) { // In PHP >= 4.3 get raw POST data from this file $body = implode("\n", $lines); } else { if (method_exists($this, '_importGlobalVariable')) { $this->post = &$this->_importGlobalVariable('post'); } $body = ''; foreach($this->post as $key => $value) { if($body != '') $body .= '&'; $body .= rawurlencode($key) . '=' . rawurlencode($value); } } $a2unhashed .= ':'.md5($body); } $a2 = md5($a2unhashed); $combined = $a1.':'. $this->auth['nonce'].':'. $this->auth['nc'].':'. $this->auth['cnonce'].':'. $this->auth['qop'].':'. $a2; $expectedResponse = md5($combined); if(!isset($this->auth['opaque']) || $this->auth['opaque'] == $this->opaque) { if($response == $expectedResponse) { // password is valid if(!$this->stale) { return true; } else { $this->drawLogin(); } } } return false; } // }}} // {{{ _judgeStale() /** * judge if nonce from client is stale. * * @access private * @param string $nonce nonce value from client * @return bool stale */ function _judgeStale($nonce) { $stale = false; if(!$this->_decodeNonce($nonce, $time, $hash_cli)) { $this->nextNonce = false; $stale = true; return $stale; } if ($time < time() - $this->options['nonceLife']) { $this->nextNonce = $this->_getNonce(); $stale = true; } else { $this->nextNonce = $nonce; } return $stale; } // }}} // {{{ _nonceDecode() /** * decode nonce string * * @access private * @param string $nonce nonce value from client * @param string $time decoded time * @param string $hash decoded hash * @return bool false if nonce is invalid */ function _decodeNonce($nonce, &$time, &$hash) { if (method_exists($this, '_importGlobalVariable')) { $this->server = &$this->_importGlobalVariable('server'); } if (strlen($nonce) != AUTH_HTTP_NONCE_TIME_LEN + AUTH_HTTP_NONCE_HASH_LEN) { return false; } $time = base64_decode(substr($nonce, 0, AUTH_HTTP_NONCE_TIME_LEN)); $hash_cli = substr($nonce, AUTH_HTTP_NONCE_TIME_LEN, AUTH_HTTP_NONCE_HASH_LEN); $hash = md5($time . $this->server['HTTP_USER_AGENT'] . $this->options['noncekey']); if ($hash_cli != $hash) { return false; } return true; } // }}} // {{{ _getNonce() /** * return nonce to detect timeout * * @access private * @return string nonce value */ function _getNonce() { if (method_exists($this, '_importGlobalVariable')) { $this->server = &$this->_importGlobalVariable('server'); } $time = time(); $hash = md5($time . $this->server['HTTP_USER_AGENT'] . $this->options['noncekey']); return base64_encode($time) . $hash; } // }}} // {{{ authenticationInfo() /** * output HTTP Authentication-Info header * * @notes md5 hash of contents is required if 'qop' is 'auth-int' * * @access private * @param string MD5 hash of content */ function authenticationInfo($contentMD5 = '') { if($this->getAuth() && ($this->getAuthData('a1') != null)) { $a1 = $this->getAuthData('a1'); // Work out authorisation response $a2unhashed = ":".$this->selfURI(); if($this->auth['qop'] == 'auth-int') { $a2unhashed .= ':'.$contentMD5; } $a2 = md5($a2unhashed); $combined = $a1.':'. $this->nonce.':'. $this->auth['nc'].':'. $this->auth['cnonce'].':'. $this->auth['qop'].':'. $a2; // Send authentication info $wwwauth = 'Authentication-Info: '; if($this->nonce != $this->nextNonce) { $wwwauth .= 'nextnonce="'.$this->nextNonce.'", '; } $wwwauth .= 'qop='.$this->auth['qop'].', '; $wwwauth .= 'rspauth="'.md5($combined).'", '; $wwwauth .= 'cnonce="'.$this->auth['cnonce'].'", '; $wwwauth .= 'nc='.$this->auth['nc'].''; header($wwwauth); } } // }}} // {{{ setOption() /** * set authentication option * * @access public * @param mixed $name key of option * @param mixed $value value of option * @return void */ function setOption($name, $value = null) { if (is_array($name)) { foreach($name as $key => $value) { if (array_key_exists( $key, $this->options)) { $this->options[$key] = $value; } } } else { if (array_key_exists( $name, $this->options)) { $this->options[$name] = $value; } } } // }}} // {{{ getOption() /** * get authentication option * * @access public * @param string $name key of option * @return mixed option value */ function getOption($name) { if (array_key_exists( $name, $this->options)) { return $this->options[$name]; } if ($name == 'CancelText') { return $this->CancelText; } if ($name == 'Realm') { return $this->realm; } return false; } // }}} // {{{ selfURI() /** * get self URI * * @access public * @return string self URI */ function selfURI() { if (method_exists($this, '_importGlobalVariable')) { $this->server = &$this->_importGlobalVariable('server'); } if (preg_match("/MSIE/",$this->server['HTTP_USER_AGENT'])) { // query string should be removed for MSIE $uri = preg_replace("/^(.*)\?/","\\1",$this->server['REQUEST_URI']); } else { $uri = $this->server['REQUEST_URI']; } return $uri; } // }}} } // }}} /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?> Auth_HTTP-2.1.8/README000064400000000000000000000010201220715273400141340ustar00rootroot00000000000000This package is http://pear.php.net/package/Auth_HTTP and has been migrated from https://svn.php.net/repository/pear/packages/Auth_HTTP Please report all new issues via the PEAR bug tracker. If this package is marked as unmaintained and you have fixes, please submit your pull requests and start discussion on the pear-qa mailing list. To test, run either $ phpunit tests/ or $ pear run-tests -r To build, simply $ pear package To install from scratch $ pear install package.xml To upgrade $ pear upgrade -f package.xml Auth_HTTP-2.1.8/docs/000075500000000000000000000000001220715273400142135ustar00rootroot00000000000000Auth_HTTP-2.1.8/docs/sample.sql000064400000000000000000000013321220715273400162140ustar00rootroot00000000000000-- SQLite schema for permission administration -- usage: sqlite /tmp/user.db < sample.sql CREATE TABLE auth ( username VARCHAR(50) NOT NULL, -- username password VARCHAR(50) NOT NULL -- password ); -- plain password --INSERT INTO auth VALUES ('taro','secret'); --INSERT INTO auth VALUES ('jiro','secret'); -- md5 hash password: secret --INSERT INTO auth VALUES ('taro','5ebe2294ecd0e0f08eab7690d2a6ee69'); --INSERT INTO auth VALUES ('jiro','5ebe2294ecd0e0f08eab7690d2a6ee69'); -- a1 (md5(username:realm:password)) for http digest authentication -- realm: sample, password: secret INSERT INTO auth VALUES ('taro','d0f7c5ba4f2f2ed16f2a714332633ad5'); INSERT INTO auth VALUES ('jiro','d41438d297ee671f2249cc0d6c1f3997'); Auth_HTTP-2.1.8/docs/test_basic_simple.php000064400000000000000000000011161220715273400204140ustar00rootroot00000000000000DSN); $auth = new Auth_HTTP("DB", $options); $auth->setRealm('dummy', 'sample'); $auth->start(); ?> HTTP Basic authentication test for simple case authType."
"; print "username: ".$auth->username."
"; print "password: ".$auth->password."
"; print "auth: ".print_r($auth->auth)."
"; if($auth->getAuth()) { print "authentication is succeeded.
"; } ?> Auth_HTTP-2.1.8/docs/test_digest_get.php000064400000000000000000000014141220715273400201010ustar00rootroot00000000000000DSN, 'authType'=>'digest'); $auth = new Auth_HTTP("DB", $options); $auth->setRealm('dummy', 'sample'); $auth->start(); ?> HTTP digest authentication for GET method authMethod."
"; print "username: ".$auth->username."
"; print "password: ".$auth->password."
"; print "auth: ".print_r($auth->auth)."
"; if($auth->getAuth()) { print << EOS; } if (!empty($_POST['title'])) {echo 'Title: '.$_POST['title'];} ?> Auth_HTTP-2.1.8/docs/test_digest_post.php000064400000000000000000000013331220715273400203070ustar00rootroot00000000000000DSN, 'authType'=>'digest'); $auth = new Auth_HTTP("DB", $options); $auth->setRealm('dummy', 'sample'); $auth->start(); ?> HTTP digest authentication for POST method getAuth()) { print << EOS; } if (!empty($_POST['title'])) {echo 'POST:Title: '.$_POST['title'].'
';} if (!empty($_GET['foo'])) {echo 'GET:foo: '.$_GET['foo'].'
';} print "METHOD: ".$_SERVER['REQUEST_METHOD']."
"; ?> Auth_HTTP-2.1.8/docs/test_digest_simple.php000064400000000000000000000011451220715273400206140ustar00rootroot00000000000000DSN, 'authType'=>'digest'); $auth = new Auth_HTTP("DB", $options); $auth->setRealm('dummy', 'sample'); $auth->start(); ?> HTTP digest authentication test for simple case authType."
"; print "username: ".$auth->username."
"; print "password: ".$auth->password."
"; print "auth: ".print_r($auth->auth)."
"; if($auth->getAuth()) { print "authentication is succeeded.
"; } ?> package.xml000064400000000000000000000162031220715273400131760ustar00rootroot00000000000000 Auth_HTTP pear.php.net HTTP authentication The PEAR::Auth_HTTP class provides methods for creating an HTTP authentication system using PHP, that is similar to Apache's realm-based .htaccess authentication. David Costa gurugeek gurugeek@php.net yes Rui Hirokawa hirokawa hirokawa@php.net yes 2012-01-28 2.1.8 2.1.8 stable stable PHP License Updated the version of PHP licence from 2.0.2 to 3.0.1. 4.0.0 1.4.0b1 Auth pear.php.net 1.2.0 1.0 1.0 stable stable 2001-08-23 PHP License This is the initial independent release of the Auth_HTTP package. 2.0 2.0 stable stable 2003-10-16 PHP License Starting with this release, the code will not be placed in Auth_HTTP/Auth_HTTP.php anymore. Instead Auth/HTTP.php is used, which conforms to the PEAR standards. In order to make use of the new version, you will need to change your scripts to include the file at the new location! The old version in Auth_HTTP/Auth_HTTP.php will not be removed when upgrading. Other changes: * If it is possible, the session ID will be chosen based on the user's authentication credentials. (Patch by: Marko Karppinen) * Cleaned up internal variable usage. (Patch by: Brad Bulger) 2.1.0 2.1.0 beta beta 2004-05-30 PHP License - Added _sessionName which fixes a major issue with realm sharing. - Added sessionSharing option to use unique session id. Currently, this option is set to true by default to maintain backward compatibility. - Added setOption and getOption to set/get option value. - Starting with this release, HTTP Digest Authentication (RFC2617) is experimentally supported. The code for HTTP Digest Authentication is originally developed by Tom Pike. 2.1.1 2.1.1 beta beta 2004-07-12 PHP License - Fixed a bug #1634 (URI parameter was handled incorrectry.) 2.1.3rc1 2.1.3rc1 beta beta 2004-08-22 PHP License - Fixed a bug #2061 (importglobalvariable() was removed in Auth 1.3.0r2.) - now Auth_HTTP requires Auth >= 1.3.0r2. 2.1.4 2.1.4 stable stable 2005-01-02 PHP License - Fixed a bug #2380: constructor couldn't handle non-array option. - The first stable release with HTTP Digest Authenthication support. 2.1.5 2.1.5 stable stable 2005-04-02 PHP License - Fixed a bug #3630 getAuthData failes due to session rename. 2.1.6RC1 2.1.6RC1 beta beta 2005-04-11 PHP License - Fixed bug #4047. - Fixed backward compatibility with PHP 4.x - Added PHP_AUTH_DIGEST support. 2.1.7 2.1.7 stable stable 2012-01-26 PHP License QA release Bug #7536 Package PEAR never included Doc Bug #7655 Suggested Adjustments to Documentation Bug #7784 Auth::start() changes session id Bug #16742 Please move tests/ to docs/ 2.1.8 2.1.8 stable stable 2012-01-29 PHP License Updated the version of PHP licence from 2.0.2 to 3.0.1.