Added option to enroll Yubikey during registration + option in admin CP to require enrollment
authorDan
Sun, 01 Mar 2009 21:45:44 -0500
changeset 8 032ca892b9a2
parent 7 c8fc1493eacd
child 9 65965da01c41
Added option to enroll Yubikey during registration + option in admin CP to require enrollment
plugins/Yubikey.php
plugins/yubikey/admincp.php
plugins/yubikey/usercp.php
--- a/plugins/Yubikey.php	Sun Mar 01 21:44:08 2009 -0500
+++ b/plugins/Yubikey.php	Sun Mar 01 21:45:44 2009 -0500
@@ -92,6 +92,7 @@
         msg_please_touch_key: 'Please touch your Yubikey',
         msg_close_instructions: 'Press <tt>Esc</tt> to cancel',
         msg_invalid_chars: 'OTP contains invalid characters',
+        msg_too_long: 'OTP is too long',
         msg_validating_otp: 'Validating OTP...',
         msg_otp_valid: 'OTP validated',
         btn_enter_otp: 'Enter a Yubikey OTP',
@@ -148,6 +149,13 @@
         field_allow_plain_login: 'Allow me to log in without my Yubikey',
         field_allow_plain_login_hint: 'If this option is turned off, you will be unable to access your account if all of your enrolled Yubikeys become lost or broken. However, turning this option off provides greater security.',
         err_double_enrollment: 'One of the Yubikeys you tried to enroll is already enrolled on another account on this website. A single Yubikey can only be associated with one account at a time.',
+        err_double_enrollment_single: 'The Yubikey you tried to enroll is already enrolled on another account on this website. A single Yubikey can only be associated with one account at a time.',
+        
+        reg_field_otp: 'Enroll a <a href="http://www.yubico.com/products/yubikey" onclick="window.open(this.href); return false;">Yubikey</a>:',
+        reg_field_otp_hint_optional: 'If you have a Yubikey, you can authorize it for use in your new account here.',
+        reg_field_otp_hint_required: 'Please enroll a Yubikey here to create an account. This is a required step.',
+        reg_err_otp_required: 'Please enroll a Yubikey to register on this site.',
+        reg_err_otp_invalid: 'Your Yubikey OTP failed to validate.'
       },
       yubiacp: {
         th: 'Yubikey authentication',
@@ -157,6 +165,9 @@
         field_api_key_id: 'Yubico numeric ID:',
         field_auth_server: 'Authentication server URL:',
         field_enroll_limit: 'Number of enrolled keys permitted per account:',
+        field_reg_require_otp_title: 'Yubikey required for registration:',
+        field_reg_require_otp_hint: 'If this is enabled, users will be asked to enroll a Yubikey during registration. The enrolled Yubikey will be authorized for the new account.',
+        field_reg_require_otp: 'Require Yubikey during registration',
         
         err_invalid_auth_server: 'The URL to the Yubikey authentication server that you entered is invalid.'
       }
--- a/plugins/yubikey/admincp.php	Sun Mar 01 21:44:08 2009 -0500
+++ b/plugins/yubikey/admincp.php	Sun Mar 01 21:45:44 2009 -0500
@@ -61,6 +61,19 @@
       </td>
     </tr>
     
+    <tr>
+      <td class="row2">
+        <?php echo $lang->get('yubiacp_field_reg_require_otp_title'); ?><br />
+        <small><?php echo $lang->get('yubiacp_field_reg_require_otp_hint'); ?></small>
+      </td>
+      <td class="row2">
+        <label>
+          <input type="checkbox" name="yubikey_reg_require_otp" <?php if ( getConfig('yubikey_reg_require_otp', '0') == '1' ) echo 'checked="checked" '; ?>/>
+          <?php echo $lang->get('yubiacp_field_reg_require_otp'); ?>
+        </label>
+      </td>
+    </tr>
+    
   <?php
 }
 
@@ -73,6 +86,7 @@
   setConfig('yubikey_api_key', $_POST['yubikey_api_key']);
   setConfig('yubikey_api_key_id', intval($_POST['yubikey_api_key_id']));
   setConfig('yubikey_enroll_limit', intval($_POST['yubikey_enroll_limit']));
+  setConfig('yubikey_reg_require_otp', isset($_POST['yubikey_reg_require_otp']) ? '1' : '0');
   
   if ( preg_match('#^(?:https?://)?(\[?[a-z0-9-:]+(?:\.[a-z0-9-:]+\]?)*)(/.*)$#', $_POST['yubikey_auth_server']) )
     setConfig('yubikey_auth_server', $_POST['yubikey_auth_server']);
--- a/plugins/yubikey/usercp.php	Sun Mar 01 21:44:08 2009 -0500
+++ b/plugins/yubikey/usercp.php	Sun Mar 01 21:45:44 2009 -0500
@@ -6,6 +6,9 @@
 $plugins->attachHook("userprefs_jbox", "yubikey_ucp_setup();");
 $plugins->attachHook("userprefs_body", "return yubikey_user_cp(\$section);");
 $plugins->attachHook("login_form_html", "yubikey_inject_html_login();");
+$plugins->attachHook("ucp_register_form", "yubikey_inject_registration_form();");
+$plugins->attachHook("ucp_register_validate", "yubikey_register_validate(\$error);");
+$plugins->attachHook("user_registered", "yubikey_register_insert_key(\$user_id);");
 
 function yubikey_ucp_setup()
 {
@@ -268,3 +271,76 @@
   <?php
 }
 
+function yubikey_inject_registration_form()
+{
+  global $lang;
+  
+  $preset_otp = isset($_POST['yubikey_otp']) ? $_POST['yubikey_otp'] : false;
+  ?>
+  <tr>
+    <td class="row1">
+      <?php echo $lang->get('yubiucp_reg_field_otp'); ?><br />
+      <small><?php
+        if ( getConfig('yubikey_reg_require_otp', '0') == '1' )
+          echo $lang->get('yubiucp_reg_field_otp_hint_required');
+        else
+          echo $lang->get('yubiucp_reg_field_otp_hint_optional');
+      ?></small>
+    </td>
+    <td class="row1">
+      <?php
+      echo generate_yubikey_field('yubikey_otp', $preset_otp);
+      ?>
+    </td>
+    <td class="row1">
+    </td>
+  </tr>
+  <?php
+}
+
+function yubikey_register_validate(&$error)
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
+  $otp_required = getConfig('yubikey_reg_require_otp', '0') == '1';
+  $have_otp = !empty($_POST['yubikey_otp']);
+  if ( $otp_required && !$have_otp )
+  {
+    $error = $lang->get('yubiucp_reg_err_otp_required');
+    return false;
+  }
+  if ( $have_otp )
+  {
+    $result = yubikey_validate_otp($_POST['yubikey_otp']);
+    if ( !$result['success'] )
+    {
+      $error = '<b>' . $lang->get('yubiucp_reg_err_otp_invalid') . '</b><br />' . $lang->get("yubiauth_err_{$result['error']}");
+      return false;
+    }
+    // check for double enrollment
+    $yubi_uid = substr($_POST['yubikey_otp'], 0, 12);
+    // Note on SQL injection: yubikey_validate_otp() has already ensured that this is safe
+    $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "yubikey WHERE yubi_uid = '$yubi_uid';");
+    if ( !$q )
+      $db->_die();
+    if ( $db->numrows() > 0 )
+    {
+      $error = '<b>' . $lang->get('yubiucp_reg_err_otp_invalid') . '</b><br />' . $lang->get('yubiucp_err_double_enrollment_single');
+      return false;
+    }
+    $db->free_result();
+  }
+}
+
+function yubikey_register_insert_key($user_id)
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  if ( !empty($_POST['yubikey_otp']) )
+  {
+    $yubi_uid = $db->escape(substr($_POST['yubikey_otp'], 0, 12));
+    $q = $db->sql_query('INSERT INTO ' . table_prefix . "yubikey ( user_id, yubi_uid ) VALUES ( $user_id, '$yubi_uid' );");
+    if ( !$q )
+      $db->_die();
+  }
+}