Changeset 1331 for TI12-security


Ignore:
Timestamp:
26/07/06 16:35:41 (13 years ago)
Author:
pjkersha
Message:

NDG/SecurityCGI.py: split into interface classes for service provider and identity provider with a common
_SecurityCGI base class.

NDG/Session.py: changed interface to UserSession?.createSecurityCookie so that caller doesn't need to explicitly
know cookie security tags names but can pass key/val pairs as a dictionary.

Location:
TI12-security/trunk/python/NDG
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/NDG/SecurityCGI.py

    r1300 r1331  
    3030class SecurityCGIError(Exception): 
    3131    """Exception handling for NDG Security CGI class.""" 
    32  
    33     def __init__(self, msg): 
    34         self.__msg = msg 
    35           
    36     def __str__(self): 
    37         return self.__msg 
     32    pass 
    3833 
    3934    
    40 class SecurityCGI(cgi.FieldStorage): 
    41     """CGI interface class for NDG Security 
     35class _SecurityCGI(cgi.FieldStorage): 
     36    """CGI interface base class for NDG Security 
    4237     
    4338    Terms used throughout:         
    44         remote site     - where user is accessing resources 
    45         home site       - where user's credentials are held or they login""" 
     39        Service Provider   - where user is accessing resources 
     40        Identity Provider  - where user's credentials are held or they login 
     41    """ 
     42 
     43    acAllowMapping = "allowMapping" 
     44    acAllowMappingWithPrompt = "allowMappingWithPrompt" 
     45    acNoMapping = "noMapping" 
     46     
     47    acMappingFlags = [acAllowMapping, acAllowMappingWithPrompt, acNoMapping] 
     48     
     49    #_________________________________________________________________________ 
     50    def __init__(self, 
     51                 smWSDL, 
     52                 smPubKeyFilePath=None, 
     53                 clntPubKeyFilePath=None, 
     54                 clntPriKeyFilePath=None, 
     55                 clntPriKeyPwd=None, 
     56                 scriptName=__file__, 
     57                 wsDebug=False, 
     58                 **cgiFieldStorageKwArgs): 
     59        """smWSDL:            URI For Session Manager WSDL used for user 
     60                              authentication 
     61        wsDebug:              print output from WS transactions to stderr""" 
     62 
     63        self.smWSDL = smWSDL 
     64        self.smClnt = None 
     65         
     66        self.smPubKeyFilePath = smPubKeyFilePath 
     67         
     68        self.clntPubKeyFilePath = clntPubKeyFilePath 
     69        self.clntPriKeyFilePath = clntPriKeyFilePath 
     70        self.clntPriKeyPwd = clntPriKeyPwd 
     71 
     72        self.scriptName = scriptName 
     73 
     74        self._wsDebug = False         
     75        self.acMappingFlag = None 
     76        self.attCert = None 
     77                 
     78        cgi.FieldStorage.__init__(self, **cgiFieldStorageKwArgs) 
     79 
     80  
     81    #_________________________________________________________________________ 
     82    def processFields(self, **kwargs): 
     83        """Call appropriate actions according to the fields set"""         
     84        raise NotImplementedError, \ 
     85            self.processFields.__doc__.replace('\n       ','') 
     86     
     87     
     88    #_________________________________________________________________________ 
     89    # Use instance name as an alias to processFields method 
     90    __call__ = processFields 
     91 
     92 
     93    #_________________________________________________________________________ 
     94    def __getACmappingFlag(self): 
     95        """Flag determines whether mapping is permitted when contacting an 
     96        Attribute Authority to get an Attribute Certificate""" 
     97        return self.__acMappingFlag 
     98 
     99 
     100    def __setACmappingFlag(self, acMappingFlag): 
     101        """Flag determines whether mapping is permitted when contacting an 
     102        Attribute Authority to get an Attribute Certificate""" 
     103         
     104        if acMappingFlag not in self.acMappingFlags: 
     105            raise AttributeError, \ 
     106                "\"%s\" is invalid for acMappingFlag" % \ 
     107                self.acMappingFlags 
     108                 
     109        self.__acMappingFlag = acMappingFlag 
     110  
     111         
     112    def __delACmappingFlag(self): 
     113        """Prevent certificate mapping flag from being deleted.""" 
     114        raise AttributeError, \ 
     115                        "\"acMappingFlag\" attribute cannot be deleted" 
     116        
     117     
     118    acMappingFlag = property(fget=__getACmappingFlag, 
     119                            fset=__setACmappingFlag, 
     120                            fdel=__delACmappingFlag, 
     121                            doc="mapping flag for AttCert requests to an AA") 
     122     
     123     
     124    #_________________________________________________________________________ 
     125    def _getAttCert(self, sessCookie=None, reqRole=None): 
     126        """Contact Attribute Authority to get Attribute Certificate for data 
     127        access 
     128 
     129        sessCookie:     NDG security session cookie 
     130        reqRole:        specify the required role to get authorisation.  Set 
     131                        this to optimise the process for getting the required 
     132                        AC from a trusted host in order to perform mapping""" 
     133 
     134        # Check for session cookie input 
     135        if not sessCookie: 
     136            # No cookie set as input argument check for environment variable 
     137            if 'HTTP_COOKIE' in os.environ: 
     138                sessCookie = SimpleCookie(os.environ['HTTP_COOKIE'])     
     139            else: 
     140                raise SecurityCGIError, \ 
     141                    "Attribute certificate request requires a security cookie" 
     142 
     143        # Check cookie is valid 
     144        try: 
     145            UserSession.isValidSecurityCookie(sessCookie, raiseExcep=True) 
     146             
     147        except UserSessionError, e: 
     148            raise SecurityCGIError, 'Checking existing session cookie: %s' % e 
     149 
     150 
     151        # Configure flags for attribute certificate request.  This determines 
     152        # whether mapping of certificates from trusted hosts is allowed 
     153        if self.acMappingFlag == self.acAllowMapping: 
     154            bMapFromTrustedHosts = True 
     155            bRtnExtAttCertList = False 
     156 
     157        elif self.acMappingFlag == self.acAllowMappingWithPrompt: 
     158            bMapFromTrustedHosts = False 
     159            bRtnExtAttCertList = True 
     160        else: 
     161            bMapFromTrustedHosts = False 
     162            bRtnExtAttCertList = False 
     163 
     164 
     165        # Instantiate WS proxy and request authorisation 
     166        try: 
     167            if not self.smClnt: 
     168                self.smClnt = SessionClient(\ 
     169                            smWSDL=self.smWSDL, 
     170                            smPubKeyFilePath=self.smPubKeyFilePath, 
     171                            clntPubKeyFilePath=self.clntPubKeyFilePath, 
     172                            clntPriKeyFilePath=self.clntPriKeyFilePath, 
     173                            traceFile=self._wsDebug and sys.stderr or None) 
     174 
     175            authzResp = self.smClnt.reqAuthorisation(sessCookie=sessCookie, 
     176                                    aaWSDL=self.aaWSDL, 
     177                                    aaPubKey=self.aaPubKey, 
     178                                    reqRole=reqRole, 
     179                                    mapFromTrustedHosts=bMapFromTrustedHosts, 
     180                                    rtnExtAttCertList=bRtnExtAttCertList, 
     181                                    clntPriKeyPwd=self.clntPriKeyPwd) 
     182        except Exception, e: 
     183            raise SecurityCGIError, "Attribute Certificate request: %s" % e 
     184 
     185 
     186        if authzResp['statCode'] == authzResp.AccessGranted: 
     187            self.onAttCertGranted(authzResp['attCert']) 
     188         
     189        elif authzResp['statCode'] == authzResp.AccessDenied: 
     190            self.onAttCertDenied(authzResp['extAttCertList'],  
     191                                 authzResp['errMsg']) 
     192             
     193        elif authzResp['statCode'] == authzResp.AccessError: 
     194            raise SecurityCGIError, authzResp['errMsg'] 
     195             
     196     
     197    #_________________________________________________________________________ 
     198    def onAttCertGranted(self, attCert): 
     199        """Callback invoked by getAttCert - handle case where an Attribute 
     200        Authority has granted a new attribute certificate to the user.  Derive 
     201        from this class and override this method as required. 
     202        """ 
     203        pass 
     204     
     205     
     206    #_________________________________________________________________________ 
     207    def onAttCertDenied(self, extAttCertList, errMsg): 
     208        """Callback invoked by getAttCert - handle case where an Attribute 
     209        Authority has denied an attribute certificate to the user.  Derive 
     210        from this class and override this method as required. 
     211         
     212        extAttCertList:    a list of attribute certificates from trusted 
     213                           hosts.  Any of these could be selected and  
     214                           presented back to the target AA in order to get 
     215                           a mapped certificate.  This list may be None if  
     216                           no ACs could be obtained or if the  
     217                           mapFromTrustedHosts flag in the call to the Session 
     218                           Manager WS reqAuthorisation method was set to  
     219                           False. 
     220                            
     221        errMsg:            the error message returned from the call to the 
     222                           AA to get an AC.""" 
     223         
     224        if not extAttCertList: 
     225            self.showLogin(pageTitle="Access denied by Attribute Authority") 
     226            raise SecurityCGIError, errMsg 
     227         
     228        else: 
     229            # Display list of attCerts to choose from 
     230            print \ 
     231"""Content-type: text/html 
     232 
     233<html> 
     234<head> 
     235    <title>Select an Attribute Certificate</title> 
     236    <style type=\"text/css\"> 
     237    <!-- 
     238    .al { 
     239    text-align: justify 
     240    } 
     241    a{ 
     242    text-decoration:none; 
     243    } 
     244    a:hover{ 
     245    color:#0000FF; 
     246    } 
     247        body { font-family: Verdana, sans-serif; font-size: 11} 
     248        table { font-family: Verdana, sans-serif; font-size: 11} 
     249    --> 
     250    </style> 
     251</head> 
     252<body> 
     253    <form action="%s" method="POST"> 
     254    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
     255    <tbody>""" 
     256     
     257            for attCert in extAttCertList: 
     258                print \ 
     259"""    <tr> 
     260        <td>%s</td> 
     261    </tr>""" % attCert['issuer'] 
     262                 
     263                print \ 
     264"""    </tbody> 
     265    </table> 
     266    </form> 
     267</body> 
     268</html>""" 
     269     
     270        # end of onAttCertDenied() 
     271         
     272 
     273#_____________________________________________________________________________ 
     274class ServiceProviderSecurityCGI(_SecurityCGI): 
    46275 
    47276    #_________________________________________________________________________ 
     
    51280                 smPubKeyFilePath=None, 
    52281                 aaPubKeyFilePath=None, 
    53                  clntPubKeyFilePath=None, 
    54                  clntPriKeyFilePath=None, 
    55                  clntPriKeyPwd=None, 
    56                  userName=None, 
    57                  passPhrase=None, 
    58                  scriptName=None, 
    59282                 trustedHostInfo=None, 
    60283                 cookieLifetimeHrs=8, 
    61                  wsDebug=False, 
    62                  **cgiFieldStorageKwArgs): 
    63         """scriptName:        name of script to call in forms - defaults to 
    64                               this file.  Modify if you inherit from this 
    65                               class. 
    66         smWSDL:               URI For Session Manager WSDL used for user 
     284                 **securityCGIKwArgs): 
     285        """smWSDL:            URI For Session Manager WSDL used for user 
    67286                              authentication 
    68287        aaWSDL:               URI for Attribute Authority WSDL used to get a 
     
    75294        self.smWSDL = smWSDL 
    76295        self.smClnt = None 
     296         
    77297        self.aaWSDL = aaWSDL 
    78298        self.aaClnt = None 
    79299         
    80         self.userName = userName 
    81         self.passPhrase = passPhrase 
    82          
    83300        self.smPubKeyFilePath = smPubKeyFilePath 
    84301        self.aaPubKeyFilePath = aaPubKeyFilePath 
    85          
    86         self.clntPubKeyFilePath = clntPubKeyFilePath 
    87         self.clntPriKeyFilePath = clntPriKeyFilePath 
    88         self.clntPriKeyPwd = clntPriKeyPwd 
    89  
    90         if scriptName: 
    91             self.scriptName = scriptName 
    92         else: 
    93             self.scriptName = __file__ 
    94302 
    95303        self.trustedHostInfo = trustedHostInfo 
     
    100308                            timedelta(seconds=self.cookieLifetimeHrs*60*60) 
    101309 
    102         self.__wsDebug = False         
    103         self._authorisationMethod = None 
     310        self._wsDebug = False         
     311        self.acMappingFlag = None 
    104312        self.attCert = None 
    105313                 
    106         cgi.FieldStorage.__init__(self, **cgiFieldStorageKwArgs) 
     314        super(self.__class__, self).__init__(self, **securityCGIKwArgs) 
    107315 
    108316  
     
    111319        """Call appropriate actions according to the fields set""" 
    112320 
    113         bAuthorise = "authorise" in self 
    114          
    115321        if 'requestURI' in self: 
    116             # Request credentials from user's home site 
    117             self.requestCreds(**kwargs) 
    118  
    119         elif 'NDG-ID1' in self and 'NDG-ID2' in self: 
    120             # Receive credentials back from home site and set a new cookie at 
    121             # remote site 
    122             if 'expires' in self: 
    123                 encodedExpiry = self['expires'].value 
    124             else: 
    125                 encodedExpiry = None 
    126  
    127             self.receiveCredsResponse(self['NDG-ID1'].value, 
    128                                       self['NDG-ID2'].value, 
    129                                       encodedExpiry=encodedExpiry, 
    130                                       **kwargs) 
    131  
    132         elif 'authenticate' in self: 
    133             # User has entered login details - now authenticate using the  
    134             # Session Manager WS 
    135             sessCookie = self.authenticate() 
    136              
    137             if bAuthorise: 
    138                 # Authorisation and authentication arguments were set 
    139                 # - Call authentication first 
    140                 sessCookie = self.authenticate(setCookie=False) 
    141  
    142                 # Call authorisation passing the session ID for authorise to 
    143                 # set the cookie 
    144                 self.getAttCert(sessCookie) 
    145              
    146             if 'returnURI' in self: 
    147                 # The authentication process is as a result of a redirect  
    148                 # request from another site - redirect back to the remote site 
    149                 # returning the credentials contained in the NDG security 
    150                 self.processCredsRequest(sessCookie=sessCookie, 
    151                                          setCookie=True,  
    152                                          **kwargs) 
     322            # Request credentials from user's identity provider 
     323            self._requestCreds(**kwargs) 
     324 
     325        elif not [True for tag in UserSession.cookieTags if tag not in self]: 
     326            # Credentials tags were set -  set a new cookie at service  
     327            # provider site 
     328            encodedExpiry='expires' in self and self['expires'].value or None 
     329 
     330            self._receiveCredsResponse(encodedExpiry=encodedExpiry, 
     331                                       **kwargs) 
     332     
     333     
     334    #_________________________________________________________________________ 
     335    def showHomeSiteSelect(self, 
     336                           trustedHostInfo=None, 
     337                           scriptName=None, 
     338                           contentTypeHdr=False, 
     339                           htmlTag=False, 
     340                           hdrTag=False, 
     341                           hdrTxt='', 
     342                           bodyTag=False, 
     343                           pageTitle=""): 
     344 
     345        if trustedHostInfo: 
     346            self.trustedHostInfo = trustedHostInfo 
     347 
     348        if not self.trustedHostInfo: 
     349            self.getTrustedHostInfo() 
     350             
     351        if scriptName: 
     352            self.scriptName = scriptName 
     353             
    153354                 
    154         elif bAuthorise: 
    155             self.getAttCert() 
    156                      
    157         elif 'returnURI' in self: 
    158             # Home site receives request from remote site for credentials and 
    159             # returns them 
    160             self.processCredsRequest(**kwargs) 
     355        if contentTypeHdr: 
     356            print "Content-type: text/html\n\n" 
     357                 
     358        if htmlTag: 
     359            print "<html>\n" 
     360 
     361        if hdrTag:             
     362            if not hdrTxt: 
     363                hdrTxt = """    <style type=\"text/css\"> 
     364<!-- 
     365.al { 
     366text-align: justify 
     367} 
     368a{ 
     369text-decoration:none; 
     370} 
     371a:hover{ 
     372color:#0000FF; 
     373} 
     374    body { font-family: Verdana, sans-serif; font-size: 11} 
     375    table { font-family: Verdana, sans-serif; font-size: 11} 
     376--> 
     377</style>""" 
     378 
     379            print """<head> 
     380             
     381    <title>%s</title> 
     382    %s 
     383</head>""" % (pageTitle, hdrTxt) 
     384     
     385     
     386        if bodyTag: 
     387            print "<body>\n" 
     388 
     389            print """ 
     390    <form action="%s" method="POST"> 
     391    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
     392    <tbody> 
     393    <tr> 
     394      <td> 
     395        <select name="requestURI">         
     396          <option value="">Select your home site...""" % self.scriptName 
     397           
     398            for hostname, info in self.trustedHostInfo.items(): 
     399                print "<option value=\"%s\">%s" % (info['loginURI'], hostname) 
     400                 
     401            print \ 
     402"""        </select> 
     403      </td> 
     404      <td align="right"> 
     405        <input type=submit value="Go"> 
     406      </td> 
     407    </tr> 
     408    </tbody> 
     409    </table> 
     410    </form>""" 
     411 
     412        if bodyTag: 
     413            print "</body>\n" 
     414 
     415        if htmlTag: 
     416            print "</html>\n" 
     417     
     418        # end of showHomeSiteSelect() 
     419 
     420 
     421    #_________________________________________________________________________ 
     422    def showCredsReceived(self, sessCookie): 
     423        """Called from _receiveCredsResponse() once a cookie has been created. 
     424        Makes a page to set the cookie and display to the user that they have 
     425        been authenticated.  Derived class should override this method as 
     426        required""" 
     427        print """Content-type: text/html" 
     428%s 
     429 
     430<html> 
     431<head> 
     432<title>Credentials Received</title> 
     433</head> 
     434<body> 
     435    Credentials Received 
     436</body> 
     437</html>""" % sessCookie.output() 
     438 
     439 
     440    #_________________________________________________________________________ 
     441    def getTrustedHostInfo(self): 
     442        """Call Attribute Authority to find out trusted hosts.  These can be 
     443        use to populate list for use to select Identity Provider for login""" 
     444         
     445        try: 
     446            if not self.aaClnt: 
     447                self.aaClnt = AttAuthorityClient(aaWSDL=self.aaWSDL, 
     448                            aaPubKeyFilePath=self.aaPubKeyFilePath, 
     449                            clntPubKeyFilePath=self.clntPubKeyFilePath, 
     450                            clntPriKeyFilePath=self.clntPriKeyFilePath, 
     451                            traceFile=self._wsDebug and sys.stderr or None) 
     452             
     453            self.trustedHostInfo = self.aaClnt.getTrustedHostInfo( 
     454                                           clntPriKeyPwd=self.clntPriKeyPwd) 
     455        except Exception, e: 
     456            raise SecurityCGIError, "Attribute Authority client: %s" % e 
     457 
     458     
     459    #_________________________________________________________________________ 
     460    def _createCookie(self, encodedExpiry=None): 
     461        """Convert credentials passed over URI from users Identity Provider  
     462        into a new cookie""" 
     463 
     464        if encodedExpiry: 
     465            # Expiry is taken from encoded value passed over URI 
     466            dtExpiry = None 
     467            expiryStr = base64.urlsafe_b64decode(encodedExpiry) 
    161468        else: 
    162             # Remote site presents possible sites for user to get their  
    163             # credentials from 
    164             self.showHomeSiteSelect(**kwargs) 
    165      
    166      
    167     #_________________________________________________________________________ 
    168     # Use instance name as an alias to processFields method 
    169     __call__ = processFields 
     469            # Expiry is set from life time in hours input in __init__ 
     470            dtExpiry = self.dtCookieExpiry 
     471            expiryStr = None 
     472 
     473         
     474        try: 
     475            tagsDict = dict([(tag, self[tag].value) \ 
     476                             for tag in UserSession.cookieTags]) 
     477        except KeyError, e: 
     478            raise SecurityCGIError, "Missing cookie tag: %s" % e 
     479         
     480        sessCookie =  UserSession.createSecurityCookie(dtExpiry=dtExpiry, 
     481                                                       expiryStr=expiryStr, 
     482                                                       **tagsDict) 
     483         
     484        return sessCookie 
    170485     
    171486 
     
    178493                      delayTime=0, 
    179494                      redirectMsg=''): 
    180         """Request credentials from a user's home site 
     495        """Request credentials from a user's Identity Provider 
    181496         
    182497        requestURI:   site to request credentials from - default is  
     
    211526 
    212527    #_________________________________________________________________________ 
    213     def _receiveCredsResponse(self, 
    214                               sessID, 
    215                               sessMgrURI, 
    216                               encodedExpiry=None, 
    217                               **showCredsReceivedKwArgs): 
     528    def _receiveCredsResponse(self, encodedExpiry=None): 
    218529        """Remote site receives returned credentials and creates a new cookie 
    219530        for its domain""" 
    220         sessCookie = self.createCookie(sessID, sessMgrURI, encodedExpiry) 
     531        sessCookie = self._createCookie(encodedExpiry=encodedExpiry) 
    221532        self.showCredsReceived(sessCookie) 
    222  
    223     #_________________________________________________________________________ 
    224     def showCredsReceived(self,  
    225                           sessCookie,  
    226                           pageTitle='',  
    227                           hdrTxt='',  
    228                           bodyTxt=''): 
    229         """Called from receiveCredsResponse() once a cookie has been created. 
    230         Makes a page to set the cookie and display to the user that they have 
    231         been authenticated.  Derived class should override this method as 
    232         required""" 
    233         print """Content-type: text/html" 
    234 %s 
    235  
    236 <html> 
    237 <head> 
    238 <title>%s</title> 
    239 %s 
    240 </head> 
    241 <body> 
    242     %s 
    243 </body> 
    244 </html>""" % (sessCookie.output(), pageTitle, hdrTxt, bodyTxt) 
    245  
    246      
    247     #_________________________________________________________________________ 
    248     def _createCookie(self, sessID, sessMgrURI, encodedExpiry=None): 
    249         """Convert credentials passed over URI from users home site into a new 
    250         cookie""" 
    251  
    252         if encodedExpiry: 
    253             # Expiry is taken from encoded value passed over URI 
    254             dtExpiry = None 
    255             expiryStr = base64.urlsafe_b64decode(encodedExpiry) 
     533         
     534 
     535#_____________________________________________________________________________ 
     536class IdentityProviderSecurityCGI(_SecurityCGI): 
     537 
     538    #_________________________________________________________________________ 
     539    def __init__(self, smWSDL, **securityCGIKwArgs): 
     540        """smWSDL:            URI For Session Manager WSDL used for user 
     541                              authentication""" 
     542 
     543        self.smWSDL = smWSDL 
     544        self.smClnt = None 
     545         
     546        self.userName = userName 
     547        self.passPhrase = passPhrase 
     548         
     549        self.smPubKeyFilePath = smPubKeyFilePath 
     550                                 
     551        super(self.__class__, self).__init__(self, **securityCGIKwArgs) 
     552 
     553     
     554    #_________________________________________________________________________ 
     555    def processFields(self, **kwargs): 
     556        """Call appropriate actions according to the fields set""" 
     557 
     558     
     559        bAuthorise = "authorise" in self 
     560         
     561        if 'returnURI' in self: 
     562            # Identity provider receives request from remote site for  
     563            # credentials and returns them 
     564            self._processCredsRequest(**kwargs) 
     565 
     566        elif 'authenticate' in self: 
     567            # User has entered login details - now authenticate using the  
     568            # Session Manager WS 
     569            sessCookie = self._authenticate() 
     570             
     571            if bAuthorise: 
     572                # Authorisation and authentication arguments were set -  
     573                # Now call authorisation passing the session cookie 
     574                self._getAttCert(sessCookie) 
     575             
     576            if 'returnURI' in self: 
     577                # The authentication process is as a result of a redirect  
     578                # request from another site - redirect back to the remote site 
     579                # returning the credentials contained in the NDG security 
     580                self._processCredsRequest(sessCookie=sessCookie, 
     581                                          setCookie=True,  
     582                                          **kwargs) 
     583                 
     584        elif bAuthorise: 
     585            # Handle a get attribute certificate request 
     586            self._getAttCert() 
     587                     
    256588        else: 
    257             # Expiry is set from life time in hours input in __init__ 
    258             dtExpiry = self.dtCookieExpiry 
    259             expiryStr = None 
    260  
    261         return UserSession.createSecurityCookie(sessID, 
    262                                                 sessMgrURI, 
    263                                                 dtExpiry=dtExpiry, 
    264                                                 expiryStr=expiryStr) 
    265  
    266  
    267         #_________________________________________________________________________ 
     589            # Remote site presents possible sites for user to get their  
     590            # credentials from 
     591            self.showHomeSiteSelect(**kwargs) 
     592 
     593 
     594    #_________________________________________________________________________ 
    268595    def _processCredsRequest(self, 
    269596                             returnURI=None, 
     
    308635                            redirectMsg='', 
    309636                            setCookie=False): 
    310         """User's home site returns credentials to requestor via a HTTP  
    311         redirect 
     637        """User's Identity Provider returns credentials to requestor via a  
     638        HTTP redirect 
    312639         
    313640        sessCookie:   NDG Session cookie 
     
    392719                    recalled followed by authorisation""" 
    393720 
    394         if self.__wsDebug: 
    395             traceFile = sys.stderr 
    396         else: 
    397             traceFile = None 
    398  
    399  
    400         if 'userName' in self: 
    401             self.userName = self['userName'].value 
    402              
    403         if 'passPhrase' in self: 
    404             self.passPhrase = self['passPhrase'].value 
    405              
    406         if 'returnURI' in self: 
    407             returnURI = self['returnURI'].value 
    408         else: 
    409             returnURI = None 
     721        self.userName = 'userName' in self and self['userName'].value or None 
     722        self.passPhrase = \ 
     723                    'passPhrase' in self and self['passPhrase'].value or None 
     724                     
     725        returnURI = 'returnURI' in self and self['returnURI'].value or None 
    410726             
    411727             
     
    427743            if not self.smClnt: 
    428744                self.smClnt = SessionClient(smWSDL=self.smWSDL, 
    429                                    smPubKeyFilePath=self.smPubKeyFilePath, 
    430                                    clntPubKeyFilePath=self.clntPubKeyFilePath, 
    431                                    clntPriKeyFilePath=self.clntPriKeyFilePath, 
    432                                    traceFile=traceFile) 
     745                               smPubKeyFilePath=self.smPubKeyFilePath, 
     746                               clntPubKeyFilePath=self.clntPubKeyFilePath, 
     747                               clntPriKeyFilePath=self.clntPriKeyFilePath, 
     748                               traceFile=self._wsDebug and sys.stderr or None) 
    433749 
    434750            sSessCookie = self.smClnt.connect(userName=self.userName, 
     
    442758                           bAuthorise=bAuthorise, 
    443759                           pageTitle="Login - internal error") 
    444             raise SecurityCGIError, "Session client: " + str(e) 
    445  
    446  
    447     #_________________________________________________________________________ 
    448     def _getAttCert(self, sessCookie=None, reqRole=None): 
    449         """Contact Attribute Authority to get Attribute Certificate for data 
    450         access 
    451  
    452         sessCookie:     NDG security session cookie 
    453         reqRole:        specify the required role to get authorisation.  Set 
    454                         this to optimise the process for getting the required 
    455                         AC from a trusted host in order to perform mapping""" 
    456  
    457         if self.__wsDebug: 
    458             traceFile = sys.stderr 
    459         else: 
    460             traceFile = None 
    461  
    462  
    463         # Check for session cookie input 
    464         if not sessCookie: 
    465             # No cookie set as input argument check for environment variable 
    466             if 'HTTP_COOKIE' in os.environ: 
    467                 sessCookie = SimpleCookie(os.environ['HTTP_COOKIE'])     
    468             else: 
    469                 raise SecurityCGIError, \ 
    470                     "Attribute certificate request requires a security cookie" 
    471  
    472         # Check cookie is valid 
    473         try: 
    474             UserSession.isValidSecurityCookie(sessCookie, raiseExcep=True) 
    475              
    476         except UserSessionError, e: 
    477             raise SecurityCGIError, 'Checking existing session cookie: %s' % e 
    478  
    479  
    480         # Configure flags for attribute certificate request.  This determines 
    481         # whether mapping of certificates from trusted hosts is allowed 
    482         if self._authorisationMethod == 'allowMapping': 
    483             bMapFromTrustedHosts = True 
    484             bRtnExtAttCertList = False 
    485  
    486         elif self._authorisationMethod == 'allowMappingWithPrompt': 
    487             bMapFromTrustedHosts = False 
    488             bRtnExtAttCertList = True 
    489         else: 
    490             bMapFromTrustedHosts = False 
    491             bRtnExtAttCertList = False 
    492  
    493  
    494         # Instantiate WS proxy and request authorisation 
    495         try: 
    496             if not self.smClnt: 
    497                 self.smClnt = SessionClient( 
    498                                 smWSDL=self.smWSDL, 
    499                                 smPubKeyFilePath=self.smPubKeyFilePath, 
    500                                 clntPubKeyFilePath=self.clntPubKeyFilePath, 
    501                                 clntPriKeyFilePath=self.clntPriKeyFilePath, 
    502                                 traceFile=traceFile) 
    503  
    504             resp = self.smClnt.reqAuthorisation(sessCookie=sessCookie, 
    505                                 aaWSDL=self.aaWSDL, 
    506                                 aaPubKey=self.aaPubKey, 
    507                                 reqRole=reqRole, 
    508                                 mapFromTrustedHosts=bMapFromTrustedHosts, 
    509                                 rtnExtAttCertList=bRtnExtAttCertList, 
    510                                 clntPriKeyPwd=self.clntPriKeyPwd) 
    511         except Exception, e: 
    512             # Socket error returns tuple - reformat to just give msg 
    513             raise SecurityCGIError, "Session client: " + str(e) 
    514  
    515  
    516         if resp['statCode'] == 'AccessGranted': 
    517             self.onAttCertGranted(resp['attCert']) 
    518          
    519         elif resp['statCode'] == 'AccessDenied': 
    520             self.onAttCertDenied(resp['extAttCertList'], resp['errMsg']) 
    521              
    522         elif resp['statCode'] == 'AccessError': 
    523             raise SecurityCGIError, resp['errMsg'] 
    524              
    525      
    526     #_________________________________________________________________________ 
    527     def onAttCertGranted(self, attCert): 
    528         """Callback invoked by getAttCert - handle case where an Attribute 
    529         Authority has granted a new attribute certificate to the user.  Derive 
    530         from this class and override this method as required. 
    531         """ 
    532         pass 
    533      
    534      
    535     #_________________________________________________________________________ 
    536     def onAttCertDenied(self, extAttCertList, errMsg): 
    537         """Callback invoked by getAttCert - handle case where an Attribute 
    538         Authority has denied an attribute certificate to the user.  Derive 
    539         from this class and override this method as required. 
    540          
    541         extAttCertList:    a list of attribute certificates from trusted 
    542                            hosts.  Any of these could be selected and  
    543                            presented back to the target AA in order to get 
    544                            a mapped certificate.  This list may be None if  
    545                            no ACs could be obtained or if the  
    546                            mapFromTrustedHosts flag in the call to the Session 
    547                            Manager WS reqAuthorisation method was set to  
    548                            False. 
    549                             
    550         errMsg:            the error message returned from the call to the 
    551                            AA to get an AC.""" 
    552          
    553         if not extAttCertList: 
    554             self.showLogin(pageTitle="Access denied by Attribute Authority") 
    555             raise SecurityCGIError, errMsg 
    556          
    557         else: 
    558             # Display list of attCerts to choose from 
    559             if contentTypeHdr: 
    560                 print "Content-type: text/html\n\n" 
    561                      
    562             if htmlTag: 
    563                 print "<html>\n" 
    564      
    565             if hdrTag:             
    566                 if not hdrTxt: 
    567                     hdrTxt = """    <style type=\"text/css\"> 
    568 <!-- 
    569 .al { 
    570 text-align: justify 
    571 } 
    572 a{ 
    573 text-decoration:none; 
    574 } 
    575 a:hover{ 
    576 color:#0000FF; 
    577 } 
    578     body { font-family: Verdana, sans-serif; font-size: 11} 
    579     table { font-family: Verdana, sans-serif; font-size: 11} 
    580 --> 
    581 </style>""" 
    582  
    583                 print """<head> 
    584              
    585     <title>%s</title> 
    586     %s 
    587 </head>""" % (pageTitle, hdrTxt) 
    588      
    589      
    590                 if bodyTag: 
    591                     print "<body>\n" 
    592                  
    593                 print """ 
    594     <form action="%s" method="POST"> 
    595     <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
    596     <tbody>""" 
    597                 for attCert in extAttCertList: 
    598                     print \ 
    599 """    <tr> 
    600         <td>%s</td> 
    601     </tr>""" % attCert['issuer'] 
    602                  
    603                 print \ 
    604 """    </tbody> 
    605     </table> 
    606     </form>""" 
    607  
    608                 if bodyTag: 
    609                     print "</body>\n" 
    610          
    611                 if htmlTag: 
    612                     print "</html>\n" 
    613      
    614         # end of handleAttCertDenied() 
     760            raise SecurityCGIError, "Session client: %s" % e 
    615761 
    616762     
     
    675821     
    676822        # Set authorisation method default 
    677         authorisationMethodChk = {  "allowMapping":              '', 
    678                                     "allowMappingWithPrompt" :   '', 
    679                                     "noMapping":                 ''} 
    680      
    681         if self._authorisationMethod is None: 
     823        acMappingFlagChkBox = {}.fromkeys(self.acMappingFlag, '') 
     824     
     825        if self.acMappingFlag is None: 
    682826            # Default to safest option for user 
    683             authorisationMethodChk["allowMappingWithPrompt"] = ' checked' 
     827            acMappingFlagChkBox[self.acAllowMappingWithPrompt] = ' checked' 
    684828        else: 
    685             authorisationMethodChk[self._authorisationMethod] = ' checked' 
     829            acMappingFlagChkBox[self.acMappingFlag] = ' checked' 
    686830     
    687831        print \ 
     
    736880    <div id="advSettings" style="position: relative; visibility: hidden;"> 
    737881        <h4>Role Mapping for access to other trusted sites</h4> 
    738         <p>Your account has roles or <i>privileges</i> which determine what data  
    739 you have access to.  If you access data at another NDG trusted site, these roles  
    740 can be mapped to local roles at that site to help you gain access:        </p>    
    741      <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5>        <tbody> 
     882        <p>Your account has roles or <i>privileges</i> which determine what  
     883        data you have access to.  If you access data at another NDG trusted  
     884        site, these roles can be mapped to local roles at that site to help  
     885        you gain access: 
     886        </p>    
     887        <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
     888        <tbody> 
    742889        <tr> 
    743         <td> 
    744             <input type="radio" name="authorisationMethod"  
    745 value="allowMapping"%s>        </td> 
    746890            <td> 
    747                 Allow my roles to be mapped to local roles at other NDG trusted  
    748 sites.            </td> 
     891                <input type="radio" name="authorisationMethod" value="%s"%s> 
     892            </td> 
     893            <td> 
     894            Allow my roles to be mapped to local roles at other NDG trusted  
     895            sites. 
     896            </td> 
    749897        </tr> 
    750898        <tr> 
    751899            <td> 
    752                 <input type="radio" name="authorisationMethod"  
    753 value="allowMappingWithPrompt"%s>            </td> 
    754         <td> 
     900                <input type="radio" name="authorisationMethod" value="%s"%s>            </td> 
     901            <td> 
    755902            Allow my roles to be mapped, but prompt me so that I may choose  
    756 which roles to map before gaining access.        </td> 
     903            which roles to map before gaining access. 
     904            </td> 
    757905        <tr> 
    758         <td> 
    759             <input type="radio" name="authorisationMethod" value="noMapping"%s> 
    760         </td> 
    761         <td> 
    762             Don't allow mapping of my roles. 
    763         </td> 
     906            <td> 
     907                <input type="radio" name="authorisationMethod" value="%s"%s> 
     908            </td> 
     909            <td> 
     910                Don't allow mapping of my roles. 
     911            </td> 
    764912        </tr> 
    765913        </tbody> 
     
    767915    </div> 
    768916    </form> 
    769     """ % (authorisationMethodChk['allowMapping'], \ 
    770            authorisationMethodChk['allowMappingWithPrompt'], \ 
    771            authorisationMethodChk['noMapping']) 
     917    """ % (self.acAllowMapping, 
     918           acMappingFlagChkBox[self.acAllowMapping],  
     919           self.acAllowMappingWithPrompt, 
     920           acMappingFlagChkBox[self.acAllowMappingWithPrompt], 
     921           self.acNoMapping, 
     922           acMappingFlagChkBox[self.acNoMapping]) 
    772923     
    773924        if bodyTag: print "</body>" 
     
    775926     
    776927        # end of showLogin() 
    777      
    778      
    779     #_________________________________________________________________________ 
    780     def showHomeSiteSelect(self, 
    781                            trustedHostInfo=None, 
    782                            scriptName=None, 
    783                            contentTypeHdr=False, 
    784                            htmlTag=False, 
    785                            hdrTag=False, 
    786                            hdrTxt='', 
    787                            bodyTag=False, 
    788                            pageTitle=""): 
    789  
    790         if trustedHostInfo: 
    791             self.trustedHostInfo = trustedHostInfo 
    792  
    793         if not self.trustedHostInfo: 
    794             self.getTrustedHostInfo() 
    795              
    796         if scriptName: 
    797             self.scriptName = scriptName 
    798              
    799                  
    800         if contentTypeHdr: 
    801             print "Content-type: text/html\n\n" 
    802                  
    803         if htmlTag: 
    804             print "<html>\n" 
    805  
    806         if hdrTag:             
    807             if not hdrTxt: 
    808                 hdrTxt = """    <style type=\"text/css\"> 
    809 <!-- 
    810 .al { 
    811 text-align: justify 
    812 } 
    813 a{ 
    814 text-decoration:none; 
    815 } 
    816 a:hover{ 
    817 color:#0000FF; 
    818 } 
    819     body { font-family: Verdana, sans-serif; font-size: 11} 
    820     table { font-family: Verdana, sans-serif; font-size: 11} 
    821 --> 
    822 </style>""" 
    823  
    824             print """<head> 
    825              
    826     <title>%s</title> 
    827     %s 
    828 </head>""" % (pageTitle, hdrTxt) 
    829      
    830      
    831         if bodyTag: 
    832             print "<body>\n" 
    833  
    834             print """ 
    835     <form action="%s" method="POST"> 
    836     <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5> 
    837     <tbody> 
    838     <tr> 
    839       <td> 
    840         <select name="requestURI">         
    841           <option value="">Select your home site...""" % self.scriptName 
    842            
    843             for hostname, info in self.trustedHostInfo.items(): 
    844                 print "<option value=\"%s\">%s" % (info['loginURI'], hostname) 
    845                  
    846             print \ 
    847 """        </select> 
    848       </td> 
    849       <td align="right"> 
    850         <input type=submit value="Go"> 
    851       </td> 
    852     </tr> 
    853     </tbody> 
    854     </table> 
    855     </form>""" 
    856  
    857         if bodyTag: 
    858             print "</body>\n" 
    859  
    860         if htmlTag: 
    861             print "</html>\n" 
    862      
    863         # end of showHomeSiteSelect() 
    864  
    865  
    866     #_________________________________________________________________________ 
    867     def getTrustedHostInfo(self): 
    868         """Call Attribute Authority to find out trusted hosts.  These can be 
    869         use to populate list for use to select home site for login""" 
    870          
    871         if self.__wsDebug: 
    872             traceFile = sys.stderr 
    873         else: 
    874             traceFile = None 
    875  
    876         try: 
    877             if not self.aaClnt: 
    878                 self.aaClnt = AttAuthorityClient(aaWSDL=self.aaWSDL, 
    879                                 aaPubKeyFilePath=self.aaPubKeyFilePath, 
    880                                 clntPubKeyFilePath=self.clntPubKeyFilePath, 
    881                                 clntPriKeyFilePath=self.clntPriKeyFilePath, 
    882                                 traceFile=traceFile) 
    883              
    884             self.trustedHostInfo = self.aaClnt.getTrustedHostInfo( 
    885                                            clntPriKeyPwd=self.clntPriKeyPwd) 
    886         except Exception, e: 
    887             raise SecurityCGIError, "Attribute Authority client: " + str(e) 
  • TI12-security/trunk/python/NDG/Session.py

    r1325 r1331  
    294294                                            cookieDomain=self.__cookieDomain, 
    295295                                            asString=asString) 
    296          
     296 
    297297     
    298298    #_________________________________________________________________________     
    299299    @classmethod 
    300300    def createSecurityCookie(cls,  
    301                              sessID,  
    302                              encrSessMgrWSDLuri, 
    303301                             expiryStr=None, 
    304302                             dtExpiry=None, 
    305303                             cookieDomain=None, 
    306                              asString=False): 
     304                             asString=False, 
     305                             **cookieTagKwArgs): 
    307306        """Class method for generic cookie creation independent of individual 
    308307        UserSession details.  This is useful for making a fresh cookie from 
     
    325324        """ 
    326325         
     326        try: 
     327            sessID = cookieTagKwArgs['NDG-ID1'] 
     328            encrSessMgrWSDLuri = cookieTagKwArgs['NDG-ID2'] 
     329             
     330        except KeyError: 
     331            c = cls.cookieTags 
     332            msg = len(c) > 1 and 's %s and %s' % (', '.join(c[:-1]), c[-1]) \ 
     333                or ' ' + c[-1] 
     334            raise UserSessionError, "The Cookie tag keyword%s" % c 
     335 
     336             
    327337        if len(sessID) < cls.__sessIDlen: 
    328338            UserSessionError, "Session ID has an invalid length" 
Note: See TracChangeset for help on using the changeset viewer.