WP_Http_Streams::verify_ssl_certificate

Advertisement

Summery Summery

Verifies the received SSL certificate against its Common Names and subjectAltName fields.

Syntax Syntax

WP_Http_Streams::verify_ssl_certificate( stream $stream, string $host )

Description Description

PHP’s SSL verifications only verify that it’s a valid Certificate, it doesn’t verify if the certificate is valid for the hostname which was requested. This function verifies the requested hostname against certificate’s subjectAltName field, if that is empty, or contains no DNS entries, a fallback to the Common Name field is used.

IP Address support is included if the request is being made to an IP address.

Parameters Parameters

$stream

(Required) The PHP Stream which the SSL request is being made over

$host

(Required) The hostname being requested

Return Return

(bool) If the cerficiate presented in $stream is valid for $host

Source Source

File: wp-includes/class-wp-http-streams.php

	 * @return bool If the cerficiate presented in $stream is valid for $host
	 */
	public static function verify_ssl_certificate( $stream, $host ) {
		$context_options = stream_context_get_options( $stream );

		if ( empty( $context_options['ssl']['peer_certificate'] ) ) {
			return false;
		}

		$cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] );
		if ( ! $cert ) {
			return false;
		}

		/*
		 * If the request is being made to an IP address, we'll validate against IP fields
		 * in the cert (if they exist)
		 */
		$host_type = ( WP_Http::is_ip_address( $host ) ? 'ip' : 'dns' );

		$certificate_hostnames = array();
		if ( ! empty( $cert['extensions']['subjectAltName'] ) ) {
			$match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] );
			foreach ( $match_against as $match ) {
				list( $match_type, $match_host ) = explode( ':', $match );
				if ( strtolower( trim( $match_type ) ) === $host_type ) { // IP: or DNS:
					$certificate_hostnames[] = strtolower( trim( $match_host ) );
				}
			}
		} elseif ( ! empty( $cert['subject']['CN'] ) ) {
			// Only use the CN when the certificate includes no subjectAltName extension.
			$certificate_hostnames[] = strtolower( $cert['subject']['CN'] );
		}

		// Exact hostname/IP matches.
		if ( in_array( strtolower( $host ), $certificate_hostnames, true ) ) {
			return true;
		}

		// IP's can't be wildcards, Stop processing.
		if ( 'ip' === $host_type ) {
			return false;
		}

		// Test to see if the domain is at least 2 deep for wildcard support.
		if ( substr_count( $host, '.' ) < 2 ) {
			return false;
		}

		// Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com.
		$wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host );

Advertisement

Changelog Changelog

Changelog
Version Description
3.7.0 Introduced.

Advertisement

Leave a Reply