<commit_before><?php namespace phpSec\Auth;
/**
  phpSec - A PHP security library

  @author    <NAME> <<EMAIL>>
  @copyright Copyright (c) <NAME>, 2011
  @link      https://github.com/phpsec/phpSec
  @license   http://opensource.org/licenses/mit-license.php The MIT License
  @package   phpSec
 */
use phpSec\Crypt\Rand;

/**
 * Implements validation of Yubikey against Yubico servers.
 * @package phpSec
 */
class Yubikey {
  /**
   * Yubico client Id.
   * @see https://upgrade.yubico.com/getapikey/
   */
  public $clientId = null;

  /**
   * Yubico client shared secret.
   * @see https://upgrade.yubico.com/getapikey/
   */
  public $clientSecret = null;

  /**
   * Number of servers to try before giving up.
   */
  public $_numServers = 3;

  /**
   * Timeout in seconds for each server.
   */
  public $_serverTimeout = 3;

  /**
   * Last error produced by phpsecYubikey::verify().
   * @see https://phpseclib.com/manual/09-Yubikey-Authentication.md
   */
  public $lastError = null;

  /**
   * Yubico authentication servers.
   */
  private $_servers = array(
    'http://api.yubico.com/wsapi/2.0/verify',
    'http://api2.yubico.com/wsapi/2.0/verify',
    'http://api3.yubico.com/wsapi/2.0/verify',
    'http://api4.yubico.com/wsapi/2.0/verify',
    'http://api5.yubico.com/wsapi/2.0/verify',
  );

  /**
   * phpSec core Pimple container.
   */
  private $psl = null;

  /**
   * Constructor.
   *
   * @param \phpSec\Core $psl
   *   phpSec core Pimple container.
   */
  public function __construct(\phpSec\Core $psl) {
    $this->psl = $psl;
  }

  /**
   * Verify Yubikey one time password against the Yubico servers.
   *
   * @param string $otp
   *   One time password to verify.
   *
   * @return boolean
   *   True on valid OTP, false on invalid. If this method returns false
   *   $lastError will contain details.
   *
   * @see https://phpseclib.com/manual/09-Yubikey-Authentication.md
   */
  public function verify($otp) {
    $rand = $this->psl['crypt/rand'];

    if($this->clientId === null || $this->clientSecret === null) {
      $this->lastError = 'YUBIKEY_CLIENT_DATA_NEEDED';
      return false;
    }

    if(!self::validOtp($otp)) {
      $this->lastError = 'YUBIKEY_INVALID_OTP';
      return false;
    }
    /* Setup the data needed to make the request. */
    $data['otp']       = $otp;
    $data['id']        = $this->clientId;
    $data['nonce']     = $rand->str(20);
    $data['timestamp'] = 1;
    $data['h']         = $this->sign($data);

    /* Do the request. */
    $response = $this->getResponse($data);
    if($response === false) {
      $this->lastError = 'YUBIKEY_SERVER_ERROR';
      return false;
    }

    /* Check status of response. If not OK return false. */
    if($response['status'] != 'OK') {
      switch($response['status']) {
        case 'REPLAYED_OTP':
          $this->lastError = 'YUBIKEY_SERVER_REPLAYED_OTP';
          break;
        case 'REPLAYED_REQUEST':
          $this->lastError = 'YUBIKEY_SERVER_REPLAYED_REQUEST';
          break;
        case 'BAD_OTP':
          $this->lastError = 'YUBIKEY_SERVER_BAD_OTP';
          break;
        case 'NO_SUCH_CLIENT':
          $this->lastError = 'YUBIKEY_SERVER_NO_SUCH_CLIENT';
          break;
        case 'BAD_SIGNATURE':
          $this->lastError = 'YUBIKEY_SERVER_BAD_SIGNATURE';
          break;
        default:
          $this->lastError = 'YUBIKEY_SERVER_SAYS_NO';
          break;
      }
      return false;
    }

    /* If tokens don't match return false. */
    if($response['otp'] != $otp) {
      $this->$lastError = 'YUBIKEY_NO_MATCH';
      return false;
    }

    /* Sign the request to see if it matches signature from server. */
    $signature = $this->sign($response);
    if($signature !== $response['h']) {
      $this->lastError = 'YUBIKEY_BAD_SERVER_SIGNATURE';<commit_msg>Fixes bug in setting error message.<commit_after><?php namespace phpSec\Auth;
/**
  phpSec - A PHP security library

  @author    <NAME> <<EMAIL>>
  @copyright Copyright (c) <NAME>, 2011
  @link      https://github.com/phpsec/phpSec
  @license   http://opensource.org/licenses/mit-license.php The MIT License
  @package   phpSec
 */
use phpSec\Crypt\Rand;

/**
 * Implements validation of Yubikey against Yubico servers.
 * @package phpSec
 */
class Yubikey {
  /**
   * Yubico client Id.
   * @see https://upgrade.yubico.com/getapikey/
   */
  public $clientId = null;

  /**
   * Yubico client shared secret.
   * @see https://upgrade.yubico.com/getapikey/
   */
  public $clientSecret = null;

  /**
   * Number of servers to try before giving up.
   */
  public $_numServers = 3;

  /**
   * Timeout in seconds for each server.
   */
  public $_serverTimeout = 3;

  /**
   * Last error produced by phpsecYubikey::verify().
   * @see https://phpseclib.com/manual/09-Yubikey-Authentication.md
   */
  public $lastError = null;

  /**
   * Yubico authentication servers.
   */
  private $_servers = array(
    'http://api.yubico.com/wsapi/2.0/verify',
    'http://api2.yubico.com/wsapi/2.0/verify',
    'http://api3.yubico.com/wsapi/2.0/verify',
    'http://api4.yubico.com/wsapi/2.0/verify',
    'http://api5.yubico.com/wsapi/2.0/verify',
  );

  /**
   * phpSec core Pimple container.
   */
  private $psl = null;

  /**
   * Constructor.
   *
   * @param \phpSec\Core $psl
   *   phpSec core Pimple container.
   */
  public function __construct(\phpSec\Core $psl) {
    $this->psl = $psl;
  }

  /**
   * Verify Yubikey one time password against the Yubico servers.
   *
   * @param string $otp
   *   One time password to verify.
   *
   * @return boolean
   *   True on valid OTP, false on invalid. If this method returns false
   *   $lastError will contain details.
   *
   * @see https://phpseclib.com/manual/09-Yubikey-Authentication.md
   */
  public function verify($otp) {
    $rand = $this->psl['crypt/rand'];

    if($this->clientId === null || $this->clientSecret === null) {
      $this->lastError = 'YUBIKEY_CLIENT_DATA_NEEDED';
      return false;
    }

    if(!self::validOtp($otp)) {
      $this->lastError = 'YUBIKEY_INVALID_OTP';
      return false;
    }
    /* Setup the data needed to make the request. */
    $data['otp']       = $otp;
    $data['id']        = $this->clientId;
    $data['nonce']     = $rand->str(20);
    $data['timestamp'] = 1;
    $data['h']         = $this->sign($data);

    /* Do the request. */
    $response = $this->getResponse($data);
    if($response === false) {
      $this->lastError = 'YUBIKEY_SERVER_ERROR';
      return false;
    }

    /* Check status of response. If not OK return false. */
    if($response['status'] != 'OK') {
      switch($response['status']) {
        case 'REPLAYED_OTP':
          $this->lastError = 'YUBIKEY_SERVER_REPLAYED_OTP';
          break;
        case 'REPLAYED_REQUEST':
          $this->lastError = 'YUBIKEY_SERVER_REPLAYED_REQUEST';
          break;
        case 'BAD_OTP':
          $this->lastError = 'YUBIKEY_SERVER_BAD_OTP';
          break;
        case 'NO_SUCH_CLIENT':
          $this->lastError = 'YUBIKEY_SERVER_NO_SUCH_CLIENT';
          break;
        case 'BAD_SIGNATURE':
          $this->lastError = 'YUBIKEY_SERVER_BAD_SIGNATURE';
          break;
        default:
          $this->lastError = 'YUBIKEY_SERVER_SAYS_NO';
          break;
      }
      return false;
    }

    /* If tokens don't match return false. */
    if($response['otp'] != $otp) {
      $this->lastError = 'YUBIKEY_NO_MATCH';
      return false;
    }

    /* Sign the request to see if it matches signature from server. */
    $signature = $this->sign($response);
    if($signature !== $response['h']) {
      $this->lastError = 'YUBIKEY_BAD_SERVER_SIGNATURE';
{'fraction_non_alphanumeric': 0.15102200234344487, 'fraction_numerical': 0.00703033459185002, 'mean_word_length': 2.4187805963506896, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 51, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6785927', 'n_tokens_mistral': 2728, 'n_tokens_neox': 2655, 'n_words': 550}