def dispatch(self, req): path = req.uri[1:] if (path[-1] == "/"): path = path[:-1] if not configs.has_key(path): if req.method == "POST": self.send_fault( Fault(Fault.Client, "Unknown Database Path %s" % (repr(configs.keys()))), req) else: # Construct simple table of contents page xml = ['<databases>'] for k in configs: xml.append("<database><path>%s</path></database>" % k) xml.append('</databases>') txt = ''.join(xml) self.send_xml(txt, req) else: xreq = None config = configs[path] if (req.method == "POST"): try: data = req.read() dstr = StringIO.StringIO(data) ps = ParsedSoap(dstr, readerclass=reader) except Exception, e: try: self.send_fault(FaultFromException(e, 0), req) except Exception, e: self.send_fault(FaultFromException(e, 0), req) return callname = ps.body_root.localName classname = callname[0].upper() + callname[1:] try: try: mod = SRW.protocolModules[ps.body_root.namespaceURI] except KeyError: log("%r -> %r" % (ps.body_root.namespaceURI, data)) self.send_fault(Fault(Fault.Client, 'Bad Namespace'), req) return config = config[ps.body_root.namespaceURI] objType = getattr(mod, classname) xreq = ps.Parse(objType) xreq.configure(config) xreq.calledAt = path result = self.call(xreq) except AttributeError, err: # result = self.processUnknownOperation(classname, err, config) self.send_fault( Fault(Fault.Client, 'Unknown Operation (%s)' % str(err)), req) return
def do_POST(self): """The POST command.""" chunked = False # If the headers indicate chunked transfer encoding, fake # a Content-Length header field that matches the first chunk. try: te = self.headers['transfer-encoding'] if te.startswith('chunked'): chunked = True length = int(self.rfile.readline(), 16) if length > 0: self.headers['content-length'] = length pass pass pass except: pass # Process the request. SOAPRequestHandler.do_POST(self) # If we're using chunked transfer encoding, check for the last chunk. if chunked: crlf = self.rfile.readline() length = int(self.rfile.readline(), 16) if not length == 0: self.send_fault(Fault(500, "Cannot handle multiple chunks")) pass pass pass
def AsQuery(): '''Handle the Amazon QUERY interface''' try: form = cgi.FieldStorage() args = {} signStr = "" for var in form: args[var] = form[var].value if (var != "Signature"): signStr += var + args[var] log("[QUERY] %s=%s\n" % (var, args[var])) secretKey = userDict[args['AWSAccessKeyId']][0] calculatedSig = base64.b64encode(hmac.new(secretKey, signStr, hashlib.sha1).digest()) if (args['Signature'] != calculatedSig): _CGISendFault(Fault(Fault.Client, 'Could not authenticate')) return tashi.aws.util.authorizedUser = userDict[args['AWSAccessKeyId']][1] log("[AUTH] authorizedUser = %s\n" % (tashi.aws.util.authorizedUser)) functionName = args['Action'] res = eval("%s(args)" % (functionName)) _CGISendXML(res) except Exception, e: _CGISendFault(Fault(Fault.Client, str(e)))
def validate(self, xml): '''A simple blob of code that validates the xmldsig in an xml string using xmlsec1''' doc = minidom.parseString(xml) tokens = doc.getElementsByTagName("wsse:BinarySecurityToken") if (len(tokens) != 1): return -1 token = tokens[0] if (len(token.childNodes) != 1): return -1 childNode = token.childNodes[0] if (not getattr(childNode, 'wholeText', None)): return -1 cert = childNode.wholeText CERT_DIGEST = md5.md5(cert).hexdigest() log("[AUTH] CERT_DIGEST=%s\n" % (CERT_DIGEST)) output = xml ofile = "/tmp/%5.5d.%s.xml" % (os.getpid(), md5.md5(output).hexdigest()) f2 = open(ofile, "w") f2.write(output) f2.close() # XXXpipe: what are we doing here? (stdin, stdout) = os.popen4( "xmlsec1 --verify --id-attr:Id Timestamp --id-attr:Id Body --pubkey-cert-pem /var/lib/tashi-ec2/%s.crt --print-debug %s" % (CERT_DIGEST, ofile)) stdin.close() res = stdout.read() stdout.close() os.unlink(ofile) verified = False lines = res.split("\n") cmpRe = re.compile('==== Subject Name: (.*)') for line in lines: if (line.strip() == "OK"): verified = True res = cmpRe.match(line) if (res): varStrs = res.groups()[0].split("/") for var in varStrs: (key, sep, val) = var.partition("=") if (key != '' and val != ''): vars[key] = val if (not verified): _CGISendFault(Fault(Fault.Client, 'Could not authenticate')) return verified tashi.aws.util.authorizedUser = vars.get('CN', 'UNKNOWN') log("[AUTH] authorizedUser = %s\n" % (tashi.aws.util.authorizedUser)) return verified
def AsCGI(nsdict={}, typesmodule=None, rpc=False, modules=None): '''Dispatch within a CGI script. ''' if os.environ.get('REQUEST_METHOD') != 'POST': _CGISendFault(Fault(Fault.Client, 'Must use POST')) return ct = os.environ['CONTENT_TYPE'] try: if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, sys.stdin) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(os.environ['CONTENT_LENGTH']) ps = ParsedSoap(sys.stdin.read(length)) except ParseException as e: _CGISendFault(FaultFromZSIException(e)) return _Dispatch(ps, modules, _CGISendXML, _CGISendFault, nsdict=nsdict, typesmodule=typesmodule, rpc=rpc)
def AsJonPy(request=None, modules=None, **kw): '''Dispatch within a jonpy CGI/FastCGI script. ''' kw['request'] = request if request.environ.get('REQUEST_METHOD') != 'POST': _JonPySendFault(Fault(Fault.Client, 'Must use POST'), **kw) return ct = request.environ['CONTENT_TYPE'] try: if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, request.stdin) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(request.environ['CONTENT_LENGTH']) ps = ParsedSoap(request.stdin.read(length)) except ParseException as e: _JonPySendFault(FaultFromZSIException(e), **kw) return _Dispatch(ps, modules, _JonPySendXML, _JonPySendFault, **kw)
def WSDLFaultFromException(ex, inheader, tb=None, actor=None): '''Return a Fault object created from a Python exception. <SOAP-ENV:Fault> <faultcode>SOAP-ENV:Server</faultcode> <faultstring>Processing Failure</faultstring> <detail> <ZSI:FaultDetail> <ZSI:string></ZSI:string> <ZSI:trace></ZSI:trace> </ZSI:FaultDetail> </detail> </SOAP-ENV:Fault> ''' tracetext = None if tb: try: lines = '\n'.join(['%s:%d:%s' % (name, line, func) for name, line, func, text in traceback.extract_tb(tb)]) except: pass else: tracetext = lines exceptionName = "" try: exceptionName = ":".join([ex.__module__, ex.__class__.__name__]) except: pass if isinstance(ex, Fault): return ex elt = ZSIFaultDetail(string=exceptionName + "\n" + str(ex), trace=tracetext) if inheader: detail, headerdetail = None, elt else: detail, headerdetail = elt, None return Fault(Fault.Server, 'Processing Failure', actor, detail, headerdetail)
class reqHandler: def send_xml(self, text, req, code=200): req.content_type = 'text/xml' req.content_length = len(text) req.send_http_header() req.write(text) def send_fault(self, f, req): self.send_xml(f.AsSOAP(), req, 500) def processUnknownOperation(self, operation, err, config): result = SRW.types.ExplainResponse('explainResponse') req = SRW.types.ExplainRequest('explainRequest', opts={ 'recordPacking': 'xml', 'version': "1.1" }, config=config) result.processQuery(session, req) if isinstance(err, SRWDiagnostics.SRWDiagnostic): result.diagnostics = [err] else: diag = SRWDiagnostics.Diagnostic4() diag.uri = diag.uri diag.details = operation + ": " + str(err) diag.message = diag.message result.diagnostics = [diag] return result def dispatch(self, req): path = req.uri[1:] if (path[-1] == "/"): path = path[:-1] if not configs.has_key(path): if req.method == "POST": self.send_fault( Fault(Fault.Client, "Unknown Database Path %s" % (repr(configs.keys()))), req) else: # Construct simple table of contents page xml = ['<databases>'] for k in configs: xml.append("<database><path>%s</path></database>" % k) xml.append('</databases>') txt = ''.join(xml) self.send_xml(txt, req) else: xreq = None config = configs[path] if (req.method == "POST"): try: data = req.read() dstr = StringIO.StringIO(data) ps = ParsedSoap(dstr, readerclass=reader) except Exception, e: try: self.send_fault(FaultFromException(e, 0), req) except Exception, e: self.send_fault(FaultFromException(e, 0), req) return callname = ps.body_root.localName classname = callname[0].upper() + callname[1:] try: try: mod = SRW.protocolModules[ps.body_root.namespaceURI] except KeyError: log("%r -> %r" % (ps.body_root.namespaceURI, data)) self.send_fault(Fault(Fault.Client, 'Bad Namespace'), req) return config = config[ps.body_root.namespaceURI] objType = getattr(mod, classname) xreq = ps.Parse(objType) xreq.configure(config) xreq.calledAt = path result = self.call(xreq) except AttributeError, err: # result = self.processUnknownOperation(classname, err, config) self.send_fault( Fault(Fault.Client, 'Unknown Operation (%s)' % str(err)), req) return except Exception, err: self.send_fault( Fault(Fault.Client, 'Broken request %s: (%s)' % (err, data)), req) return
except AttributeError, err: result = self.processUnknownOperation( operation, err, config) reply = StringIO.StringIO() if (req.method == "GET"): sw = SoapWriter(reply, envelope=0) else: sw = SoapWriter(reply, nsdict=SRW.protocolNamespaces) try: sw.serialize(result, inline=1) sw.close() text = reply.getvalue() except Exception, err: self.send_fault(Fault(Fault.Client, 'Busted (%s)' % str(err)), req) return if (req.method == "GET"): if xreq and hasattr(xreq, 'stylesheet') and xreq.stylesheet: headerText = u'<?xml version="1.0"?>\n<?xml-stylesheet type="text/xsl" href="%s"?>\n' % ( xreq.stylesheet) elif xreq and hasattr( xreq, 'defaultStylesheet') and xreq.defaultStylesheet: headerText = u'<?xml version="1.0"?>\n<?xml-stylesheet type="text/xsl" href="%s"?>\n' % ( xreq.defaultStylesheet) else: headerText = u"" text = text.replace(
address.parse(ps) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if action and action != address.getAction(): e = WSActionException('SOAP Action("%s") must match WS-Action("%s") if specified.' \ %(action,address.getAction())) return SendFault(FaultFromException(e, 0, None), **kw) action = address.getAction() if isinstance(service, ServiceInterface) is False: e = NoSuchService('no service at POST(%s) in container: %s' % (post, server)) return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if not service.authorize(None, post, action): return SendFault(Fault(Fault.Server, "Not authorized"), code=401) #try: # raise NotAuthorized() #except Exception, e: #return SendFault(FaultFromException(e, 0, None), code=401, **kw) ##return SendFault(FaultFromException(NotAuthorized(), 0, None), code=401, **kw) try: method = service.getOperation(ps, address) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) try: if isWSResource is True: request, result = method(ps, address) else:
def _Dispatch(ps, server, SendResponse, SendFault, post, action, nsdict={}, **kw): '''Send ParsedSoap instance to ServiceContainer, which dispatches to appropriate service via post, and method via action. Response is a self-describing pyobj, which is passed to a SoapWriter. Call SendResponse or SendFault to send the reply back, appropriately. server -- ServiceContainer instance ''' localURL = 'http://%s:%d%s' % (server.server_name, server.server_port, post) address = action service = server.getNode(post) isWSResource = False if isinstance(service, WSAResource): isWSResource = True service.setServiceURL(localURL) address = Address() try: address.parse(ps) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if action and action != address.getAction(): e = WSActionException('SOAP Action("%s") must match WS-Action("%s") if specified.' \ %(action,address.getAction())) return SendFault(FaultFromException(e, 0, None), **kw) action = address.getAction() if isinstance(service, ServiceInterface) is False: e = NoSuchService('no service at POST(%s) in container: %s' % (post, server)) return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if not service.authorize(None, post, action): return SendFault(Fault(Fault.Server, "Not authorized"), code=401) #try: # raise NotAuthorized() #except Exception, e: #return SendFault(FaultFromException(e, 0, None), code=401, **kw) ##return SendFault(FaultFromException(NotAuthorized(), 0, None), code=401, **kw) try: method = service.getOperation(ps, address) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) try: if isWSResource is True: _, result = method(ps, address) else: _, result = method(ps) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Verify if Signed service.verify(ps) # If No response just return. if result is None: return SendResponse('', **kw) sw = SoapWriter(nsdict=nsdict) try: sw.serialize(result) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if isWSResource is True: action = service.getResponseAction(ps, action) addressRsp = Address(action=action) try: addressRsp.setResponseFromWSAddress(address, localURL) addressRsp.serialize(sw) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Create Signatures service.sign(sw) try: soapdata = str(sw) return SendResponse(soapdata, **kw) except Exception as e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)