Skip to content

Commit 017092f

Browse files
committed
WIP fix ensure callers
Signed-off-by: Ivan Kanakarakis <[email protected]>
1 parent 696e36a commit 017092f

File tree

2 files changed

+156
-73
lines changed

2 files changed

+156
-73
lines changed

src/saml2/client.py

Lines changed: 115 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
from saml2 import BINDING_HTTP_POST
1515
from saml2 import BINDING_SOAP
1616

17-
from saml2.xmldsig import DefaultSignature
18-
1917
from saml2.ident import decode, code
2018
from saml2.httpbase import HTTPError
2119
from saml2.s_utils import sid
@@ -50,6 +48,7 @@ def prepare_for_authenticate(
5048
consent=None, extensions=None,
5149
sign=None,
5250
sigalg=None,
51+
digest_alg=None,
5352
response_binding=saml2.BINDING_HTTP_POST,
5453
**kwargs,
5554
):
@@ -81,6 +80,7 @@ def prepare_for_authenticate(
8180
extensions=extensions,
8281
sign=sign,
8382
sigalg=sigalg,
83+
digest_alg=digest_alg,
8484
response_binding=response_binding,
8585
**kwargs,
8686
)
@@ -107,6 +107,7 @@ def prepare_for_negotiated_authenticate(
107107
sign=None,
108108
response_binding=saml2.BINDING_HTTP_POST,
109109
sigalg=None,
110+
digest_alg=None,
110111
**kwargs,
111112
):
112113
""" Makes all necessary preparations for an authentication request
@@ -140,8 +141,8 @@ def prepare_for_negotiated_authenticate(
140141
# XXX ^through self.create_authn_request(...)
141142
# XXX - sign_redirect will add the signature to the query params
142143
# XXX ^through self.apply_binding(...)
143-
sign_post = (binding == BINDING_HTTP_POST and sign)
144-
sign_redirect = (binding == BINDING_HTTP_REDIRECT and sign)
144+
sign_post = False if binding == BINDING_HTTP_REDIRECT else sign
145+
sign_redirect = False if binding == BINDING_HTTP_POST and sign else sign
145146

146147
reqid, request = self.create_authn_request(
147148
destination,
@@ -153,6 +154,7 @@ def prepare_for_negotiated_authenticate(
153154
extensions=extensions,
154155
sign=sign_post,
155156
sign_alg=sigalg,
157+
digest_alg=digest_alg,
156158
**kwargs,
157159
)
158160

@@ -172,8 +174,15 @@ def prepare_for_negotiated_authenticate(
172174
else:
173175
raise SignOnError("No supported bindings available for authentication")
174176

175-
def global_logout(self, name_id, reason="", expire=None, sign=None,
176-
sign_alg=None, digest_alg=None):
177+
def global_logout(
178+
self,
179+
name_id,
180+
reason="",
181+
expire=None,
182+
sign=None,
183+
sign_alg=None,
184+
digest_alg=None,
185+
):
177186
""" More or less a layer of indirection :-/
178187
Bootstrapping the whole thing by finding all the IdPs that should
179188
be notified.
@@ -198,14 +207,28 @@ def global_logout(self, name_id, reason="", expire=None, sign=None,
198207

199208
# find out which IdPs/AAs I should notify
200209
entity_ids = self.users.issuers_of_info(name_id)
201-
return self.do_logout(name_id, entity_ids, reason, expire, sign,
202-
sign_alg=sign_alg, digest_alg=digest_alg)
203-
204-
# XXX calls DefaultSignature
205-
# XXX calls self.sign
206-
def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
207-
expected_binding=None, sign_alg=None, digest_alg=None,
208-
**kwargs):
210+
return self.do_logout(
211+
name_id,
212+
entity_ids,
213+
reason,
214+
expire,
215+
sign,
216+
sign_alg=sign_alg,
217+
digest_alg=digest_alg,
218+
)
219+
220+
def do_logout(
221+
self,
222+
name_id,
223+
entity_ids,
224+
reason,
225+
expire,
226+
sign=None,
227+
expected_binding=None,
228+
sign_alg=None,
229+
digest_alg=None,
230+
**kwargs,
231+
):
209232
"""
210233
211234
:param name_id: Identifier of the Subject (a NameID instance)
@@ -234,6 +257,7 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
234257
for binding in [BINDING_SOAP, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT]:
235258
if expected_binding and binding != expected_binding:
236259
continue
260+
237261
try:
238262
srvs = self.metadata.single_logout_service(
239263
entity_id, binding, "idpsso"
@@ -247,44 +271,37 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
247271

248272
destination = next(locations(srvs), None)
249273
logger.info("destination to provider: %s", destination)
274+
250275
try:
251276
session_info = self.users.get_info_from(
252277
name_id, entity_id, False
253278
)
254279
session_indexes = [session_info['session_index']]
255280
except KeyError:
256281
session_indexes = None
282+
283+
sign_post = False if binding == BINDING_HTTP_REDIRECT else sign
284+
sign_redirect = False if binding == BINDING_HTTP_POST and sign else sign
285+
257286
req_id, request = self.create_logout_request(
258-
destination, entity_id, name_id=name_id, reason=reason,
259-
expire=expire, session_indexes=session_indexes)
260-
261-
sign = sign if sign is not None else self.logout_requests_signed
262-
def_sig = DefaultSignature()
263-
sign_alg = def_sig.get_sign_alg() if sign_alg is None else sign_alg
264-
digest_alg = (
265-
def_sig.get_digest_alg()
266-
if digest_alg is None
267-
else digest_alg
287+
destination,
288+
entity_id,
289+
name_id=name_id,
290+
reason=reason,
291+
expire=expire,
292+
session_indexes=session_indexes,
293+
sign=sign_post,
294+
sign_alg=sign_alg,
295+
digest_alg=digest_alg,
268296
)
269297

270-
if sign:
271-
if binding == BINDING_HTTP_REDIRECT:
272-
srequest = str(request)
273-
else:
274-
srequest = self.sign(
275-
request, sign_alg=sign_alg, digest_alg=digest_alg
276-
)
277-
else:
278-
srequest = str(request)
279-
280298
relay_state = self._relay_state(req_id)
281-
282299
http_info = self.apply_binding(
283300
binding,
284-
srequest,
301+
str(request),
285302
destination,
286303
relay_state,
287-
sign=sign,
304+
sign=sign_redirect,
288305
sigalg=sign_alg,
289306
)
290307

@@ -357,11 +374,15 @@ def handle_logout_response(self, response, sign_alg=None, digest_alg=None):
357374
status["entity_ids"].remove(issuer)
358375
if "sign_alg" in status:
359376
sign_alg = status["sign_alg"]
360-
return self.do_logout(decode(status["name_id"]),
361-
status["entity_ids"],
362-
status["reason"], status["not_on_or_after"],
363-
status["sign"], sign_alg=sign_alg,
364-
digest_alg=digest_alg)
377+
return self.do_logout(
378+
decode(status["name_id"]),
379+
status["entity_ids"],
380+
status["reason"],
381+
status["not_on_or_after"],
382+
status["sign"],
383+
sign_alg=sign_alg,
384+
digest_alg=digest_alg,
385+
)
365386

366387
def _use_soap(self, destination, query_type, **kwargs):
367388
_create_func = getattr(self, "create_%s" % query_type)
@@ -473,6 +494,7 @@ def do_attribute_query(
473494
binding=BINDING_SOAP,
474495
nsprefix=None,
475496
sign_alg=None,
497+
digest_alg=None,
476498
):
477499
""" Does a attribute request to an attribute authority, this is
478500
by default done over SOAP.
@@ -502,10 +524,9 @@ def do_attribute_query(
502524
response_args = {}
503525

504526
if not binding:
505-
binding, destination = self.pick_binding("attribute_service",
506-
None,
507-
"attribute_authority",
508-
entity_id=entityid)
527+
binding, destination = self.pick_binding(
528+
"attribute_service", None, "attribute_authority", entity_id=entityid
529+
)
509530
else:
510531
srvs = self.metadata.attribute_service(entityid, binding)
511532
if srvs is []:
@@ -514,37 +535,62 @@ def do_attribute_query(
514535
destination = next(locations(srvs), None)
515536

516537
if binding == BINDING_SOAP:
517-
return self._use_soap(destination, "attribute_query",
518-
consent=consent, extensions=extensions,
519-
sign=sign, subject_id=subject_id,
520-
attribute=attribute,
521-
sp_name_qualifier=sp_name_qualifier,
522-
name_qualifier=name_qualifier,
523-
format=nameid_format,
524-
response_args=response_args)
538+
return self._use_soap(
539+
destination,
540+
"attribute_query",
541+
consent=consent,
542+
extensions=extensions,
543+
sign=sign,
544+
sign_alg=sign_alg,
545+
digest_alg=digest_alg,
546+
subject_id=subject_id,
547+
attribute=attribute,
548+
sp_name_qualifier=sp_name_qualifier,
549+
name_qualifier=name_qualifier,
550+
format=nameid_format,
551+
response_args=response_args,
552+
)
525553
elif binding == BINDING_HTTP_POST:
526554
mid = sid()
527-
query = self.create_attribute_query(destination, subject_id,
528-
attribute, mid, consent,
529-
extensions, sign, nsprefix)
530-
self.state[query.id] = {"entity_id": entityid,
531-
"operation": "AttributeQuery",
532-
"subject_id": subject_id,
533-
"sign": sign}
555+
query = self.create_attribute_query(
556+
destination,
557+
name_id=subject_id,
558+
attribute=attribute,
559+
message_id=mid,
560+
consent=consent,
561+
extensions=extensions,
562+
sign=sign,
563+
sign_alg=sign_alg,
564+
digest_alg=digest_alg,
565+
nsprefix=nsprefix,
566+
)
567+
self.state[query.id] = {
568+
"entity_id": entityid,
569+
"operation": "AttributeQuery",
570+
"subject_id": subject_id,
571+
"sign": sign,
572+
}
534573
relay_state = self._relay_state(query.id)
535574
return self.apply_binding(
536575
binding,
537576
str(query),
538577
destination,
539578
relay_state,
540-
sign=sign,
579+
sign=False,
541580
sigalg=sign_alg,
542581
)
543582
else:
544583
raise SAMLError("Unsupported binding")
545584

546585
def handle_logout_request(
547-
self, request, name_id, binding, sign=None, sign_alg=None, relay_state=""
586+
self,
587+
request,
588+
name_id,
589+
binding,
590+
sign=None,
591+
sign_alg=None,
592+
digest_alg=None,
593+
relay_state="",
548594
):
549595
"""
550596
Deal with a LogoutRequest
@@ -594,7 +640,12 @@ def handle_logout_request(
594640
sign = self.logout_responses_signed
595641

596642
response = self.create_logout_response(
597-
_req.message, response_bindings, status, sign, sign_alg=sign_alg
643+
_req.message,
644+
bindings=response_bindings,
645+
status=status,
646+
sign=sign,
647+
sign_alg=sign_alg,
648+
digest_alg=digest_alg,
598649
)
599650
rinfo = self.response_args(_req.message, response_bindings)
600651

src/saml2/server.py

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,25 @@ def update_farg(in_response_to, consumer_url, farg=None):
328328
consumer_url])
329329
return farg
330330

331-
def setup_assertion(self, authn, sp_entity_id, in_response_to, consumer_url,
332-
name_id, policy, _issuer, authn_statement, identity,
333-
best_effort, sign_response, farg=None,
334-
session_not_on_or_after=None, **kwargs):
331+
def setup_assertion(
332+
self,
333+
authn,
334+
sp_entity_id,
335+
in_response_to,
336+
consumer_url,
337+
name_id,
338+
policy,
339+
_issuer,
340+
authn_statement,
341+
identity,
342+
best_effort,
343+
sign_response,
344+
farg=None,
345+
session_not_on_or_after=None,
346+
sign_alg=None,
347+
digest_alg=None,
348+
**kwargs,
349+
):
335350
"""
336351
Construct and return the Assertion
337352
@@ -360,8 +375,15 @@ def setup_assertion(self, authn, sp_entity_id, in_response_to, consumer_url,
360375
ast.apply_policy(sp_entity_id, policy)
361376
except MissingValue as exc:
362377
if not best_effort:
363-
return self.create_error_response(in_response_to, consumer_url,
364-
exc, sign_response)
378+
response = self.create_error_response(
379+
in_response_to,
380+
destination=consumer_url,
381+
info=exc,
382+
sign=sign_response,
383+
sign_alg=sign_alg,
384+
digest_alg=digest_alg,
385+
)
386+
return str(response).split("\n")
365387

366388
farg = self.update_farg(in_response_to, consumer_url, farg)
367389

@@ -785,9 +807,14 @@ def create_authn_response(
785807
)
786808
except IOError as exc:
787809
response = self.create_error_response(
788-
in_response_to, destination, sp_entity_id, exc, name_id
810+
in_response_to,
811+
destination=destination,
812+
info=exc,
813+
sign=sign_response,
814+
sign_alg=sign_alg,
815+
digest_alg=digest_alg,
789816
)
790-
return ("%s" % response).split("\n")
817+
return str(response).split("\n")
791818

792819
try:
793820
_authn = authn
@@ -806,7 +833,12 @@ def create_authn_response(
806833
)
807834
except MissingValue as exc:
808835
return self.create_error_response(
809-
in_response_to, destination, sp_entity_id, exc, name_id
836+
in_response_to,
837+
destination=destination,
838+
info=exc,
839+
sign=sign_response,
840+
sign_alg=sign_alg,
841+
digest_alg=digest_alg,
810842
)
811843

812844
# XXX DONE idp create > create_authn_response > _authn_response > _response

0 commit comments

Comments
 (0)