|
10 | 10 | import base64
|
11 | 11 | from subprocess import PIPE, Popen
|
12 | 12 | from datetime import datetime, timedelta
|
| 13 | +import sys |
13 | 14 |
|
14 | 15 | import pytest
|
15 | 16 |
|
|
46 | 47 | get_elliptic_curves,
|
47 | 48 | )
|
48 | 49 |
|
49 |
| -from .util import EqualityTestsMixin, is_consistent_type, WARNING_TYPE_EXPECTED |
| 50 | +from OpenSSL._util import ffi as _ffi, lib as _lib |
| 51 | + |
| 52 | +from .util import ( |
| 53 | + EqualityTestsMixin, |
| 54 | + is_consistent_type, |
| 55 | + WARNING_TYPE_EXPECTED, |
| 56 | + NON_ASCII, |
| 57 | +) |
50 | 58 |
|
51 | 59 |
|
52 | 60 | def normalize_privatekey_pem(pem):
|
@@ -2228,6 +2236,68 @@ def test_add_cert_accepts_duplicate(self):
|
2228 | 2236 | store.add_cert(cert)
|
2229 | 2237 | store.add_cert(cert)
|
2230 | 2238 |
|
| 2239 | + @pytest.mark.parametrize( |
| 2240 | + "cafile, capath, call_cafile, call_capath", |
| 2241 | + [ |
| 2242 | + ( |
| 2243 | + "/cafile" + NON_ASCII, |
| 2244 | + None, |
| 2245 | + b"/cafile" + NON_ASCII.encode(sys.getfilesystemencoding()), |
| 2246 | + _ffi.NULL, |
| 2247 | + ), |
| 2248 | + ( |
| 2249 | + b"/cafile" + NON_ASCII.encode("utf-8"), |
| 2250 | + None, |
| 2251 | + b"/cafile" + NON_ASCII.encode("utf-8"), |
| 2252 | + _ffi.NULL, |
| 2253 | + ), |
| 2254 | + ( |
| 2255 | + None, |
| 2256 | + "/capath" + NON_ASCII, |
| 2257 | + _ffi.NULL, |
| 2258 | + b"/capath" + NON_ASCII.encode(sys.getfilesystemencoding()), |
| 2259 | + ), |
| 2260 | + ( |
| 2261 | + None, |
| 2262 | + b"/capath" + NON_ASCII.encode("utf-8"), |
| 2263 | + _ffi.NULL, |
| 2264 | + b"/capath" + NON_ASCII.encode("utf-8"), |
| 2265 | + ), |
| 2266 | + ], |
| 2267 | + ) |
| 2268 | + def test_load_locations_parameters( |
| 2269 | + self, cafile, capath, call_cafile, call_capath, monkeypatch |
| 2270 | + ): |
| 2271 | + class LibMock(object): |
| 2272 | + def load_locations(self, store, cafile, capath): |
| 2273 | + self.cafile = cafile |
| 2274 | + self.capath = capath |
| 2275 | + return 1 |
| 2276 | + |
| 2277 | + lib_mock = LibMock() |
| 2278 | + monkeypatch.setattr( |
| 2279 | + _lib, "X509_STORE_load_locations", lib_mock.load_locations |
| 2280 | + ) |
| 2281 | + |
| 2282 | + store = X509Store() |
| 2283 | + store.load_locations(cafile=cafile, capath=capath) |
| 2284 | + |
| 2285 | + assert call_cafile == lib_mock.cafile |
| 2286 | + assert call_capath == lib_mock.capath |
| 2287 | + |
| 2288 | + def test_load_locations_fails_when_all_args_are_none(self): |
| 2289 | + store = X509Store() |
| 2290 | + with pytest.raises(Error): |
| 2291 | + store.load_locations(None, None) |
| 2292 | + |
| 2293 | + def test_load_locations_raises_error_on_failure(self, tmpdir): |
| 2294 | + invalid_ca_file = tmpdir.join("invalid.pem") |
| 2295 | + invalid_ca_file.write("This is not a certificate") |
| 2296 | + |
| 2297 | + store = X509Store() |
| 2298 | + with pytest.raises(Error): |
| 2299 | + store.load_locations(cafile=str(invalid_ca_file)) |
| 2300 | + |
2231 | 2301 |
|
2232 | 2302 | class TestPKCS12(object):
|
2233 | 2303 | """
|
@@ -3884,6 +3954,70 @@ def test_get_verified_chain_invalid_chain_no_root(self):
|
3884 | 3954 | assert exc.value.args[0][2] == "unable to get issuer certificate"
|
3885 | 3955 | assert exc.value.certificate.get_subject().CN == "intermediate"
|
3886 | 3956 |
|
| 3957 | + @pytest.fixture |
| 3958 | + def root_ca_file(self, tmpdir): |
| 3959 | + return self._create_ca_file(tmpdir, "root_ca_hash_dir", self.root_cert) |
| 3960 | + |
| 3961 | + @pytest.fixture |
| 3962 | + def intermediate_ca_file(self, tmpdir): |
| 3963 | + return self._create_ca_file( |
| 3964 | + tmpdir, "intermediate_ca_hash_dir", self.intermediate_cert |
| 3965 | + ) |
| 3966 | + |
| 3967 | + @staticmethod |
| 3968 | + def _create_ca_file(base_path, hash_directory, cacert): |
| 3969 | + ca_hash = "{:08x}.0".format(cacert.subject_name_hash()) |
| 3970 | + cafile = base_path.join(hash_directory, ca_hash) |
| 3971 | + cafile.write_binary( |
| 3972 | + dump_certificate(FILETYPE_PEM, cacert), ensure=True |
| 3973 | + ) |
| 3974 | + return cafile |
| 3975 | + |
| 3976 | + def test_verify_with_ca_file_location(self, root_ca_file): |
| 3977 | + store = X509Store() |
| 3978 | + store.load_locations(str(root_ca_file)) |
| 3979 | + |
| 3980 | + store_ctx = X509StoreContext(store, self.intermediate_cert) |
| 3981 | + store_ctx.verify_certificate() |
| 3982 | + |
| 3983 | + def test_verify_with_ca_path_location(self, root_ca_file): |
| 3984 | + store = X509Store() |
| 3985 | + store.load_locations(None, str(root_ca_file.dirname)) |
| 3986 | + |
| 3987 | + store_ctx = X509StoreContext(store, self.intermediate_cert) |
| 3988 | + store_ctx.verify_certificate() |
| 3989 | + |
| 3990 | + def test_verify_with_cafile_and_capath( |
| 3991 | + self, root_ca_file, intermediate_ca_file |
| 3992 | + ): |
| 3993 | + store = X509Store() |
| 3994 | + store.load_locations( |
| 3995 | + cafile=str(root_ca_file), capath=str(intermediate_ca_file.dirname) |
| 3996 | + ) |
| 3997 | + |
| 3998 | + store_ctx = X509StoreContext(store, self.intermediate_server_cert) |
| 3999 | + store_ctx.verify_certificate() |
| 4000 | + |
| 4001 | + def test_verify_with_multiple_ca_files( |
| 4002 | + self, root_ca_file, intermediate_ca_file |
| 4003 | + ): |
| 4004 | + store = X509Store() |
| 4005 | + store.load_locations(str(root_ca_file)) |
| 4006 | + store.load_locations(str(intermediate_ca_file)) |
| 4007 | + |
| 4008 | + store_ctx = X509StoreContext(store, self.intermediate_server_cert) |
| 4009 | + store_ctx.verify_certificate() |
| 4010 | + |
| 4011 | + def test_verify_failure_with_empty_ca_directory(self, tmpdir): |
| 4012 | + store = X509Store() |
| 4013 | + store.load_locations(None, str(tmpdir)) |
| 4014 | + |
| 4015 | + store_ctx = X509StoreContext(store, self.intermediate_cert) |
| 4016 | + with pytest.raises(X509StoreContextError) as exc: |
| 4017 | + store_ctx.verify_certificate() |
| 4018 | + |
| 4019 | + assert exc.value.args[0][2] == "unable to get local issuer certificate" |
| 4020 | + |
3887 | 4021 |
|
3888 | 4022 | class TestSignVerify(object):
|
3889 | 4023 | """
|
|
0 commit comments