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

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

ows_server/ows_server/controllers/login.py,
ows_server/ows_server/controllers/logout.py: added extra debug info in message prior to connect/disconnect call.

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 "%s" connect for user "%s" ...' % \
108                  (smURI, username))
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        log.debug('Completing login')
144        # Make session
145        #
146        # Security credentials - proxyCert, userCert, ProxyPriKey and sessID
147        # could be held in the session but how secure is
148       
149        # Make a security cookie here ...
150        setSecuritySession(h=smURI,u=username,roles=attCert.roles,sid=sessID)
151        session['panelView']='History'
152        session.save()
153
154        return self.__doRedirect()
155           
156           
157    def wayf(self):
158        ''' NDG equivalent to Shibboleth WAYF '''
159       
160        self.__setup()
161        self.__securitySetup()
162       
163        aaURI = self.ndgCfg.get('NDG_SECURITY', 'attAuthorityURI')
164
165        # May be better as a 'g' global set-up at start-up?
166        #
167        # tracefile could be removed for production use
168        aaClnt = AttAuthorityClient(uri=aaURI,
169                                signingCertFilePath=self.wssCertFilePath,
170                                signingPriKeyFilePath=self.wssPriKeyFilePath,
171                                signingPriKeyPwd=self.wssPriKeyPwd,
172                                caCertFilePathList=self.wssCACertFilePathList,
173                                tracefile=self.tracefile)
174
175        # Get list of login uris for trusted sites including THIS one
176        log.debug("Calling Attribute Authority getTrustedHostInfo and " + \
177                  "getHostInfo for wayf")
178        trustedHosts = aaClnt.getTrustedHostInfo()
179        thisHost = aaClnt.getHostInfo()
180       
181        try:
182            trustedHosts[thisHost.keys()[0]] = thisHost.values()[0]
183        except TypeError:
184            raise OwsError, \
185                        "thisHost returned from Attribute Authority is empty" 
186           
187        c.providers=dict([(k,v['loginURI']) for k,v in trustedHosts.items()])
188       
189        if 'panelView' in session: del session['panelView']
190        session.save()
191        return render_response('wayf')
192       
193    def __doRedirect(self):
194       
195        # Need to pass security creds back to requestor so that they can make
196        # a cookie.  If the requestor is in the same domain as the login then
197        # this is not necessary.
198        # and now go back to whence we had come
199        log.debug('Login redirect to [%s]'%c.returnTo)
200        if c.returnTo!='':
201            # is there a keyword on redirect_to that can make this https? See:
202            # http://pylonshq.com/project/pylonshq/browser/Pylons/trunk/pylons/decorators/secure.py#L69
203
204            # Only add token if return URI is in a different domain
205            thisHostname = request.host.split(':')[0]
206           
207            # Decode return to address
208            cc = base64.urlsafe_b64decode(c.returnTo)
209
210            returnToHostname = urlparse(cc)[1]
211
212            if thisHostname not in returnToHostname:
213                if '?' in cc:
214                    cc+='&%s' % LoginServiceQuery()
215                else:
216                    cc+='?%s' % LoginServiceQuery()
217
218            h.redirect_to(cc)
219        else:
220            c.xml='<p> Logged in </p>'
221            return render_response('content')
Note: See TracBrowser for help on using the repository browser.