[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/Requests/ -> SSL.php (source)

   1  <?php
   2  /**
   3   * SSL utilities for Requests
   4   *
   5   * @package Requests
   6   * @subpackage Utilities
   7   */
   8  
   9  /**
  10   * SSL utilities for Requests
  11   *
  12   * Collection of utilities for working with and verifying SSL certificates.
  13   *
  14   * @package Requests
  15   * @subpackage Utilities
  16   */
  17  class Requests_SSL {
  18      /**
  19       * Verify the certificate against common name and subject alternative names
  20       *
  21       * Unfortunately, PHP doesn't check the certificate against the alternative
  22       * names, leading things like 'https://www.github.com/' to be invalid.
  23       *
  24       * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
  25       *
  26       * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
  27       * @param string $host Host name to verify against
  28       * @param array $cert Certificate data from openssl_x509_parse()
  29       * @return bool
  30       */
  31  	public static function verify_certificate($host, $cert) {
  32          $has_dns_alt = false;
  33  
  34          // Check the subjectAltName
  35          if (!empty($cert['extensions']) && !empty($cert['extensions']['subjectAltName'])) {
  36              $altnames = explode(',', $cert['extensions']['subjectAltName']);
  37              foreach ($altnames as $altname) {
  38                  $altname = trim($altname);
  39                  if (strpos($altname, 'DNS:') !== 0) {
  40                      continue;
  41                  }
  42  
  43                  $has_dns_alt = true;
  44  
  45                  // Strip the 'DNS:' prefix and trim whitespace
  46                  $altname = trim(substr($altname, 4));
  47  
  48                  // Check for a match
  49                  if (self::match_domain($host, $altname) === true) {
  50                      return true;
  51                  }
  52              }
  53          }
  54  
  55          // Fall back to checking the common name if we didn't get any dNSName
  56          // alt names, as per RFC2818
  57          if (!$has_dns_alt && !empty($cert['subject']['CN'])) {
  58              // Check for a match
  59              if (self::match_domain($host, $cert['subject']['CN']) === true) {
  60                  return true;
  61              }
  62          }
  63  
  64          return false;
  65      }
  66  
  67      /**
  68       * Verify that a reference name is valid
  69       *
  70       * Verifies a dNSName for HTTPS usage, (almost) as per Firefox's rules:
  71       * - Wildcards can only occur in a name with more than 3 components
  72       * - Wildcards can only occur as the last character in the first
  73       *   component
  74       * - Wildcards may be preceded by additional characters
  75       *
  76       * We modify these rules to be a bit stricter and only allow the wildcard
  77       * character to be the full first component; that is, with the exclusion of
  78       * the third rule.
  79       *
  80       * @param string $reference Reference dNSName
  81       * @return boolean Is the name valid?
  82       */
  83  	public static function verify_reference_name($reference) {
  84          $parts = explode('.', $reference);
  85  
  86          // Check the first part of the name
  87          $first = array_shift($parts);
  88  
  89          if (strpos($first, '*') !== false) {
  90              // Check that the wildcard is the full part
  91              if ($first !== '*') {
  92                  return false;
  93              }
  94  
  95              // Check that we have at least 3 components (including first)
  96              if (count($parts) < 2) {
  97                  return false;
  98              }
  99          }
 100  
 101          // Check the remaining parts
 102          foreach ($parts as $part) {
 103              if (strpos($part, '*') !== false) {
 104                  return false;
 105              }
 106          }
 107  
 108          // Nothing found, verified!
 109          return true;
 110      }
 111  
 112      /**
 113       * Match a hostname against a dNSName reference
 114       *
 115       * @param string $host Requested host
 116       * @param string $reference dNSName to match against
 117       * @return boolean Does the domain match?
 118       */
 119  	public static function match_domain($host, $reference) {
 120          // Check if the reference is blocklisted first
 121          if (self::verify_reference_name($reference) !== true) {
 122              return false;
 123          }
 124  
 125          // Check for a direct match
 126          if ($host === $reference) {
 127              return true;
 128          }
 129  
 130          // Calculate the valid wildcard match if the host is not an IP address
 131          // Also validates that the host has 3 parts or more, as per Firefox's
 132          // ruleset.
 133          if (ip2long($host) === false) {
 134              $parts    = explode('.', $host);
 135              $parts[0] = '*';
 136              $wildcard = implode('.', $parts);
 137              if ($wildcard === $reference) {
 138                  return true;
 139              }
 140          }
 141  
 142          return false;
 143      }
 144  }


Generated: Thu Dec 15 01:00:02 2022 Cross-referenced by PHPXref 0.7.1