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

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

Added sign and verify to wsServer but problems with canonicalization causing verify error. This seems to be
due to attribute order differences. These shouldn't happen given the same canonicalization method for
signature and verification but the could be a problem with the way that the DOM code creates the nodes in
sign() ?

sing was added to server side code by overriding SOAPRequestHandler.do_POST and making a custom _Dispatch
function.

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