mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-06 03:16:17 +03:00
fix(client-certificates): report error to the browser if incorrect passphrase (#32007)
This commit is contained in:
parent
dbc4bc84d6
commit
71e614dc5a
@ -142,34 +142,14 @@ class SocksProxyConnection {
|
||||
dummyServer.emit('connection', this.internal);
|
||||
dummyServer.on('secureConnection', internalTLS => {
|
||||
debugLogger.log('client-certificates', `Browser->Proxy ${this.host}:${this.port} chooses ALPN ${internalTLS.alpnProtocol}`);
|
||||
const tlsOptions: tls.ConnectionOptions = {
|
||||
socket: this.target,
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
rejectUnauthorized: !this.socksProxy.ignoreHTTPSErrors,
|
||||
ALPNProtocols: [internalTLS.alpnProtocol || 'http/1.1'],
|
||||
...clientCertificatesToTLSOptions(this.socksProxy.clientCertificates, new URL(`https://${this.host}:${this.port}`).origin),
|
||||
};
|
||||
if (!net.isIP(this.host))
|
||||
tlsOptions.servername = this.host;
|
||||
const targetTLS = tls.connect(tlsOptions);
|
||||
|
||||
targetTLS.on('secureConnect', () => {
|
||||
internalTLS.pipe(targetTLS);
|
||||
targetTLS.pipe(internalTLS);
|
||||
});
|
||||
|
||||
// Handle close and errors
|
||||
let targetTLS: tls.TLSSocket | undefined = undefined;
|
||||
const closeBothSockets = () => {
|
||||
internalTLS.end();
|
||||
targetTLS.end();
|
||||
targetTLS?.end();
|
||||
};
|
||||
|
||||
internalTLS.on('end', () => closeBothSockets());
|
||||
targetTLS.on('end', () => closeBothSockets());
|
||||
|
||||
internalTLS.on('error', () => closeBothSockets());
|
||||
targetTLS.on('error', error => {
|
||||
const handleError = (error: Error) => {
|
||||
debugLogger.log('client-certificates', `error when connecting to target: ${error.message}`);
|
||||
const responseBody = 'Playwright client-certificate error: ' + error.message;
|
||||
if (internalTLS?.alpnProtocol === 'h2') {
|
||||
@ -204,7 +184,38 @@ class SocksProxyConnection {
|
||||
].join('\r\n'));
|
||||
closeBothSockets();
|
||||
}
|
||||
};
|
||||
|
||||
let secureContext: tls.SecureContext;
|
||||
try {
|
||||
secureContext = tls.createSecureContext(clientCertificatesToTLSOptions(this.socksProxy.clientCertificates, new URL(`https://${this.host}:${this.port}`).origin));
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const tlsOptions: tls.ConnectionOptions = {
|
||||
socket: this.target,
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
rejectUnauthorized: !this.socksProxy.ignoreHTTPSErrors,
|
||||
ALPNProtocols: [internalTLS.alpnProtocol || 'http/1.1'],
|
||||
servername: !net.isIP(this.host) ? this.host : undefined,
|
||||
secureContext,
|
||||
};
|
||||
|
||||
targetTLS = tls.connect(tlsOptions);
|
||||
|
||||
targetTLS.on('secureConnect', () => {
|
||||
internalTLS.pipe(targetTLS);
|
||||
targetTLS.pipe(internalTLS);
|
||||
});
|
||||
|
||||
internalTLS.on('end', () => closeBothSockets());
|
||||
targetTLS.on('end', () => closeBothSockets());
|
||||
|
||||
internalTLS.on('error', () => closeBothSockets());
|
||||
targetTLS.on('error', handleError);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ openssl x509 \
|
||||
-out client/trusted/cert.pem \
|
||||
-set_serial 01 \
|
||||
-days 365
|
||||
# create pfx
|
||||
openssl pkcs12 -export -out client/trusted/cert.pfx -inkey client/trusted/key.pem -in client/trusted/cert.pem -passout pass:secure
|
||||
```
|
||||
|
||||
## Self-signed certificate (invalid)
|
||||
|
BIN
tests/assets/client-certificates/client/trusted/cert.pfx
Normal file
BIN
tests/assets/client-certificates/client/trusted/cert.pfx
Normal file
Binary file not shown.
@ -257,6 +257,36 @@ test.describe('browser', () => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test('should pass with matching certificates in pfx format', async ({ browser, startCCServer, asset, browserName }) => {
|
||||
const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && process.platform === 'darwin' });
|
||||
const page = await browser.newPage({
|
||||
ignoreHTTPSErrors: true,
|
||||
clientCertificates: [{
|
||||
origin: new URL(serverURL).origin,
|
||||
pfxPath: asset('client-certificates/client/trusted/cert.pfx'),
|
||||
passphrase: 'secure'
|
||||
}],
|
||||
});
|
||||
await page.goto(serverURL);
|
||||
await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!');
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test('should throw a http error if the pfx passphrase is incorect', async ({ browser, startCCServer, asset, browserName }) => {
|
||||
const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && process.platform === 'darwin' });
|
||||
const page = await browser.newPage({
|
||||
ignoreHTTPSErrors: true,
|
||||
clientCertificates: [{
|
||||
origin: new URL(serverURL).origin,
|
||||
pfxPath: asset('client-certificates/client/trusted/cert.pfx'),
|
||||
passphrase: 'this-password-is-incorrect'
|
||||
}],
|
||||
});
|
||||
await page.goto(serverURL);
|
||||
await expect(page.getByText('Playwright client-certificate error: mac verify failure')).toBeVisible();
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test('should pass with matching certificates on context APIRequestContext instance', async ({ browser, startCCServer, asset, browserName }) => {
|
||||
const serverURL = await startCCServer({ host: '127.0.0.1' });
|
||||
const baseOptions = {
|
||||
|
Loading…
Reference in New Issue
Block a user