views:

150

answers:

2

For security, requests to a PHP webservice will require a Date: header.

I need to calculate if the Date: header is within 15 minutes of the computer clock. I can easily do this by comparing

$dt = new DateTime($_SERVER['HTTP_DATE']);

to the actual date. However, strotime also supports formats such as "now", which will always be 'valid'.

Is there a straightforward way to make sure people specify an absolute date. Strictly checking RFC2616 is even better, but not a requirement.

See: http://www.ietf.org/rfc/rfc2616.txt section 3.3.1

A: 
$request_time = strtotime($_SERVER['HTTP_DATE']);
$server_time = time();
$difference = abs($request_time - $server_time);
if($difference <= (15 * 60)) {
    //good to go
}

This just converts them both to Unix timestamps and compares them to make sure they're less than or equal to 15 minutes apart.

zacharydanger
The problem with this solution is that it will accept invalid dates such as "now".
pix0r
+4  A: 

Did some research and it looks like you can solve this using strptime(). Note that this is untested, and I'm just guessing that strptime() will properly convert the string to GMT based on the supplied timezone. This should at least get you started.

$in = $_SERVER['HTTP_DATE'];
$out = 0;

$strptime_patterns = array(
    // Matches: Sun, 06 Nov 1994 08:49:37 GMT
    '%a, %d %h %Y %H:%M:%S %z',
    '%a, %d %h %Y %H:%M:%S %Z',
    // Matches: Sunday, 06-Nov-94 08:49:37 GMT
    '%A, %d-%h-%y %H:%M:%S %z',
    '%A, %d-%h-%y %H:%M:%S %Z',
    // Matches: Sun Nov  6 08:49:37 1994
    '%a %h %e %H:%M:%S %Y'
);

foreach ($strptime_patterns as $pat) {
    if ($arr = strptime($in, $pat)) {
        $out = mktime($arr['tm_hour'], $arr['tm_min'], $arr['tm_sec'], $arr['tm_mon'], $arr['tm_mday'], $arr['tmp_year'] + 1900);
        break;
    }
}

if ($out > gmmktime()) {
    // Invalid date - in the future
} elseif ($out >= gmmktime() - (15 * 60)) {
    // Valid, not expired
} elseif ($out > 0) {
    // Valid date, but expired
} else {
    // Invalid date
}
pix0r
Since Evert is concerned about "hacks" like "now" it should test for gmmktime() >= valid date >= gmmktime() - (15 * 60)
VolkerK
Good point. You should always watch out for users traveling back in time to exploit your web service ;)
pix0r
This will definitely get me started.. thanks!
Evert