Added timestamp-based verification.
authorDan
Sun, 08 Mar 2009 00:45:45 -0500
changeset 10 748fa1b80031
parent 9 65965da01c41
child 11 794e7b1a97e7
Added timestamp-based verification.
plugins/Yubikey.php
plugins/yubikey/corelib.php
plugins/yubikey/yubikey.js
--- a/plugins/Yubikey.php	Mon Mar 02 10:56:51 2009 -0500
+++ b/plugins/Yubikey.php	Sun Mar 08 00:45:45 2009 -0500
@@ -117,6 +117,7 @@
         err_missing_api_key: 'Your OTP could not be validated because no Yubico API key is registered on this site.',
         err_http_response_error: 'Your OTP could not be validated because the Yubico authentication server reported an error.',
         err_malformed_response: 'Your OTP could not be validated because the Yubico authentication server returned an unexpected response.',
+        err_timestamp_check_failed: 'Your OTP could not be validated because the timestamp of the response from the Yubico authentication server was out of bounds.',
         err_response_missing_sig: 'Your OTP could not be validated because the Yubico authentication server did not sign its response.',
         err_response_invalid_sig: 'Your OTP could not be validated because the signature of the authentication response was invalid.',
         err_response_missing_status: '%this.yubiauth_err_malformed_response%',
--- a/plugins/yubikey/corelib.php	Mon Mar 02 10:56:51 2009 -0500
+++ b/plugins/yubikey/corelib.php	Sun Mar 08 00:45:45 2009 -0500
@@ -126,9 +126,19 @@
   }
   if ( $response['status'] === 'OK' )
   {
-    return array(
-        'success' => true
-      );
+    if ( yubikey_verify_timestamp($response['t']) )
+    {
+      return array(
+          'success' => true
+        );
+    }
+    else
+    {
+      return array(
+          'success' => false,
+          'error' => 'timestamp_check_failed'
+        );
+    }
   }
   else
   {
@@ -168,16 +178,56 @@
   return $sig;
 }
 
+/**
+ * Validate the timestamp returned in a Yubico API response. Borrowed from Drupal and backported for friendliness with earlier versions of PHP.
+ * @param string Yubico timestamp
+ * @return bool True if valid, false otherwise
+ */
+
+function yubikey_verify_timestamp($timestamp)
+{
+  $tolerance = intval(getConfig('yubikey_api_ts_tolerance', 150));
+  
+  $now = time();
+  $timestamp_seconds = strtotime(substr($timestamp, 0, -4));
+
+  if ( !$timestamp || !$now )
+  {
+    return false;
+  }
+
+  if ( ( $timestamp_seconds + $tolerance ) > $now && ( $timestamp_seconds - $tolerance ) < $now )
+  {
+    return true;
+  }
+
+  return false;
+}
+
+
 $plugins->attachHook('compile_template', 'yubikey_attach_headers($this);');
 
 function yubikey_attach_headers(&$template)
 {
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  
   if ( getConfig('yubikey_enable', '1') != '1' )
     return true;
   
   $template->add_header('<script type="text/javascript" src="' . scriptPath . '/plugins/yubikey/yubikey.js"></script>');
   $template->add_header('<link rel="stylesheet" type="text/css" href="' . scriptPath . '/plugins/yubikey/yubikey.css" />');
   // config option for all users have yubikey
-  $template->add_header('<script type="text/javascript">var yk_reg_require_otp = ' . getConfig('yubikey_reg_require_otp', '0') . '</script>');
+  $user_flags = 0;
+  if ( $session->user_logged_in )
+  {
+    $q = $db->sql_query('SELECT COUNT(yubi_uid) > 0 FROM ' . table_prefix . "yubikey WHERE user_id = {$session->user_id};");
+    if ( !$q )
+      $db->_die();
+    
+    list($user_flags) = $db->fetchrow_num();
+    $db->free_result();
+  }
+  
+  $template->add_header('<script type="text/javascript">var yk_reg_require_otp = ' . getConfig('yubikey_reg_require_otp', '0') . '; var yk_user_enabled = ' . $user_flags . ';</script>');
 }
 
--- a/plugins/yubikey/yubikey.js	Mon Mar 02 10:56:51 2009 -0500
+++ b/plugins/yubikey/yubikey.js	Sun Mar 08 00:45:45 2009 -0500
@@ -252,7 +252,7 @@
       $('#messageBoxButtons input:button:first').focus();
       $('#ajax_login_field_captcha').focus();
     });
-  if ( window.yk_reg_require_otp )
+  if ( window.yk_reg_require_otp || window.yk_user_enabled )
   {
     setTimeout(function()
       {