Skip to content

Commit a72c850

Browse files
author
Hans Hörberg
committed
Merge remote-tracking branch 'upstream/master'
2 parents 596d71a + 3a9326f commit a72c850

File tree

11 files changed

+219
-67
lines changed

11 files changed

+219
-67
lines changed

example/idp2/idp.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
import re
88
import socket
99
import time
10+
import ssl
1011

1112
from Cookie import SimpleCookie
1213
from hashlib import sha1
1314
from urlparse import parse_qs
15+
from cherrypy import wsgiserver
16+
from cherrypy.wsgiserver import ssl_pyopenssl
1417

1518
from saml2 import BINDING_HTTP_ARTIFACT
1619
from saml2 import BINDING_URI
@@ -1044,13 +1047,15 @@ def application(environ, start_response):
10441047
parser.add_argument(dest="config")
10451048
args = parser.parse_args()
10461049

1050+
CONFIG = importlib.import_module(args.config)
1051+
10471052
AUTHN_BROKER = AuthnBroker()
10481053
AUTHN_BROKER.add(authn_context_class_ref(PASSWORD),
10491054
username_password_authn, 10,
1050-
"http://%s" % socket.gethostname())
1055+
CONFIG.BASE)
10511056
AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED),
1052-
"", 0, "http://%s" % socket.gethostname())
1053-
CONFIG = importlib.import_module(args.config)
1057+
"", 0, CONFIG.BASE)
1058+
10541059
IDP = server.Server(args.config, cache=Cache())
10551060
IDP.ticket = {}
10561061

@@ -1062,6 +1067,17 @@ def application(environ, start_response):
10621067
HOST = CONFIG.HOST
10631068
PORT = CONFIG.PORT
10641069

1065-
SRV = make_server(HOST, PORT, application)
1066-
print("IdP listening on %s:%s" % (HOST, PORT))
1067-
SRV.serve_forever()
1070+
SRV = wsgiserver.CherryPyWSGIServer((HOST, PORT), application)
1071+
1072+
_https = ""
1073+
if CONFIG.HTTPS:
1074+
SRV.ssl_adapter = ssl_pyopenssl.pyOpenSSLAdapter(CONFIG.SERVER_CERT,
1075+
CONFIG.SERVER_KEY, CONFIG.CERT_CHAIN)
1076+
_https = " using SSL/TLS"
1077+
logger.info("Server starting")
1078+
print("IDP listening on %s:%s%s" % (HOST, PORT, _https))
1079+
try:
1080+
SRV.start()
1081+
except KeyboardInterrupt:
1082+
SRV.stop()
1083+

example/idp2/idp_conf.py.example

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ def full_path(local_file):
2828
HOST = 'localhost'
2929
PORT = 8088
3030

31-
BASE = "http://%s:%s" % (HOST, PORT)
31+
HTTPS = True
32+
33+
if HTTPS:
34+
BASE = "https://%s:%s" % (HOST, PORT)
35+
else:
36+
BASE = "http://%s:%s" % (HOST, PORT)
37+
38+
# HTTPS cert information
39+
SERVER_CERT = "pki/mycert.pem"
40+
SERVER_KEY = "pki/mykey.pem"
41+
CERT_CHAIN = ""
3242

3343
CONFIG = {
3444
"entityid": "%s/idp.xml" % BASE,

example/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mako
2+
cherrypy

example/sp-wsgi/sp.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,6 @@ def do(self, response, binding, relay_state="", mtype="response"):
379379
cookie = self.cache.set_cookie(user)
380380

381381
resp = Redirect("/", headers=[
382-
("Location", "/"),
383382
cookie,
384383
])
385384
return resp(self.environ, self.start_response)

src/saml2/client.py

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

17+
import saml2.xmldsig as ds
18+
1719
from saml2.ident import decode, code
1820
from saml2.httpbase import HTTPError
1921
from saml2.s_utils import sid
@@ -161,7 +163,7 @@ def global_logout(self, name_id, reason="", expire=None, sign=None):
161163
return self.do_logout(name_id, entity_ids, reason, expire, sign)
162164

163165
def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
164-
expected_binding=None):
166+
expected_binding=None, **kwargs):
165167
"""
166168
167169
:param name_id: Identifier of the Subject (a NameID instance)
@@ -172,6 +174,7 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
172174
:param sign: Whether to sign the request or not
173175
:param expected_binding: Specify the expected binding then not try it
174176
all
177+
:param kwargs: Extra key word arguments.
175178
:return:
176179
"""
177180
# check time
@@ -203,9 +206,14 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
203206

204207
destination = destinations(srvs)[0]
205208
logger.info("destination to provider: %s" % destination)
209+
try:
210+
session_info = self.users.get_info_from(name_id, entity_id)
211+
session_indexes = [session_info['session_index']]
212+
except KeyError:
213+
session_indexes = None
206214
req_id, request = self.create_logout_request(
207215
destination, entity_id, name_id=name_id, reason=reason,
208-
expire=expire)
216+
expire=expire, session_indexes=session_indexes)
209217

210218
# to_sign = []
211219
if binding.startswith("http://"):
@@ -214,15 +222,23 @@ def do_logout(self, name_id, entity_ids, reason, expire, sign=None,
214222
if sign is None:
215223
sign = self.logout_requests_signed
216224

225+
sigalg = None
226+
key = None
217227
if sign:
218-
srequest = self.sign(request)
228+
if binding == BINDING_HTTP_REDIRECT:
229+
sigalg = kwargs.get("sigalg", ds.sig_default)
230+
key = kwargs.get("key", self.signkey)
231+
srequest = str(request)
232+
else:
233+
srequest = self.sign(request)
219234
else:
220-
srequest = "%s" % request
235+
srequest = str(request)
221236

222237
relay_state = self._relay_state(req_id)
223238

224239
http_info = self.apply_binding(binding, srequest, destination,
225-
relay_state)
240+
relay_state, sigalg=sigalg,
241+
key=key)
226242

227243
if binding == BINDING_SOAP:
228244
response = self.send(**http_info)

src/saml2/metadata.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,17 @@
5959
XMLNSXS = " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
6060
bXMLNSXS = b" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
6161

62+
6263
def metadata_tostring_fix(desc, nspair, xmlstring=""):
6364
if not xmlstring:
6465
xmlstring = desc.to_string(nspair)
6566

6667
if six.PY2:
6768
if "\"xs:string\"" in xmlstring and XMLNSXS not in xmlstring:
68-
xmlstring = xmlstring.replace(MDNS, MDNS+XMLNSXS)
69+
xmlstring = xmlstring.replace(MDNS, MDNS + XMLNSXS)
6970
else:
7071
if b"\"xs:string\"" in xmlstring and bXMLNSXS not in xmlstring:
71-
xmlstring = xmlstring.replace(bMDNS, bMDNS+bXMLNSXS)
72+
xmlstring = xmlstring.replace(bMDNS, bMDNS + bXMLNSXS)
7273

7374
return xmlstring
7475

@@ -77,7 +78,7 @@ def create_metadata_string(configfile, config=None, valid=None, cert=None,
7778
keyfile=None, mid=None, name=None, sign=None):
7879
valid_for = 0
7980
nspair = {"xs": "http://www.w3.org/2001/XMLSchema"}
80-
#paths = [".", "/opt/local/bin"]
81+
# paths = [".", "/opt/local/bin"]
8182

8283
if valid:
8384
valid_for = int(valid) # Hours
@@ -97,21 +98,17 @@ def create_metadata_string(configfile, config=None, valid=None, cert=None,
9798
secc = security_context(conf)
9899

99100
if mid:
100-
desc = entities_descriptor(eds, valid_for, name, mid,
101-
sign, secc)
102-
valid_instance(desc)
103-
104-
return metadata_tostring_fix(desc, nspair)
101+
eid, xmldoc = entities_descriptor(eds, valid_for, name, mid,
102+
sign, secc)
105103
else:
106104
eid = eds[0]
107105
if sign:
108106
eid, xmldoc = sign_entity_descriptor(eid, mid, secc)
109107
else:
110108
xmldoc = None
111109

112-
valid_instance(eid)
113-
xmldoc = metadata_tostring_fix(eid, nspair, xmldoc)
114-
return xmldoc
110+
valid_instance(eid)
111+
return metadata_tostring_fix(eid, nspair, xmldoc)
115112

116113

117114
def _localized_name(val, klass):
@@ -346,6 +343,7 @@ def do_idpdisc(discovery_response):
346343
return idpdisc.DiscoveryResponse(index="0", location=discovery_response,
347344
binding=idpdisc.NAMESPACE)
348345

346+
349347
ENDPOINTS = {
350348
"sp": {
351349
"artifact_resolution_service": (md.ArtifactResolutionService, True),
@@ -425,7 +423,8 @@ def do_endpoints(conf, endpoints):
425423
servs = []
426424
i = 1
427425
for args in conf[endpoint]:
428-
if isinstance(args, six.string_types): # Assume it's the location
426+
if isinstance(args,
427+
six.string_types): # Assume it's the location
429428
args = {"location": args,
430429
"binding": DEFAULT_BINDING[endpoint]}
431430
elif isinstance(args, tuple) or isinstance(args, list):
@@ -453,16 +452,16 @@ def do_endpoints(conf, endpoints):
453452
pass
454453
return service
455454

455+
456456
DEFAULT = {
457457
"want_assertions_signed": "true",
458458
"authn_requests_signed": "false",
459459
"want_authn_requests_signed": "false",
460-
#"want_authn_requests_only_with_valid_cert": "false",
460+
# "want_authn_requests_only_with_valid_cert": "false",
461461
}
462462

463463

464464
def do_attribute_consuming_service(conf, spsso):
465-
466465
service_description = service_name = None
467466
requested_attributes = []
468467
acs = conf.attribute_converters
@@ -557,7 +556,8 @@ def do_spsso_descriptor(conf, cert=None, enc_cert=None):
557556

558557
if cert or enc_cert:
559558
metadata_key_usage = conf.metadata_key_usage
560-
spsso.key_descriptor = do_key_descriptor(cert=cert, enc_cert=enc_cert, use=metadata_key_usage)
559+
spsso.key_descriptor = do_key_descriptor(cert=cert, enc_cert=enc_cert,
560+
use=metadata_key_usage)
561561

562562
for key in ["want_assertions_signed", "authn_requests_signed"]:
563563
try:
@@ -605,10 +605,11 @@ def do_idpsso_descriptor(conf, cert=None, enc_cert=None):
605605
idpsso.extensions.add_extension_element(do_uiinfo(ui_info))
606606

607607
if cert or enc_cert:
608-
idpsso.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage)
608+
idpsso.key_descriptor = do_key_descriptor(cert, enc_cert,
609+
use=conf.metadata_key_usage)
609610

610611
for key in ["want_authn_requests_signed"]:
611-
#"want_authn_requests_only_with_valid_cert"]:
612+
# "want_authn_requests_only_with_valid_cert"]:
612613
try:
613614
val = conf.getattr(key, "idp")
614615
if val is None:
@@ -635,7 +636,8 @@ def do_aa_descriptor(conf, cert=None, enc_cert=None):
635636
_do_nameid_format(aad, conf, "aa")
636637

637638
if cert or enc_cert:
638-
aad.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage)
639+
aad.key_descriptor = do_key_descriptor(cert, enc_cert,
640+
use=conf.metadata_key_usage)
639641

640642
attributes = conf.getattr("attribute", "aa")
641643
if attributes:
@@ -664,7 +666,8 @@ def do_aq_descriptor(conf, cert=None, enc_cert=None):
664666
_do_nameid_format(aqs, conf, "aq")
665667

666668
if cert or enc_cert:
667-
aqs.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage)
669+
aqs.key_descriptor = do_key_descriptor(cert, enc_cert,
670+
use=conf.metadata_key_usage)
668671

669672
return aqs
670673

@@ -685,7 +688,8 @@ def do_pdp_descriptor(conf, cert=None, enc_cert=None):
685688
_do_nameid_format(pdp, conf, "pdp")
686689

687690
if cert:
688-
pdp.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage)
691+
pdp.key_descriptor = do_key_descriptor(cert, enc_cert,
692+
use=conf.metadata_key_usage)
689693

690694
return pdp
691695

@@ -702,7 +706,8 @@ def entity_descriptor(confd):
702706
if confd.encryption_keypairs is not None:
703707
enc_cert = []
704708
for _encryption in confd.encryption_keypairs:
705-
enc_cert.append("".join(open(_encryption["cert_file"]).readlines()[1:-1]))
709+
enc_cert.append(
710+
"".join(open(_encryption["cert_file"]).readlines()[1:-1]))
706711

707712
entd = md.EntityDescriptor()
708713
entd.entity_id = confd.entityid
@@ -736,13 +741,15 @@ def entity_descriptor(confd):
736741
entd.idpsso_descriptor = do_idpsso_descriptor(confd, mycert, enc_cert)
737742
if "aa" in serves:
738743
confd.context = "aa"
739-
entd.attribute_authority_descriptor = do_aa_descriptor(confd, mycert, enc_cert)
744+
entd.attribute_authority_descriptor = do_aa_descriptor(confd, mycert,
745+
enc_cert)
740746
if "pdp" in serves:
741747
confd.context = "pdp"
742748
entd.pdp_descriptor = do_pdp_descriptor(confd, mycert, enc_cert)
743749
if "aq" in serves:
744750
confd.context = "aq"
745-
entd.authn_authority_descriptor = do_aq_descriptor(confd, mycert, enc_cert)
751+
entd.authn_authority_descriptor = do_aq_descriptor(confd, mycert,
752+
enc_cert)
746753

747754
return entd
748755

src/saml2/response.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,9 +1036,11 @@ def session_info(self):
10361036
"issuer": self.issuer(), "not_on_or_after": nooa,
10371037
"authz_decision_info": self.authz_decision_info()}
10381038
else:
1039+
authn_statement = self.assertion.authn_statement[0]
10391040
return {"ava": self.ava, "name_id": self.name_id,
10401041
"came_from": self.came_from, "issuer": self.issuer(),
1041-
"not_on_or_after": nooa, "authn_info": self.authn_info()}
1042+
"not_on_or_after": nooa, "authn_info": self.authn_info(),
1043+
"session_index": authn_statement.session_index}
10421044

10431045
def __str__(self):
10441046
if not isinstance(self.xmlstr, six.string_types):

0 commit comments

Comments
 (0)