~canonical-sysadmins/wordpress/4.8.1

« back to all changes in this revision

Viewing changes to wp-includes/Requests/SSL.php

  • Committer: Barry Price
  • Date: 2016-08-17 04:50:12 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: barry.price@canonical.com-20160817045012-qfui81zhqnqv2ba9
Merge WP4.6 from upstream

Show diffs side-by-side

added added

removed removed

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