Skip to content

Commit b4abecf

Browse files
Merge pull request #744 from peppelinux/sign_dig_algs
2 parents 2f756ba + eeaf5e0 commit b4abecf

File tree

12 files changed

+1248
-648
lines changed

12 files changed

+1248
-648
lines changed

docs/howto/config.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ The globally unique identifier of the entity.
247247
.. note:: It is recommended that the entityid should point to a real
248248
webpage where the metadata for the entity can be found.
249249

250+
250251
key_file
251252
^^^^^^^^
252253

@@ -1013,6 +1014,23 @@ Example::
10131014
}
10141015
}
10151016

1017+
1018+
signing_algorithm
1019+
"""""""""""""""""
1020+
1021+
Default algorithm to be used. Example::
1022+
1023+
'signing_algorithm': "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
1024+
1025+
1026+
digest_algorithm
1027+
"""""""""""""""""
1028+
1029+
Default algorithm to be used. Example::
1030+
1031+
'digest_algorithm': "http://www.w3.org/2001/04/xmlenc#sha512"
1032+
1033+
10161034
logout_responses_signed
10171035
"""""""""""""""""""""""
10181036

@@ -1031,6 +1049,7 @@ Example::
10311049
}
10321050
}
10331051

1052+
10341053
subject_data
10351054
""""""""""""
10361055

src/saml2/client.py

Lines changed: 114 additions & 61 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,12 +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)
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+
)
203219

204-
def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
205-
expected_binding=None, sign_alg=None, digest_alg=None,
206-
**kwargs):
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+
):
207232
"""
208233
209234
:param name_id: Identifier of the Subject (a NameID instance)
@@ -232,6 +257,7 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
232257
for binding in [BINDING_SOAP, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT]:
233258
if expected_binding and binding != expected_binding:
234259
continue
260+
235261
try:
236262
srvs = self.metadata.single_logout_service(
237263
entity_id, binding, "idpsso"
@@ -245,44 +271,37 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
245271

246272
destination = next(locations(srvs), None)
247273
logger.info("destination to provider: %s", destination)
274+
248275
try:
249276
session_info = self.users.get_info_from(
250277
name_id, entity_id, False
251278
)
252279
session_indexes = [session_info['session_index']]
253280
except KeyError:
254281
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+
255286
req_id, request = self.create_logout_request(
256-
destination, entity_id, name_id=name_id, reason=reason,
257-
expire=expire, session_indexes=session_indexes)
258-
259-
sign = sign if sign is not None else self.logout_requests_signed
260-
def_sig = DefaultSignature()
261-
sign_alg = def_sig.get_sign_alg() if sign_alg is None else sign_alg
262-
digest_alg = (
263-
def_sig.get_digest_alg()
264-
if digest_alg is None
265-
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,
266296
)
267297

268-
if sign:
269-
if binding == BINDING_HTTP_REDIRECT:
270-
srequest = str(request)
271-
else:
272-
srequest = self.sign(
273-
request, sign_alg=sign_alg, digest_alg=digest_alg
274-
)
275-
else:
276-
srequest = str(request)
277-
278298
relay_state = self._relay_state(req_id)
279-
280299
http_info = self.apply_binding(
281300
binding,
282-
srequest,
301+
str(request),
283302
destination,
284303
relay_state,
285-
sign=sign,
304+
sign=sign_redirect,
286305
sigalg=sign_alg,
287306
)
288307

@@ -355,11 +374,15 @@ def handle_logout_response(self, response, sign_alg=None, digest_alg=None):
355374
status["entity_ids"].remove(issuer)
356375
if "sign_alg" in status:
357376
sign_alg = status["sign_alg"]
358-
return self.do_logout(decode(status["name_id"]),
359-
status["entity_ids"],
360-
status["reason"], status["not_on_or_after"],
361-
status["sign"], sign_alg=sign_alg,
362-
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+
)
363386

364387
def _use_soap(self, destination, query_type, **kwargs):
365388
_create_func = getattr(self, "create_%s" % query_type)
@@ -471,6 +494,7 @@ def do_attribute_query(
471494
binding=BINDING_SOAP,
472495
nsprefix=None,
473496
sign_alg=None,
497+
digest_alg=None,
474498
):
475499
""" Does a attribute request to an attribute authority, this is
476500
by default done over SOAP.
@@ -500,10 +524,9 @@ def do_attribute_query(
500524
response_args = {}
501525

502526
if not binding:
503-
binding, destination = self.pick_binding("attribute_service",
504-
None,
505-
"attribute_authority",
506-
entity_id=entityid)
527+
binding, destination = self.pick_binding(
528+
"attribute_service", None, "attribute_authority", entity_id=entityid
529+
)
507530
else:
508531
srvs = self.metadata.attribute_service(entityid, binding)
509532
if srvs is []:
@@ -512,37 +535,62 @@ def do_attribute_query(
512535
destination = next(locations(srvs), None)
513536

514537
if binding == BINDING_SOAP:
515-
return self._use_soap(destination, "attribute_query",
516-
consent=consent, extensions=extensions,
517-
sign=sign, subject_id=subject_id,
518-
attribute=attribute,
519-
sp_name_qualifier=sp_name_qualifier,
520-
name_qualifier=name_qualifier,
521-
format=nameid_format,
522-
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+
)
523553
elif binding == BINDING_HTTP_POST:
524554
mid = sid()
525-
query = self.create_attribute_query(destination, subject_id,
526-
attribute, mid, consent,
527-
extensions, sign, nsprefix)
528-
self.state[query.id] = {"entity_id": entityid,
529-
"operation": "AttributeQuery",
530-
"subject_id": subject_id,
531-
"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+
}
532573
relay_state = self._relay_state(query.id)
533574
return self.apply_binding(
534575
binding,
535576
str(query),
536577
destination,
537578
relay_state,
538-
sign=sign,
579+
sign=False,
539580
sigalg=sign_alg,
540581
)
541582
else:
542583
raise SAMLError("Unsupported binding")
543584

544585
def handle_logout_request(
545-
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="",
546594
):
547595
"""
548596
Deal with a LogoutRequest
@@ -592,7 +640,12 @@ def handle_logout_request(
592640
sign = self.logout_responses_signed
593641

594642
response = self.create_logout_response(
595-
_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,
596649
)
597650
rinfo = self.response_args(_req.message, response_bindings)
598651

0 commit comments

Comments
 (0)