Skip to content

Commit b3de531

Browse files
committed
Fully remove the ca_path parameter; add docs for signature location pinning
1 parent 5fbc7df commit b3de531

File tree

4 files changed

+26
-21
lines changed

4 files changed

+26
-21
lines changed

README.rst

+9-3
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,14 @@ Assuming ``metadata.xml`` contains SAML metadata for the assertion source:
9090
`SAML signature wrapping <https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91.pdf>`_.
9191

9292
In SignXML, you can ensure that the information signed is what you expect to be signed by only trusting the
93-
data returned by the ``verify()`` method. The ``signed_xml`` attribute of the return value is the XML node or string that
94-
was signed.
93+
data returned by ``XMLVerifier.verify()``. The ``signed_xml`` attribute of the return value is the XML node or string
94+
that was signed. We also recommend that you assert the expected location for the signature within the document:
95+
96+
.. code-block:: python
97+
98+
from signxml import XMLVerifier, SignatureConfiguration
99+
config = SignatureConfiguration(location="./")
100+
XMLVerifier(...).verify(..., expect_config=config)
95101
96102
**Recommended reading:** `W3C XML Signature Best Practices for Applications
97103
<http://www.w3.org/TR/xmldsig-bestpractices/#practices-applications>`_, `On Breaking SAML: Be Whoever You Want to Be
@@ -106,7 +112,7 @@ Assuming ``metadata.xml`` contains SAML metadata for the assertion source:
106112
``x509_cert`` argument to specify a certificate that was pre-shared out-of-band (e.g. via SAML metadata, as
107113
shown in *Verifying SAML assertions*), or ``cert_subject_name`` to specify a
108114
subject name that must be in the signing X.509 certificate given by the signature (verified as if it were a
109-
domain name), or ``ca_pem_file``/``ca_path`` to give a custom CA.
115+
domain name), or ``ca_pem_file`` to give a custom CA.
110116

111117
XML signature construction methods: enveloped, detached, enveloping
112118
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

signxml/util/__init__.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,10 @@ class X509CertChainVerifier:
225225
contact SignXML maintainers.
226226
"""
227227

228-
def __init__(self, ca_pem_file=None, ca_path=None, verification_time=None):
228+
def __init__(self, ca_pem_file=None, verification_time=None):
229229
if ca_pem_file is None:
230230
ca_pem_file = certifi.where()
231231
self.ca_pem_file = ca_pem_file
232-
if ca_path is not None:
233-
msg = "CApath is not supported. If you need this feature, please contact SignXML maintainers."
234-
raise NotImplementedError(msg)
235-
236232
self.verification_time = verification_time
237233

238234
@property

signxml/verifier.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ def _apply_transforms(self, payload, *, transforms_node: etree._Element, signatu
233233

234234
return payload
235235

236-
def get_cert_chain_verifier(self, ca_pem_file, ca_path):
237-
return X509CertChainVerifier(ca_pem_file=ca_pem_file, ca_path=ca_path)
236+
def get_cert_chain_verifier(self, ca_pem_file):
237+
return X509CertChainVerifier(ca_pem_file=ca_pem_file)
238238

239239
def _match_key_values(self, key_value, der_encoded_key_value, signing_cert, signature_alg):
240240
if self.config.ignore_ambiguous_key_info is False:
@@ -279,7 +279,6 @@ def verify(
279279
cert_subject_name: Optional[str] = None,
280280
cert_resolver: Optional[Callable] = None,
281281
ca_pem_file: Optional[Union[str, bytes]] = None,
282-
ca_path: Optional[str] = None,
283282
hmac_key: Optional[str] = None,
284283
validate_schema: bool = True,
285284
parser=None,
@@ -302,8 +301,16 @@ def verify(
302301
signed by that signature.
303302
304303
In SignXML, you can ensure that the information signed is what you expect to be signed by only trusting the
305-
data returned by the ``verify()`` method. The return value is the XML node or string that was signed. Also,
306-
depending on the canonicalization method used by the signature, comments in the XML data may not be subject to
304+
data returned by ``XMLVerifier.verify()``. The ``signed_xml`` attribute of the return value is the XML node or string
305+
that was signed. We also recommend that you assert the expected location for the signature within the document:
306+
307+
.. code-block:: python
308+
309+
from signxml import XMLVerifier, SignatureConfiguration
310+
config = SignatureConfiguration(location="./")
311+
XMLVerifier(...).verify(..., expect_config=config)
312+
313+
Depending on the canonicalization method used by the signature, comments in the XML data may not be subject to
307314
signing, so may need to be untrusted. If so, they are excised from the return value of ``verify()``.
308315
309316
**Recommended reading:** http://www.w3.org/TR/xmldsig-bestpractices/#practices-applications
@@ -316,7 +323,7 @@ def verify(
316323
``x509_cert`` argument to specify a certificate that was pre-shared out-of-band (e.g. via SAML metadata, as
317324
shown in :ref:`Verifying SAML assertions <verifying-saml-assertions>`), or ``cert_subject_name`` to specify a
318325
subject name that must be in the signing X.509 certificate given by the signature (verified as if it were a
319-
domain name), or ``ca_pem_file``/``ca_path`` to give a custom CA.
326+
domain name), or ``ca_pem_file`` to give a custom CA.
320327
321328
:param data: Signature data to verify
322329
:type data: String, file-like object, or XML ElementTree Element API compatible object
@@ -336,10 +343,6 @@ def verify(
336343
:param ca_pem_file:
337344
Filename of a PEM file containing certificate authority information to use when verifying certificate-based
338345
signatures.
339-
:param ca_path:
340-
Path to a directory containing PEM-formatted certificate authority files to use when verifying
341-
certificate-based signatures. If neither **ca_pem_file** nor **ca_path** is given, the Mozilla CA bundle
342-
provided by :py:mod:`certifi` will be loaded.
343346
:param hmac_key: If using HMAC, a string containing the shared secret.
344347
:param validate_schema: Whether to validate **data** against the XML Signature schema.
345348
:param parser:
@@ -433,7 +436,7 @@ def verify(
433436
else:
434437
cert_chain = [x509.load_pem_x509_certificate(add_pem_header(cert)) for cert in certs]
435438

436-
cert_verifier = self.get_cert_chain_verifier(ca_pem_file=ca_pem_file, ca_path=ca_path)
439+
cert_verifier = self.get_cert_chain_verifier(ca_pem_file=ca_pem_file)
437440

438441
signing_cert = cert_verifier.verify(cert_chain)
439442
elif isinstance(self.x509_cert, x509.Certificate):

test/test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def reset_tree(t, method):
6868

6969
def get_verifier_for_year(year: int):
7070
class _Verifier(XMLVerifier):
71-
def get_cert_chain_verifier(self, ca_pem_file, ca_path):
72-
verifier = super().get_cert_chain_verifier(ca_pem_file, ca_path)
71+
def get_cert_chain_verifier(self, ca_pem_file):
72+
verifier = super().get_cert_chain_verifier(ca_pem_file)
7373
verifier.verification_time = datetime(year, 1, 1)
7474
return verifier
7575

0 commit comments

Comments
 (0)