1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
| /** HTTP Digest authentication class */
class HTTPDigest
{
//The Digest opaque value (any string will do, never sent in plain text over the wire).
var $opaque = 'opaque-baznat';
// The authentication realm name.
var $realm = 'Baznat-Web';
// The base URL of the application, auth data will be used for all resources under this URL.
function baseURL() {
global $g_mode_local;
if ($g_mode_local) {
return "/";
}
return "/php/"; // autrement dit: www.baznat.net/php/
}
// Are passwords stored as an a1 hash (username:realm:password) rather than plain text.
// The private key.
var $privateKey = 'sdfgljhsdglzqerbhbezy';
// The life of the nonce value in seconds
var $nonceLife = 10800; /* 60 secondes*60 minutes*3 == 3 heures */
var $username;
function getNonce() {
$time = ceil(time() / $this->nonceLife) * $this->nonceLife;
return md5(date('Y-m-d H:i', $time).':'.$_SERVER['REMOTE_ADDR'].':'.$this->privateKey);
}
function getOpaque() {
return md5($this->opaque);
}
function getRealm() {
return $this->realm;
}
function getAuthHeader() {
/* header "Authorization" transféré via le .htaccess */
return $_SERVER['REMOTE_USER'];
}
function getEncPAssword($u, $p) {
return md5($u.':'.$this->getRealm().':'.$p);
}
function send() {
header('HTTP/1.0 401 Unauthorized');
header('WWW-Authenticate: Digest '.
'realm="'.$this->realm.'", '.
'domain="'.$this->baseURL().'", '.
'qop=auth, '.
'algorithm=MD5, '.
'nonce="'.$this->getNonce().'", '.
'opaque="'.$this->getOpaque().(time() + 10500).'"'
); // au bout de 60 secondes * 60 minutes * 3 heure - 5 minutes d'inactivité, l'identification est re-demandée
}
function authenticate($users, &$last_possible, &$given_name) {
global $g_mode_local;
$last_possible = 0;
$given_name = false;
$authorization = $this->getAuthHeader();
if ($authorization) {
if (substr($authorization, 0, 5) == 'Basic') {
errlog(__FILE__, __LINE__, "l'utilisateur tente une authentification HTTP basic, HTTP Digest attendu", false);
exit;
}
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) ) {
$given_name = $username = $username[1];
if ($g_mode_local && strcmp(strtolower($_SERVER['SERVER_NAME']), "localhost") == 0) {
// !!! ATTENTION ceci desactive la verification du mot de passe en mode local !!!
$last_possible = substr($opaque[1], $l = strlen($this->getOpaque()));
$users->get_password_hash($username);
return $username;
}
$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
$requestURI = substr($requestURI, 0, strlen($uri[1]));
}
if (!est_un_login($username)) {
errlog(__FILE__, __LINE__, "Login mal formé: ABANDON", false);
return NULL;
}
$passphrase = $users->get_password_hash($username);
$last_possible = substr($opaque[1], $l = strlen($this->getOpaque()));
$opaque = substr($opaque[1], 0, $l);
if (isset($passphrase) &&
$opaque == $this->getOpaque() &&
$uri[1] == $requestURI &&
$nonce[1] == $this->getNonce() ) {
$a1 = $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) {
return $username;
}
else {
errlog(__FILE__, __LINE__, "mauvais mot de passe pour $given_name", false);
}
}
else if ($nonce[1] != $this->getNonce()) {
errlog(__FILE__, __LINE__, "Nonce invalide, serveur = ".$this->getNonce()." != {$nonce[1]}", false);
}
}
}
else {
errlog(__FILE__, __LINE__, "HTTP Digest headers not being passed to PHP by the server, unable to authenticate user", false);
exit;
}
return NULL;
}
function doAuth($user) {
if (!$this->getAuthHeader()) {
$this->send();
$style = "<link rel='stylesheet' type='text/css' href='../style/baznat.css'/>\n";
$htm = htm_head("Authentification invalide", "", $style, null);
$htm .= "<body>".htm_bandeau_haut(false, "../")."<div id='centre_pb'>";
$htm .= "<p id='pb_ident'>Pas d'authentification reçue, vous n'êtes pas connecté.<br><a href='./actions.php'>Connexion</a></p>";
$htm .= "</div>".htm_bandeau_bas()."</body>";
echo $htm;
errlog(__FILE__, __LINE__, "Le navigateur n'a pas renvoyé d'identification: demande de connexion ou annulation de connexion", false);
exit;
}
$this->username = $this->authenticate($user, $last_possible, $given_name);
if (!$this->username) {
$this->send();
$style = "<link rel='stylesheet' type='text/css' href='../style/baznat.css'/>\n";
$htm = htm_head("Accès refusé", "", $style, null);
$htm .= "<body>".htm_bandeau_haut(false, "../")."<div id='centre_pb'>";
$htm .= "<p id='pb_ident'>Accès refusé, vérifiez votre mot de passe (contactez l'administrateur en cas de refus persistant).<br><a href='./actions.php'>Connexion</a></p>";
$htm .= "</div>".htm_bandeau_bas()."</body>";
echo $htm;
errlog(__FILE__, __LINE__, "Accès refusé ".($given_name ? "pour $given_name" : "par l'utilisateur"), false);
exit;
}
else if (time() > $last_possible) {
$this->send();
$style = "<link rel='stylesheet' type='text/css' href='../style/baznat.css'/>\n";
$htm = htm_head("Session expirée", "", $style, null);
$htm .= "<body>".htm_bandeau_haut(false, "../")."<div id='centre_pb'>";
$htm .= "<p id='pb_ident'>Votre session est restée inactive trop longtemps.<br>Vous devez vous <a href='./actions.php'>identifier</a> de nouveau.</p>";
$htm .= "</div>".htm_bandeau_bas()."</body>";
echo $htm;
errlog(__FILE__, __LINE__, "Session expirée ".($given_name ? "pour $given_name" : "et non renouvelée"), false);
exit;
}
else if (time() - ($last_possible - 10500) < 70) {
errlog(__FILE__, __LINE__, $this->username." est connecté", false);
}
}
}
$g_HTTPDigest = new HTTPDigest();
$g_user = new utilisateur();
$g_HTTPDigest->doAuth($g_user);
?> |
Partager