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 ( 14fda8...a01f18 )
by Freek
02:10
created

SslCertificate::wildcardHostCoversHost()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 2
dl 0
loc 20
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\SslCertificate;
4
5
use Carbon\Carbon;
6
use Spatie\Macroable\Macroable;
7
8
class SslCertificate
9
{
10
    use Macroable;
11
12
    /** @var array */
13
    protected $rawCertificateFields = [];
14
15
    /** @var string */
16
    protected $fingerprint = '';
17
18
    public static function download(): Downloader
19
    {
20
        return new Downloader();
21
    }
22
23
    public static function createForHostName(string $url, int $timeout = 30): self
24
    {
25
        $sslCertificate = Downloader::downloadCertificateFromUrl($url, $timeout);
26
27
        return $sslCertificate;
28
    }
29
30
    public function __construct(array $rawCertificateFields, string $fingerprint = '')
31
    {
32
        $this->rawCertificateFields = $rawCertificateFields;
33
34
        $this->fingerprint = $fingerprint;
35
    }
36
37
    public function getRawCertificateFields(): array
38
    {
39
        return $this->rawCertificateFields;
40
    }
41
42
    public function getIssuer(): string
43
    {
44
        return $this->rawCertificateFields['issuer']['CN'] ?? '';
45
    }
46
47
    public function getDomain(): string
48
    {
49
        if (! array_key_exists('CN', $this->rawCertificateFields['subject'])) {
50
            return '';
51
        }
52
53
        if (is_string($this->rawCertificateFields['subject']['CN'])) {
54
            return $this->rawCertificateFields['subject']['CN'];
55
        }
56
57
        if (is_array($this->rawCertificateFields['subject']['CN'])) {
58
            return $this->rawCertificateFields['subject']['CN'][0];
59
        }
60
61
        return '';
62
    }
63
64
    public function getSignatureAlgorithm(): string
65
    {
66
        return $this->rawCertificateFields['signatureTypeSN'] ?? '';
67
    }
68
69
    public function getFingerprint(): string
70
    {
71
        return $this->fingerprint;
72
    }
73
74
    public function getAdditionalDomains(): array
75
    {
76
        $additionalDomains = explode(', ', $this->rawCertificateFields['extensions']['subjectAltName'] ?? '');
77
78
        return array_map(function (string $domain) {
79
            return str_replace('DNS:', '', $domain);
80
        }, $additionalDomains);
81
    }
82
83
    public function validFromDate(): Carbon
84
    {
85
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validFrom_time_t']);
86
    }
87
88
    public function expirationDate(): Carbon
89
    {
90
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validTo_time_t']);
91
    }
92
93
    public function isExpired(): bool
94
    {
95
        return $this->expirationDate()->isPast();
96
    }
97
98
    public function isValid(string $url = null)
99
    {
100
        if (! Carbon::now()->between($this->validFromDate(), $this->expirationDate())) {
101
            return false;
102
        }
103
104
        if (! empty($url)) {
105
            return $this->appliesToUrl($url ?? $this->getDomain());
106
        }
107
108
        return true;
109
    }
110
111
    public function isSelfSigned(): bool
112
    {
113
        return $this->getIssuer() === $this->getDomain();
114
    }
115
116
    public function usesSha1Hash(): bool
117
    {
118
        $certificateFields = $this->getRawCertificateFields();
119
120
        if ($certificateFields['signatureTypeSN'] === 'RSA-SHA1') {
121
            return true;
122
        }
123
124
        if ($certificateFields['signatureTypeLN'] === 'sha1WithRSAEncryption') {
125
            return true;
126
        }
127
128
        return false;
129
    }
130
131
    public function isValidUntil(Carbon $carbon, string $url = null): bool
132
    {
133
        if ($this->expirationDate()->lte($carbon)) {
134
            return false;
135
        }
136
137
        return $this->isValid($url);
138
    }
139
140
    public function daysUntilExpirationDate(): int
141
    {
142
        $endDate = $this->expirationDate();
143
144
        $interval = Carbon::now()->diff($endDate);
145
146
        return (int) $interval->format('%r%a');
147
    }
148
149
    public function getDomains(): array
150
    {
151
        $allDomains = $this->getAdditionalDomains();
152
153
        $uniqueDomains = array_unique($allDomains);
154
155
        return array_values(array_filter($uniqueDomains));
156
    }
157
158
    public function appliesToUrl(string $url): bool
159
    {
160
        $host = (new Url($url))->getHostName();
161
162
        $certificateHosts = $this->getDomains();
163
164
        foreach ($certificateHosts as $certificateHost) {
165
            if ($host === $certificateHost) {
166
                return true;
167
            }
168
169
            if ($this->wildcardHostCoversHost($certificateHost, $host)) {
170
                return true;
171
            }
172
        }
173
174
        return false;
175
    }
176
177
    protected function wildcardHostCoversHost(string $wildcardHost, string $host): bool
178
    {
179
        if ($host === $wildcardHost) {
180
            return true;
181
        }
182
183
        if (! starts_with($wildcardHost, '*')) {
184
            return false;
185
        }
186
187
        if (substr_count($wildcardHost, '.') < substr_count($host, '.')) {
188
            return false;
189
        }
190
191
        $wildcardHostWithoutWildcard = substr($wildcardHost, 1);
192
193
        $hostWithDottedPrefix = ".{$host}";
194
195
        return ends_with($hostWithDottedPrefix, $wildcardHostWithoutWildcard);
196
    }
197
198
    public function getRawCertificateFieldsJson(): string
199
    {
200
        return json_encode($this->getRawCertificateFields());
201
    }
202
203
    public function getHash(): string
204
    {
205
        return md5($this->getRawCertificateFieldsJson());
206
    }
207
208
    public function __toString(): string
209
    {
210
        return $this->getRawCertificateFieldsJson();
211
    }
212
213
    public function containsDomain(string $domain): bool
214
    {
215
        $certificateHosts = $this->getDomains();
216
217
        foreach ($certificateHosts as $certificateHost) {
218
            if ($certificateHost == $domain) {
219
                return true;
220
            }
221
222
            if (ends_with($domain, '.'.$certificateHost)) {
223
                return true;
224
            }
225
        }
226
227
        return false;
228
    }
229
}
230