Skip to content

Commit 1b29661

Browse files
authored
Copy certificate subject from peercertificate, use ssl.PROTOCOL_TLSv1_2 for client wrap and allow TLSv1_1 for server wrap (#370)
1 parent d6e6077 commit 1b29661

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

proxy/common/pki.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
countryName_max = 2
4040
stateOrProvinceName = State or Province Name (full name)
4141
localityName = Locality Name (eg, city)
42-
0.organizationName = Organization Name (eg, company)
42+
organizationName = Organization Name (eg, company)
4343
organizationalUnitName = Organizational Unit Name (eg, section)
4444
commonName = Common Name (eg, fully qualified host name)
4545
commonName_max = 64

proxy/http/proxy/server.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def access_log(self) -> None:
356356
self.response.total_size,
357357
connection_time_ms))
358358

359-
def gen_ca_signed_certificate(self, cert_file_path: str) -> None:
359+
def gen_ca_signed_certificate(self, cert_file_path: str, certificate: Dict[str, Any]) -> None:
360360
'''CA signing key (default) is used for generating a public key
361361
for common_name, if one already doesn't exist. Using generated
362362
public key a CSR request is generated, which is then signed by
@@ -366,11 +366,19 @@ def gen_ca_signed_certificate(self, cert_file_path: str) -> None:
366366
returns signed certificate path.'''
367367
assert(self.request.host and self.flags.ca_cert_dir and self.flags.ca_signing_key_file and
368368
self.flags.ca_key_file and self.flags.ca_cert_file)
369+
370+
upstream_subject = {s[0][0]: s[0][1] for s in certificate['subject']}
369371
public_key_path = os.path.join(self.flags.ca_cert_dir,
370372
'{0}.{1}'.format(text_(self.request.host), 'pub'))
371373
private_key_path = self.flags.ca_signing_key_file
372374
private_key_password = ''
373-
subject = '/CN={0}'.format(text_(self.request.host))
375+
subject = '/CN={0}/C={1}/ST={2}/L={3}/O={4}/OU={5}'.format(
376+
upstream_subject.get('commonName', text_(self.request.host)),
377+
upstream_subject.get('countryName', 'NA'),
378+
upstream_subject.get('stateOrProvinceName', 'Unavailable'),
379+
upstream_subject.get('localityName', 'Unavailable'),
380+
upstream_subject.get('organizationName', 'Unavailable'),
381+
upstream_subject.get('organizationalUnitName', 'Unavailable'))
374382
alt_subj_names = [text_(self.request.host), ]
375383
validity_in_days = 365 * 2
376384
timeout = 10
@@ -412,7 +420,7 @@ def generated_cert_file_path(ca_cert_dir: str, host: str) -> str:
412420
return os.path.join(ca_cert_dir, '%s.pem' % host)
413421

414422
def generate_upstream_certificate(
415-
self, _certificate: Optional[Dict[str, Any]]) -> str:
423+
self, certificate: Dict[str, Any]) -> str:
416424
if not (self.flags.ca_cert_dir and self.flags.ca_signing_key_file and
417425
self.flags.ca_cert_file and self.flags.ca_key_file):
418426
raise HttpProtocolException(
@@ -424,15 +432,16 @@ def generate_upstream_certificate(
424432
self.flags.ca_cert_dir, text_(self.request.host))
425433
with self.lock:
426434
if not os.path.isfile(cert_file_path):
427-
self.gen_ca_signed_certificate(cert_file_path)
435+
self.gen_ca_signed_certificate(cert_file_path, certificate)
428436
return cert_file_path
429437

430438
def wrap_server(self) -> None:
431439
assert self.server is not None
432440
assert isinstance(self.server.connection, socket.socket)
433441
ctx = ssl.create_default_context(
434442
ssl.Purpose.SERVER_AUTH, cafile=self.flags.ca_file)
435-
ctx.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
443+
ctx.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1
444+
ctx.check_hostname = True
436445
self.server.connection.setblocking(True)
437446
self.server._conn = ctx.wrap_socket(
438447
self.server.connection,
@@ -450,7 +459,8 @@ def wrap_client(self) -> None:
450459
self.client.connection,
451460
server_side=True,
452461
certfile=generated_cert,
453-
keyfile=self.flags.ca_signing_key_file)
462+
keyfile=self.flags.ca_signing_key_file,
463+
ssl_version=ssl.PROTOCOL_TLSv1_2)
454464
self.client.connection.setblocking(False)
455465
logger.debug(
456466
'TLS interception using %s', generated_cert)

tests/http/test_http_proxy_tls_interception.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ def mock_connection() -> Any:
168168
server_side=True,
169169
keyfile=self.flags.ca_signing_key_file,
170170
certfile=HttpProxyPlugin.generated_cert_file_path(
171-
self.flags.ca_cert_dir, host)
171+
self.flags.ca_cert_dir, host),
172+
ssl_version=ssl.PROTOCOL_TLSv1_2
172173
)
173174
self.assertEqual(self._conn.setblocking.call_count, 2)
174175
self.assertEqual(

0 commit comments

Comments
 (0)