0) { debug("Replayed session counter=" . $sessionCounter . ', seen=' . $seenSessionCounter); sendResp(S_REPLAYED_OTP); exit; } else { debug("Session counter OK (" . $sessionCounter . ")"); } //// Check the session use // $sessionUse = $decoded_token["session_use"]; // From the req $seenSessionUse = $ad['sessionUse']; // From DB $sucDiff = $seenSessionUse - $sessionUse; if ($sucDiff > 0) { debug("Replayed session use=" . $sessionUse . ', seen=' . $seenSessionUse); sendResp(S_REPLAYED_OTP); exit; } else { debug("Session counter OK (" . $sessionCounter . ")"); } //// Check the time stamp // if ($scDiff == 0) { // Same use session, check time stamp diff $ts = $decoded_token['timestamp']; $seenTs = ($ad['high'] << 16) + $ad['low']; $tsDiff = $ts - $seenTs; if ($tsDiff <= 0) { debug("Replayed time stamp=" . $ts . ', seen=' . $seenTs); sendResp(S_REPLAYED_OTP); exit; } else { updDB($ad['id'], $decoded_token, $client); $tsDelta = $tsDiff * TS_SEC; debug("Timestamp OK (" . $ts . ") delta count=" . $tsDiff . '-> delta secs=' . $tsDelta); } //// Check the real time // if ($ad['chk_time']) { $lastTime = strtotime($ad['accessed']); debug('Last accessed: '.$ad['accessed'].', '.$lastTime.', '.date("F j, Y, g:i a", $lastTime)); $elapsed = time() - $lastTime; debug('Elapsed time from last validation: ' . $elapsed . ' secs'); $deviation = abs($elapsed - $tsDelta); $percent = truncate(100*$deviation/$elapsed, 8) . '%'; debug("Key time deviation vs. elapsed time=".$deviation.' secs ('. $percent.')'); if ($deviation > TS_TOLERANCE * $elapsed) { debug("Is the OTP generated from a real crypto key?"); sendResp(S_PHISHED_OTP); exit; } } } // End check time stamp //// Check the high counter // //$hi = $decoded_token["high"]; // From the req //$seenHi = $ad['high']; // From DB //$hiDiff = $seenHi - $hi; //if ($scDiff == 0 && $hiDiff > 0) { // debug("Replayed hi counter=".$hi.', seen='.$seenHi); // sendResp(S_REPLAYED_OTP); // exit; //} else { // debug("Hi counter OK (".$hi.")"); //} //// Check the low counter // //$lo = $decoded_token["low"]; // From the req //$seenLo = $ad['low']; // From DB //$loDiff = $seenLo - $lo; //if ($scDiff == 0 && $hiDiff == 0 && $loDiff >= 0) { // debug("Replayed low counter=".$lo.', seen='.$seenLo); // sendResp(S_REPLAYED_OTP); // exit; //} else { // debug("Lo counter OK (".$lo.")"); //} //// Update the DB only upon validation success // if (updDB($ad['id'], $decoded_token, $client)) { debug('Validation database updated'); sendResp(S_OK); } else { debug('Failed to update validation database'); sendResp(S_BACKEND_ERROR); } ////////////////////////// // Functions ////////////////////////// function sendResp($status, $info = null) { global $ad, $apiKey; if ($status == null) { $status = S_BACKEND_ERROR; } $a['status'] = $status; #$a['info'] = $info; $a['t'] = getUTCTimeStamp(); $h = sign($a, $apiKey); echo "h=" . $h . "\r\n"; echo "t=" . ($a['t']) . "\r\n"; echo "status=" . ($a['status']) . "\r\n"; if ($a['info'] != null) { echo "info=" . ($a['info']) . "\r\n"; } echo "\r\n"; } // End sendResp function updDB($keyid, $new, $client) { $stmt = 'UPDATE yubikeys SET ' . 'accessed=NOW(),' . 'counter=' . $new['session_counter'] . ',' . 'sessionUse=' . $new['session_use'] . ',' . 'low=' . $new['low'] . ',' . 'high=' . $new['high'] . ' WHERE id=' . $keyid; if (!query($stmt)) { $err = 'Failed to update validation data of key: ' . $keyid . ' by ' . $stmt; debug($err); writeLog($err); return false; } addHist(0, $_SERVER['REMOTE_ADDR'], $keyid, $client); return true; } ?>