@@ -104,6 +104,7 @@ def data_file(*name):
104104SIGNING_CA = data_file ("capath" , "ceff1710.0" )
105105# cert with all kinds of subject alt names
106106ALLSANFILE = data_file ("allsans.pem" )
107+ IDNSANSFILE = data_file ("idnsans.pem" )
107108
108109REMOTE_HOST = "self-signed.pythontest.net"
109110
@@ -1598,7 +1599,6 @@ def test_error_types(self):
15981599
15991600
16001601class SimpleBackgroundTests (unittest .TestCase ):
1601-
16021602 """Tests that connect to a simple server running in the background"""
16031603
16041604 def setUp (self ):
@@ -2616,6 +2616,70 @@ def test_dual_rsa_ecc(self):
26162616 cipher = s .cipher ()[0 ].split ('-' )
26172617 self .assertTrue (cipher [:2 ], ('ECDHE' , 'ECDSA' ))
26182618
2619+ def test_check_hostname_idn (self ):
2620+ if support .verbose :
2621+ sys .stdout .write ("\n " )
2622+
2623+ server_context = ssl .SSLContext (ssl .PROTOCOL_TLS )
2624+ server_context .load_cert_chain (IDNSANSFILE )
2625+
2626+ context = ssl .SSLContext (ssl .PROTOCOL_TLS )
2627+ context .verify_mode = ssl .CERT_REQUIRED
2628+ context .check_hostname = True
2629+ context .load_verify_locations (SIGNING_CA )
2630+
2631+ # correct hostname should verify, when specified in several
2632+ # different ways
2633+ idn_hostnames = [
2634+ ('könig.idn.pythontest.net' ,
2635+ 'könig.idn.pythontest.net' ,),
2636+ ('xn--knig-5qa.idn.pythontest.net' ,
2637+ 'xn--knig-5qa.idn.pythontest.net' ),
2638+ (b'xn--knig-5qa.idn.pythontest.net' ,
2639+ b'xn--knig-5qa.idn.pythontest.net' ),
2640+
2641+ ('königsgäßchen.idna2003.pythontest.net' ,
2642+ 'königsgäßchen.idna2003.pythontest.net' ),
2643+ ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net' ,
2644+ 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net' ),
2645+ (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net' ,
2646+ b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net' ),
2647+ ]
2648+ for server_hostname , expected_hostname in idn_hostnames :
2649+ server = ThreadedEchoServer (context = server_context , chatty = True )
2650+ with server :
2651+ with context .wrap_socket (socket .socket (),
2652+ server_hostname = server_hostname ) as s :
2653+ self .assertEqual (s .server_hostname , expected_hostname )
2654+ s .connect ((HOST , server .port ))
2655+ cert = s .getpeercert ()
2656+ self .assertEqual (s .server_hostname , expected_hostname )
2657+ self .assertTrue (cert , "Can't get peer certificate." )
2658+
2659+ with ssl .SSLSocket (socket .socket (),
2660+ server_hostname = server_hostname ) as s :
2661+ s .connect ((HOST , server .port ))
2662+ s .getpeercert ()
2663+ self .assertEqual (s .server_hostname , expected_hostname )
2664+
2665+ # bug https://bugs.python.org/issue28414
2666+ # IDNA 2008 deviations are broken
2667+ idna2008 = 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'
2668+ server = ThreadedEchoServer (context = server_context , chatty = True )
2669+ with server :
2670+ with self .assertRaises (UnicodeError ):
2671+ with context .wrap_socket (socket .socket (),
2672+ server_hostname = idna2008 ) as s :
2673+ s .connect ((HOST , server .port ))
2674+
2675+ # incorrect hostname should raise an exception
2676+ server = ThreadedEchoServer (context = server_context , chatty = True )
2677+ with server :
2678+ with context .wrap_socket (socket .socket (),
2679+ server_hostname = "python.example.org" ) as s :
2680+ with self .assertRaises (ssl .CertificateError ):
2681+ s .connect ((HOST , server .port ))
2682+
26192683 def test_wrong_cert (self ):
26202684 """Connecting when the server rejects the client's certificate
26212685
0 commit comments