source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/sessionMgr.tac @ 4129

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/conf/sessionMgr.tac@4129
Revision 4129, 9.3 KB checked in by cbyrom, 11 years ago (diff)

General refactoring and updating of code, including:

Removal of refC14nKw and singnedInfoC14nKw keywords in wsssecurity session manager config
(the refC14nInclNS and signedInfoC14nInclNS keywords are sufficient);
Creation of new DOM signature handler class, dom.py, based on the wsSecurity
class;
Abstraction of common code between dom.py and etree.py into new parent
class, BaseSignatureHandler?.py.
Fixing and extending use of properties in the SignatureHandler? code.
Fixing a few bugs with the original SignatureHandler? code.
Updating of test cases to new code/code structure.

Line 
1#!/usr/bin/env python
2"""NDG Security Session Manager .tac file
3
4This file enables the Session Manager web service to be
5called under the Twisted framework
6
7NERC Data Grid Project
8"""
9__author__ = "P J Kershaw"
10__date__ = "23/11/06"
11__copyright__ = "(C) 2007 STFC & NERC"
12__license__ = \
13"""This software may be distributed under the terms of the Q Public
14License, version 1.0 or later."""
15__contact__ = "P.J.Kershaw@rl.ac.uk"
16__revision__ = '$Id$'
17
18import os, base64
19
20from logging.config import fileConfig
21try:
22        _logConfig = os.path.join(os.environ["NDGSEC_DIR"],
23                                                          'conf',
24                                                          'sessionMgrLog.cfg')
25        fileConfig(_logConfig)
26
27except KeyError:
28        from warnings import warn
29        warn(\
30        '"NDGSEC_DIR" environment variable must be set to enable logging config',
31        RuntimeWarning)
32       
33import logging
34log = logging.getLogger(__name__)
35
36from ZSI.twisted.WSresource import WSResource
37from twisted.application import service, internet
38from twisted.web.server import Site
39from twisted.web.resource import Resource
40
41from ndg.security.server.SessionMgr.SessionMgr_services_server import \
42        SessionMgrService as _SessionMgrService
43from ndg.security.server.SessionMgr import SessionMgr
44from ndg.security.common.wssecurity.dom import SignatureHandler
45from ndg.security.server.twisted import WSSecurityHandler, \
46        WSSecurityHandlerChainFactory
47       
48
49from ndg.security.common.X509 import X509CertRead
50
51
52class SessionMgrService(_SessionMgrService, WSResource):
53
54    # Add WS-Security handlers
55    factory = WSSecurityHandlerChainFactory
56       
57    def __init__(self):
58        '''Initialize Session Manager class - encapsulates inner workings
59        including session management and proxy delegation
60       
61        @type ps: ZSI ParsedSoap
62        @param ps: client SOAP message
63        @rtype: tuple
64        @return: request and response objects'''
65       
66        # Stop in debugger at beginning of SOAP stub if environment variable
67        # is set
68        self.__debug = bool(os.environ.get('NDGSEC_INT_DEBUG'))
69        if self.__debug:
70                import pdb
71                pdb.set_trace()
72
73        WSResource.__init__(self) 
74        self.sm = SessionMgr()
75
76
77    def soap_connect(self, ps, **kw):
78        '''Connect to Session Manager and create a user session
79       
80        @type ps: ZSI ParsedSoap
81        @param ps: client SOAP message
82        @rtype: tuple
83        @return: request and response objects'''
84
85        if self.__debug:
86                import pdb
87                pdb.set_trace()
88               
89        request, response = _SessionMgrService.soap_connect(self, ps)
90       
91        result = self.sm.connect(username=request.Username,
92                                                                 passphrase=request.Passphrase,
93                                                                 createServerSess=request.CreateServerSess)
94                                       
95        response.UserCert, response.UserPriKey, response.issuingCert, \
96                response.SessID = result
97                         
98        return request, response
99
100
101    def soap_disconnect(self, ps, **kw):
102        '''Disconnect and remove user's session
103       
104        @type ps: ZSI ParsedSoap
105        @param ps: client SOAP message
106        @rtype: tuple
107        @return: request and response objects'''
108        if self.__debug:
109                import pdb
110                pdb.set_trace()
111                           
112        request, response = _SessionMgrService.soap_disconnect(self, ps)
113       
114        # Derive designated user ID differently according to whether
115        # a session ID was passed and the message was signed
116        sessID = request.SessID or None
117               
118        if srv.sm['useSignatureHandler']:
119            # Get certificate corresponding to private key that signed the
120            # message - i.e. the user's proxy
121            userCert = WSSecurityHandler.signatureHandler.verifyingCert
122        else:
123            userCert = request.UserCert
124
125        self.sm.deleteUserSession(sessID=sessID, userCert=userCert)
126        return request, response
127
128
129    def soap_getSessionStatus(self, ps, **kw):
130        '''Check for existence of a session with given session ID or user
131        Distinguished Name
132       
133        @type ps: ZSI ParsedSoap
134        @param ps: client SOAP message
135        @rtype: tuple
136        @return: request and response objects'''
137
138        if self.__debug:
139                import pdb
140                pdb.set_trace()
141               
142        request, response = _SessionMgrService.soap_getSessionStatus(self, ps)
143       
144        response.IsAlive = self.sm.getSessionStatus(userDN=request.UserDN,
145                                                                                            sessID=request.SessID)
146                         
147        return request, response
148
149
150    def soap_getAttCert(self, ps, **kw):
151        '''Get Attribute Certificate from a given Attribute Authority
152        and cache it in user's Credential Wallet
153       
154        @type ps: ZSI ParsedSoap
155        @param ps: client SOAP message
156        @rtype: tuple
157        @return: request and response objects'''
158        if self.__debug:
159                import pdb
160                pdb.set_trace()
161               
162        request, response = _SessionMgrService.soap_getAttCert(self, ps)
163
164        # Get certificate corresponding to private key that signed the
165        # message - i.e. the user's             
166        if srv.sm['useSignatureHandler']:
167            # Get certificate corresponding to private key that signed the
168            # message - i.e. the user's proxy
169            userCert = WSSecurityHandler.signatureHandler.verifyingCert
170        else:
171            userCert = None
172       
173                # Cert used in signature is prefered over userCert input element -
174                # userCert may have been omitted.
175        result = self.sm.getAttCert(\
176                                            userCert=userCert or request.UserCert,
177                                                sessID=request.SessID,
178                                                aaURI=request.AttAuthorityURI,
179                                                reqRole=request.ReqRole,
180                                                mapFromTrustedHosts=request.MapFromTrustedHosts,
181                                                rtnExtAttCertList=request.RtnExtAttCertList,
182                                                extAttCertList=request.ExtAttCert,
183                                                extTrustedHostList=request.ExtTrustedHost)
184
185
186        if result[0]:
187                response.AttCert = result[0].toString() 
188               
189        response.Msg, response.ExtAttCertOut = result[1:]
190       
191        return request, response
192
193
194    def soap_getX509Cert(self, ps, **kw):
195        '''Return Session Manager's X.509 certificate
196       
197        @type ps: ZSI ParsedSoap
198        @param ps: client SOAP message
199        @rtype: tuple
200        @return: request and response objects'''       
201        if self.__debug:
202                import pdb
203                pdb.set_trace()
204               
205        request, response = _SessionMgrService.soap_getX509Cert(self, ps)
206
207        x509Cert = X509CertRead(srv.sm['certFile'])
208        response.X509Cert = base64.encodestring(x509Cert.asDER())
209        return request, response
210
211
212# Create Service
213srv = SessionMgrService()
214
215if srv.sm['useSignatureHandler']:
216        # Initialise WS-Security signature handler passing Session Manager
217        # public and private keys
218   
219    # Inclusive namespaces for Exclusive C14N
220        refC14nInclNS = srv.sm['wssRefInclNS']
221        signedInfoC14nInclNS = srv.sm['wssSignedInfoInclNS']
222
223        WSSecurityHandler.signatureHandler = SignatureHandler(\
224                                                        verifyingCertFilePath=srv.sm['clntCertFile'],
225                            signingCertFilePath=srv.sm['certFile'],
226                            signingPriKeyFilePath=srv.sm['keyFile'],
227                            signingPriKeyPwd=srv.sm['keyPwd'],
228                            caCertFilePathList=srv.sm.get('caCertFileList'),
229                                        refC14nInclNS=refC14nInclNS,
230                                        signedInfoC14nInclNS=signedInfoC14nInclNS,
231                                        applySignatureConfirmation=True)
232
233# Add Service to Session Manager branch
234root = Resource()
235root.putChild('SessionManager', srv)
236siteFactory = Site(root)
237
238if srv.sm['useSSL']:
239        # Use SSL connection
240        log.info("Running over https ...")     
241
242        # Using M2Crypto ...
243        import os
244        os.putenv("OPENSSL_ALLOW_PROXY_CERTS", "1")
245
246        import twisted.protocols.policies as policies
247        from M2Crypto import SSL
248        from M2Crypto.SSL import TwistedProtocolWrapper
249        from M2Crypto.SSL.TwistedProtocolWrapper import TLSProtocolWrapper
250       
251        siteFactory.startTLS = True
252        siteFactory.sslChecker = SSL.Checker.Checker()
253
254        # TODO: Python ssl client seems to require SSL vers 2 is this a security
255        # risk?
256        ctx = SSL.Context(protocol='sslv23')
257        ctx.set_cipher_list("NULL-MD5:ALL:!ADH:!EXP:@STRENGTH")
258        ctx.load_cert(srv.sm['sslCertFile'], 
259                          srv.sm['sslKeyFile'],
260                          callback=lambda *args, **kw: srv.sm['sslKeyPwd'])
261                         
262        ctx.set_allow_unknown_ca(False)
263
264    # TODO: resolve check - verify_peer setting fails with
265    # BIOError: 'no certificate returned' error 18
266#    ctx.set_verify(SSL.verify_peer, 10)
267        ctx.set_verify(SSL.verify_client_once, 1)
268
269        ctx.load_verify_locations(capath=srv.sm['sslCACertDir'])
270
271        class ContextFactory:
272            def getContext(self):
273                return ctx
274       
275        factory = policies.WrappingFactory(siteFactory)
276        factory.protocol.TLS = True
277        factory.protocol = lambda factory, wrappedProtocol: \
278            TLSProtocolWrapper(factory,
279                               wrappedProtocol,
280                               startPassThrough=0,
281                               client=0,
282                               contextFactory=ContextFactory(),
283                               postConnectionCheck=None)
284       
285        siteFactory = factory
286       
287        port = internet.TCPServer(srv.sm['portNum'], siteFactory)
288        port.CERTFILE = srv.sm['sslCertFile']
289        port.KEYFILE = srv.sm['sslKeyFile']
290        root.__class__.server = port
291else:   
292        # Non-SSL
293        log.info("Running over http ...")
294        port = internet.TCPServer(srv.sm['portNum'], siteFactory)
295
296application = service.Application("SessionManagerContainer")
297port.setServiceParent(application)
Note: See TracBrowser for help on using the repository browser.