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 ( 4fdfe3...3b1798 )
by Freek
01:14
created

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