GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 6e7d81...a2520d )
by Daniel
03:15
created

SslCertificate::appliesToUrl()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 8
nop 1
dl 0
loc 21
ccs 10
cts 11
cp 0.9091
crap 5.0187
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
namespace LiquidWeb\SslCertificate;
4
5
use Carbon\Carbon;
6
use phpseclib\Math\BigInteger;
7
8
class SslCertificate
9
{
10
    /** @var bool */
11
    protected $trusted;
12
13
    /** @var bool */
14
    protected $revoked;
15
16
    /** @var string */
17
    protected $ip;
18
19
    /** @var BigInteger */
20
    protected $serial;
21
22
    /** @var string */
23
    protected $testedDomain;
24
25
    /** @var array */
26
    protected $certificateFields = [];
27
28
    /** @var array */
29
    protected $certificateChains = [];
30
31
    /** @var array */
32
    protected $connectionMeta = [];
33
34
    /** @var SslRevocationList */
35
    protected $crl;
36
37
    /** @var array */
38
    protected $crlLinks = [];
39
40
    /** @var Carbon */
41
    protected $revokedTime;
42
43 1
    public static function createForHostName(string $url, int $timeout = 30): SslCertificate
44
    {
45 1
        $downloadResults = Downloader::downloadCertificateFromUrl($url, $timeout);
46
47 1
        return new static($downloadResults);
48
    }
49
50 2
    private static function extractCrlLinks($rawCrlPoints): string
51
    {
52 2
        $tempCrlItem = explode('URI:', $rawCrlPoints);
53 2
        $cleanCrlItem = trim($tempCrlItem[1]);
54
55 2
        return $cleanCrlItem;
56
    }
57
58 2
    private static function parseCrlLinks($rawCrlInput): array
59
    {
60 2
        $crlLinks = [];
61 2
        $crlRawItems = explode('Full Name:', $rawCrlInput);
62
        // Remove the stuff before the first 'Full Name:' item
63 2
        array_splice($crlRawItems, 0, 1);
64 2
        foreach ($crlRawItems as $item) {
65 2
            $crlLink = self::extractCrlLinks($item);
66 2
            array_push($crlLinks, $crlLink);
67 2
            unset($crlLink);
68
        }
69
70 2
        return $crlLinks;
71
    }
72
73 2
    private function getRevokedDate()
74
    {
75 2
        foreach ($this->crl->getRevokedList() as $broke) {
76 2
            if ($this->serial->equals($broke['userCertificate'])) {
77 2
                return new Carbon($broke['revocationDate']['utcTime']);
78
            }
79
        }
80 1
    }
81
82 2
    private function isClrRevoked()
83
    {
84 2
        if (! $this->hasCrlLink()) {
85
            return;
86
        }
87 2
        foreach ($this->crl->getRevokedList() as $broke) {
88 2
            if ($this->serial->equals($broke['userCertificate'])) {
89 1
                $this->trusted = false;
90
91 2
                return true;
92
            }
93
        }
94
95 1
        return false;
96
    }
97
98 22
    private static function parseCertChains(array $chains): array
99
    {
100 22
        $output = [];
101 22
        foreach ($chains as $cert) {
102 22
            array_push($output, new SslChain($cert));
103
        }
104
105 22
        return $output;
106
    }
107
108 22
    public function __construct(array $downloadResults)
109
    {
110 22
        $this->ip = $downloadResults['dns-resolves-to'];
111 22
        $this->serial = new BigInteger($downloadResults['cert']['serialNumber']);
112 22
        $this->testedDomain = $downloadResults['tested'];
113 22
        $this->trusted = $downloadResults['trusted'];
114 22
        $this->certificateFields = $downloadResults['cert'];
115 22
        $this->certificateChains = self::parseCertChains($downloadResults['full_chain']);
116 22
        $this->connectionMeta = $downloadResults['connection'];
117
118 22
        if (isset($downloadResults['cert']['extensions']['crlDistributionPoints'])) {
119 2
            $this->crlLinks = self::parseCrlLinks($downloadResults['cert']['extensions']['crlDistributionPoints']);
120 2
            $this->crl = SslRevocationList::createFromUrl($this->getCrlLinks()[0]);
121 2
            $this->revoked = $this->isClrRevoked();
122 2
            $this->revokedTime = $this->getRevokedDate();
123
        }
124 22
    }
125
126 2
    public function hasSslChain(): bool
127
    {
128 2
        if (isset($this->certificateChains) && count($this->certificateChains) >= 1) {
129 1
            return true;
130
        }
131
132 1
        return false;
133
    }
134
135 1
    public function getTestedDomain(): string
136
    {
137 1
        return $this->testedDomain;
138
    }
139
140 1
    public function getCertificateFields(): array
141
    {
142 1
        return $this->certificateFields;
143
    }
144
145 1
    public function getCertificateChains(): array
146
    {
147 1
        return $this->certificateChains;
148
    }
149
150 1
    public function getSerialNumber(): string
151
    {
152 1
        return strtoupper($this->serial->toHex());
153
    }
154
155 2
    public function hasCrlLink(): bool
156
    {
157 2
        return isset($this->certificateFields['extensions']['crlDistributionPoints']);
158
    }
159
160 2
    public function getCrlLinks()
161
    {
162 2
        if (! $this->hasCrlLink()) {
163
            return;
164
        }
165
166 2
        return $this->crlLinks;
167
    }
168
169
    public function getCrl()
170
    {
171
        if (! $this->hasCrlLink()) {
172
            return;
173
        }
174
175
        return $this->crl;
176
    }
177
178 6
    public function isRevoked()
179
    {
180 6
        return $this->revoked;
181
    }
182
183 1
    public function getCrlRevokedTime()
184
    {
185 1
        if ($this->isRevoked()) {
186 1
            return $this->revokedTime;
187
        }
188
    }
189
190 1
    public function getResolvedIp(): string
191
    {
192 1
        return $this->ip;
193
    }
194
195 1
    public function getIssuer(): string
196
    {
197 1
        return $this->certificateFields['issuer']['CN'];
198
    }
199
200 7
    public function getDomain(): string
201
    {
202 7
        return $this->certificateFields['subject']['CN'] ?? '';
203
    }
204
205 1
    public function getSignatureAlgorithm(): string
206
    {
207 1
        return $this->certificateFields['signatureTypeSN'] ?? '';
208
    }
209
210 6
    public function getAdditionalDomains(): array
211
    {
212 6
        $additionalDomains = explode(', ', $this->certificateFields['extensions']['subjectAltName'] ?? '');
213
214 6
        return array_map(function (string $domain) {
215 6
            return str_replace('DNS:', '', $domain);
216 6
        }, $additionalDomains);
217
    }
218
219
    public function getConnectionMeta(): array
220
    {
221
        return $this->connectionMeta;
222
    }
223
224 6
    public function validFromDate(): Carbon
225
    {
226 6
        return Carbon::createFromTimestampUTC($this->certificateFields['validFrom_time_t']);
227
    }
228
229 7
    public function expirationDate(): Carbon
230
    {
231 7
        return Carbon::createFromTimestampUTC($this->certificateFields['validTo_time_t']);
232
    }
233
234 1
    public function isExpired(): bool
235
    {
236 1
        return $this->expirationDate()->isPast();
237
    }
238
239 1
    public function isTrusted(): bool
240
    {
241 1
        return $this->trusted;
242
    }
243
244 5
    public function isValid(string $url = null): bool
245
    {
246
        // Verify SSL not expired
247 5
        if (! Carbon::now()->between($this->validFromDate(), $this->expirationDate())) {
248 2
            return false;
249
        }
250
        // If a URL is provided verify the SSL applies to the domain
251 5
        if ($this->appliesToUrl($url ?? $this->getDomain()) === false) {
252 1
            return false;
253
        }
254
        // Check SerialNumber for CRL list
255 5
        if ($this->isRevoked()) {
256 1
            return false;
257
        }
258
259 4
        return true;
260
    }
261
262 1
    public function isValidUntil(Carbon $carbon, string $url = null): bool
263
    {
264 1
        if ($this->expirationDate()->gt($carbon)) {
265 1
            return false;
266
        }
267
268 1
        return $this->isValid($url);
269
    }
270
271 5
    public function appliesToUrl(string $url): bool
272
    {
273 5
        if (starts_with($url, '*.') === true) {
274
            $url = substr($url, 2);
275
        }
276 5
        $host = (new Url($url))->getHostName();
277
278 5
        $certificateHosts = array_merge([$this->getDomain()], $this->getAdditionalDomains());
279
280 5
        foreach ($certificateHosts as $certificateHost) {
281 5
            if ($host === $certificateHost) {
282 5
                return true;
283
            }
284
285 1
            if ($this->wildcardHostCoversHost($certificateHost, $host)) {
286 1
                return true;
287
            }
288
        }
289
290 1
        return false;
291
    }
292
293 1
    protected function wildcardHostCoversHost(string $wildcardHost, string $host): bool
294
    {
295 1
        if (! starts_with($wildcardHost, '*')) {
296 1
            return false;
297
        }
298
299 1
        $wildcardHostWithoutWildcard = substr($wildcardHost, 2);
300
301 1
        return ends_with($host, $wildcardHostWithoutWildcard);
302
    }
303
}
304