source: TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/WS-Security/wsServer.py @ 7080

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/WS-Security/wsServer.py@7080
Revision 7080, 7.2 KB checked in by pjkersha, 9 years ago (diff)
  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2
3"""WS-Security test server
4
5NERC Data Grid Project
6
7P J Kershaw 01/09/06
8
9Copyright (C) 2009 Science and Technology Facilities Council
10
11"""
12
13__revision__ = '$Id$'
14
15import sys
16import socket
17
18# Web service interface
19from ZSI import *
20from ZSI.dispatch import SOAPRequestHandler, _client_binding
21from ZSI.auth import _auth_tc, AUTH, ClientBinding
22
23from BaseHTTPServer import HTTPServer
24
25from wsSecurity import *
26from wsInterface import *
27
28
29#_________________________________________________________________________
30def echo(ps):
31    """example service simply returns message sent to it"""
32   
33    request = ps.Parse(echoRequestWrapper)
34    response = echoResponseWrapper()   
35    response._message = request._message
36   
37    return response
38
39def _Dispatch(ps, modules, SendResponse, SendFault, docstyle=0,
40              nsdict={}, typesmodule=None, rpc=None, **kw):
41    '''Find a handler for the SOAP request in ps; search modules.
42    Call SendResponse or SendFault to send the reply back, appropriately.
43
44    Default Behavior -- Use "handler" method to parse request, and return
45       a self-describing request (w/typecode).
46
47    Other Behaviors:
48        docstyle -- Parse result into an XML typecode (DOM). Behavior, wrap result
49          in a body_root "Response" appended message.
50
51        rpc -- Specify RPC wrapper of result. Behavior, ignore body root (RPC Wrapper)
52           of request, parse all "parts" of message via individual typecodes.  Expect
53           response pyobj w/typecode to represent the entire message (w/RPC Wrapper),
54           else pyobj w/o typecode only represents "parts" of message.
55
56    '''
57   
58    # WS-Security handler called here
59#    signatureHandler = SignatureHandler(\
60#                            certFilePath='../../Junk-cert.pem',
61#                            priKeyFilePath='../../Junk-key.pem',
62#                            priKeyPwd=open('../../tmp2').read().strip())
63#    signatureHandler.verify(ps)
64    # Test decryption
65    encryptionHandler = EncryptionHandler(\
66                            certFilePath='../../Junk-cert.pem',
67                            priKeyFilePath='../../Junk-key.pem',
68                            priKeyPwd=open('../../tmp2').read().strip())
69    encryptionHandler.decrypt(ps)
70
71   
72    global _client_binding
73    try:
74        what = ps.body_root.localName
75
76        # See what modules have the element name.
77        if modules is None:
78            modules = ( sys.modules['__main__'], )
79
80        handlers = [ getattr(m, what) for m in modules if hasattr(m, what) ]
81        if len(handlers) == 0:
82            raise TypeError("Unknown method " + what)
83
84        # Of those modules, see who's callable.
85        handlers = [ h for h in handlers if callable(h) ]
86        if len(handlers) == 0:
87            raise TypeError("Unimplemented method " + what)
88        if len(handlers) > 1:
89            raise TypeError("Multiple implementations found: " + `handlers`)
90        handler = handlers[0]
91
92        _client_binding = ClientBinding(ps)
93        if docstyle:
94            result = handler(ps.body_root)
95            tc = TC.XML(aslist=1, pname=what + 'Response')
96        elif rpc is None:
97            # Not using typesmodule, expect
98            # result to carry typecode
99            result = handler(ps)
100            if hasattr(result, 'typecode') is False:
101                raise TypeError("Expecting typecode in result")
102            tc = result.typecode
103        else:
104            data = _child_elements(ps.body_root)
105            if len(data) == 0:
106                arg = []
107            else:
108                try:
109                    try:
110                        type = data[0].localName
111                        tc = getattr(typesmodule, type).typecode
112                    except Exception, e:
113                        tc = TC.Any()
114                    arg = [ tc.parse(e, ps) for e in data ]
115                except EvaluateException, e:
116                    SendFault(FaultFromZSIException(e), **kw)
117                    return
118            result = handler(*arg)
119            if hasattr(result, 'typecode'):
120                tc = result.typecode
121            else:
122                tc = TC.Any(aslist=1, pname=what + 'Response')
123                result = [ result ]
124
125               
126        sw = SoapWriter(nsdict=nsdict)
127       
128        sw.serialize(result, tc, rpc=rpc)
129         
130        # Test encryption handler independently of signature       
131#        signatureHandler = SignatureHandler(\
132#                                certFilePath='../../Junk-cert.pem',
133#                                priKeyFilePath='../../Junk-key.pem',
134#                                priKeyPwd=open('../../tmp2').read().strip())
135#        signatureHandler.sign(sw)
136        encryptionHandler = EncryptionHandler(\
137                                certFilePath='../../Junk-cert.pem',
138                                priKeyFilePath='../../Junk-key.pem',
139                                priKeyPwd=open('../../tmp2').read().strip())
140        encryptionHandler.encrypt(sw)
141       
142        return SendResponse(str(sw), **kw)
143   
144    except Exception, e:
145        # Something went wrong, send a fault.
146        return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)
147
148#_____________________________________________________________________________
149class EchoSOAPRequestHandler(SOAPRequestHandler):
150    """Implement to allow overloaded do_POST in order to handle WS-Security
151    for outbound messages"""
152 
153    def do_POST(self):
154        """Override default to allow custom dispatch call"""
155        try:
156            ct = self.headers['content-type']
157            if ct.startswith('multipart/'):
158                cid = resolvers.MIMEResolver(ct, self.rfile)
159                xml = cid.GetSOAPPart()
160                ps = ParsedSoap(xml, resolver=cid.Resolve)
161            else:
162                length = int(self.headers['content-length'])
163                ps = ParsedSoap(self.rfile.read(length))
164        except ParseException, e:
165            self.send_fault(FaultFromZSIException(e))
166            return
167        except Exception, e:
168            # Faulted while processing; assume it's in the header.
169            self.send_fault(FaultFromException(e, 1, sys.exc_info()[2]))
170            return
171       
172        _Dispatch(ps, self.server.modules, self.send_xml, self.send_fault,
173                  docstyle=self.server.docstyle, nsdict=self.server.nsdict,
174                  typesmodule=self.server.typesmodule, rpc=self.server.rpc)
175
176
177#_____________________________________________________________________________
178def AsServer(port=80, 
179             modules=None, 
180             docstyle=0, 
181             nsdict={}, 
182             typesmodule=None,
183             rpc=None,
184             **kw):
185   
186    address = ('', port)
187    httpd = HTTPServer(address, EchoSOAPRequestHandler)
188    httpd.modules = modules
189    httpd.docstyle = docstyle
190    httpd.nsdict = nsdict
191    httpd.typesmodule = typesmodule
192    httpd.rpc = rpc
193    httpd.serve_forever()
194
195
196if __name__ == '__main__':
197    print "Server listening ..."
198
199    try:
200        AsServer(port=8080)
201
202    except KeyboardInterrupt:
203        sys.exit(0)
204
205    except socket.error, e:
206        print >>sys.stderr, "Server socket error: %s" % e[1]
207        sys.exit(1)
208
209#    except Exception, e:
210#        print >>sys.stderr, "Server: %s" % e
211#        sys.exit(1)
Note: See TracBrowser for help on using the repository browser.