|
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