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
Pull Request — master (#117)
by
unknown
58s
created

SslCertificate::createForCertificateString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
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
    /** @var string */
19
    private $fingerprintSha256 = '';
20
21
    /** @var string */
22
    private $remoteAddress = '';
23
24
    public static function download(): Downloader
25
    {
26
        return new Downloader();
27
    }
28
29
    public static function createForHostName(string $url, int $timeout = 30): self
30
    {
31
        return Downloader::downloadCertificateFromUrl($url, $timeout);
32
    }
33
34
    public static function createForCertificateString(string $certificateString): self
35
    {
36
        return Local::certificateAsString($certificateString);
37
    }
38
39
    public static function createForCertificatePath(string $path): self
40
    {
41
        return Local::certificateFromLocalPath($path);
42
    }
43
44
    public function __construct(
45
        array $rawCertificateFields,
46
        string $fingerprint = '',
47
        string $fingerprintSha256 = '',
48
        string $remoteAddress = '')
49
    {
50
        $this->rawCertificateFields = $rawCertificateFields;
51
52
        $this->fingerprint = $fingerprint;
53
54
        $this->fingerprintSha256 = $fingerprintSha256;
55
56
        $this->remoteAddress = $remoteAddress;
57
    }
58
59
    public function getRawCertificateFields(): array
60
    {
61
        return $this->rawCertificateFields;
62
    }
63
64
    public function getIssuer(): string
65
    {
66
        return $this->rawCertificateFields['issuer']['CN'] ?? '';
67
    }
68
69
    public function getDomain(): string
70
    {
71
        if (! array_key_exists('CN', $this->rawCertificateFields['subject'])) {
72
            return '';
73
        }
74
75
        if (is_string($this->rawCertificateFields['subject']['CN'])) {
76
            return $this->rawCertificateFields['subject']['CN'];
77
        }
78
79
        if (is_array($this->rawCertificateFields['subject']['CN'])) {
80
            return $this->rawCertificateFields['subject']['CN'][0];
81
        }
82
83
        return '';
84
    }
85
86
    public function getSignatureAlgorithm(): string
87
    {
88
        return $this->rawCertificateFields['signatureTypeSN'] ?? '';
89
    }
90
91
    public function getFingerprint(): string
92
    {
93
        return $this->fingerprint;
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function getFingerprintSha256(): string
100
    {
101
        return $this->fingerprintSha256;
102
    }
103
104
    public function getAdditionalDomains(): array
105
    {
106
        $additionalDomains = explode(', ', $this->rawCertificateFields['extensions']['subjectAltName'] ?? '');
107
108
        return array_map(function (string $domain) {
109
            return str_replace('DNS:', '', $domain);
110
        }, $additionalDomains);
111
    }
112
113
    public function validFromDate(): Carbon
114
    {
115
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validFrom_time_t']);
116
    }
117
118
    public function expirationDate(): Carbon
119
    {
120
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validTo_time_t']);
121
    }
122
123
    public function isExpired(): bool
124
    {
125
        return $this->expirationDate()->isPast();
126
    }
127
128
    public function isValid(string $url = null)
129
    {
130
        if (! Carbon::now()->between($this->validFromDate(), $this->expirationDate())) {
131
            return false;
132
        }
133
134
        if (! empty($url)) {
135
            return $this->appliesToUrl($url ?? $this->getDomain());
136
        }
137
138
        return true;
139
    }
140
141
    public function isSelfSigned(): bool
142
    {
143
        return $this->getIssuer() === $this->getDomain();
144
    }
145
146
    public function usesSha1Hash(): bool
147
    {
148
        $certificateFields = $this->getRawCertificateFields();
149
150
        if ($certificateFields['signatureTypeSN'] === 'RSA-SHA1') {
151
            return true;
152
        }
153
154
        if ($certificateFields['signatureTypeLN'] === 'sha1WithRSAEncryption') {
155
            return true;
156
        }
157
158
        return false;
159
    }
160
161
    public function isValidUntil(Carbon $carbon, string $url = null): bool
162
    {
163
        if ($this->expirationDate()->lte($carbon)) {
164
            return false;
165
        }
166
167
        return $this->isValid($url);
168
    }
169
170
    public function daysUntilExpirationDate(): int
171
    {
172
        $endDate = $this->expirationDate();
173
174
        $interval = Carbon::now()->diff($endDate);
175
176
        return (int) $interval->format('%r%a');
177
    }
178
179
    public function getDomains(): array
180
    {
181
        $allDomains = $this->getAdditionalDomains();
182
        $allDomains[] = $this->getDomain();
183
        $uniqueDomains = array_unique($allDomains);
184
185
        return array_values(array_filter($uniqueDomains));
186
    }
187
188
    public function appliesToUrl(string $url): bool
189
    {
190
        if (filter_var($url, FILTER_VALIDATE_IP)) {
191
            $host = $url;
192
        } else {
193
            $host = (new Url($url))->getHostName();
194
        }
195
196
        $certificateHosts = $this->getDomains();
197
198
        foreach ($certificateHosts as $certificateHost) {
199
            $certificateHost = str_replace('ip address:', '', strtolower($certificateHost));
200
            if ($host === $certificateHost) {
201
                return true;
202
            }
203
204
            if ($this->wildcardHostCoversHost($certificateHost, $host)) {
205
                return true;
206
            }
207
        }
208
209
        return false;
210
    }
211
212
    protected function wildcardHostCoversHost(string $wildcardHost, string $host): bool
213
    {
214
        if ($host === $wildcardHost) {
215
            return true;
216
        }
217
218
        if (! starts_with($wildcardHost, '*')) {
219
            return false;
220
        }
221
222
        if (substr_count($wildcardHost, '.') < substr_count($host, '.')) {
223
            return false;
224
        }
225
226
        $wildcardHostWithoutWildcard = substr($wildcardHost, 1);
227
228
        $hostWithDottedPrefix = ".{$host}";
229
230
        return ends_with($hostWithDottedPrefix, $wildcardHostWithoutWildcard);
231
    }
232
233
    public function getRawCertificateFieldsJson(): string
234
    {
235
        return json_encode($this->getRawCertificateFields());
236
    }
237
238
    public function getHash(): string
239
    {
240
        return md5($this->getRawCertificateFieldsJson());
241
    }
242
243
    public function getRemoteAddress(): string
244
    {
245
        return $this->remoteAddress;
246
    }
247
248
    public function __toString(): string
249
    {
250
        return $this->getRawCertificateFieldsJson();
251
    }
252
253
    public function containsDomain(string $domain): bool
254
    {
255
        $certificateHosts = $this->getDomains();
256
257
        foreach ($certificateHosts as $certificateHost) {
258
            if ($certificateHost == $domain) {
259
                return true;
260
            }
261
262
            if (ends_with($domain, '.'.$certificateHost)) {
263
                return true;
264
            }
265
        }
266
267
        return false;
268
    }
269
270
    public function isPreCertificate(): bool
271
    {
272
        if (! array_key_exists('extensions', $this->rawCertificateFields)) {
273
            return false;
274
        }
275
276
        if (! array_key_exists('ct_precert_poison', $this->rawCertificateFields['extensions'])) {
277
            return false;
278
        }
279
280
        return true;
281
    }
282
}
283