11848Szelenkov@nginx.comimport ssl 21843Szelenkov@nginx.comimport subprocess 31843Szelenkov@nginx.com 42478Szelenkov@nginx.comimport pytest 5*2616Szelenkov@nginx.com 62491Szelenkov@nginx.comfrom unit.applications.tls import ApplicationTLS 71843Szelenkov@nginx.comfrom unit.option import option 81843Szelenkov@nginx.com 92488Szelenkov@nginx.comprerequisites = {'modules': {'openssl': 'any'}} 102488Szelenkov@nginx.com 112491Szelenkov@nginx.comclient = ApplicationTLS() 121843Szelenkov@nginx.com 132491Szelenkov@nginx.com 142491Szelenkov@nginx.com@pytest.fixture(autouse=True) 152491Szelenkov@nginx.comdef setup_method_fixture(): 162491Szelenkov@nginx.com assert 'success' in client.conf( 172491Szelenkov@nginx.com { 182592Szelenkov@nginx.com "listeners": {"*:8080": {"pass": "routes"}}, 192491Szelenkov@nginx.com "routes": [{"action": {"return": 200}}], 202491Szelenkov@nginx.com "applications": {}, 212491Szelenkov@nginx.com } 222491Szelenkov@nginx.com ) 232491Szelenkov@nginx.com 242491Szelenkov@nginx.com 252491Szelenkov@nginx.comdef add_tls(cert='default'): 262491Szelenkov@nginx.com assert 'success' in client.conf( 272491Szelenkov@nginx.com {"pass": "routes", "tls": {"certificate": cert}}, 282592Szelenkov@nginx.com 'listeners/*:8080', 292491Szelenkov@nginx.com ) 302491Szelenkov@nginx.com 312491Szelenkov@nginx.com 322491Szelenkov@nginx.comdef check_cert(host, expect, ctx): 332491Szelenkov@nginx.com resp, sock = client.get_ssl( 342491Szelenkov@nginx.com headers={ 352491Szelenkov@nginx.com 'Host': host, 362491Szelenkov@nginx.com 'Content-Length': '0', 372491Szelenkov@nginx.com 'Connection': 'close', 382491Szelenkov@nginx.com }, 392491Szelenkov@nginx.com start=True, 402491Szelenkov@nginx.com context=ctx, 412491Szelenkov@nginx.com ) 422491Szelenkov@nginx.com 432491Szelenkov@nginx.com assert resp['status'] == 200 442491Szelenkov@nginx.com assert sock.getpeercert()['subject'][0][0][1] == expect 452491Szelenkov@nginx.com 462491Szelenkov@nginx.com 472491Szelenkov@nginx.comdef config_bundles(bundles): 482491Szelenkov@nginx.com client.certificate('root', False) 492491Szelenkov@nginx.com 502491Szelenkov@nginx.com for b in bundles: 512491Szelenkov@nginx.com client.openssl_conf(rewrite=True, alt_names=bundles[b]['alt_names']) 522491Szelenkov@nginx.com subj = f'/CN={bundles[b]["subj"]}/' if 'subj' in bundles[b] else '/' 532491Szelenkov@nginx.com 542491Szelenkov@nginx.com subprocess.check_output( 552491Szelenkov@nginx.com [ 562491Szelenkov@nginx.com 'openssl', 572491Szelenkov@nginx.com 'req', 582491Szelenkov@nginx.com '-new', 592491Szelenkov@nginx.com '-subj', 602491Szelenkov@nginx.com subj, 612491Szelenkov@nginx.com '-config', 622491Szelenkov@nginx.com f'{option.temp_dir}/openssl.conf', 632491Szelenkov@nginx.com '-out', 642491Szelenkov@nginx.com f'{option.temp_dir}/{b}.csr', 652491Szelenkov@nginx.com '-keyout', 662491Szelenkov@nginx.com f'{option.temp_dir}/{b}.key', 672491Szelenkov@nginx.com ], 682491Szelenkov@nginx.com stderr=subprocess.STDOUT, 691843Szelenkov@nginx.com ) 701843Szelenkov@nginx.com 712491Szelenkov@nginx.com generate_ca_conf() 722491Szelenkov@nginx.com 732491Szelenkov@nginx.com for b in bundles: 742491Szelenkov@nginx.com subj = f'/CN={bundles[b]["subj"]}/' if 'subj' in bundles[b] else '/' 752491Szelenkov@nginx.com 762491Szelenkov@nginx.com subprocess.check_output( 772491Szelenkov@nginx.com [ 782491Szelenkov@nginx.com 'openssl', 792491Szelenkov@nginx.com 'ca', 802491Szelenkov@nginx.com '-batch', 812491Szelenkov@nginx.com '-subj', 822491Szelenkov@nginx.com subj, 832491Szelenkov@nginx.com '-config', 842491Szelenkov@nginx.com f'{option.temp_dir}/ca.conf', 852491Szelenkov@nginx.com '-keyfile', 862491Szelenkov@nginx.com f'{option.temp_dir}/root.key', 872491Szelenkov@nginx.com '-cert', 882491Szelenkov@nginx.com f'{option.temp_dir}/root.crt', 892491Szelenkov@nginx.com '-in', 902491Szelenkov@nginx.com f'{option.temp_dir}/{b}.csr', 912491Szelenkov@nginx.com '-out', 922491Szelenkov@nginx.com f'{option.temp_dir}/{b}.crt', 932491Szelenkov@nginx.com ], 942491Szelenkov@nginx.com stderr=subprocess.STDOUT, 951843Szelenkov@nginx.com ) 961843Szelenkov@nginx.com 972491Szelenkov@nginx.com load_certs(bundles) 982491Szelenkov@nginx.com 992491Szelenkov@nginx.com context = ssl.create_default_context() 1002491Szelenkov@nginx.com context.check_hostname = False 1012491Szelenkov@nginx.com context.verify_mode = ssl.CERT_REQUIRED 1022491Szelenkov@nginx.com context.load_verify_locations(f'{option.temp_dir}/root.crt') 1031843Szelenkov@nginx.com 1042491Szelenkov@nginx.com return context 1052491Szelenkov@nginx.com 1062491Szelenkov@nginx.com 1072491Szelenkov@nginx.comdef generate_ca_conf(): 108*2616Szelenkov@nginx.com with open(f'{option.temp_dir}/ca.conf', 'w', encoding='utf-8') as f: 1092491Szelenkov@nginx.com f.write( 1102491Szelenkov@nginx.com f"""[ ca ] 1111843Szelenkov@nginx.comdefault_ca = myca 1121843Szelenkov@nginx.com 1131843Szelenkov@nginx.com[ myca ] 1142330Szelenkov@nginx.comnew_certs_dir = {option.temp_dir} 1152330Szelenkov@nginx.comdatabase = {option.temp_dir}/certindex 1161843Szelenkov@nginx.comdefault_md = sha256 1171843Szelenkov@nginx.compolicy = myca_policy 1182330Szelenkov@nginx.comserial = {option.temp_dir}/certserial 1191843Szelenkov@nginx.comdefault_days = 1 1201843Szelenkov@nginx.comx509_extensions = myca_extensions 1211843Szelenkov@nginx.comcopy_extensions = copy 1221843Szelenkov@nginx.com 1231843Szelenkov@nginx.com[ myca_policy ] 1241843Szelenkov@nginx.comcommonName = optional 1251843Szelenkov@nginx.com 1261843Szelenkov@nginx.com[ myca_extensions ] 1271843Szelenkov@nginx.combasicConstraints = critical,CA:TRUE""" 1281843Szelenkov@nginx.com ) 1291843Szelenkov@nginx.com 130*2616Szelenkov@nginx.com with open(f'{option.temp_dir}/certserial', 'w', encoding='utf-8') as f: 1312491Szelenkov@nginx.com f.write('1000') 1322491Szelenkov@nginx.com 133*2616Szelenkov@nginx.com with open(f'{option.temp_dir}/certindex', 'w', encoding='utf-8') as f: 1342491Szelenkov@nginx.com f.write('') 1352491Szelenkov@nginx.com 1362491Szelenkov@nginx.com 1372491Szelenkov@nginx.comdef load_certs(bundles): 1382491Szelenkov@nginx.com for bname, bvalue in bundles.items(): 1392491Szelenkov@nginx.com assert 'success' in client.certificate_load( 1402491Szelenkov@nginx.com bname, bname 1412491Szelenkov@nginx.com ), f'certificate {bvalue["subj"]} upload' 1422491Szelenkov@nginx.com 1432491Szelenkov@nginx.com 1442491Szelenkov@nginx.comdef remove_tls(): 1452592Szelenkov@nginx.com assert 'success' in client.conf({"pass": "routes"}, 'listeners/*:8080') 1462491Szelenkov@nginx.com 1472491Szelenkov@nginx.com 1482491Szelenkov@nginx.comdef test_tls_sni(): 1492491Szelenkov@nginx.com bundles = { 1502491Szelenkov@nginx.com "default": {"subj": "default", "alt_names": ["default"]}, 1512491Szelenkov@nginx.com "localhost.com": { 1522491Szelenkov@nginx.com "subj": "localhost.com", 1532491Szelenkov@nginx.com "alt_names": ["alt1.localhost.com"], 1542491Szelenkov@nginx.com }, 1552491Szelenkov@nginx.com "example.com": { 1562491Szelenkov@nginx.com "subj": "example.com", 1572491Szelenkov@nginx.com "alt_names": ["alt1.example.com", "alt2.example.com"], 1582491Szelenkov@nginx.com }, 1592491Szelenkov@nginx.com } 1602491Szelenkov@nginx.com ctx = config_bundles(bundles) 1612491Szelenkov@nginx.com add_tls(["default", "localhost.com", "example.com"]) 1622491Szelenkov@nginx.com 1632491Szelenkov@nginx.com check_cert('alt1.localhost.com', bundles['localhost.com']['subj'], ctx) 1642491Szelenkov@nginx.com check_cert('alt2.example.com', bundles['example.com']['subj'], ctx) 1652491Szelenkov@nginx.com check_cert('blah', bundles['default']['subj'], ctx) 1662491Szelenkov@nginx.com 1671843Szelenkov@nginx.com 1682491Szelenkov@nginx.comdef test_tls_sni_no_hostname(): 1692491Szelenkov@nginx.com bundles = { 1702491Szelenkov@nginx.com "localhost.com": {"subj": "localhost.com", "alt_names": []}, 1712491Szelenkov@nginx.com "example.com": { 1722491Szelenkov@nginx.com "subj": "example.com", 1732491Szelenkov@nginx.com "alt_names": ["example.com"], 1742491Szelenkov@nginx.com }, 1752491Szelenkov@nginx.com } 1762491Szelenkov@nginx.com ctx = config_bundles(bundles) 1772491Szelenkov@nginx.com add_tls(["localhost.com", "example.com"]) 1782491Szelenkov@nginx.com 1792491Szelenkov@nginx.com resp, sock = client.get_ssl( 1802491Szelenkov@nginx.com headers={'Content-Length': '0', 'Connection': 'close'}, 1812491Szelenkov@nginx.com start=True, 1822491Szelenkov@nginx.com context=ctx, 1832491Szelenkov@nginx.com ) 1842491Szelenkov@nginx.com assert resp['status'] == 200 1852491Szelenkov@nginx.com assert ( 1862491Szelenkov@nginx.com sock.getpeercert()['subject'][0][0][1] 1872491Szelenkov@nginx.com == bundles['localhost.com']['subj'] 1882491Szelenkov@nginx.com ) 1892491Szelenkov@nginx.com 1902491Szelenkov@nginx.com 1912491Szelenkov@nginx.comdef test_tls_sni_upper_case(): 1922491Szelenkov@nginx.com bundles = { 1932491Szelenkov@nginx.com "localhost.com": {"subj": "LOCALHOST.COM", "alt_names": []}, 1942491Szelenkov@nginx.com "example.com": { 1952491Szelenkov@nginx.com "subj": "example.com", 1962491Szelenkov@nginx.com "alt_names": ["ALT1.EXAMPLE.COM", "*.ALT2.EXAMPLE.COM"], 1972491Szelenkov@nginx.com }, 1982491Szelenkov@nginx.com } 1992491Szelenkov@nginx.com ctx = config_bundles(bundles) 2002491Szelenkov@nginx.com add_tls(["localhost.com", "example.com"]) 2012491Szelenkov@nginx.com 2022491Szelenkov@nginx.com check_cert('localhost.com', bundles['localhost.com']['subj'], ctx) 2032491Szelenkov@nginx.com check_cert('LOCALHOST.COM', bundles['localhost.com']['subj'], ctx) 2042491Szelenkov@nginx.com check_cert('EXAMPLE.COM', bundles['localhost.com']['subj'], ctx) 2052491Szelenkov@nginx.com check_cert('ALT1.EXAMPLE.COM', bundles['example.com']['subj'], ctx) 2062491Szelenkov@nginx.com check_cert('WWW.ALT2.EXAMPLE.COM', bundles['example.com']['subj'], ctx) 2072491Szelenkov@nginx.com 2081843Szelenkov@nginx.com 2092491Szelenkov@nginx.comdef test_tls_sni_only_bundle(): 2102491Szelenkov@nginx.com bundles = { 2112491Szelenkov@nginx.com "localhost.com": { 2122491Szelenkov@nginx.com "subj": "localhost.com", 2132491Szelenkov@nginx.com "alt_names": ["alt1.localhost.com", "alt2.localhost.com"], 2142491Szelenkov@nginx.com } 2152491Szelenkov@nginx.com } 2162491Szelenkov@nginx.com ctx = config_bundles(bundles) 2172491Szelenkov@nginx.com add_tls(["localhost.com"]) 2182491Szelenkov@nginx.com 2192491Szelenkov@nginx.com check_cert('domain.com', bundles['localhost.com']['subj'], ctx) 2202491Szelenkov@nginx.com check_cert('alt1.domain.com', bundles['localhost.com']['subj'], ctx) 2212491Szelenkov@nginx.com 2221843Szelenkov@nginx.com 2232491Szelenkov@nginx.comdef test_tls_sni_wildcard(): 2242491Szelenkov@nginx.com bundles = { 2252491Szelenkov@nginx.com "localhost.com": {"subj": "localhost.com", "alt_names": []}, 2262491Szelenkov@nginx.com "example.com": { 2272491Szelenkov@nginx.com "subj": "example.com", 2282491Szelenkov@nginx.com "alt_names": ["*.example.com", "*.alt.example.com"], 2292491Szelenkov@nginx.com }, 2302491Szelenkov@nginx.com } 2312491Szelenkov@nginx.com ctx = config_bundles(bundles) 2322491Szelenkov@nginx.com add_tls(["localhost.com", "example.com"]) 2332491Szelenkov@nginx.com 2342491Szelenkov@nginx.com check_cert('example.com', bundles['localhost.com']['subj'], ctx) 2352491Szelenkov@nginx.com check_cert('www.example.com', bundles['example.com']['subj'], ctx) 2362491Szelenkov@nginx.com check_cert('alt.example.com', bundles['example.com']['subj'], ctx) 2372491Szelenkov@nginx.com check_cert('www.alt.example.com', bundles['example.com']['subj'], ctx) 2382491Szelenkov@nginx.com check_cert('www.alt.example.ru', bundles['localhost.com']['subj'], ctx) 2392491Szelenkov@nginx.com 2402491Szelenkov@nginx.com 2412491Szelenkov@nginx.comdef test_tls_sni_duplicated_bundle(): 2422491Szelenkov@nginx.com bundles = { 2432491Szelenkov@nginx.com "localhost.com": { 2442491Szelenkov@nginx.com "subj": "localhost.com", 2452491Szelenkov@nginx.com "alt_names": ["localhost.com", "alt2.localhost.com"], 2461922Szelenkov@nginx.com } 2472491Szelenkov@nginx.com } 2482491Szelenkov@nginx.com ctx = config_bundles(bundles) 2492491Szelenkov@nginx.com add_tls(["localhost.com", "localhost.com"]) 2502491Szelenkov@nginx.com 2512491Szelenkov@nginx.com check_cert('localhost.com', bundles['localhost.com']['subj'], ctx) 2522491Szelenkov@nginx.com check_cert('alt2.localhost.com', bundles['localhost.com']['subj'], ctx) 2532491Szelenkov@nginx.com 2542491Szelenkov@nginx.com 2552491Szelenkov@nginx.comdef test_tls_sni_same_alt(): 2562491Szelenkov@nginx.com bundles = { 2572491Szelenkov@nginx.com "localhost": {"subj": "subj1", "alt_names": "same.altname.com"}, 2582491Szelenkov@nginx.com "example": {"subj": "subj2", "alt_names": "same.altname.com"}, 2592491Szelenkov@nginx.com } 2602491Szelenkov@nginx.com ctx = config_bundles(bundles) 2612491Szelenkov@nginx.com add_tls(["localhost", "example"]) 2622491Szelenkov@nginx.com 2632491Szelenkov@nginx.com check_cert('localhost', bundles['localhost']['subj'], ctx) 2642491Szelenkov@nginx.com check_cert('example', bundles['localhost']['subj'], ctx) 2652491Szelenkov@nginx.com 2661922Szelenkov@nginx.com 2672491Szelenkov@nginx.comdef test_tls_sni_empty_cn(): 2682491Szelenkov@nginx.com bundles = {"localhost": {"alt_names": ["alt.localhost.com"]}} 2692491Szelenkov@nginx.com ctx = config_bundles(bundles) 2702491Szelenkov@nginx.com add_tls(["localhost"]) 2712491Szelenkov@nginx.com 2722491Szelenkov@nginx.com resp, sock = client.get_ssl( 2732491Szelenkov@nginx.com headers={ 2742491Szelenkov@nginx.com 'Host': 'domain.com', 2752491Szelenkov@nginx.com 'Content-Length': '0', 2762491Szelenkov@nginx.com 'Connection': 'close', 2772491Szelenkov@nginx.com }, 2782491Szelenkov@nginx.com start=True, 2792491Szelenkov@nginx.com context=ctx, 2802491Szelenkov@nginx.com ) 2812491Szelenkov@nginx.com 2822491Szelenkov@nginx.com assert resp['status'] == 200 2832491Szelenkov@nginx.com assert sock.getpeercert()['subjectAltName'][0][1] == 'alt.localhost.com' 2842491Szelenkov@nginx.com 2852491Szelenkov@nginx.com 2862491Szelenkov@nginx.comdef test_tls_sni_invalid(): 2872491Szelenkov@nginx.com _ = config_bundles({"localhost": {"subj": "subj1", "alt_names": ''}}) 2882491Szelenkov@nginx.com add_tls(["localhost"]) 2892491Szelenkov@nginx.com 2902491Szelenkov@nginx.com def check_certificate(cert): 2912491Szelenkov@nginx.com assert 'error' in client.conf( 2922491Szelenkov@nginx.com {"pass": "routes", "tls": {"certificate": cert}}, 2932592Szelenkov@nginx.com 'listeners/*:8080', 2941922Szelenkov@nginx.com ) 2951922Szelenkov@nginx.com 2962491Szelenkov@nginx.com check_certificate('') 2972491Szelenkov@nginx.com check_certificate('blah') 2982491Szelenkov@nginx.com check_certificate([]) 2992491Szelenkov@nginx.com check_certificate(['blah']) 3002491Szelenkov@nginx.com check_certificate(['localhost', 'blah']) 3012491Szelenkov@nginx.com check_certificate(['localhost', []]) 302