source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/login.py @ 2873

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/controllers/login.py@2873
Revision 2873, 8.9 KB checked in by lawrence, 12 years ago (diff)

Some slight improvements to error trapping in login.py

Line 
1import sys,cgi
2from urlparse import urlparse
3import base64
4
5from ows_server.lib.base import *
6from ows_server.lib.security_util import setSecuritySession, LoginServiceQuery
7from ows_common.exception_report import OwsError
8from paste.request import parse_querystring
9import logging
10log = logging.getLogger(__name__)
11
12from ndg.security.common.AttAuthority import AttAuthorityClient
13from ndg.security.common.SessionMgr import SessionMgrClient, SessionExpired, \
14    AttributeRequestDenied
15
16
17class LoginController(BaseController):
18    ''' Provides the pylons controller for local login '''
19   
20    def __setup(self):
21        """Get 'r' return to URL argument from current URL query string"""
22        #where are we going back to?
23#        self.inputs=dict(parse_querystring(request.environ))
24#        if 'r' in self.inputs:
25#            c.returnTo=self.inputs['r']
26#        elif 'HTTP_REFERER' in request.environ:
27#            #Added by Dom, 06/07/07
28#            #http redirect  based on parse_querystring wasn't working so added this condition
29#            #NOTE:  Not been able to test whether this has broken discovery/browse due to missing templates.
30#            c.returnTo=request.environ['HTTP_REFERER']
31        # Try request.params - above method skips 'r' when passed in a hidden
32        # field in a HTTP POST
33        c.returnTo=request.params.get('r','')
34           
35
36    def __securitySetup(self):
37        '''PKI settings for Attribute Authority and Session Manager'''
38       
39        self.ndgCfg = request.environ['ndgConfig']
40
41        tracefileExpr = self.ndgCfg.get('NDG_SECURITY', 'tracefile')
42        if tracefileExpr:
43            self.tracefile = eval(tracefileExpr)
44       
45        # ... for SSL connections to security web services
46        try:
47            self.sslCACertFilePathList = \
48            self.ndgCfg.get('NDG_SECURITY', 'sslCACertFilePathList').split()
49               
50        except AttributeError:
51            raise OwsError, 'No "sslCACertFilePathList" security setting'
52
53        self.sslPeerCertCN = self.ndgCfg.get('NDG_SECURITY', 'sslPeerCertCN')
54
55        # ...and for WS-Security digital signature
56        self.wssCertFilePath = self.ndgCfg.get('NDG_SECURITY', 
57                                               'wssCertFilePath')
58        self.wssPriKeyFilePath = self.ndgCfg.get('NDG_SECURITY', 
59                                                 'wssKeyFilePath')
60        self.wssPriKeyPwd = self.ndgCfg.get('NDG_SECURITY', 'wssKeyPwd')
61
62        try:
63            self.wssCACertFilePathList = \
64            self.ndgCfg.get('NDG_SECURITY', 'wssCACertFilePathList').split()
65               
66        except AttributeError:
67            raise OwsError, 'No "wssCACertFilePathList" security setting'
68
69   
70    def index(self):
71        ''' Ok, you really want to login here '''
72        if 'ndgSec' in session: self.__doRedirect()
73        self.__setup()
74        return render_response('login')
75
76
77    def getCredentials(self):
78        """Authenticate user and cache user credentials in
79        Session Manager following user login"""
80       
81        try:
82            self.__setup()
83            self.__securitySetup()
84   
85            smURI = self.ndgCfg.get('NDG_SECURITY', 'sessionMgrURI')
86   
87            # May be better as a 'g' global set-up at start-up?
88            #
89            # tracefile could be removed for production use
90            smClnt = SessionMgrClient(uri=smURI,
91                                sslCACertFilePathList=self.sslCACertFilePathList,
92                                sslPeerCertCN=self.sslPeerCertCN,
93                                signingCertFilePath=self.wssCertFilePath,
94                                signingPriKeyFilePath=self.wssPriKeyFilePath,
95                                signingPriKeyPwd=self.wssPriKeyPwd,
96                                caCertFilePathList=self.wssCACertFilePathList,
97                                tracefile=self.tracefile)
98                               
99            username = request.params['username']
100            passphrase = request.params['passphrase']                     
101                               
102        except Exception,e:
103            c.xml='Error establishing security context [%s]'%cgi.escape(e)
104            return Response(render('content'),code=400)
105       
106        # Connect to Session Manager
107        log.debug("Calling Session Manager connect for user ")
108        try:
109            sessID = smClnt.connect(username, passphrase=passphrase)[-1]
110        except Exception, e:
111            c.xml = \
112    "Error logging in.  Please check your username/pass-phrase and try again."
113            log.error("Session Manager connect returned: %s" % e)
114            return Response(render('login'),code=401)
115       
116        # Cache user attributes in Session Manager
117        log.debug("Calling Session Manager getAttCert for user ")
118        try:
119            # Set the Attribute Authority address for the Session Manager to
120            # send its attribute request to
121            aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI')
122
123            # Make request for attribute certificate
124            attCert = smClnt.getAttCert(sessID=sessID, attAuthorityURI=aaURI)
125        except SessionExpired, e:
126            log.info("Session expired getting Attribute Certificate: %s" % e)
127            c.xml = "Session has expired, please re-login"
128            return Response(render('login'),code=401)
129           
130        except AttributeRequestDenied, e:
131            log.error("Login: attribute Certificate request denied: %s" % e)
132            c.xml = "No authorisation roles are available for your " + \
133                    "account.  Please check with your site administrator."
134            return Response(render('login'),code=401)
135           
136        except Exception, e:
137            log.error("Login: attribute Certificate request: %s" % e)
138            c.xml = "An internal error occured.  Please report this to " + \
139                    "your site administrator."
140            return Response(render('login'),code=400)
141
142        log.debug('Completing login')
143        # Make session
144        #
145        # Security credentials - proxyCert, userCert, ProxyPriKey and sessID
146        # could be held in the session but how secure is
147       
148        # Make a security cookie here ...
149        setSecuritySession(h=smURI,u=username,roles=attCert.roles,sid=sessID)
150        session['panelView']='History'
151        session.save()
152
153        return self.__doRedirect()
154           
155           
156    def wayf(self):
157        ''' NDG equivalent to Shibboleth WAYF '''
158       
159        self.__setup()
160        self.__securitySetup()
161       
162        aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI')
163
164        # May be better as a 'g' global set-up at start-up?
165        #
166        # tracefile could be removed for production use
167        aaClnt = AttAuthorityClient(uri=aaURI,
168                                signingCertFilePath=self.wssCertFilePath,
169                                signingPriKeyFilePath=self.wssPriKeyFilePath,
170                                signingPriKeyPwd=self.wssPriKeyPwd,
171                                caCertFilePathList=self.wssCACertFilePathList,
172                                tracefile=self.tracefile)
173
174        # Get list of login uris for trusted sites including THIS one
175        log.debug("Calling Attribute Authority getTrustedHostInfo and " + \
176                  "getHostInfo for wayf")
177        trustedHosts = aaClnt.getTrustedHostInfo()
178        thisHost = aaClnt.getHostInfo()
179       
180        try:
181            trustedHosts[thisHost.keys()[0]] = thisHost.values()[0]
182        except TypeError:
183            raise OwsError, \
184                        "thisHost returned from Attribute Authority is empty" 
185           
186        c.providers=dict([(k,v['loginURI']) for k,v in trustedHosts.items()])
187       
188        if 'panelView' in session: del session['panelView']
189        session.save()
190        return render_response('wayf')
191       
192    def __doRedirect(self):
193       
194        # Need to pass security creds back to requestor so that they can make
195        # a cookie.  If the requestor is in the same domain as the login then
196        # this is not necessary.
197        # and now go back to whence we had come
198        log.debug('Login redirect to [%s]'%c.returnTo)
199        if c.returnTo!='':
200            # is there a keyword on redirect_to that can make this https? See:
201            # http://pylonshq.com/project/pylonshq/browser/Pylons/trunk/pylons/decorators/secure.py#L69
202
203            # Only add token if return URI is in a different domain
204            thisHostname = request.host.split(':')[0]
205           
206            # Decode return to address
207            cc = base64.urlsafe_b64decode(c.returnTo)
208
209            returnToHostname = urlparse(cc)[1]
210
211            if thisHostname not in returnToHostname:
212                if '?' in cc:
213                    cc+='&%s' % LoginServiceQuery()
214                else:
215                    cc+='?%s' % LoginServiceQuery()
216
217            h.redirect_to(cc)
218        else:
219            c.xml='<p> Logged in </p>'
220            return render_response('content')
Note: See TracBrowser for help on using the repository browser.