You are here

class TfaBasicRecoveryCode in TFA Basic plugins 7

Class TfaBasicRecoveryCode

Hierarchy

Expanded class hierarchy of TfaBasicRecoveryCode

1 string reference to 'TfaBasicRecoveryCode'
tfa_basic_tfa_api in ./tfa_basic.module
Implements hook_tfa_api().

File

includes/tfa_recovery.inc, line 10
class for TFA Basic

View source
class TfaBasicRecoveryCode extends TfaBasePlugin implements TfaValidationPluginInterface {

  /**
   * @var string
   */
  protected $usedCode;
  public function __construct(array $context) {
    parent::__construct($context);

    // Set in settings.php.
    $this->encryptionKey = variable_get('tfa_basic_secret_key', drupal_get_private_key());
  }

  /**
   * @copydoc TfaBasePlugin::ready()
   */
  public function ready() {
    $codes = $this
      ->getCodes();
    return !empty($codes);
  }

  /**
   * @copydoc TfaBasePlugin::getForm()
   */
  public function getForm(array $form, array &$form_state) {
    $form['recover'] = array(
      '#type' => 'textfield',
      '#title' => t('Enter one of your recovery codes'),
      '#required' => TRUE,
      '#description' => t('Recovery codes were generated when you first set up TFA. Format: XXX XX XXX'),
      '#attributes' => array(
        'autocomplete' => 'off',
      ),
    );
    if (module_exists('elements')) {
      $form['recover']['#type'] = 'numberfield';
    }
    $form['actions']['#type'] = 'actions';
    $form['actions']['login'] = array(
      '#type' => 'submit',
      '#value' => t('Verify'),
    );
    return $form;
  }

  /**
   * @copydoc TfaBasePlugin::validateForm()
   */
  public function validateForm(array $form, array &$form_state) {
    return $this
      ->validate($form_state['values']['recover']);
  }

  /**
   * @copydoc TfaBasePlugin::finalize()
   */
  public function finalize() {

    // Mark code as used.
    if ($this->usedCode) {
      $num = db_update('tfa_recovery_code')
        ->fields(array(
        'used' => REQUEST_TIME,
      ))
        ->condition('id', $this->usedCode)
        ->condition('uid', $this->context['uid'])
        ->execute();
      if ($num) {
        watchdog('tfa_basic', 'Used TFA recovery code !id by user !uid', array(
          '!id' => $this->usedCode,
          '!uid' => $this->context['uid'],
        ), WATCHDOG_NOTICE);
      }
    }
  }

  /**
   * Get unused recovery codes.
   *
   * @todo consider returning used codes so validate() can error with
   * appropriate message
   *
   * @return array
   *   Array of codes indexed by ID.
   */
  public function getCodes() {

    // Lookup codes for account and decrypt.
    $codes = array();
    $result = db_query("SELECT id, code FROM {tfa_recovery_code} WHERE uid = :uid AND used = 0", array(
      ':uid' => $this->context['uid'],
    ));
    if (!empty($result)) {
      foreach ($result as $data) {
        $encrypted = base64_decode($data->code);

        // trim() prevents extraneous escape characters.
        $code = trim($this
          ->decrypt($encrypted));
        if (!empty($code)) {
          $codes[$data->id] = $code;
        }
      }
    }
    return $codes;
  }

  /**
   * @copydoc TfaBasePlugin::validate()
   */
  protected function validate($code) {
    $this->isValid = FALSE;

    // Get codes and compare.
    $codes = $this
      ->getCodes();
    if (empty($codes)) {
      $this->errorMessages['code'] = t('You have no unused codes available.');
      return FALSE;
    }

    // Remove empty spaces.
    $code = str_replace(' ', '', $code);
    foreach ($codes as $id => $stored) {

      // Remove spaces from stored code.
      if (str_replace(' ', '', $stored) === $code) {
        $this->isValid = TRUE;
        $this->usedCode = $id;
        return $this->isValid;
      }
    }
    $this->errorMessages['code'] = t('Invalid recovery code.');
    return $this->isValid;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
TfaBasePlugin::$code protected property TFA code.
TfaBasePlugin::$codeLength protected property Code Length.
TfaBasePlugin::$context protected property Context of current TFA process.
TfaBasePlugin::$encryptionKey protected property Encryption key.
TfaBasePlugin::$errorMessages protected property Error messages.
TfaBasePlugin::$isValid protected property Code is valid.
TfaBasePlugin::CRYPT_VERSION constant
TfaBasePlugin::decrypt protected function Decrypt a encrypted string.
TfaBasePlugin::decryptLegacyDataWithMcrypt protected function Decrypt using the deprecated Mcrypt extension.
TfaBasePlugin::decryptLegacyDataWithOpenSSL protected function Use OpenSSL to decrypt data that was originally encrypted with Mcrypt.
TfaBasePlugin::encrypt protected function Encrypt a plaintext string.
TfaBasePlugin::encryptWithMcrypt protected function Encrypt using the deprecated Mcrypt extension.
TfaBasePlugin::generate protected function Generate a random string of characters of length $this->codeLength.
TfaBasePlugin::getErrorMessages public function Get error messages suitable for form_set_error().
TfaBasePlugin::submitForm public function Submit form. 1
TfaBasePlugin::timingSafeEquals private function A timing safe equals comparison.
TfaBasicRecoveryCode::$usedCode protected property
TfaBasicRecoveryCode::finalize public function @copydoc TfaBasePlugin::finalize()
TfaBasicRecoveryCode::getCodes public function Get unused recovery codes.
TfaBasicRecoveryCode::getForm public function @copydoc TfaBasePlugin::getForm() Overrides TfaValidationPluginInterface::getForm
TfaBasicRecoveryCode::ready public function @copydoc TfaBasePlugin::ready() Overrides TfaBasePlugin::ready
TfaBasicRecoveryCode::validate protected function @copydoc TfaBasePlugin::validate() Overrides TfaBasePlugin::validate
TfaBasicRecoveryCode::validateForm public function @copydoc TfaBasePlugin::validateForm() Overrides TfaValidationPluginInterface::validateForm
TfaBasicRecoveryCode::__construct public function Plugin constructor. Overrides TfaBasePlugin::__construct 1