Skip to content

Commit 72e69e4

Browse files
Merge pull request #834 from mheuwes/soap-fixes
Fix AttributeError and signature mangling during construction of SOAP request
2 parents 1149990 + 44d967d commit 72e69e4

File tree

5 files changed

+66
-12
lines changed

5 files changed

+66
-12
lines changed

src/saml2/client.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ def prepare_for_negotiated_authenticate(
152152
# XXX ^through self.create_authn_request(...)
153153
# XXX - sign_redirect will add the signature to the query params
154154
# XXX ^through self.apply_binding(...)
155-
sign_post = False if binding == BINDING_HTTP_REDIRECT else sign
156-
sign_redirect = False if binding == BINDING_HTTP_POST and sign else sign
155+
sign_redirect = sign and binding == BINDING_HTTP_REDIRECT
156+
sign_post = sign and not sign_redirect
157157

158158
reqid, request = self.create_authn_request(
159159
destination=destination,
@@ -318,10 +318,8 @@ def do_logout(
318318
session_indexes = None
319319

320320
sign = sign if sign is not None else self.logout_requests_signed
321-
sign_post = sign and (
322-
binding == BINDING_HTTP_POST or binding == BINDING_SOAP
323-
)
324321
sign_redirect = sign and binding == BINDING_HTTP_REDIRECT
322+
sign_post = sign and not sign_redirect
325323

326324
log_report = {
327325
"message": "Invoking SLO on entity",

src/saml2/httpbase.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ def use_soap(self, request, destination="", soap_headers=None, sign=False,
315315

316316
if sign and self.sec:
317317
_signed = self.sec.sign_statement(soap_message,
318-
class_name=class_name(request),
318+
node_name=class_name(request),
319319
node_id=request.id)
320320
soap_message = _signed
321321

src/saml2/pack.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
240240
if thingy[0:5].lower() == '<?xml':
241241
logger.debug("thingy0: %s", thingy)
242242
_part = thingy.split("\n")
243-
thingy = "".join(_part[1:])
243+
thingy = "\n".join(_part[1:])
244244
thingy = thingy.replace(PREFIX, "")
245245
logger.debug("thingy: %s", thingy)
246246
_child = ElementTree.Element('')

src/saml2/request.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from saml2 import time_util
44
from saml2 import BINDING_HTTP_REDIRECT
5-
from saml2 import BINDING_HTTP_POST
65
from saml2.attribute_converter import to_local
76
from saml2.s_utils import OtherError
87

@@ -55,22 +54,22 @@ def _loads(
5554
logger.debug("xmlstr: %s, relay_state: %s, sigalg: %s, signature: %s",
5655
self.xmlstr, relay_state, sigalg, signature)
5756

58-
signed_post = must and binding == BINDING_HTTP_POST
59-
signed_redirect = must and binding == BINDING_HTTP_REDIRECT
57+
sign_redirect = must and binding == BINDING_HTTP_REDIRECT
58+
sign_post = must and not sign_redirect
6059
incorrectly_signed = IncorrectlySigned("Request was not signed correctly")
6160

6261
try:
6362
self.message = self.signature_check(
6463
xmldata,
6564
origdoc=origdoc,
66-
must=signed_post,
65+
must=sign_post,
6766
only_valid_cert=only_valid_cert,
6867
)
6968
except Exception as e:
7069
self.message = None
7170
raise incorrectly_signed from e
7271

73-
if signed_redirect:
72+
if sign_redirect:
7473
if sigalg is None or signature is None:
7574
raise incorrectly_signed
7675

tests/test_50_server.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from saml2.sigver import make_temp, DecryptError, EncryptError, CertificateError
1313
from saml2.assertion import Policy
1414
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
15+
from saml2.response import IncorrectlySigned
1516
from saml2.saml import NameID, NAMEID_FORMAT_TRANSIENT
1617
from saml2.samlp import response_from_string
1718

@@ -32,6 +33,7 @@
3233
from saml2.soap import make_soap_enveloped_saml_thingy
3334
from saml2 import BINDING_HTTP_POST
3435
from saml2 import BINDING_HTTP_REDIRECT
36+
from saml2 import BINDING_SOAP
3537
from saml2.time_util import instant
3638

3739
from pytest import raises
@@ -2245,10 +2247,65 @@ def test_slo_soap(self):
22452247
self.server.ident.close()
22462248

22472249
with closing(Server("idp_soap_conf")) as idp:
2250+
request = idp.parse_logout_request(saml_soap)
2251+
assert request
2252+
2253+
idp.config.setattr("idp", "want_authn_requests_signed", True)
2254+
assert idp.config.getattr("want_authn_requests_signed", "idp")
2255+
2256+
with raises(IncorrectlySigned):
2257+
# check unsigned requests over SOAP to fail
2258+
request = idp.parse_logout_request(saml_soap)
2259+
assert not request
2260+
2261+
idp.ident.close()
2262+
2263+
def test_slo_soap_signed(self):
2264+
soon = time_util.in_a_while(days=1)
2265+
sinfo = {
2266+
"name_id": nid,
2267+
"issuer": "urn:mace:example.com:saml:roland:idp",
2268+
"not_on_or_after": soon,
2269+
"user": {
2270+
"givenName": "Leo",
2271+
"sn": "Laport",
2272+
}
2273+
}
2274+
2275+
sp = client.Saml2Client(config_file="server_conf")
2276+
sp.users.add_information_about_person(sinfo)
2277+
2278+
req_id, logout_request = sp.create_logout_request(
2279+
name_id=nid, destination="http://localhost:8088/slo",
2280+
issuer_entity_id="urn:mace:example.com:saml:roland:idp",
2281+
reason="I'm tired of this", sign=True, sign_alg=ds.SIG_RSA_SHA512,
2282+
digest_alg=ds.DIGEST_SHA512,
2283+
)
2284+
2285+
saml_soap = sp.apply_binding(BINDING_SOAP, logout_request, sign=False)
2286+
saml_soap = saml_soap["data"]
2287+
self.server.ident.close()
2288+
2289+
with closing(Server("idp_soap_conf")) as idp:
2290+
idp.config.setattr("idp", "want_authn_requests_signed", True)
2291+
assert idp.config.getattr("want_authn_requests_signed", "idp")
2292+
2293+
with raises(IncorrectlySigned):
2294+
# idp_soap_conf has invalid certificate for sp
2295+
request = idp.parse_logout_request(saml_soap)
2296+
assert not request
2297+
2298+
idp.ident.close()
2299+
2300+
with closing(Server("idp_conf_verify_cert")) as idp:
2301+
idp.config.setattr("idp", "want_authn_requests_signed", True)
2302+
assert idp.config.getattr("want_authn_requests_signed", "idp")
2303+
22482304
request = idp.parse_logout_request(saml_soap)
22492305
idp.ident.close()
22502306
assert request
22512307

2308+
22522309
# ------------------------------------------------------------------------
22532310

22542311

0 commit comments

Comments
 (0)