|
1 | 1 | import fs from 'node:fs' |
2 | 2 | import path from 'node:path' |
| 3 | +import crypto from 'node:crypto' |
3 | 4 | import { describe, expect, test } from 'vitest' |
4 | 5 | import { |
5 | 6 | asyncFlatten, |
6 | 7 | bareImportRE, |
| 8 | + extractHostnamesFromSubjectAltName, |
7 | 9 | flattenId, |
8 | 10 | generateCodeFrame, |
9 | 11 | getHash, |
@@ -165,6 +167,59 @@ describe('resolveHostname', () => { |
165 | 167 | }) |
166 | 168 | }) |
167 | 169 |
|
| 170 | +describe('extractHostnamesFromSubjectAltName', () => { |
| 171 | + const testCases = [ |
| 172 | + ['DNS:localhost', ['localhost']], |
| 173 | + ['DNS:localhost, DNS:foo.localhost', ['localhost', 'foo.localhost']], |
| 174 | + ['DNS:*.localhost', ['vite.localhost']], |
| 175 | + ['DNS:[::1]', []], // [::1] is skipped |
| 176 | + ['othername:"foo,bar", DNS:localhost', ['localhost']], // handle quoted correctly |
| 177 | + ] as const |
| 178 | + |
| 179 | + for (const [input, expected] of testCases) { |
| 180 | + test(`should extract names from subjectAltName: ${input}`, () => { |
| 181 | + expect(extractHostnamesFromSubjectAltName(input)).toStrictEqual(expected) |
| 182 | + }) |
| 183 | + } |
| 184 | + |
| 185 | + test('should extract names from actual certificate', () => { |
| 186 | + const certText = ` |
| 187 | +-----BEGIN CERTIFICATE----- |
| 188 | +MIID7zCCAtegAwIBAgIJS9D2rIN7tA8mMA0GCSqGSIb3DQEBCwUAMGkxFDASBgNV |
| 189 | +BAMTC2V4YW1wbGUub3JnMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWEx |
| 190 | +EzARBgNVBAcTCkJsYWNrc2J1cmcxDTALBgNVBAoTBFRlc3QxDTALBgNVBAsTBFRl |
| 191 | +c3QwHhcNMjUwMTMwMDQxNTI1WhcNMjUwMzAxMDQxNTI1WjBpMRQwEgYDVQQDEwtl |
| 192 | +eGFtcGxlLm9yZzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYD |
| 193 | +VQQHEwpCbGFja3NidXJnMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MIIB |
| 194 | +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxNPlCqTmUZ7/F7GyFWDopqZ6 |
| 195 | +w19Y7/98B10JEeFGTAQIj/RP2UgZNcTABQDUvtkF7y+bOeoVJW7Zz8ozQYhRaDp8 |
| 196 | +CN2gXMcYeTUku/pKLXyCzHHVrOPAXTeU7sMRgLvPCrrJtx5OjvndW+O/PhohPRi3 |
| 197 | +iEpPvpM8gi7MVRGhnWVSx0/Ynx5c0+/vqyBTzrM2OX7Ufg8Nv7LaTXpCAnmIQp+f |
| 198 | +Sqq7HZ7t6Y7laS4RApityvlnFHZ4f2cEibAKv/vXLED7bgAlGb8R1viPRdMtAPuI |
| 199 | +MYvHBgGFjyX1fmq6Mz3aqlAscJILtbQlwty1oYyaENE0lq8+nZXQ+t6I+CIVLQID |
| 200 | +AQABo4GZMIGWMAsGA1UdDwQEAwIC9DAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYB |
| 201 | +BQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDCDBUBgNVHREETTBLgglsb2NhbGhvc3SC |
| 202 | +DWZvby5sb2NhbGhvc3SCECoudml0ZS5sb2NhbGhvc3SCBVs6OjFdhwR/AAABhxD+ |
| 203 | +gAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBi302qLCgxWsUalgc2 |
| 204 | +olFxVKob1xCciS8yUVX6HX0vza0WJ7oGW6qZsBbQtfgDwB/dHv7rwsfpjRWvFhmq |
| 205 | +gEUrewa1h0TIC+PPTYYz4M0LOwcLIWZLZr4am1eI7YP9NDgRdhfAfM4hw20vjf2a |
| 206 | +kYLKyRTC5+3/ly5opMq+CGLQ8/gnFxhP3ho8JYrRnqLeh3KCTGen3kmbAhD4IOJ9 |
| 207 | +lxMwFPTTWLFFjxbXjXmt5cEiL2mpcq13VCF2HmheCen37CyYIkrwK9IfLhBd5QQh |
| 208 | +WEIBLwjKCAscrtyayXWp6zUTmgvb8PQf//3Mh2DiEngAi3WI/nL+8Y0RkqbvxBar |
| 209 | +X2JN |
| 210 | +-----END CERTIFICATE----- |
| 211 | + `.trim() |
| 212 | + const cert = new crypto.X509Certificate(certText) |
| 213 | + expect( |
| 214 | + extractHostnamesFromSubjectAltName(cert.subjectAltName ?? ''), |
| 215 | + ).toStrictEqual([ |
| 216 | + 'localhost', |
| 217 | + 'foo.localhost', |
| 218 | + 'vite.vite.localhost', // *.vite.localhost |
| 219 | + ]) |
| 220 | + }) |
| 221 | +}) |
| 222 | + |
168 | 223 | describe('posToNumber', () => { |
169 | 224 | test('simple', () => { |
170 | 225 | const actual = posToNumber('a\nb', { line: 2, column: 0 }) |
|
0 commit comments