24
24
import shelve
25
25
import sys
26
26
import memcache
27
- from saml2 .sdb import SessionStorage , SessionStorageMDB
27
+ from saml2 .mongo_store import IdentMDB , SessionStorageMDB
28
+ from saml2 .sdb import SessionStorage
28
29
from saml2 .schema import soapenv
29
30
30
31
from saml2 .samlp import NameIDMappingResponse
@@ -65,26 +66,34 @@ def __init__(self, config_file="", config=None, _cache="", stype="idp",
65
66
self .init_config (stype )
66
67
self ._cache = _cache
67
68
self .ticket = {}
68
- self .authn = {}
69
- self .assertion = {}
70
69
self .user2uid = {}
71
70
self .uid2user = {}
71
+ #
72
72
self .session_db = self .choose_session_storage ()
73
73
# Needed for
74
74
self .symkey = symkey
75
75
self .seed = rndstr ()
76
76
self .iv = os .urandom (16 )
77
77
78
+ def support_AssertionIDRequest (self ):
79
+ return True
80
+
81
+ def support_AuthnQuery (self ):
82
+ return True
83
+
78
84
def choose_session_storage (self ):
79
85
_spec = self .config .getattr ("session_storage" , "idp" )
80
- if not _spec or _spec . lower () == "memory" :
86
+ if not _spec :
81
87
return SessionStorage ()
82
- else :
88
+ elif isinstance (_spec , basestring ):
89
+ if _spec .lower () == "memory" :
90
+ return SessionStorage ()
91
+ else : # Should be tuple
83
92
typ , data = _spec
84
93
if typ .lower () == "mongodb" :
85
94
return SessionStorageMDB (data )
86
- else :
87
- raise NotImplementedError ("No such storage type implemented" )
95
+
96
+ raise NotImplementedError ("No such storage type implemented" )
88
97
89
98
def init_config (self , stype = "idp" ):
90
99
""" Remaining init of the server configuration
@@ -98,6 +107,7 @@ def init_config(self, stype="idp"):
98
107
# default database is in memory which is OK in some setups
99
108
dbspec = self .config .getattr ("subject_data" , "idp" )
100
109
idb = None
110
+ typ = ""
101
111
if not dbspec :
102
112
idb = {}
103
113
elif isinstance (dbspec , basestring ):
@@ -112,11 +122,11 @@ def init_config(self, stype="idp"):
112
122
elif typ == "dict" : # in-memory dictionary
113
123
idb = {}
114
124
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 )
118
126
119
- if idb is not None :
127
+ if typ == "mongodb" :
128
+ pass
129
+ elif idb is not None :
120
130
self .ident = IdentDB (idb )
121
131
elif dbspec :
122
132
raise Exception ("Couldn't open identity database: %s" %
@@ -254,16 +264,12 @@ def _authn_response(self, in_response_to, consumer_url,
254
264
policy , issuer = _issuer ,
255
265
authn_class = authn_class ,
256
266
authn_auth = authn_authn )
257
- self .session_db .store_authn_statement (assertion .authn_statement ,
258
- name_id )
259
267
elif authn_decl :
260
268
assertion = ast .construct (sp_entity_id , in_response_to ,
261
269
consumer_url , name_id ,
262
270
self .config .attribute_converters ,
263
271
policy , issuer = _issuer ,
264
272
authn_decl = authn_decl )
265
- self .session_db .store_authn_statement (assertion .authn_statement ,
266
- name_id )
267
273
else :
268
274
assertion = ast .construct (sp_entity_id , in_response_to ,
269
275
consumer_url , name_id ,
@@ -285,7 +291,8 @@ def _authn_response(self, in_response_to, consumer_url,
285
291
286
292
args ["assertion" ] = assertion
287
293
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 )
289
296
290
297
return self ._response (in_response_to , consumer_url , status , issuer ,
291
298
sign_response , to_sign , ** args )
@@ -297,7 +304,7 @@ def create_attribute_response(self, identity, in_response_to, destination,
297
304
sp_entity_id , userid = "" , name_id = None ,
298
305
status = None , issuer = None ,
299
306
sign_assertion = False , sign_response = False ,
300
- attributes = None ):
307
+ attributes = None , ** kwargs ):
301
308
""" Create an attribute assertion response.
302
309
303
310
:param identity: A dictionary with attributes and values that are
@@ -312,6 +319,7 @@ def create_attribute_response(self, identity, in_response_to, destination,
312
319
:param sign_assertion: Whether the assertion should be signed or not
313
320
:param sign_response: Whether the whole response should be signed
314
321
:param attributes:
322
+ :param kwargs: To catch extra keyword arguments
315
323
:return: A response instance
316
324
"""
317
325
if not name_id and userid :
@@ -360,7 +368,7 @@ def create_authn_response(self, identity, in_response_to, destination,
360
368
sp_entity_id , name_id_policy = None , userid = None ,
361
369
name_id = None , authn = None , authn_decl = None ,
362
370
issuer = None , sign_response = False ,
363
- sign_assertion = False ):
371
+ sign_assertion = False , ** kwargs ):
364
372
""" Constructs an AuthenticationResponse
365
373
366
374
:param identity: Information about an user
@@ -387,18 +395,28 @@ def create_authn_response(self, identity, in_response_to, destination,
387
395
if "name_id_format" in _sp :
388
396
nid_formats .extend ([n ["text" ] for n in
389
397
_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 )
395
412
except IOError , exc :
396
413
response = self .create_error_response (in_response_to ,
397
414
destination ,
398
415
sp_entity_id ,
399
416
exc , name_id )
400
417
return ("%s" % response ).split ("\n " )
401
-
418
+
419
+
402
420
try :
403
421
return self ._authn_response (in_response_to , # in_response_to
404
422
destination , # consumer_url
@@ -421,15 +439,16 @@ def create_authn_request_response(self, identity, in_response_to,
421
439
name_id_policy = None , userid = None ,
422
440
name_id = None , authn = None , authn_decl = None ,
423
441
issuer = None , sign_response = False ,
424
- sign_assertion = False ):
442
+ sign_assertion = False , ** kwargs ):
425
443
426
444
return self .create_authn_response (identity , in_response_to , destination ,
427
445
sp_entity_id , name_id_policy , userid ,
428
446
name_id , authn , authn_decl , issuer ,
429
447
sign_response , sign_assertion )
430
448
431
449
#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 ):
433
452
"""
434
453
435
454
:param assertion_id:
@@ -455,7 +474,7 @@ def create_assertion_id_request_response(self, assertion_id, sign=False):
455
474
def create_name_id_mapping_response (self , name_id = None , encrypted_id = None ,
456
475
in_response_to = None ,
457
476
issuer = None , sign_response = False ,
458
- status = None ):
477
+ status = None , ** kwargs ):
459
478
"""
460
479
protocol for mapping a principal's name identifier into a
461
480
different name identifier for the same principal.
@@ -485,7 +504,7 @@ def create_name_id_mapping_response(self, name_id=None, encrypted_id=None,
485
504
def create_authn_query_response (self , subject , session_index = None ,
486
505
requested_context = None , in_response_to = None ,
487
506
issuer = None , sign_response = False ,
488
- status = None ):
507
+ status = None , ** kwargs ):
489
508
"""
490
509
A successful <Response> will contain one or more assertions containing
491
510
authentication statements.
@@ -520,7 +539,7 @@ def create_ecp_authn_request_response(self, acs_url, identity,
520
539
userid = None , name_id = None , authn = None ,
521
540
authn_decl = None , issuer = None ,
522
541
sign_response = False ,
523
- sign_assertion = False ):
542
+ sign_assertion = False , ** kwargs ):
524
543
525
544
# ----------------------------------------
526
545
# <ecp:Response
0 commit comments