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

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

Oops ... quick bug fix in login.py
(can't test this stuff in my sand box)

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        self.__setup()
82       
83        try:
84            self.__securitySetup()
85   
86            smURI = self.ndgCfg.get('NDG_SECURITY', 'sessionMgrURI')
87   
88            # May be better as a 'g' global set-up at start-up?
89            #
90            # tracefile could be removed for production use
91            smClnt = SessionMgrClient(uri=smURI,
92                                sslCACertFilePathList=self.sslCACertFilePathList,
93                                sslPeerCertCN=self.sslPeerCertCN,
94                                signingCertFilePath=self.wssCertFilePath,
95                                signingPriKeyFilePath=self.wssPriKeyFilePath,
96                                signingPriKeyPwd=self.wssPriKeyPwd,
97                                caCertFilePathList=self.wssCACertFilePathList,
98                                tracefile=self.tracefile)
99                               
100            username = request.params['username']
101            passphrase = request.params['passphrase']                     
102                               
103        except Exception,e:
104            c.xml='Error establishing security context [%s]'%cgi.escape(e)
105            return Response(render('content'),code=400)
106       
107        # Connect to Session Manager
108        log.debug("Calling Session Manager connect for user ")
109        try:
110            sessID = smClnt.connect(username, passphrase=passphrase)[-1]
111        except Exception, e:
112            c.xml = \
113    "Error logging in.  Please check your username/pass-phrase and try again."
114            log.error("Session Manager connect returned: %s" % e)
115            return Response(render('login'),code=401)
116       
117        # Cache user attributes in Session Manager
118        log.debug("Calling Session Manager getAttCert for user ")
119        try:
120            # Set the Attribute Authority address for the Session Manager to
121            # send its attribute request to
122            aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI')
123
124            # Make request for attribute certificate
125            attCert = smClnt.getAttCert(sessID=sessID, attAuthorityURI=aaURI)
126        except SessionExpired, e:
127            log.info("Session expired getting Attribute Certificate: %s" % e)
128            c.xml = "Session has expired, please re-login"
129            return Response(render('login'),code=401)
130           
131        except AttributeRequestDenied, e:
132            log.error("Login: attribute Certificate request denied: %s" % e)
133            c.xml = "No authorisation roles are available for your " + \
134                    "account.  Please check with your site administrator."
135            return Response(render('login'),code=401)
136           
137        except Exception, e:
138            log.error("Login: attribute Certificate request: %s" % e)
139            c.xml = "An internal error occured.  Please report this to " + \
140                    "your site administrator."
141            return Response(render('login'),code=400)
142
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        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        if c.returnTo!='':
199            # is there a keyword on redirect_to that can make this https? See:
200            # http://pylonshq.com/project/pylonshq/browser/Pylons/trunk/pylons/decorators/secure.py#L69
201
202            # Only add token if return URI is in a different domain
203            thisHostname = request.host.split(':')[0]
204           
205            # Decode return to address
206            cc = base64.urlsafe_b64decode(c.returnTo)
207
208            returnToHostname = urlparse(cc)[1]
209
210            if thisHostname not in returnToHostname:
211                if '?' in cc:
212                    cc+='&%s' % LoginServiceQuery()
213                else:
214                    cc+='?%s' % LoginServiceQuery()
215
216            h.redirect_to(cc)
217        else:
218            c.xml='<p> Logged in </p>'
219            return render_response('content')
Note: See TracBrowser for help on using the repository browser.