10
10
from urlparse import parse_qs
11
11
from Cookie import SimpleCookie
12
12
import os
13
+ from saml2 .authn import is_equal
13
14
from saml2 .profile import ecp
14
15
15
16
from saml2 import server
@@ -73,12 +74,14 @@ def get_eptid(idp, req_info, session):
73
74
req_info .sender (), session ["permanent_id" ],
74
75
session ["authn_auth" ])
75
76
77
+
76
78
# -----------------------------------------------------------------------------
77
79
78
80
79
81
def dict2list_of_tuples (d ):
80
82
return [(k , v ) for k , v in d .items ()]
81
83
84
+
82
85
# -----------------------------------------------------------------------------
83
86
84
87
@@ -95,22 +98,22 @@ def unpack_redirect(self):
95
98
return dict ([(k , v [0 ]) for k , v in parse_qs (_qs ).items ()])
96
99
else :
97
100
return None
98
-
101
+
99
102
def unpack_post (self ):
100
103
_dict = parse_qs (get_post (self .environ ))
101
104
logger .debug ("unpack_post:: %s" % _dict )
102
105
try :
103
106
return dict ([(k , v [0 ]) for k , v in _dict .items ()])
104
107
except Exception :
105
108
return None
106
-
109
+
107
110
def unpack_soap (self ):
108
111
try :
109
112
query = get_post (self .environ )
110
113
return {"SAMLRequest" : query , "RelayState" : "" }
111
114
except Exception :
112
115
return None
113
-
116
+
114
117
def unpack_either (self ):
115
118
if self .environ ["REQUEST_METHOD" ] == "GET" :
116
119
_dict = self .unpack_redirect ()
@@ -292,7 +295,7 @@ def do(self, query, binding_in, relay_state="", encrypt_cert=None):
292
295
293
296
if not _resp :
294
297
identity = USERS [self .user ].copy ()
295
- #identity["eduPersonTargetedID"] = get_eptid(IDP, query, session)
298
+ # identity["eduPersonTargetedID"] = get_eptid(IDP, query, session)
296
299
logger .info ("Identity: %s" % (identity ,))
297
300
298
301
if REPOZE_ID_EQUIVALENT :
@@ -357,7 +360,8 @@ def redirect(self):
357
360
358
361
_req = self .req_info .message
359
362
360
- if "SigAlg" in saml_msg and "Signature" in saml_msg : # Signed request
363
+ if "SigAlg" in saml_msg and "Signature" in saml_msg : # Signed
364
+ # request
361
365
issuer = _req .issuer .text
362
366
_certs = IDP .metadata .certs (issuer , "any" , "signing" )
363
367
verified_ok = False
@@ -405,7 +409,7 @@ def post(self):
405
409
return self .not_authn (key , _req .requested_authn_context )
406
410
407
411
# def artifact(self):
408
- # # Can be either by HTTP_Redirect or HTTP_POST
412
+ # # Can be either by HTTP_Redirect or HTTP_POST
409
413
# _req = self._store_request(self.unpack_either())
410
414
# if isinstance(_req, basestring):
411
415
# return self.not_authn(_req)
@@ -424,10 +428,9 @@ def ecp(self):
424
428
except TypeError :
425
429
resp = Unauthorized ()
426
430
else :
427
- logger .debug ("Authz_info: %s" % _info )
428
431
try :
429
432
(user , passwd ) = _info .split (":" )
430
- if PASSWD [user ] != passwd :
433
+ if is_equal ( PASSWD [user ], passwd ) :
431
434
resp = Unauthorized ()
432
435
self .user = user
433
436
self .environ [
@@ -449,6 +452,7 @@ def ecp(self):
449
452
self .op_type = "ecp"
450
453
return self .operation (_dict , BINDING_SOAP )
451
454
455
+
452
456
# -----------------------------------------------------------------------------
453
457
# === Authentication ====
454
458
# -----------------------------------------------------------------------------
@@ -474,11 +478,11 @@ def do_authentication(environ, start_response, authn_context, key,
474
478
# -----------------------------------------------------------------------------
475
479
476
480
PASSWD = {
477
- "daev0001" : "qwerty" ,
478
- "haho0032" : "qwerty" ,
479
- "roland" : "dianakra" ,
480
- "babs" : "howes" ,
481
- "upper" : "crust" }
481
+ "daev0001" : "qwerty" ,
482
+ "haho0032" : "qwerty" ,
483
+ "roland" : "dianakra" ,
484
+ "babs" : "howes" ,
485
+ "upper" : "crust" }
482
486
483
487
484
488
def username_password_authn (environ , start_response , reference , key ,
@@ -552,7 +556,7 @@ def not_found(environ, start_response):
552
556
# === Single log out ===
553
557
# -----------------------------------------------------------------------------
554
558
555
- #def _subject_sp_info(req_info):
559
+ # def _subject_sp_info(req_info):
556
560
# # look for the subject
557
561
# subject = req_info.subject_id()
558
562
# subject = subject.text.strip()
@@ -570,7 +574,7 @@ def do(self, request, binding, relay_state="", encrypt_cert=None):
570
574
logger .error ("Bad request: %s" % exc )
571
575
resp = BadRequest ("%s" % exc )
572
576
return resp (self .environ , self .start_response )
573
-
577
+
574
578
msg = req_info .message
575
579
if msg .name_id :
576
580
lid = IDP .ident .find_local_id (msg .name_id )
@@ -587,52 +591,53 @@ def do(self, request, binding, relay_state="", encrypt_cert=None):
587
591
logger .error ("ServiceError: %s" % exc )
588
592
resp = ServiceError ("%s" % exc )
589
593
return resp (self .environ , self .start_response )
590
-
594
+
591
595
resp = IDP .create_logout_response (msg , [binding ])
592
-
596
+
593
597
try :
594
598
hinfo = IDP .apply_binding (binding , "%s" % resp , "" , relay_state )
595
599
except Exception as exc :
596
600
logger .error ("ServiceError: %s" % exc )
597
601
resp = ServiceError ("%s" % exc )
598
602
return resp (self .environ , self .start_response )
599
-
603
+
600
604
#_tlh = dict2list_of_tuples(hinfo["headers"])
601
605
delco = delete_cookie (self .environ , "idpauthn" )
602
606
if delco :
603
607
hinfo ["headers" ].append (delco )
604
608
logger .info ("Header: %s" % (hinfo ["headers" ],))
605
609
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
606
610
return resp (self .environ , self .start_response )
607
-
611
+
612
+
608
613
# ----------------------------------------------------------------------------
609
614
# Manage Name ID service
610
615
# ----------------------------------------------------------------------------
611
616
612
617
613
618
class NMI (Service ):
614
-
615
619
def do (self , query , binding , relay_state = "" , encrypt_cert = None ):
616
620
logger .info ("--- Manage Name ID Service ---" )
617
621
req = IDP .parse_manage_name_id_request (query , binding )
618
622
request = req .message
619
-
623
+
620
624
# Do the necessary stuff
621
625
name_id = IDP .ident .handle_manage_name_id_request (
622
626
request .name_id , request .new_id , request .new_encrypted_id ,
623
627
request .terminate )
624
-
628
+
625
629
logger .debug ("New NameID: %s" % name_id )
626
-
630
+
627
631
_resp = IDP .create_manage_name_id_response (request )
628
-
632
+
629
633
# It's using SOAP binding
630
634
hinfo = IDP .apply_binding (BINDING_SOAP , "%s" % _resp , "" ,
631
635
relay_state , response = True )
632
-
636
+
633
637
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
634
638
return resp (self .environ , self .start_response )
635
-
639
+
640
+
636
641
# ----------------------------------------------------------------------------
637
642
# === Assertion ID request ===
638
643
# ----------------------------------------------------------------------------
@@ -648,9 +653,9 @@ def do(self, aid, binding, relay_state="", encrypt_cert=None):
648
653
except Unknown :
649
654
resp = NotFound (aid )
650
655
return resp (self .environ , self .start_response )
651
-
656
+
652
657
hinfo = IDP .apply_binding (BINDING_URI , "%s" % assertion , response = True )
653
-
658
+
654
659
logger .debug ("HINFO: %s" % hinfo )
655
660
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
656
661
return resp (self .environ , self .start_response )
@@ -680,6 +685,7 @@ def do(self, request, binding, relay_state="", encrypt_cert=None):
680
685
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
681
686
return resp (self .environ , self .start_response )
682
687
688
+
683
689
# ----------------------------------------------------------------------------
684
690
# === Authn query service ===
685
691
# ----------------------------------------------------------------------------
@@ -734,6 +740,7 @@ def do(self, request, binding, relay_state="", encrypt_cert=None):
734
740
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
735
741
return resp (self .environ , self .start_response )
736
742
743
+
737
744
# ----------------------------------------------------------------------------
738
745
# Name ID Mapping service
739
746
# When an entity that shares an identifier for a principal with an identity
@@ -757,17 +764,17 @@ def do(self, query, binding, relay_state="", encrypt_cert=None):
757
764
except PolicyError :
758
765
resp = BadRequest ("Unknown entity" )
759
766
return resp (self .environ , self .start_response )
760
-
767
+
761
768
info = IDP .response_args (request )
762
769
_resp = IDP .create_name_id_mapping_response (name_id , ** info )
763
-
770
+
764
771
# Only SOAP
765
772
hinfo = IDP .apply_binding (BINDING_SOAP , "%s" % _resp , "" , "" ,
766
773
response = True )
767
-
774
+
768
775
resp = Response (hinfo ["data" ], headers = hinfo ["headers" ])
769
776
return resp (self .environ , self .start_response )
770
-
777
+
771
778
772
779
# ----------------------------------------------------------------------------
773
780
# Cookie handling
@@ -862,10 +869,10 @@ def metadata(environ, start_response):
862
869
try :
863
870
path = args .path
864
871
if path is None or len (path ) == 0 :
865
- path = os .path .dirname (os .path .abspath ( __file__ ))
872
+ path = os .path .dirname (os .path .abspath (__file__ ))
866
873
if path [- 1 ] != "/" :
867
874
path += "/"
868
- metadata = create_metadata_string (path + args .config , IDP .config ,
875
+ metadata = create_metadata_string (path + args .config , IDP .config ,
869
876
args .valid , args .cert , args .keyfile ,
870
877
args .id , args .name , args .sign )
871
878
start_response ('200 OK' , [('Content-Type' , "text/xml" )])
@@ -874,6 +881,7 @@ def metadata(environ, start_response):
874
881
logger .error ("An error occured while creating metadata:" + ex .message )
875
882
return not_found (environ , start_response )
876
883
884
+
877
885
def staticfile (environ , start_response ):
878
886
try :
879
887
path = args .path
@@ -882,12 +890,17 @@ def staticfile(environ, start_response):
882
890
if path [- 1 ] != "/" :
883
891
path += "/"
884
892
path += environ .get ('PATH_INFO' , '' ).lstrip ('/' )
893
+ path = os .path .realpath (path )
894
+ if not path .startswith (args .path ):
895
+ resp = Unauthorized ()
896
+ return resp (environ , start_response )
885
897
start_response ('200 OK' , [('Content-Type' , "text/xml" )])
886
898
return open (path , 'r' ).read ()
887
899
except Exception as ex :
888
900
logger .error ("An error occured while creating metadata:" + ex .message )
889
901
return not_found (environ , start_response )
890
902
903
+
891
904
def application (environ , start_response ):
892
905
"""
893
906
The main WSGI application. Dispatch the current request to
@@ -924,7 +937,6 @@ def application(environ, start_response):
924
937
except KeyError :
925
938
user = None
926
939
927
-
928
940
url_patterns = AUTHN_URLS
929
941
if not user :
930
942
logger .info ("-- No USER --" )
@@ -956,7 +968,7 @@ def application(environ, start_response):
956
968
# by moving some initialization out of __name__ == '__main__' section.
957
969
# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp
958
970
959
- args = type ('Config' , (object ,), { })
971
+ args = type ('Config' , (object ,), {})
960
972
args .config = 'idp_conf'
961
973
args .mako_root = './'
962
974
args .path = None
@@ -984,7 +996,8 @@ def application(environ, start_response):
984
996
parser = argparse .ArgumentParser ()
985
997
parser .add_argument ('-p' , dest = 'path' , help = 'Path to configuration file.' )
986
998
parser .add_argument ('-v' , dest = 'valid' ,
987
- help = "How long, in days, the metadata is valid from the time of creation" )
999
+ help = "How long, in days, the metadata is valid from "
1000
+ "the time of creation" )
988
1001
parser .add_argument ('-c' , dest = 'cert' , help = 'certificate' )
989
1002
parser .add_argument ('-i' , dest = 'id' ,
990
1003
help = "The ID of the entities descriptor" )
0 commit comments