60
60
from saml2 .samlp import SessionIndex
61
61
from saml2 .samlp import artifact_resolve_from_string
62
62
from saml2 .samlp import response_from_string
63
- from saml2 .sigver import SignatureError
63
+ from saml2 .sigver import SignatureError , XMLSEC_SESSION_KEY_URI_TO_ALG
64
64
from saml2 .sigver import SigverError
65
65
from saml2 .sigver import get_pem_wrapped_unwrapped
66
66
from saml2 .sigver import make_temp
78
78
from saml2 .xmldsig import SIG_ALLOWED_ALG
79
79
from saml2 .xmldsig import DefaultSignature
80
80
81
-
82
81
logger = logging .getLogger (__name__ )
83
82
84
83
__author__ = "rolandh"
@@ -181,6 +180,9 @@ def __init__(self, entity_type, config=None, config_file="", virtual_organizatio
181
180
182
181
self .sec = security_context (self .config )
183
182
183
+ self .encrypt_assertion_session_key_algs = self .config .encrypt_assertion_session_key_algs
184
+ self .encrypt_assertion_cert_key_algs = self .config .encrypt_assertion_cert_key_algs
185
+
184
186
if virtual_organization :
185
187
if isinstance (virtual_organization , str ):
186
188
self .vorg = self .config .vorg [virtual_organization ]
@@ -644,34 +646,97 @@ def has_encrypt_cert_in_metadata(self, sp_entity_id):
644
646
return True
645
647
return False
646
648
647
- def _encrypt_assertion (self , encrypt_cert , sp_entity_id , response , node_xpath = None ):
649
+ def _encrypt_assertion (
650
+ self ,
651
+ encrypt_cert ,
652
+ sp_entity_id ,
653
+ response ,
654
+ node_xpath = None ,
655
+ encrypt_cert_session_key_alg = None ,
656
+ encrypt_cert_cert_key_alg = None ,
657
+ ):
648
658
"""Encryption of assertions.
649
659
650
660
:param encrypt_cert: Certificate to be used for encryption.
651
661
:param sp_entity_id: Entity ID for the calling service provider.
652
662
:param response: A samlp.Response
663
+ :param encrypt_cert_cert_key_alg: algorithm used for encrypting session key
664
+ :param encrypt_cert_session_key_alg: algorithm used for encrypting assertion
665
+ :param encrypt_cert_cert_key_alg:
653
666
:param node_xpath: Unquie path to the element to be encrypted.
654
667
:return: A new samlp.Resonse with the designated assertion encrypted.
655
668
"""
656
669
_certs = []
657
670
658
671
if encrypt_cert :
659
- _certs .append ((None , encrypt_cert ))
672
+ _certs .append ((None , encrypt_cert , None , None ))
660
673
elif sp_entity_id is not None :
661
- _certs = self .metadata .certs (sp_entity_id , "any" , "encryption" )
674
+ _certs = self .metadata .certs (sp_entity_id , "any" , "encryption" , get_with_usage_and_encryption_methods = True )
662
675
exception = None
663
- for _cert_name , _cert in _certs :
676
+
677
+ # take certs with encryption and encryption_methods first (priority 1)
678
+ sorted_certs = []
679
+ for _unpacked_cert in _certs :
680
+ _cert_name , _cert , _cert_use , _cert_encryption_methods = _unpacked_cert
681
+ if _cert_use == "encryption" and _cert_encryption_methods :
682
+ sorted_certs .append (_unpacked_cert )
683
+
684
+ # take certs with encryption or encryption_methods (priority 2)
685
+ for _unpacked_cert in _certs :
686
+ _cert_name , _cert , _cert_use , _cert_encryption_methods = _unpacked_cert
687
+ if _cert_use == "encryption" and _unpacked_cert not in sorted_certs :
688
+ sorted_certs .append (_unpacked_cert )
689
+
690
+ for _unpacked_cert in _certs :
691
+ if _unpacked_cert not in sorted_certs :
692
+ sorted_certs .append (_unpacked_cert )
693
+
694
+ for _cert_name , _cert , _cert_use , _cert_encryption_methods in sorted_certs :
664
695
wrapped_cert , unwrapped_cert = get_pem_wrapped_unwrapped (_cert )
665
696
try :
666
697
tmp = make_temp (
667
698
wrapped_cert .encode ("ascii" ),
668
699
decode = False ,
669
700
delete_tmpfiles = self .config .delete_tmpfiles ,
670
701
)
702
+
703
+ msg_enc = (
704
+ encrypt_cert_session_key_alg
705
+ if encrypt_cert_session_key_alg
706
+ else self .encrypt_assertion_session_key_algs [0 ]
707
+ )
708
+ key_enc = (
709
+ encrypt_cert_cert_key_alg if encrypt_cert_cert_key_alg else self .encrypt_assertion_cert_key_algs [0 ]
710
+ )
711
+
712
+ if encrypt_cert != _cert and _cert_encryption_methods :
713
+ viable_session_key_algs = []
714
+ for alg in self .encrypt_assertion_session_key_algs :
715
+ for cert_method in _cert_encryption_methods :
716
+ if cert_method .get ("algorithm" ) == alg :
717
+ viable_session_key_algs .append (alg )
718
+
719
+ viable_cert_algs = []
720
+ for alg in self .encrypt_assertion_cert_key_algs :
721
+ for cert_method in _cert_encryption_methods :
722
+ if cert_method .get ("algorithm" ) == alg :
723
+ viable_cert_algs .append (alg )
724
+
725
+ if viable_session_key_algs :
726
+ msg_enc = viable_session_key_algs [0 ]
727
+
728
+ if viable_cert_algs :
729
+ key_enc = viable_cert_algs [0 ]
730
+
731
+ key_type = XMLSEC_SESSION_KEY_URI_TO_ALG .get (msg_enc )
732
+
671
733
response = self .sec .encrypt_assertion (
672
734
response ,
673
735
tmp .name ,
674
- pre_encryption_part (key_name = _cert_name , encrypt_cert = unwrapped_cert ),
736
+ pre_encryption_part (
737
+ key_name = _cert_name , encrypt_cert = unwrapped_cert , msg_enc = msg_enc , key_enc = key_enc
738
+ ),
739
+ key_type = key_type ,
675
740
node_xpath = node_xpath ,
676
741
)
677
742
return response
@@ -697,7 +762,11 @@ def _response(
697
762
encrypt_assertion_self_contained = False ,
698
763
encrypted_advice_attributes = False ,
699
764
encrypt_cert_advice = None ,
765
+ encrypt_cert_advice_cert_key_alg = None ,
766
+ encrypt_cert_advice_session_key_alg = None ,
700
767
encrypt_cert_assertion = None ,
768
+ encrypt_cert_assertion_cert_key_alg = None ,
769
+ encrypt_cert_assertion_session_key_alg = None ,
701
770
sign_assertion = None ,
702
771
pefim = False ,
703
772
sign_alg = None ,
@@ -731,8 +800,16 @@ def _response(
731
800
element should be encrypted.
732
801
:param encrypt_cert_advice: Certificate to be used for encryption of
733
802
assertions in the advice element.
803
+ :param encrypt_cert_advice_cert_key_alg: algorithm used for encrypting session key
804
+ by encrypt_cert_advice
805
+ :param encrypt_cert_advice_session_key_alg: algorithm used for encrypting assertion
806
+ when using encrypt_cert_advice
734
807
:param encrypt_cert_assertion: Certificate to be used for encryption
735
808
of assertions.
809
+ :param encrypt_cert_assertion_cert_key_alg: algorithm used for encrypting session key
810
+ by encrypt_cert_assertion
811
+ :param encrypt_cert_assertion_session_key_alg: algorithm used for encrypting assertion when
812
+ using encrypt_cert_assertion
736
813
:param sign_assertion: True if assertions should be signed.
737
814
:param pefim: True if a response according to the PEFIM profile
738
815
should be created.
@@ -856,6 +933,8 @@ def _response(
856
933
sp_entity_id ,
857
934
response ,
858
935
node_xpath = node_xpath ,
936
+ encrypt_cert_session_key_alg = encrypt_cert_advice_session_key_alg ,
937
+ encrypt_cert_cert_key_alg = encrypt_cert_advice_cert_key_alg ,
859
938
)
860
939
response = response_from_string (response )
861
940
@@ -900,7 +979,13 @@ def _response(
900
979
response = signed_instance_factory (response , self .sec , to_sign_assertion )
901
980
902
981
# XXX encrypt assertion
903
- response = self ._encrypt_assertion (encrypt_cert_assertion , sp_entity_id , response )
982
+ response = self ._encrypt_assertion (
983
+ encrypt_cert_assertion ,
984
+ sp_entity_id ,
985
+ response ,
986
+ encrypt_cert_session_key_alg = encrypt_cert_assertion_session_key_alg ,
987
+ encrypt_cert_cert_key_alg = encrypt_cert_assertion_cert_key_alg ,
988
+ )
904
989
else :
905
990
# XXX sign other parts! (defiend by to_sign)
906
991
if to_sign :
@@ -1357,7 +1442,6 @@ def create_manage_name_id_response(
1357
1442
digest_alg = None ,
1358
1443
** kwargs ,
1359
1444
):
1360
-
1361
1445
rinfo = self .response_args (request , bindings )
1362
1446
1363
1447
response = self ._status_response (
0 commit comments