You are here

public function HttpblEvaluator::evaluateVisitor in http:BL 8

Manages remote and local lookups on visiting host IPs, evaluates their remote status as safe or suspicious and determines a locally stored status (safe / white-listed, grey-listed, or blacklisted) which is used (by other functions) to determine an appropriate, subsequent response to a request.

Overrides HttpblEvaluatorInterface::evaluateVisitor

File

src/HttpblEvaluator.php, line 147

Class

HttpblEvaluator
HttpblEvaluator evaluates visitor/host page requests.

Namespace

Drupal\httpbl

Code

public function evaluateVisitor($ip, $request, $project_supported) {

  // Evaluated status that was already locally stored or was calculated based on
  // a score retrieved from Project Honeypot.

  /** @var integer $evaluated_status */
  static $evaluated_status;

  // If not a supported lookup, mark "safe" and log notice.
  // This will avoid any further processing or storage.
  if (!$project_supported) {
    $evaluated_status = HTTPBL_LIST_SAFE;
    $this->logTrapper
      ->trapNotice('HttpBL evaluation not supported for IPv6 @ip.', [
      '@ip' => $ip,
    ]);
  }

  // Evaluated status was already calculated -- return.
  if (is_int($evaluated_status)) {
    $evaluated = [
      'evaluated',
      $evaluated_status,
    ];

    /** @var array $evaluated */
    return $evaluated;
  }

  // Check if visitor already has a white-listed session (granted by the white-list challenge).
  if (self::visitor_whitelisted_session($ip)) {
    $evaluated_status = HTTPBL_LIST_SAFE;
    $this->logTrapper
      ->trapDebug('@ip already session white-listed for request @request.', [
      '@ip' => $ip,
      '@request' => $request
        ->getRequestUri(),
    ]);
    $evaluated = [
      'evaluated',
      $evaluated_status,
    ];
    return $evaluated;
  }
  elseif (\Drupal::state()
    ->get('httpbl.storage') > HTTPBL_DB_OFF) {
    $evaluated_status = $this
      ->getIpLocalStatus($ip);

    //Humanize the status results for any verbose logging.
    $human = 'Not found';
    $status = $evaluated_status;
    if (is_string($evaluated_status)) {
      switch ($evaluated_status) {
        case '0':
          $human = 'white-listed';
          break;
        case '1':
          $human = 'blacklisted';
          break;
        case '2':
          $human = 'greylisted';

          // Prepare to set up a challenge response.
          $_SESSION['httpbl_ip'] = $ip;
          $_SESSION['httpbl_challenge'] = TRUE;
          break;
      }
    }
    $this->logTrapper
      ->trapDebug('Local query for @ip: @human (status = @status).', [
      '@ip' => $ip,
      '@status' => $status,
      '@human' => $human,
    ]);
  }

  // Visitor is not already white listed and not found in Httpbl table, so we'll do a DNS Lookup.
  if (!is_numeric($evaluated_status)) {
    $this->logTrapper
      ->trapDebug('Honeypot DNS Lookup for IP @ip.', [
      '@ip' => $ip,
    ]);

    // Do a Project Honeypot DNS lookup, and continue if lookup was succesful
    if ($response = $this
      ->httpbl_dnslookup($ip)) {
      $stats = \Drupal::state()
        ->get('httpbl.stats') ?: TRUE;
      $black_threshold = \Drupal::state()
        ->get('httpbl.black_threshold') ?: HTTPBL_THRESHOLD_BLACK;
      $grey_threshold = \Drupal::state()
        ->get('httpbl.grey_threshold') ?: HTTPBL_THRESHOLD_GREY;
      $score = $response['threat'];

      //@todo Someday we'll do something with the 'type' response from P.H.

      //$type = $response['type'];

      // Blacklisted?
      // (Is the threat score at Project Honeypot above our threshold?)
      if ($score > $black_threshold && $response['type']) {
        $this->logTrapper
          ->trapWarning('@ip ranked: blacklisted (Threat Score = @score).', [
          '@ip' => $ip,
          '@score' => $score,
          'link' => self::projectLink($ip),
        ]);

        // If settings indicate we are storing results...
        if (\Drupal::state()
          ->get('httpbl.storage') > HTTPBL_DB_OFF) {

          // Store this blacklisted IP.
          $this
            ->setIpLocalStatus($ip, HTTPBL_LIST_BLACK, \Drupal::state()
            ->get('httpbl.blacklist_offset') ?: 31536000);

          // Increment the stats if configured to do so.
          if ($stats) {
            \Drupal::state()
              ->set('httpbl.stat_black', \Drupal::state()
              ->get('httpbl.stat_black') + 1);
          }
        }
        $evaluated_status = HTTPBL_LIST_BLACK;
        $evaluated = [
          'evaluated',
          $evaluated_status,
        ];
        return $evaluated;
      }
      elseif ($score > $grey_threshold && $response['type']) {

        // Prepare to set up a challenge response.
        $_SESSION['httpbl_ip'] = $ip;
        $_SESSION['httpbl_challenge'] = TRUE;
        $this->logTrapper
          ->trapNotice('@ip ranked: grey-listed (Threat Score = @score).', [
          '@ip' => $ip,
          '@score' => $score,
          'link' => self::projectLink($ip),
        ]);

        // Store the results if configured to do so.
        if (\Drupal::state()
          ->get('httpbl.storage') > HTTPBL_DB_OFF) {
          $this
            ->setIpLocalStatus($ip, HTTPBL_LIST_GREY, \Drupal::state()
            ->get('httpbl.greylist_offset') ?: 86400);

          // Increment the stats if configured to do so.
          if ($stats) {
            \Drupal::state()
              ->set('httpbl.stat_grey', \Drupal::state()
              ->get('httpbl.stat_grey') + 1);
          }
        }
        $evaluated_status = HTTPBL_LIST_GREY;
        $evaluated = [
          'evaluated',
          $evaluated_status,
        ];
        return $evaluated;
      }
    }
    else {

      // No result from Project Honeypot, so log and then...
      $this->logTrapper
        ->trapInfo('No Honeypot profile for @ip. ("safe").', [
        '@ip' => $ip,
        'link' => self::projectLink($ip),
      ]);

      // If settings indicate we are storing results,
      if (\Drupal::state()
        ->get('httpbl.storage') > HTTPBL_DB_OFF) {

        // White-list locally - with configured offset settings (default is 3 hours).
        $this
          ->setIpLocalStatus($ip, HTTPBL_LIST_SAFE, \Drupal::state()
          ->get('httpbl.safe_offset') ?: 10800);
      }

      // Evaluated (assumed) Safe.
      $evaluated_status = HTTPBL_LIST_SAFE;
    }
    $evaluated = [
      'evaluated',
      $evaluated_status,
    ];
    return $evaluated;
  }
  elseif (!($evaluated_status == HTTPBL_LIST_SAFE)) {

    // This line will show when only blocking comment submissions.
    drupal_set_message(t('Your IP address (@ip) is restricted on this site.', [
      '@ip' => $ip,
    ]), 'error', FALSE);
  }

  // Fini!
  $evaluated = [
    'evaluated',
    $evaluated_status,
  ];
  return $evaluated;
}