source: TI12-security/trunk/python/NDG/SecurityCGI.py @ 1190

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/NDG/SecurityCGI.py@1190
Revision 1190, 28.3 KB checked in by pjkersha, 13 years ago (diff)

NDG/SecurityCGI.py: processCredsRequest only picks up an existing cookie if no cookie was input, AND if an
existing cookie is picked up and is not an NDG security one, then it's silently ignored.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2
3"""NDG Security CGI services
4
5NERC Data Grid Project
6
7P J Kershaw 23/05/06
8
9Copyright (C) 2006 CCLRC & NERC
10
11This software may be distributed under the terms of the Q Public License,
12version 1.0 or later.
13"""
14from Cookie import SimpleCookie
15
16import sys
17import cgi
18import os
19import base64
20
21# Set cookie expiry
22from datetime import datetime
23from datetime import timedelta
24
25from NDG.SecurityClient import *
26from NDG.Session import UserSession
27from NDG.Session import UserSessionError
28
29
30class SecurityCGIError(Exception):
31    """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
38
39   
40class SecurityCGI(cgi.FieldStorage):
41    """CGI interface class for NDG Security
42   
43    Terms used throughout:       
44        remote site     - where user is accessing resources
45        home site       - where user's credentials are held or they login"""
46
47    #_________________________________________________________________________
48    def __init__(self,
49                 smWSDL,
50                 aaWSDL,
51                 smPubKeyFilePath=None,
52                 aaPubKeyFilePath=None,
53                 clntPubKeyFilePath=None,
54                 clntPriKeyFilePath=None,
55                 clntPriKeyPwd=None,
56                 userName=None,
57                 passPhrase=None,
58                 scriptName=None,
59                 trustedHostInfo=None,
60                 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
67                              authentication
68        aaWSDL:               URI for Attribute Authority WSDL used to get a
69                              list of login URI for trusted hosts
70        trustedHostInfo:      dictionary of URIs for trusted hosts indexed by
71                              hostname
72        cookieLifetimeHrs:    cookie lifetime in hours
73        wsDebug:              print output from WS transactions to stderr"""
74
75        self.smWSDL = smWSDL
76        self.smClnt = None
77        self.aaWSDL = aaWSDL
78        self.aaClnt = None
79       
80        self.userName = userName
81        self.passPhrase = passPhrase
82       
83        self.smPubKeyFilePath = smPubKeyFilePath
84        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__
94
95        self.trustedHostInfo = trustedHostInfo
96        self.cookieLifetimeHrs = cookieLifetimeHrs
97
98        # Work out expiry time offset from the time this script is run
99        self.dtCookieExpiry = datetime.utcnow() + \
100                            timedelta(seconds=self.cookieLifetimeHrs*60*60)
101
102        self.__wsDebug = False
103        self._authorisationMethod = None
104
105        self.attCert = None
106       
107       
108        cgi.FieldStorage.__init__(self, **cgiFieldStorageKwArgs)
109
110 
111    #_________________________________________________________________________
112    def processFields(self, **kwargs):
113        """Call appropriate actions according to the fields set"""
114
115        bAuthorise = "authorise" in self
116       
117        if 'requestURI' in self:
118            # Request credentials from user's home site
119            self.requestCreds(**kwargs)
120
121        elif 'NDG-ID1' in self and 'NDG-ID2' in self:
122            # Receive credentials back from home site and set a new cookie at
123            # remote site
124            if 'expires' in self:
125                encodedExpiry = self['expires'].value
126            else:
127                encodedExpiry = None
128
129            self.receiveCredsResponse(self['NDG-ID1'].value,
130                                      self['NDG-ID2'].value,
131                                      encodedExpiry=encodedExpiry,
132                                      **kwargs)
133
134        elif 'authenticate' in self:
135            # User has entered login details - now authenticate using the
136            # Session Manager WS
137            sessCookie = self.authenticate()
138           
139            if bAuthorise:
140
141                # Authorisation and authentication arguments were set
142                # - Call authentication first
143                cookie = self.authenticate(setCookie=False)
144
145                # Call authorisation passing the session ID for authorise to
146                # set the cookie
147                self.getAttCert(cookie)
148           
149            if 'returnURI' in self:
150                # The authentication process is as a result of a redirect
151                # request from another site - redirect back to the remote site
152                # returning the credentials contained in the NDG security
153                self.processCredsRequest(sessCookie=sessCookie,
154                                         setCookie=True, 
155                                         **kwargs)
156               
157        elif bAuthorise:
158            self.getAttCert()
159                   
160        elif 'returnURI' in self:
161            # Home site receives request from remote site for credentials and
162            # returns them
163            self.processCredsRequest(**kwargs)
164        else:
165            # Remote site presents possible sites for user to get their
166            # credentials from
167            self.showHomeSiteSelect(**kwargs)
168   
169   
170    #_________________________________________________________________________
171    # Use instance name as an alias to processFields method
172    __call__ = processFields
173   
174
175    #_________________________________________________________________________
176    def requestCreds(self,
177                     requestURI=None,
178                     returnURI=None,
179                     pageTitle='',
180                     headTags='',
181                     delayTime=0,
182                     redirectMsg=''):
183        """Request credentials from a user's home site
184       
185        requestURI:   site to request credentials from - default is
186                      'requestURI' CGI form value
187        pageTitle:    Give the redirect page a title
188        headTags:     Optionally add additional tags in <head/> section
189        delayTime:    time in seconds before carrying out redirect - redirect
190                      page will be displayed in this interval
191        redirectMsg:  Message to put on redirect page.  Can be plain text or
192                      formatted HTML"""
193
194        if returnURI is None:
195            returnURI = self['returnURI'].value
196
197        if requestURI is None:
198            requestURI = self['requestURI'].value
199
200        print """Content-type: text/html
201
202<html>
203<head>
204<title>%s</title>
205<meta http-equiv="REFRESH" content="%d; url=%s?returnURI=%s">
206%s
207</head>
208<body>
209%s
210</body>
211</html>""" % \
212    (pageTitle, delayTime, requestURI, returnURI, headTags, redirectMsg)
213
214
215    #_________________________________________________________________________
216    def receiveCredsResponse(self,
217                             sessID,
218                             sessMgrURI,
219                             encodedExpiry=None,
220                             **showCredsReceivedKwArgs):
221        """Remote site receives returned credentials and creates a new cookie
222        for its domain"""
223        sessCookie = self.createCookie(sessID, sessMgrURI, encodedExpiry)
224        self.showCredsReceived(sessCookie)
225
226    #_________________________________________________________________________
227    def showCredsReceived(sessCookie, pageTitle='', hdrTxt='', bodyTxt=''):
228        """Called from receiveCredsResponse() once a cookie has been created.
229        Makes a page to set the cookie and display to the user that they have
230        been authenticated.  Derived class should override this method as
231        required"""
232        print """Content-type: text/html"
233%s
234
235<html>
236<head>
237<title>%s</title>
238%s
239</head>
240<body>
241    %s
242</body>
243</html>""" % (sessCookie.output(), pageTitle, hdrTxt, bodyTxt)
244
245   
246    #_________________________________________________________________________
247    def createCookie(self, sessID, sessMgrURI, encodedExpiry=None):
248        """Convert credentials passed over URI from users home site into a new
249        cookie"""
250
251        if encodedExpiry:
252            # Expiry is taken from encoded value passed over URI
253            dtExpiry = None
254            expiryStr = base64.urlsafe_b64decode(encodedExpiry)
255        else:
256            # Expiry is set from life time in hours input in __init__
257            dtExpiry = self.dtCookieExpiry
258            expiryStr = None
259
260        return UserSession.createSecurityCookie(sessID,
261                                                sessMgrURI,
262                                                dtExpiry=dtExpiry,
263                                                expiryStr=expiryStr)
264
265
266        #_________________________________________________________________________
267    def processCredsRequest(self,
268                            returnURI=None,
269                            bAuthorise=False, 
270                            sessCookie=None, 
271                            **returnCredsKwArgs):
272        """Receive request from remote site for credentials.  Process and
273        return via a redirect"""
274
275        if returnURI is None:
276            returnURI = self['returnURI'].value
277                                                         
278        # Check for cookie in environment
279        if sessCookie is None and 'HTTP_COOKIE' in os.environ:
280   
281            # Get session ID from existing cookie
282            sessCookie = SimpleCookie(os.environ['HTTP_COOKIE'])
283
284        # Check for NDG cookie
285        if sessCookie and UserSession.isValidSecurityCookie(sessCookie):
286               
287            # Return cookie to requestor
288            self.returnCreds(sessCookie, returnURI, **returnCredsKwArgs)
289
290        else:
291            # No cookie present - display login.  Submit must redirect back to
292            # this script with '?authenticate=1&returnURI=<...>'
293            self.showLogin(returnURI=returnURI,
294                           bAuthorise=bAuthorise, 
295                           pageTitle="NDG Login")
296
297   
298    #_________________________________________________________________________
299    def returnCreds(self,
300                    sessCookie, 
301                    returnURI=None,
302                    pageTitle='',
303                    hdrTxt='',
304                    delayTime=0,
305                    redirectMsg='',
306                    setCookie=False):
307        """User's home site returns credentials to requestor via a HTTP
308        redirect
309       
310        sessCookie:   NDG Session cookie
311        pageTitle:    Give the redirect page a title
312        headTags:     Optionally add additional tags in <head/> section
313        delayTime:    time in seconds before carrying out redirect - redirect
314                      page will be displayed in this interval
315        redirectMsg:  Message to put on redirect page.  Can be plain text or
316                      formatted HTML"""
317
318        if returnURI is None:
319            returnURI = self['returnURI'].value
320                                         
321        if setCookie:
322            cookieTxt = sessCookie.output() + os.linesep
323        else:
324            cookieTxt = ''
325
326
327        # Allow for case where return URI already includes some args
328        if '?' in returnURI:
329            argSeparator = '&'
330        else:
331            argSeparator = '?'
332
333
334        print """Content-type: text/html
335%s
336<html>
337<head>
338<title>%s</title>
339<meta http-equiv="REFRESH"
340content="%d; url=%s%sNDG-ID1=%s&NDG-ID2=%s&expires=%s">
341%s
342</head>
343<body>
344%s
345</body>
346</html>""" % ( cookieTxt,
347               pageTitle,
348               delayTime,
349               returnURI,
350               argSeparator,
351               sessCookie['NDG-ID1'].value,
352               sessCookie['NDG-ID2'].value,
353               base64.urlsafe_b64encode(sessCookie['NDG-ID1']['expires']),
354               hdrTxt,
355               redirectMsg)
356
357
358    #_________________________________________________________________________
359    def authenticate(self, bAuthorise=False):
360        """Authenticate username and passphrase input from preceeding login
361        form
362
363        bAuthorise: set to True so that if an error occurs, login will be
364                    recalled followed by authorisation"""
365
366        if self.__wsDebug:
367            traceFile = sys.stderr
368        else:
369            traceFile = None
370
371
372        if 'userName' in self:
373            self.userName = self['userName'].value
374           
375        if 'passPhrase' in self:
376            self.passPhrase = self['passPhrase'].value
377           
378        if 'returnURI' in self:
379            returnURI = self['returnURI'].value
380        else:
381            returnURI = None
382           
383           
384        if self.userName is None:
385            self.showLogin(returnURI=returnURI,
386                           bAuthorise=bAuthorise,
387                           pageTitle="Login - error no username set")
388            raise SecurityCGIError, "no username set for authentication"
389
390        if self.passPhrase is None:
391            self.showLogin(returnURI=returnURI,
392                           bAuthorise=bAuthorise,
393                           pageTitle="Login - error no pass-phrase set")
394            raise SecurityCGIError, "no pass-phrase set for authentication"
395
396
397        # Instantiate WS proxy and request connection
398        try:
399            if not self.smClnt:
400                self.smClnt = SessionClient(smWSDL=self.smWSDL,
401                                   smPubKeyFilePath=self.smPubKeyFilePath,
402                                   clntPubKeyFilePath=self.clntPubKeyFilePath,
403                                   clntPriKeyFilePath=self.clntPriKeyFilePath,
404                                   traceFile=traceFile)
405
406            sSessCookie = self.smClnt.connect(userName=self.userName,
407                                         pPhrase=self.passPhrase,
408                                         clntPriKeyPwd=self.clntPriKeyPwd)
409            sessCookie = SimpleCookie(sSessCookie)
410            return sessCookie
411
412        except Exception, e:
413            self.showLogin(returnURI=returnURI,
414                           bAuthorise=bAuthorise,
415                           pageTitle="Login - internal error")
416            raise SecurityCGIError, "Session client: " + str(e)
417
418
419    #_________________________________________________________________________
420    def getAttCert(self, sessCookie=None, reqRole=None):
421        """Contact Attribute Authority to get Attribute Certificate for data
422        access
423
424        sessCookie:     NDG security session cookie
425        reqRole:        specify the required role to get authorisation.  Set
426                        this to optimise the process for getting the required
427                        AC from a trusted host in order to perform mapping"""
428
429        if self.__wsDebug:
430            traceFile = sys.stderr
431        else:
432            traceFile = None
433
434
435        # Check for session cookie input
436        if not sessCookie:
437            # No cookie set as input argument check for environment variable
438            if 'HTTP_COOKIE' in os.environ:
439                sessCookie = SimpleCookie(os.environ['HTTP_COOKIE'])   
440            else:
441                raise SecurityCGIError, \
442                    "Attribute certificate request requires a security cookie"
443
444        # Check cookie is valid
445        try:
446            UserSession.isValidSecurityCookie(sessCookie, raiseExcep=True)
447           
448        except UserSessionError, e:
449            raise SecurityCGIError, 'Checking existing session cookie: %s' % e
450
451
452        # Configure flags for attribute certificate request.  This determines
453        # whether mapping of certificates from trusted hosts is allowed
454        if self._authorisationMethod == 'allowMapping':
455            bMapFromTrustedHosts = True
456            bRtnExtAttCertList = False
457
458        elif self._authorisationMethod == 'allowMappingWithPrompt':
459            bMapFromTrustedHosts = False
460            bRtnExtAttCertList = True
461        else:
462            bMapFromTrustedHosts = False
463            bRtnExtAttCertList = False
464
465
466        # Instantiate WS proxy and request authorisation
467        try:
468            if not self.smClnt:
469                self.smClnt = SessionClient(
470                                smWSDL=self.smWSDL,
471                                smPubKeyFilePath=self.smPubKeyFilePath,
472                                clntPubKeyFilePath=self.clntPubKeyFilePath,
473                                clntPriKeyFilePath=self.clntPriKeyFilePath,
474                                traceFile=traceFile)
475
476            resp = self.smClnt.reqAuthorisation(sessCookie=sessCookie,
477                                aaWSDL=self.aaWSDL,
478                                aaPubKey=self.aaPubKey,
479                                reqRole=reqRole,
480                                mapFromTrustedHosts=bMapFromTrustedHosts,
481                                rtnExtAttCertList=bRtnExtAttCertList,
482                                clntPriKeyPwd=self.clntPriKeyPwd)
483        except Exception, e:
484            # Socket error returns tuple - reformat to just give msg
485            raise SecurityCGIError, "Session client: " + str(e)
486
487
488        if resp['statCode'] == 'AccessGranted':
489            self.onAttCertGranted(resp['attCert'])
490       
491        elif resp['statCode'] == 'AccessDenied':
492            self.onAttCertDenied(resp['extAttCertList'], resp['errMsg'])
493           
494        elif resp['statCode'] == 'AccessError':
495            raise SecurityCGIError, resp['errMsg']
496           
497   
498    #_________________________________________________________________________
499    def onAttCertGranted(self, attCert):
500        """Callback invoked by getAttCert - handle case where an Attribute
501        Authority has granted a new attribute certificate to the user.  Derive
502        from this class and override this method as required.
503        """
504        pass
505   
506   
507    #_________________________________________________________________________
508    def onAttCertDenied(self, extAttCertList, errMsg):
509        """Callback invoked by getAttCert - handle case where an Attribute
510        Authority has denied an attribute certificate to the user.  Derive
511        from this class and override this method as required.
512       
513        extAttCertList:    a list of attribute certificates from trusted
514                           hosts.  Any of these could be selected and
515                           presented back to the target AA in order to get
516                           a mapped certificate.  This list may be None if
517                           no ACs could be obtained or if the
518                           mapFromTrustedHosts flag in the call to the Session
519                           Manager WS reqAuthorisation method was set to
520                           False.
521                           
522        errMsg:            the error message returned from the call to the
523                           AA to get an AC."""
524       
525        if not extAttCertList:
526            self.showLogin(pageTitle="Access denied by Attribute Authority")
527            raise SecurityCGIError, errMsg
528       
529        else:
530            # Display list of attCerts to choose from
531            if contentTypeHdr:
532                print "Content-type: text/html\n\n"
533                   
534            if htmlTag:
535                print "<html>\n"
536   
537            if hdrTag:           
538                if not hdrTxt:
539                    hdrTxt = """    <style type=\"text/css\">
540<!--
541.al {
542text-align: justify
543}
544a{
545text-decoration:none;
546}
547a:hover{
548color:#0000FF;
549}
550    body { font-family: Verdana, sans-serif; font-size: 11}
551    table { font-family: Verdana, sans-serif; font-size: 11}
552-->
553</style>"""
554
555                print """<head>
556           
557    <title>%s</title>
558    %s
559</head>""" % (pageTitle, hdrTxt)
560   
561   
562                if bodyTag:
563                    print "<body>\n"
564               
565                print """
566    <form action="%s" method="POST">
567    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5>
568    <tbody>"""
569                for attCert in extAttCertList:
570                    print \
571"""    <tr>
572        <td>%s</td>
573    </tr>""" % attCert['issuer']
574               
575                print \
576"""    </tbody>
577    </table>
578    </form>"""
579
580                if bodyTag:
581                    print "</body>\n"
582       
583                if htmlTag:
584                    print "</html>\n"
585   
586        # end of handleAttCertDenied()
587
588   
589    #_________________________________________________________________________
590    def showLogin(self,
591                  returnURI=None,
592                  contentTypeHdr=True,
593                  htmlTag=True,
594                  pageTitle='',
595                  hdrTxt='',
596                  headTag=True,
597                  bodyTag=True,
598                  bAuthorise=False):
599        """Display initial NDG login form"""
600   
601        if contentTypeHdr: print "Content-type: text/html\n\n"
602       
603        if htmlTag: print "<html>"
604   
605        if headTag:
606            if not hdrTxt:
607                hdrTxt = """    <style type=\"text/css\">
608<!--
609.al {
610text-align: justify
611}
612a{
613text-decoration:none;
614}
615a:hover{
616color:#0000FF;
617}
618    body { font-family: Verdana, sans-serif; font-size: 11}
619    table { font-family: Verdana, sans-serif; font-size: 11}
620-->
621</style>"""
622                   
623            print """<head>
624        <title>%s</title>
625        %s
626    </head>""" % (pageTitle, hdrTxt)
627   
628   
629        if bodyTag: print "<body>"
630
631
632        if returnURI is None and 'returnURI' in self:
633            returnURI = self['returnURI'].value
634
635        if returnURI:
636            returnURIfield = \
637                "<input type=hidden name=returnURI value=\"%s\">" % returnURI
638        else:
639            returnURIfield = ''
640       
641   
642        if bAuthorise:
643            authoriseArg = "<input type=hidden name=authorise value=\"1\">"
644        else:
645            authoriseArg = ""
646   
647   
648        # Set authorisation method default
649        authorisationMethodChk = {  "allowMapping":              '',
650                                    "allowMappingWithPrompt" :   '',
651                                    "noMapping":                 ''}
652   
653        if self._authorisationMethod is None:
654            # Default to safest option for user
655            authorisationMethodChk["allowMappingWithPrompt"] = ' checked'
656        else:
657            authorisationMethodChk[self._authorisationMethod] = ' checked'
658   
659        print \
660    """<script language="javascript">
661    <!--
662        function toggleLayer(layerId)
663        {
664            if (document.getElementById)
665            {
666                // Standard
667                var style = document.getElementById(layerId).style;
668            }
669            else if (document.all)
670            {
671                // Old msie versions
672                var style = document.all[whichLayer].style;
673            }
674            else if (document.layers)
675            {
676                // nn4
677                var style = document.layers[whichLayer].style;
678            }
679            style.visibility = style.visibility == "visible" ?
680"hidden":"visible";        }
681    //-->
682    </script>
683    <h3>NERC Data Grid Site Login (Test)<BR clear=all></h3>
684    <hr>
685   
686    <form action="%s" method="POST">
687   
688    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5>
689    <tbody>
690    <tr><td>User Name:</td> <td><input type=text name=userName value="">
691    </td></tr>
692    <tr>
693        <td>Password:</td>
694        <td><input type=password name=passPhrase></td>
695    </tr>
696    <tr>
697        <td colspan="2" align="right">
698            <a href="javascript:toggleLayer('advSettings');">Advanced
699Settings</a>            <input type=submit value="Login">
700        </td>
701    </tr>
702    <input type=hidden name=authenticate value="1">
703    %s"""  % (self.scriptName, returnURIfield)
704   
705        print \
706    """</tbody></table>
707    <br>
708    <div id="advSettings" style="position: relative; visibility: hidden;">
709        <h4>Role Mapping for access to other trusted sites</h4>
710        <p>Your account has roles or <i>privileges</i> which determine what data
711you have access to.  If you access data at another NDG trusted site, these roles
712can be mapped to local roles at that site to help you gain access:        </p>   
713     <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5>        <tbody>
714        <tr>
715        <td>
716            <input type="radio" name="authorisationMethod"
717value="allowMapping"%s>        </td>
718            <td>
719                Allow my roles to be mapped to local roles at other NDG trusted
720sites.            </td>
721        </tr>
722        <tr>
723            <td>
724                <input type="radio" name="authorisationMethod"
725value="allowMappingWithPrompt"%s>            </td>
726        <td>
727            Allow my roles to be mapped, but prompt me so that I may choose
728which roles to map before gaining access.        </td>
729        <tr>
730        <td>
731            <input type="radio" name="authorisationMethod" value="noMapping"%s>
732        </td>
733        <td>
734            Don't allow mapping of my roles.
735        </td>
736        </tr>
737        </tbody>
738        </table>
739    </div>
740    </form>
741    """ % (authorisationMethodChk['allowMapping'], \
742           authorisationMethodChk['allowMappingWithPrompt'], \
743           authorisationMethodChk['noMapping'])
744   
745        if bodyTag: print "</body>"
746        if htmlTag: print "</html>"
747   
748        # end of showLogin()
749   
750   
751    #_________________________________________________________________________
752    def showHomeSiteSelect(self,
753                           trustedHostInfo=None,
754                           scriptName=None,
755                           contentTypeHdr=False,
756                           htmlTag=False,
757                           hdrTag=False,
758                           hdrTxt='',
759                           bodyTag=False,
760                           pageTitle=""):
761
762        if trustedHostInfo:
763            self.trustedHostInfo = trustedHostInfo
764
765        if not self.trustedHostInfo:
766            self.getTrustedHostInfo()
767           
768        if scriptName:
769            self.scriptName = scriptName
770           
771               
772        if contentTypeHdr:
773            print "Content-type: text/html\n\n"
774               
775        if htmlTag:
776            print "<html>\n"
777
778        if hdrTag:           
779            if not hdrTxt:
780                hdrTxt = """    <style type=\"text/css\">
781<!--
782.al {
783text-align: justify
784}
785a{
786text-decoration:none;
787}
788a:hover{
789color:#0000FF;
790}
791    body { font-family: Verdana, sans-serif; font-size: 11}
792    table { font-family: Verdana, sans-serif; font-size: 11}
793-->
794</style>"""
795
796            print """<head>
797           
798    <title>%s</title>
799    %s
800</head>""" % (pageTitle, hdrTxt)
801   
802   
803        if bodyTag:
804            print "<body>\n"
805
806            print """
807    <form action="%s" method="POST">
808    <table bgcolor=#ADD8E6 cellspacing=0 border=0 cellpadding=5>
809    <tbody>
810    <tr>
811      <td>
812        <select name="requestURI">       
813          <option value="">Select your home site...""" % self.scriptName
814         
815            for hostname, info in self.trustedHostInfo.items():
816                print "<option value=\"%s\">%s" % (info['loginURI'], hostname)
817               
818            print \
819"""        </select>
820      </td>
821      <td align="right">
822        <input type=submit value="Go">
823      </td>
824    </tr>
825    </tbody>
826    </table>
827    </form>"""
828
829        if bodyTag:
830            print "</body>\n"
831
832        if htmlTag:
833            print "</html>\n"
834   
835        # end of showHomeSiteSelect()
836
837
838    #_________________________________________________________________________
839    def getTrustedHostInfo(self):
840        """Call Attribute Authority to find out trusted hosts.  These can be
841        use to populate list for use to select home site for login"""
842       
843        if self.__wsDebug:
844            traceFile = sys.stderr
845        else:
846            traceFile = None
847
848        try:
849            if not self.aaClnt:
850                self.aaClnt = AttAuthorityClient(aaWSDL=self.aaWSDL,
851                                aaPubKeyFilePath=self.aaPubKeyFilePath,
852                                clntPubKeyFilePath=self.clntPubKeyFilePath,
853                                clntPriKeyFilePath=self.clntPriKeyFilePath,
854                                traceFile=traceFile)
855           
856            self.trustedHostInfo = self.aaClnt.getTrustedHostInfo(
857                                           clntPriKeyPwd=self.clntPriKeyPwd)
858        except Exception, e:
859            raise SecurityCGIError, "Attribute Authority client: " + str(e)
Note: See TracBrowser for help on using the repository browser.