import BaseHTTPServer
import SimpleHTTPServer
import SimpleXMLRPCServer
-import xmlrpclib
-import string
-# SOAP support is optional
-try:
- import SOAPpy
- from SOAPpy.Parser import parseSOAPRPC
- from SOAPpy.Types import faultType
- from SOAPpy.NS import NS
- from SOAPpy.SOAPBuilder import buildSOAP
-except ImportError:
- SOAPpy = None
-
-from cert import *
-from credential import *
-
import socket, os
from OpenSSL import SSL
-
-# See "2.2 Characters" in the XML specification:
-#
-# #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
-# avoiding
-# [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF]
-
-invalid_xml_ascii = map(chr, range(0x0, 0x8) + [0xB, 0xC] + range(0xE, 0x1F))
-xml_escape_table = string.maketrans("".join(invalid_xml_ascii), "?" * len(invalid_xml_ascii))
-
-def xmlrpclib_escape(s, replace = string.replace):
- """
- xmlrpclib does not handle invalid 7-bit control characters. This
- function augments xmlrpclib.escape, which by default only replaces
- '&', '<', and '>' with entities.
- """
-
- # This is the standard xmlrpclib.escape function
- s = replace(s, "&", "&")
- s = replace(s, "<", "<")
- s = replace(s, ">", ">",)
-
- # Replace invalid 7-bit control characters with '?'
- return s.translate(xml_escape_table)
-
-def xmlrpclib_dump(self, value, write):
- """
- xmlrpclib cannot marshal instances of subclasses of built-in
- types. This function overrides xmlrpclib.Marshaller.__dump so that
- any value that is an instance of one of its acceptable types is
- marshalled as that type.
-
- xmlrpclib also cannot handle invalid 7-bit control characters. See
- above.
- """
-
- # Use our escape function
- args = [self, value, write]
- if isinstance(value, (str, unicode)):
- args.append(xmlrpclib_escape)
-
- try:
- # Try for an exact match first
- f = self.dispatch[type(value)]
- except KeyError:
- # Try for an isinstance() match
- for Type, f in self.dispatch.iteritems():
- if isinstance(value, Type):
- f(*args)
- return
- raise TypeError, "cannot marshal %s objects" % type(value)
- else:
- f(*args)
-
-xmlrpclib.Marshaller._Marshaller__dump = xmlrpclib_dump
+from geni.util.cert import *
+from geni.util.credential import *
+from geni.util.excep import *
+from geni.util.faults import *
+from geni.util.api import GeniAPI
+from geni.util.debug import log
##
# Verification callback for pyOpenSSL. We do our own checking of keys because
print " error", err, "in verify_callback"
- return 0\r
+ return 0
##
# Taken from the web (XXX find reference). Implements an HTTPS xmlrpc server
It it very similar to SimpleXMLRPCServer but it uses HTTPS for transporting XML data.
"""
self.logRequests = logRequests
-
+ self.interface = None
+ self.key_file = key_file
+ self.cert_file = cert_file
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, True, None)
SocketServer.BaseServer.__init__(self, server_address, HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
It it very similar to SimpleXMLRPCRequestHandler but it uses HTTPS for transporting XML data.
"""
def setup(self):
- self.encoding = "utf-8"
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
- def handleXMLRPCSOAP(self, source, data):
- """
- Handle an XML-RPC or SOAP request from the specified source.
- """
-
- # Parse request into method name and arguments
- try:
- interface = xmlrpclib
- (args, method) = xmlrpclib.loads(data)
- methodresponse = True
- except Exception, e:
- if SOAPpy is not None:
- interface = SOAPpy
- (r, header, body, attrs) = parseSOAPRPC(data, header = 1, body = 1, attrs = 1)
- method = r._name
- args = r._aslist()
- # XXX Support named arguments
- else:
- raise e
-
- try:
- result = self.server._marshaled_dispatch(data, getattr(self, '_dispatch', None))
- except Exception, fault:
- # Handle expected faults
- if interface == xmlrpclib:
- result = fault
- methodresponse = None
- elif interface == SOAPpy:
- result = faultParameter(NS.ENV_T + ":Server", "Method Failed", method)
- result._setDetail("Fault: %s" % (fault))
-
-
- # Return result
- if interface == xmlrpclib:
- # XX Shouldnt we be dumping xmlrpc here
- #result = (result,)
- #data = xmlrpclib.dumps(result, methodresponse = True, encoding = self.encoding, allow_none = 1)
- data = result
- elif interface == SOAPpy:
- data = buildSOAP(kw = {'%sResponse' % method: {'Result': result}}, encoding = self.encoding)
-
- return data
-
def do_POST(self):
"""Handles the HTTPS POST request.
It was copied out from SimpleXMLRPCServer.py and modified to shutdown the socket cleanly.
"""
-
+ self.api = GeniAPI(peer_cert = self.server.peer_cert, interface = self.server.interface, key_file = self.server.key_file, cert_file = self.server.cert_file)
try:
# get arguments
request = self.rfile.read(int(self.headers["content-length"]))
- response = self.handleXMLRPCSOAP(None, request)
-
# In previous versions of SimpleXMLRPCServer, _dispatch
# could be overridden in this class, instead of in
# SimpleXMLRPCDispatcher. To maintain backwards compatibility,
# check to see if a subclass implements _dispatch and dispatch
# using that method if present.
#response = self.server._marshaled_dispatch(request, getattr(self, '_dispatch', None))
- except: # This should only happen if the module is buggy
+ # XX TODO: Need to get the real remote address
+ source = None
+ response = self.api.handle(source, request)
+
+
+ except Exception, fault:
+ # This should only happen if the module is buggy
# internal error, report as HTTP server error
self.send_response(500)
-
self.end_headers()
else:
# got a valid XML RPC response
self.trusted_cert_list = None
self.register_functions()
- ##
- # Decode the credential string that was submitted by the caller. Several
- # checks are performed to ensure that the credential is valid, and that the
- # callerGID included in the credential matches the caller that is
- # connected to the HTTPS connection.
-
- def decode_authentication(self, cred_string, operation):
- self.client_cred = Credential(string = cred_string)
- self.client_gid = self.client_cred.get_gid_caller()
- self.object_gid = self.client_cred.get_gid_object()
-
- # make sure the client_gid is not blank
- if not self.client_gid:
- raise MissingCallerGID(self.client_cred.get_subject())
-
- # make sure the client_gid matches client's certificate
- peer_cert = self.server.peer_cert
- if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
- raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
-
- # make sure the client is allowed to perform the operation
- if operation:
- if not self.client_cred.can_perform(operation):
- raise InsufficientRights(operation)
-
- if self.trusted_cert_list:
- self.client_cred.verify_chain(self.trusted_cert_list)
- if self.client_gid:
- self.client_gid.verify_chain(self.trusted_cert_list)
- if self.object_gid:
- self.object_gid.verify_chain(self.trusted_cert_list)
##
# Register functions that will be served by the XMLRPC server. This