2
2
from __future__ import print_function
3
3
4
4
import argparse
5
+ import cgi
5
6
import importlib
6
7
import logging
7
8
import os
8
9
import re
9
10
import sys
11
+ import xml .dom .minidom
10
12
11
13
import six
12
14
from six .moves .http_cookies import SimpleCookie
46
48
logger = logging .getLogger ("" )
47
49
hdlr = logging .FileHandler ('spx.log' )
48
50
base_formatter = logging .Formatter (
49
- "%(asctime)s %(name)s:%(levelname)s %(message)s" )
51
+ "%(asctime)s %(name)s:%(levelname)s %(message)s" )
50
52
51
53
hdlr .setFormatter (base_formatter )
52
54
logger .addHandler (hdlr )
@@ -329,9 +331,15 @@ def not_authn(self):
329
331
330
332
331
333
class User (object ):
332
- def __init__ (self , name_id , data ):
334
+ def __init__ (self , name_id , data , saml_response ):
333
335
self .name_id = name_id
334
336
self .data = data
337
+ self .response = saml_response
338
+
339
+ @property
340
+ def authn_statement (self ):
341
+ xml_doc = xml .dom .minidom .parseString (str (self .response .assertion .authn_statement [0 ]))
342
+ return xml_doc .toprettyxml ()
335
343
336
344
337
345
class ACS (Service ):
@@ -356,7 +364,7 @@ def do(self, response, binding, relay_state="", mtype="response"):
356
364
357
365
try :
358
366
self .response = self .sp .parse_authn_request_response (
359
- response , binding , self .outstanding_queries , self .cache .outstanding_certs )
367
+ response , binding , self .outstanding_queries , self .cache .outstanding_certs )
360
368
except UnknownPrincipal as excp :
361
369
logger .error ("UnknownPrincipal: %s" , excp )
362
370
resp = ServiceError ("UnknownPrincipal: %s" % (excp ,))
@@ -374,7 +382,7 @@ def do(self, response, binding, relay_state="", mtype="response"):
374
382
375
383
logger .info ("AVA: %s" , self .response .ava )
376
384
377
- user = User (self .response .name_id , self .response .ava )
385
+ user = User (self .response .name_id , self .response .ava , self . response )
378
386
cookie = self .cache .set_cookie (user )
379
387
380
388
resp = Redirect ("/" , headers = [
@@ -385,7 +393,7 @@ def do(self, response, binding, relay_state="", mtype="response"):
385
393
def verify_attributes (self , ava ):
386
394
logger .info ("SP: %s" , self .sp .config .entityid )
387
395
rest = POLICY .get_entity_categories (
388
- self .sp .config .entityid , self .sp .metadata )
396
+ self .sp .config .entityid , self .sp .metadata )
389
397
390
398
akeys = [k .lower () for k in ava .keys ()]
391
399
@@ -470,7 +478,7 @@ def _pick_idp(self, came_from):
470
478
_rstate = rndstr ()
471
479
self .cache .relay_state [_rstate ] = geturl (self .environ )
472
480
_entityid = _cli .config .ecp_endpoint (
473
- self .environ ["REMOTE_ADDR" ])
481
+ self .environ ["REMOTE_ADDR" ])
474
482
475
483
if not _entityid :
476
484
return - 1 , ServiceError ("No IdP to talk to" )
@@ -522,7 +530,7 @@ def _pick_idp(self, came_from):
522
530
elif self .discosrv :
523
531
if query :
524
532
idp_entity_id = _cli .parse_discovery_service_response (
525
- query = self .environ .get ("QUERY_STRING" ))
533
+ query = self .environ .get ("QUERY_STRING" ))
526
534
if not idp_entity_id :
527
535
sid_ = sid ()
528
536
self .cache .outstanding_queries [sid_ ] = came_from
@@ -532,7 +540,7 @@ def _pick_idp(self, came_from):
532
540
"sp" )["discovery_response" ][0 ][0 ]
533
541
ret += "?sid=%s" % sid_
534
542
loc = _cli .create_discovery_service_request (
535
- self .discosrv , eid , ** {"return" : ret })
543
+ self .discosrv , eid , ** {"return" : ret })
536
544
return - 1 , SeeOther (loc )
537
545
elif len (idps ) == 1 :
538
546
# idps is a dictionary
@@ -549,8 +557,8 @@ def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""):
549
557
try :
550
558
# Picks a binding to use for sending the Request to the IDP
551
559
_binding , destination = _cli .pick_binding (
552
- "single_sign_on_service" , self .bindings , "idpsso" ,
553
- entity_id = entity_id )
560
+ "single_sign_on_service" , self .bindings , "idpsso" ,
561
+ entity_id = entity_id )
554
562
logger .debug ("binding: %s, destination: %s" , _binding ,
555
563
destination )
556
564
# Binding here is the response binding that is which binding the
@@ -569,7 +577,7 @@ def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""):
569
577
"key" : req_key_str
570
578
}
571
579
spcertenc = SPCertEnc (x509_data = ds .X509Data (
572
- x509_certificate = ds .X509Certificate (text = cert_str )))
580
+ x509_certificate = ds .X509Certificate (text = cert_str )))
573
581
extensions = Extensions (extension_elements = [
574
582
element_to_extension_element (spcertenc )])
575
583
@@ -590,7 +598,7 @@ def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""):
590
598
except Exception as exc :
591
599
logger .exception (exc )
592
600
resp = ServiceError (
593
- "Failed to construct the AuthnRequest: %s" % exc )
601
+ "Failed to construct the AuthnRequest: %s" % exc )
594
602
return resp
595
603
596
604
# remember the request
@@ -668,7 +676,9 @@ def main(environ, start_response, sp):
668
676
return sso .do ()
669
677
670
678
body = dict_to_table (user .data )
671
- body += '<br><a href="/logout">logout</a>'
679
+ authn_stmt = cgi .escape (user .authn_statement )
680
+ body .append ('<br><pre>' + authn_stmt + "</pre>" )
681
+ body .append ('<br><a href="/logout">logout</a>' )
672
682
673
683
resp = Response (body )
674
684
return resp (environ , start_response )
0 commit comments