Skip to content

Commit f2c26c5

Browse files
author
Roland Hedberg
committed
Dealing with different storage modules
1 parent 5c5e525 commit f2c26c5

File tree

1 file changed

+48
-29
lines changed

1 file changed

+48
-29
lines changed

src/saml2/server.py

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
import shelve
2525
import sys
2626
import memcache
27-
from saml2.sdb import SessionStorage, SessionStorageMDB
27+
from saml2.mongo_store import IdentMDB, SessionStorageMDB
28+
from saml2.sdb import SessionStorage
2829
from saml2.schema import soapenv
2930

3031
from saml2.samlp import NameIDMappingResponse
@@ -65,26 +66,34 @@ def __init__(self, config_file="", config=None, _cache="", stype="idp",
6566
self.init_config(stype)
6667
self._cache = _cache
6768
self.ticket = {}
68-
self.authn = {}
69-
self.assertion = {}
7069
self.user2uid = {}
7170
self.uid2user = {}
71+
#
7272
self.session_db = self.choose_session_storage()
7373
# Needed for
7474
self.symkey = symkey
7575
self.seed = rndstr()
7676
self.iv = os.urandom(16)
7777

78+
def support_AssertionIDRequest(self):
79+
return True
80+
81+
def support_AuthnQuery(self):
82+
return True
83+
7884
def choose_session_storage(self):
7985
_spec = self.config.getattr("session_storage", "idp")
80-
if not _spec or _spec.lower() == "memory":
86+
if not _spec:
8187
return SessionStorage()
82-
else:
88+
elif isinstance(_spec, basestring):
89+
if _spec.lower() == "memory":
90+
return SessionStorage()
91+
else: # Should be tuple
8392
typ, data = _spec
8493
if typ.lower() == "mongodb":
8594
return SessionStorageMDB(data)
86-
else:
87-
raise NotImplementedError("No such storage type implemented")
95+
96+
raise NotImplementedError("No such storage type implemented")
8897

8998
def init_config(self, stype="idp"):
9099
""" Remaining init of the server configuration
@@ -98,6 +107,7 @@ def init_config(self, stype="idp"):
98107
# default database is in memory which is OK in some setups
99108
dbspec = self.config.getattr("subject_data", "idp")
100109
idb = None
110+
typ = ""
101111
if not dbspec:
102112
idb = {}
103113
elif isinstance(dbspec, basestring):
@@ -112,11 +122,11 @@ def init_config(self, stype="idp"):
112122
elif typ == "dict": # in-memory dictionary
113123
idb = {}
114124
elif typ == "mongodb":
115-
from mongodict import MongoDict
116-
idb = MongoDict(host='localhost', port=27017,
117-
database=addr, collection='store')
125+
self.ident = IdentMDB(addr)
118126

119-
if idb is not None:
127+
if typ == "mongodb":
128+
pass
129+
elif idb is not None:
120130
self.ident = IdentDB(idb)
121131
elif dbspec:
122132
raise Exception("Couldn't open identity database: %s" %
@@ -254,16 +264,12 @@ def _authn_response(self, in_response_to, consumer_url,
254264
policy, issuer=_issuer,
255265
authn_class=authn_class,
256266
authn_auth=authn_authn)
257-
self.session_db.store_authn_statement(assertion.authn_statement,
258-
name_id)
259267
elif authn_decl:
260268
assertion = ast.construct(sp_entity_id, in_response_to,
261269
consumer_url, name_id,
262270
self.config.attribute_converters,
263271
policy, issuer=_issuer,
264272
authn_decl=authn_decl)
265-
self.session_db.store_authn_statement(assertion.authn_statement,
266-
name_id)
267273
else:
268274
assertion = ast.construct(sp_entity_id, in_response_to,
269275
consumer_url, name_id,
@@ -285,7 +291,8 @@ def _authn_response(self, in_response_to, consumer_url,
285291

286292
args["assertion"] = assertion
287293

288-
self.session_db.store_assertion(assertion, to_sign)
294+
if self.support_AssertionIDRequest() or self.support_AuthnQuery():
295+
self.session_db.store_assertion(assertion, to_sign)
289296

290297
return self._response(in_response_to, consumer_url, status, issuer,
291298
sign_response, to_sign, **args)
@@ -297,7 +304,7 @@ def create_attribute_response(self, identity, in_response_to, destination,
297304
sp_entity_id, userid="", name_id=None,
298305
status=None, issuer=None,
299306
sign_assertion=False, sign_response=False,
300-
attributes=None):
307+
attributes=None, **kwargs):
301308
""" Create an attribute assertion response.
302309
303310
:param identity: A dictionary with attributes and values that are
@@ -312,6 +319,7 @@ def create_attribute_response(self, identity, in_response_to, destination,
312319
:param sign_assertion: Whether the assertion should be signed or not
313320
:param sign_response: Whether the whole response should be signed
314321
:param attributes:
322+
:param kwargs: To catch extra keyword arguments
315323
:return: A response instance
316324
"""
317325
if not name_id and userid:
@@ -360,7 +368,7 @@ def create_authn_response(self, identity, in_response_to, destination,
360368
sp_entity_id, name_id_policy=None, userid=None,
361369
name_id=None, authn=None, authn_decl=None,
362370
issuer=None, sign_response=False,
363-
sign_assertion=False):
371+
sign_assertion=False, **kwargs):
364372
""" Constructs an AuthenticationResponse
365373
366374
:param identity: Information about an user
@@ -387,18 +395,28 @@ def create_authn_response(self, identity, in_response_to, destination,
387395
if "name_id_format" in _sp:
388396
nid_formats.extend([n["text"] for n in
389397
_sp["name_id_format"]])
390-
391-
name_id = self.ident.construct_nameid(userid, policy,
392-
sp_entity_id,
393-
name_id_policy,
394-
nid_formats)
398+
try:
399+
snq = name_id_policy.sp_name_qualifier
400+
except AttributeError:
401+
snq = sp_entity_id
402+
403+
_nids = self.ident.find_nameid(userid, sp_name_qualifier=snq)
404+
# either none or one
405+
if _nids:
406+
name_id = _nids[0]
407+
else:
408+
name_id = self.ident.construct_nameid(userid, policy,
409+
sp_entity_id,
410+
name_id_policy,
411+
nid_formats)
395412
except IOError, exc:
396413
response = self.create_error_response(in_response_to,
397414
destination,
398415
sp_entity_id,
399416
exc, name_id)
400417
return ("%s" % response).split("\n")
401-
418+
419+
402420
try:
403421
return self._authn_response(in_response_to, # in_response_to
404422
destination, # consumer_url
@@ -421,15 +439,16 @@ def create_authn_request_response(self, identity, in_response_to,
421439
name_id_policy=None, userid=None,
422440
name_id=None, authn=None, authn_decl=None,
423441
issuer=None, sign_response=False,
424-
sign_assertion=False):
442+
sign_assertion=False, **kwargs):
425443

426444
return self.create_authn_response(identity, in_response_to, destination,
427445
sp_entity_id, name_id_policy, userid,
428446
name_id, authn, authn_decl, issuer,
429447
sign_response, sign_assertion)
430448

431449
#noinspection PyUnusedLocal
432-
def create_assertion_id_request_response(self, assertion_id, sign=False):
450+
def create_assertion_id_request_response(self, assertion_id, sign=False,
451+
**kwargs):
433452
"""
434453
435454
:param assertion_id:
@@ -455,7 +474,7 @@ def create_assertion_id_request_response(self, assertion_id, sign=False):
455474
def create_name_id_mapping_response(self, name_id=None, encrypted_id=None,
456475
in_response_to=None,
457476
issuer=None, sign_response=False,
458-
status=None):
477+
status=None, **kwargs):
459478
"""
460479
protocol for mapping a principal's name identifier into a
461480
different name identifier for the same principal.
@@ -485,7 +504,7 @@ def create_name_id_mapping_response(self, name_id=None, encrypted_id=None,
485504
def create_authn_query_response(self, subject, session_index=None,
486505
requested_context=None, in_response_to=None,
487506
issuer=None, sign_response=False,
488-
status=None):
507+
status=None, **kwargs):
489508
"""
490509
A successful <Response> will contain one or more assertions containing
491510
authentication statements.
@@ -520,7 +539,7 @@ def create_ecp_authn_request_response(self, acs_url, identity,
520539
userid=None, name_id=None, authn=None,
521540
authn_decl=None, issuer=None,
522541
sign_response=False,
523-
sign_assertion=False):
542+
sign_assertion=False, **kwargs):
524543

525544
# ----------------------------------------
526545
# <ecp:Response

0 commit comments

Comments
 (0)