|
1 | 1 | import logging
|
2 | 2 |
|
| 3 | +from saml2 import time_util |
| 4 | +from saml2 import BINDING_HTTP_REDIRECT |
| 5 | +from saml2 import BINDING_HTTP_POST |
3 | 6 | from saml2.attribute_converter import to_local
|
4 |
| -from saml2 import time_util, BINDING_HTTP_REDIRECT |
5 | 7 | from saml2.s_utils import OtherError
|
6 | 8 |
|
7 | 9 | from saml2.validate import valid_instance
|
@@ -37,81 +39,83 @@ def _clear(self):
|
37 | 39 | self.message = None
|
38 | 40 | self.not_on_or_after = 0
|
39 | 41 |
|
40 |
| - def _loads(self, xmldata, binding=None, origdoc=None, must=None, |
41 |
| - only_valid_cert=False, relayState=None, sigalg=None, signature=None): |
| 42 | + def _loads( |
| 43 | + self, |
| 44 | + xmldata, |
| 45 | + binding=None, |
| 46 | + origdoc=None, |
| 47 | + must=None, |
| 48 | + only_valid_cert=False, |
| 49 | + relay_state=None, |
| 50 | + sigalg=None, |
| 51 | + signature=None, |
| 52 | + ): |
42 | 53 | # own copy
|
43 | 54 | self.xmlstr = xmldata[:]
|
44 |
| - logger.debug("xmlstr: %s, relayState: %s, sigalg: %s, signature: %s", |
45 |
| - self.xmlstr, relayState, sigalg, signature) |
46 |
| - # If redirect binding, and provided SigAlg, Signature use that to verify |
47 |
| - # and skip signatureCheck withing SAMLRequest/xmldata |
48 |
| - _need_redirect_sig_check, _saml_msg, must = self._should_do_redirect_sig_check( |
49 |
| - binding, must, origdoc, relayState, sigalg, signature) |
| 55 | + logger.debug("xmlstr: %s, relay_state: %s, sigalg: %s, signature: %s", |
| 56 | + self.xmlstr, relay_state, sigalg, signature) |
| 57 | + |
| 58 | + signed_post = must and binding == BINDING_HTTP_POST |
| 59 | + signed_redirect = must and binding == BINDING_HTTP_REDIRECT |
| 60 | + incorrectly_signed = IncorrectlySigned("Request was not signed correctly") |
50 | 61 |
|
51 | 62 | try:
|
52 |
| - self.message = self.signature_check(xmldata, origdoc=origdoc, |
53 |
| - must=must, |
54 |
| - only_valid_cert=only_valid_cert) |
55 |
| - except TypeError: |
56 |
| - raise |
57 |
| - except Exception as excp: |
| 63 | + self.message = self.signature_check( |
| 64 | + xmldata, |
| 65 | + origdoc=origdoc, |
| 66 | + must=signed_post, |
| 67 | + only_valid_cert=only_valid_cert, |
| 68 | + ) |
| 69 | + except Exception as e: |
58 | 70 | self.message = None
|
59 |
| - logger.info("EXCEPTION: %s", excp) |
| 71 | + raise incorrectly_signed from e |
60 | 72 |
|
61 |
| - if _need_redirect_sig_check and self.message is not None: |
62 |
| - _verified_ok = self._do_redirect_sig_check(_saml_msg) |
63 |
| - # Set self.message to None, it shall raise error further down. |
64 |
| - if not _verified_ok: |
| 73 | + if signed_redirect: |
| 74 | + if sigalg is None or signature is None: |
| 75 | + raise incorrectly_signed |
| 76 | + |
| 77 | + _saml_msg = { |
| 78 | + "SAMLRequest": origdoc, |
| 79 | + "Signature": signature, |
| 80 | + "SigAlg": sigalg, |
| 81 | + } |
| 82 | + if relay_state is not None: |
| 83 | + _saml_msg["RelayState"] = relay_state |
| 84 | + try: |
| 85 | + sig_verified = self._do_redirect_sig_check(_saml_msg) |
| 86 | + except Exception as e: |
65 | 87 | self.message = None
|
66 |
| - logger.error('Failed to verify signature') |
| 88 | + raise incorrectly_signed from e |
| 89 | + else: |
| 90 | + if not sig_verified: |
| 91 | + self.message = None |
| 92 | + raise incorrectly_signed |
67 | 93 |
|
68 | 94 | if not self.message:
|
69 |
| - logger.error("Request was not correctly signed") |
70 |
| - logger.info("Request: %s", xmldata) |
71 |
| - raise IncorrectlySigned() |
| 95 | + logger.error("Request was not signed correctly") |
| 96 | + logger.info("Request data: %s", xmldata) |
| 97 | + raise incorrectly_signed |
72 | 98 |
|
73 |
| - logger.info("Request: %s", self.message) |
| 99 | + logger.info("Request message: %s", self.message) |
74 | 100 |
|
75 | 101 | try:
|
76 | 102 | valid_instance(self.message)
|
77 | 103 | except NotValid as exc:
|
78 |
| - logger.error("Not valid request: %s", exc.args[0]) |
| 104 | + logger.error("Request not valid: %s", exc.args[0]) |
79 | 105 | raise
|
80 | 106 |
|
81 | 107 | return self
|
82 | 108 |
|
83 | 109 | def _do_redirect_sig_check(self, _saml_msg):
|
84 |
| - _issuer = self.message.issuer.text.strip() |
85 |
| - _certs = self.sec.metadata.certs(_issuer, "any", "signing") |
86 |
| - logger.debug("Certs: %s, _saml_msg: %s", _certs, _saml_msg) |
87 |
| - _verified_ok = False |
88 |
| - for cert in _certs: |
89 |
| - if verify_redirect_signature(_saml_msg, self.sec.sec_backend, cert): |
90 |
| - _verified_ok = True |
91 |
| - break |
92 |
| - logger.info("Redirect request signature check: %s", _verified_ok) |
93 |
| - return _verified_ok |
94 |
| - |
95 |
| - def _should_do_redirect_sig_check(self, binding, must, origdoc, relayState, sigalg, |
96 |
| - signature): |
97 |
| - _do_redirect_sig_check = False |
98 |
| - _saml_msg = {} |
99 |
| - if binding == BINDING_HTTP_REDIRECT and must \ |
100 |
| - and sigalg is not None and signature is not None: |
101 |
| - logger.debug("Request signature check will be done using query param," |
102 |
| - " instead of SAMLRequest content") |
103 |
| - _do_redirect_sig_check = True |
104 |
| - must = False |
105 |
| - _saml_msg = { |
106 |
| - "SAMLRequest": origdoc, |
107 |
| - "SigAlg": sigalg, |
108 |
| - "Signature": signature |
109 |
| - } |
110 |
| - # RelayState is optional so only add when available, |
111 |
| - # signature validate fails if passed as None |
112 |
| - if relayState is not None: |
113 |
| - _saml_msg["RelayState"] = relayState |
114 |
| - return _do_redirect_sig_check, _saml_msg, must |
| 110 | + issuer = self.message.issuer.text.strip() |
| 111 | + certs = self.sec.metadata.certs(issuer, "any", "signing") |
| 112 | + logger.debug("Certs to verify request sig: %s, _saml_msg: %s", certs, _saml_msg) |
| 113 | + verified = any( |
| 114 | + verify_redirect_signature(_saml_msg, self.sec.sec_backend, cert) |
| 115 | + for cert_name, cert in certs |
| 116 | + ) |
| 117 | + logger.info("Redirect request signature check: %s", verified) |
| 118 | + return verified |
115 | 119 |
|
116 | 120 | def issue_instant_ok(self):
|
117 | 121 | """ Check that the request was issued at a reasonable time """
|
@@ -144,7 +148,7 @@ def _verify(self):
|
144 | 148 | def loads(self, xmldata, binding, origdoc=None, must=None,
|
145 | 149 | only_valid_cert=False, relay_state=None, sigalg=None, signature=None):
|
146 | 150 | return self._loads(xmldata, binding, origdoc, must,
|
147 |
| - only_valid_cert=only_valid_cert, relayState=relay_state, |
| 151 | + only_valid_cert=only_valid_cert, relay_state=relay_state, |
148 | 152 | sigalg=sigalg, signature=signature)
|
149 | 153 |
|
150 | 154 | def verify(self):
|
|
0 commit comments