class TfaTotp in TFA Basic plugins 7
Class TfaTotp
Hierarchy
- class \TfaBasePlugin
- class \TfaTotp implements TfaValidationPluginInterface
 
 
Expanded class hierarchy of TfaTotp
1 string reference to 'TfaTotp'
- tfa_basic_tfa_api in ./
tfa_basic.module  - Implements hook_tfa_api().
 
File
- includes/
tfa_totp.inc, line 10  - classes for tfa_totp
 
View source
class TfaTotp extends TfaBasePlugin implements TfaValidationPluginInterface {
  /**
   * @var PHPGangsta_GoogleAuthenticator
   */
  protected $ga;
  /**
   * @var int
   */
  protected $timeSkew;
  /**
   * @var bool
   */
  protected $alreadyAccepted;
  /**
   * @copydoc TfaBasePlugin::__construct()
   */
  public function __construct(array $context) {
    parent::__construct($context);
    $this->ga = new PHPGangsta_GoogleAuthenticator();
    // Allow codes within tolerance range of 3 * 30 second units.
    $this->timeSkew = variable_get('tfa_basic_time_skew', 3);
    // Recommended: set variable tfa_totp_secret_key in settings.php.
    $this->encryptionKey = variable_get('tfa_basic_secret_key', drupal_get_private_key());
    $this->alreadyAccepted = FALSE;
  }
  /**
   * @copydoc TfaBasePlugin::ready()
   */
  public function ready() {
    return $this
      ->getSeed() !== FALSE;
  }
  /**
   * @copydoc TfaValidationPluginInterface::getForm()
   */
  public function getForm(array $form, array &$form_state) {
    $form['code'] = array(
      '#type' => 'textfield',
      '#title' => t('Application verification code'),
      '#description' => t('Verification code is application generated and !length digits long.', array(
        '!length' => $this->codeLength,
      )),
      '#required' => TRUE,
      '#attributes' => array(
        'autocomplete' => 'off',
      ),
    );
    if (module_exists('elements')) {
      $form['code']['#type'] = 'numberfield';
    }
    $form['actions']['#type'] = 'actions';
    $form['actions']['login'] = array(
      '#type' => 'submit',
      '#value' => t('Verify'),
    );
    return $form;
  }
  /**
   * @copydoc TfaValidationPluginInterface::validateForm()
   */
  public function validateForm(array $form, array &$form_state) {
    if (!$this
      ->validate($form_state['values']['code'])) {
      $this->errorMessages['code'] = t('Invalid application code. Please try again.');
      if ($this->alreadyAccepted) {
        $this->errorMessages['code'] = t('Invalid code, it was recently used for a login. Please wait for the application to generate a new code.');
      }
      return FALSE;
    }
    else {
      // Store accepted code to prevent replay attacks.
      $this
        ->storeAcceptedCode($form_state['values']['code']);
      return TRUE;
    }
  }
  /**
   * @copydoc TfaBasePlugin::validate()
   */
  protected function validate($code) {
    // Strip whitespace.
    $code = preg_replace('/\\s+/', '', $code);
    if ($this
      ->alreadyAcceptedCode($code)) {
      $this->isValid = FALSE;
    }
    else {
      // Get OTP seed.
      $seed = $this
        ->getSeed();
      $this->isValid = $seed && $this->ga
        ->verifyCode($seed, $code, $this->timeSkew);
    }
    return $this->isValid;
  }
  /**
   * @param string $code
   */
  protected function storeAcceptedCode($code) {
    $code = preg_replace('/\\s+/', '', $code);
    $hash = hash('sha1', drupal_get_hash_salt() . $code);
    db_insert('tfa_accepted_code')
      ->fields(array(
      'uid' => $this->context['uid'],
      'code_hash' => $hash,
      'time_accepted' => REQUEST_TIME,
    ))
      ->execute();
  }
  /**
   * Whether code has recently been accepted.
   *
   * @param string $code
   * @return bool
   */
  protected function alreadyAcceptedCode($code) {
    $hash = hash('sha1', drupal_get_hash_salt() . $code);
    $result = db_query("SELECT code_hash FROM {tfa_accepted_code} WHERE uid = :uid AND code_hash = :code", array(
      ':uid' => $this->context['uid'],
      ':code' => $hash,
    ))
      ->fetchAssoc();
    if (!empty($result)) {
      $this->alreadyAccepted = TRUE;
      return TRUE;
    }
    return FALSE;
  }
  /**
   * Get seed for this account.
   *
   * @return string Decrypted account OTP seed or FALSE if none exists.
   */
  protected function getSeed() {
    // Lookup seed for account and decrypt.
    $result = db_query("SELECT seed FROM {tfa_totp_seed} WHERE uid = :uid", array(
      ':uid' => $this->context['uid'],
    ))
      ->fetchAssoc();
    if (!empty($result)) {
      $encrypted = base64_decode($result['seed']);
      $seed = $this
        ->decrypt($encrypted);
      if (!empty($seed)) {
        return $seed;
      }
    }
    return FALSE;
  }
  /**
   * Delete users seeds.
   *
   * @return int
   */
  public function deleteSeed() {
    $query = db_delete('tfa_totp_seed')
      ->condition('uid', $this->context['uid']);
    return $query
      ->execute();
  }
}Members
| 
            Name | 
                  Modifiers | Type | Description | Overrides | 
|---|---|---|---|---|
| 
            TfaBasePlugin:: | 
                  protected | property | TFA code. | |
| 
            TfaBasePlugin:: | 
                  protected | property | Code Length. | |
| 
            TfaBasePlugin:: | 
                  protected | property | Context of current TFA process. | |
| 
            TfaBasePlugin:: | 
                  protected | property | Encryption key. | |
| 
            TfaBasePlugin:: | 
                  protected | property | Error messages. | |
| 
            TfaBasePlugin:: | 
                  protected | property | Code is valid. | |
| 
            TfaBasePlugin:: | 
                  constant | |||
| 
            TfaBasePlugin:: | 
                  protected | function | Decrypt a encrypted string. | |
| 
            TfaBasePlugin:: | 
                  protected | function | Decrypt using the deprecated Mcrypt extension. | |
| 
            TfaBasePlugin:: | 
                  protected | function | Use OpenSSL to decrypt data that was originally encrypted with Mcrypt. | |
| 
            TfaBasePlugin:: | 
                  protected | function | Encrypt a plaintext string. | |
| 
            TfaBasePlugin:: | 
                  protected | function | Encrypt using the deprecated Mcrypt extension. | |
| 
            TfaBasePlugin:: | 
                  protected | function | Generate a random string of characters of length $this->codeLength. | |
| 
            TfaBasePlugin:: | 
                  public | function | Get error messages suitable for form_set_error(). | |
| 
            TfaBasePlugin:: | 
                  public | function | Submit form. | 1 | 
| 
            TfaBasePlugin:: | 
                  private | function | A timing safe equals comparison. | |
| 
            TfaTotp:: | 
                  protected | property | ||
| 
            TfaTotp:: | 
                  protected | property | ||
| 
            TfaTotp:: | 
                  protected | property | ||
| 
            TfaTotp:: | 
                  protected | function | Whether code has recently been accepted. | |
| 
            TfaTotp:: | 
                  public | function | Delete users seeds. | |
| 
            TfaTotp:: | 
                  public | function | 
            @copydoc TfaValidationPluginInterface::getForm() Overrides TfaValidationPluginInterface:: | 
                  |
| 
            TfaTotp:: | 
                  protected | function | Get seed for this account. | |
| 
            TfaTotp:: | 
                  public | function | 
            @copydoc TfaBasePlugin::ready() Overrides TfaBasePlugin:: | 
                  |
| 
            TfaTotp:: | 
                  protected | function | ||
| 
            TfaTotp:: | 
                  protected | function | 
            @copydoc TfaBasePlugin::validate() Overrides TfaBasePlugin:: | 
                  1 | 
| 
            TfaTotp:: | 
                  public | function | 
            @copydoc TfaValidationPluginInterface::validateForm() Overrides TfaValidationPluginInterface:: | 
                  |
| 
            TfaTotp:: | 
                  public | function | 
            @copydoc TfaBasePlugin::__construct() Overrides TfaBasePlugin:: | 
                  1 |