note 51592 added to function.fopen
| From: | abesharp at yahoo dot co dot uk | Date: | Tue, 05 Apr 2005 11:12:32 +0000 |
| Subject: | note 51592 added to function.fopen | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-87486@lists.php.net to get a copy of this message | ||
This function has a basic implementation of HTTP Digest Authentication (as per RFC 2617) to get a
file from a web server which requires digest authentication (as opposed to basic authentication -
the difference being that, with basic, your password is sent to the server as plain text, whereas
with digest, it is hashed with a server-supplied nonce to protect against sniffing and replay
attacks).
You just supply the host (e.g www.example.com), the name of the file you want (e.g
protected_page.html), and the necessary username and password, and the function returns the contents
of the protected file (or the error message that the server sends, if you supplied the wrong
credentials).
If the server only supports a QOP of auth-int (rather then auth) this function won't work, but
can be easily modified with reference to the RFC at http://www.ietf.org/rfc/rfc2617.txt
<?php
function readHTTPDigestAuthenticatedFile($host,$file,$username,$password)
{
if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
return false;
//first do the non-authenticated header so that the server
//sends back a 401 error containing its nonce and opaque
$out = "GET /$file HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
//read the reply and look for the WWW-Authenticate element
while (!feof($fp))
{
$line=fgets($fp, 512);
if (strpos($line,"WWW-Authenticate:")!==false)
$authline=trim(substr($line,18));
}
fclose($fp);
//split up the WWW-Authenticate string to find digest-realm,nonce and opaque values
//if qop value is presented as a comma-seperated list (e.g auth,auth-int) then it won't be
retrieved correctly
//but that doesn't matter because going to use 'auth' anyway
$authlinearr=explode(",",$authline);
$autharr=array();
foreach ($authlinearr as $el)
{
$elarr=explode("=",$el);
//the substr here is used to remove the double quotes from the values
$autharr[trim($elarr[0])]=substr($elarr[1],1,strlen($elarr[1])-2);
}
foreach ($autharr as $k=>$v)
echo("$k ==> $v\r\n");
//these are all the vals required from the server
$nonce=$autharr['nonce'];
$opaque=$autharr['opaque'];
$drealm=$autharr['Digest realm'];
//client nonce can be anything since this authentication session is not going to be persistent
//likewise for the cookie - just call it MyCookie
$cnonce="sausages";
//calculate the hashes of A1 and A2 as described in RFC 2617
$a1="$username:$drealm:$password";$a2="GET:/$file";
$ha1=md5($a1);$ha2=md5($a2);
//calculate the response hash as described in RFC 2617
$concat = $ha1.':'.$nonce.':00000001:'.$cnonce.':auth:'.$ha2;
$response=md5($concat);
//put together the Authorization Request Header
$out = "GET /$file HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: cookie=MyCookie\r\n";
$out .= "Authorization: Digest username=\"$username\", realm=\"$drealm\",
qop=\"auth\", algorithm=\"MD5\", uri=\"/$file\",
nonce=\"$nonce\", nc=00000001, cnonce=\"$cnonce\", opaque=\"$opaque\",
response=\"$response\"\r\n\r\n";
if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
return false;
fwrite($fp, $out);
//read in a string which is the contents of the required file
while (!feof($fp))
{
$str.=fgets($fp, 512);
}
fclose($fp);
return $str;
}
?>
----
Manual Page -- http://www.php.net/manual/en/function.fopen.php
Edit -- http://master.php.net/manage/user-notes.php?action=edit+51592
Delete: added to the manual -- http://master.php.net/manage/user-notes.php?action=delete+51592&report=yes&reason=added+to+the+manual
Delete: bad code -- http://master.php.net/manage/user-notes.php?action=delete+51592&report=yes&reason=bad+code
Delete: spam -- http://master.php.net/manage/user-notes.php?action=delete+51592&report=yes&reason=spam
Delete: useless -- http://master.php.net/manage/user-notes.php?action=delete+51592&report=yes&reason=useless
Delete: other reasons -- http://master.php.net/manage/user-notes.php?action=delete+51592&report=yes
Reject -- http://master.php.net/manage/user-notes.php?action=reject+51592&report=yes
Search -- http://master.php.net/manage/user-notes.php