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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/Tests/xmlsec/WS-Security/wsServer.py@1510
Revision 1510, 7.2 KB checked in by pjkersha, 13 years ago (diff)

Working encryption handler. Note:

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