| 1 |
<?php |
| 2 |
/** |
| 3 |
* DooDigestAuth class file. |
| 4 |
* |
| 5 |
* @author Leng Sheng Hong <darkredz@gmail.com> |
| 6 |
* @link http://www.doophp.com/ |
| 7 |
* @copyright Copyright © 2009 Leng Sheng Hong |
| 8 |
* @license http://www.doophp.com/license |
| 9 |
*/ |
| 10 |
|
| 11 |
/** |
| 12 |
* Handles HTTP digest authentication |
| 13 |
* |
| 14 |
* <p>HTTP digest authentication can be used with the URI router. |
| 15 |
* HTTP digest is much more recommended over the use of HTTP Basic auth which doesn't provide any encryption. |
| 16 |
* If you are running PHP on Apache in CGI/FastCGI mode, you would need to |
| 17 |
* add the following line to your .htaccess for digest auth to work correctly.</p> |
| 18 |
* <code>RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]</code> |
| 19 |
* |
| 20 |
* <p>This class is tested under Apache 2.2 and Cherokee web server. It should work in both mod_php and cgi mode.</p> |
| 21 |
* |
| 22 |
* @author Leng Sheng Hong <darkredz@gmail.com> |
| 23 |
* @version $Id: DooDigestAuth.php 1000 2009-07-7 18:27:22 |
| 24 |
* @package doo.auth |
| 25 |
* @since 1.0 |
| 26 |
* |
| 27 |
* @deprecated 2.3 This will be removed in Minify 3.0 |
| 28 |
*/ |
| 29 |
class DooDigestAuth{ |
| 30 |
|
| 31 |
/** |
| 32 |
* Authenticate against a list of username and passwords. |
| 33 |
* |
| 34 |
* <p>HTTP Digest Authentication doesn't work with PHP in CGI mode, |
| 35 |
* you have to add this into your .htaccess <code>RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]</code></p> |
| 36 |
* |
| 37 |
* @param string $realm Name of the authentication session |
| 38 |
* @param array $users An assoc array of username and password: array('uname1'=>'pwd1', 'uname2'=>'pwd2') |
| 39 |
* @param string $fail_msg Message to be displayed if the User cancel the login |
| 40 |
* @param string $fail_url URL to be redirect if the User cancel the login |
| 41 |
* @return string The username if login success. |
| 42 |
*/ |
| 43 |
public static function http_auth($realm, $users, $fail_msg=NULL, $fail_url=NULL){ |
| 44 |
$realm = "Restricted area - $realm"; |
| 45 |
|
| 46 |
//user => password |
| 47 |
//$users = array('admin' => '1234', 'guest' => 'guest'); |
| 48 |
if(!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && strpos($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 'Digest')===0){ |
| 49 |
$_SERVER['PHP_AUTH_DIGEST'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; |
| 50 |
} |
| 51 |
|
| 52 |
if (empty($_SERVER['PHP_AUTH_DIGEST'])) { |
| 53 |
header('WWW-Authenticate: Digest realm="'.$realm. |
| 54 |
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); |
| 55 |
header('HTTP/1.1 401 Unauthorized'); |
| 56 |
if($fail_msg!=NULL) |
| 57 |
die($fail_msg); |
| 58 |
if($fail_url!=NULL) |
| 59 |
die("<script>window.location.href = '$fail_url'</script>"); |
| 60 |
exit; |
| 61 |
} |
| 62 |
|
| 63 |
// analyze the PHP_AUTH_DIGEST variable |
| 64 |
if (!($data = self::http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || !isset($users[$data['username']])){ |
| 65 |
header('WWW-Authenticate: Digest realm="'.$realm. |
| 66 |
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); |
| 67 |
header('HTTP/1.1 401 Unauthorized'); |
| 68 |
if($fail_msg!=NULL) |
| 69 |
die($fail_msg); |
| 70 |
if($fail_url!=NULL) |
| 71 |
die("<script>window.location.href = '$fail_url'</script>"); |
| 72 |
exit; |
| 73 |
} |
| 74 |
|
| 75 |
// generate the valid response |
| 76 |
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]); |
| 77 |
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']); |
| 78 |
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2); |
| 79 |
|
| 80 |
if ($data['response'] != $valid_response){ |
| 81 |
header('HTTP/1.1 401 Unauthorized'); |
| 82 |
header('WWW-Authenticate: Digest realm="'.$realm. |
| 83 |
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); |
| 84 |
if($fail_msg!=NULL) |
| 85 |
die($fail_msg); |
| 86 |
if($fail_url!=NULL) |
| 87 |
die("<script>window.location.href = '$fail_url'</script>"); |
| 88 |
exit; |
| 89 |
} |
| 90 |
|
| 91 |
// ok, valid username & password |
| 92 |
return $data['username']; |
| 93 |
} |
| 94 |
|
| 95 |
/** |
| 96 |
* Method to parse the http auth header, works with IE. |
| 97 |
* |
| 98 |
* Internet Explorer returns a qop="xxxxxxxxxxx" in the header instead of qop=xxxxxxxxxxx as most browsers do. |
| 99 |
* |
| 100 |
* @param string $txt header string to parse |
| 101 |
* @return array An assoc array of the digest auth session |
| 102 |
*/ |
| 103 |
private static function http_digest_parse($txt) |
| 104 |
{ |
| 105 |
$res = preg_match("/username=\"([^\"]+)\"/i", $txt, $match); |
| 106 |
$data['username'] = (isset($match[1]))?$match[1]:null; |
| 107 |
$res = preg_match('/nonce=\"([^\"]+)\"/i', $txt, $match); |
| 108 |
$data['nonce'] = $match[1]; |
| 109 |
$res = preg_match('/nc=([0-9]+)/i', $txt, $match); |
| 110 |
$data['nc'] = $match[1]; |
| 111 |
$res = preg_match('/cnonce=\"([^\"]+)\"/i', $txt, $match); |
| 112 |
$data['cnonce'] = $match[1]; |
| 113 |
$res = preg_match('/qop=([^,]+)/i', $txt, $match); |
| 114 |
$data['qop'] = str_replace('"','',$match[1]); |
| 115 |
$res = preg_match('/uri=\"([^\"]+)\"/i', $txt, $match); |
| 116 |
$data['uri'] = $match[1]; |
| 117 |
$res = preg_match('/response=\"([^\"]+)\"/i', $txt, $match); |
| 118 |
$data['response'] = $match[1]; |
| 119 |
return $data; |
| 120 |
} |
| 121 |
|
| 122 |
|
| 123 |
} |
| 124 |
|