[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Implement an "allowed hosts" mechanism for the XML-RPC server layer, using
# HG changeset patch # User Ewan Mellor <ewan@xxxxxxxxxxxxx> # Node ID 6206685650f582d79f4b84f2b4d35d886cccdff0 # Parent b4baf35cff112b60c5f7d077e2c23d97e9480cf8 Implement an "allowed hosts" mechanism for the XML-RPC server layer, using code from the relocation protocol handling and some plumbing. Add a new configuration entry for the Xen-API server, including use of this mechanism. Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx> --- tools/examples/xend-config.sxp | 26 ++++++++++++++++++++++++++ tools/python/xen/util/xmlrpclib2.py | 27 ++++++++++++++++++++++----- tools/python/xen/web/connection.py | 16 +++++++++++++++- tools/python/xen/web/tcp.py | 14 ++------------ tools/python/xen/xend/XendRoot.py | 9 +++++++++ tools/python/xen/xend/server/SrvServer.py | 24 ++++++++++++++++++++++++ tools/python/xen/xend/server/XMLRPCServer.py | 13 +++++++++++-- 7 files changed, 109 insertions(+), 20 deletions(-) diff -r b4baf35cff11 -r 6206685650f5 tools/examples/xend-config.sxp --- a/tools/examples/xend-config.sxp Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/examples/xend-config.sxp Tue Nov 28 10:23:34 2006 +0000 @@ -13,6 +13,32 @@ #(logfile /var/log/xen/xend.log) #(loglevel DEBUG) + +# The Xen-API server configuration. (Please note that this server is available +# as an UNSUPPORTED PREVIEW in Xen 3.0.4, and should not be relied upon). +# +# This value configures the ports, interfaces, and access controls for the +# Xen-API server. Each entry in the list starts with either unix, a port +# number, or an address:port pair. If this is "unix", then a UDP socket is +# opened, and this entry applies to that. If it is a port, then Xend will +# listen on all interfaces on that TCP port, and if it is an address:port pair, +# then Xend will listen on the specified port, using the interface with the +# specified address. +# +# The subsequent string gives the access control for the listener in question. +# If this is missing or empty, then all connections are accepted. +# Otherwise, this should be a space-separated sequence of regular expressions; +# any host with a fully-qualified domain name or an IP address that matches one +# of these regular expressions will be accepted. +# +# Example: +# +# Listen on TCP port 9363 on all interfaces, accepting connections only from +# machines in example.com or localhost. +# (xen-api-server ((9363 '^localhost$ example\\.com$'))) +# +# Default: +# (xen-api-server ((unix))) #(xend-http-server no) #(xend-unix-server no) diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/util/xmlrpclib2.py Tue Nov 28 10:23:34 2006 +0000 @@ -30,6 +30,7 @@ import SocketServer import SocketServer import xmlrpclib, socket, os, stat +from xen.web import connection from xen.xend.XendLogging import log try: @@ -70,6 +71,11 @@ class XMLRPCRequestHandler(SimpleXMLRPCR class XMLRPCRequestHandler(SimpleXMLRPCRequestHandler): protocol_version = "HTTP/1.1" + def __init__(self, hosts_allowed, request, client_address, server): + self.hosts_allowed = hosts_allowed + SimpleXMLRPCRequestHandler.__init__(self, request, client_address, + server) + # this is inspired by SimpleXMLRPCRequestHandler's do_POST but differs # in a few non-trivial ways # 1) we never generate internal server errors. We let the exception @@ -77,6 +83,11 @@ class XMLRPCRequestHandler(SimpleXMLRPCR # 2) we don't bother checking for a _dispatch function since we don't # use one def do_POST(self): + addrport = self.client_address + if not connection.hostAllowed(addrport, self.hosts_allowed): + self.connection.shutdown(1) + return + data = self.rfile.read(int(self.headers["content-length"])) rsp = self.server._marshaled_dispatch(data) @@ -150,9 +161,14 @@ class TCPXMLRPCServer(SocketServer.Threa class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): allow_reuse_address = True - def __init__(self, addr, requestHandler=XMLRPCRequestHandler, + def __init__(self, addr, allowed, requestHandler=None, logRequests = 1): - SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests) + if requestHandler is None: + requestHandler = XMLRPCRequestHandler + SimpleXMLRPCServer.__init__(self, addr, + (lambda x, y, z: + requestHandler(allowed, x, y, z)), + logRequests) flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) flags |= fcntl.FD_CLOEXEC @@ -217,7 +233,7 @@ class UnixXMLRPCServer(TCPXMLRPCServer): class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX - def __init__(self, addr, logRequests = 1): + def __init__(self, addr, allowed, logRequests = 1): parent = os.path.dirname(addr) if os.path.exists(parent): os.chown(parent, os.geteuid(), os.getegid()) @@ -226,5 +242,6 @@ class UnixXMLRPCServer(TCPXMLRPCServer): os.unlink(addr) else: os.makedirs(parent, stat.S_IRWXU) - TCPXMLRPCServer.__init__(self, addr, UnixXMLRPCRequestHandler, - logRequests) + + TCPXMLRPCServer.__init__(self, addr, allowed, + UnixXMLRPCRequestHandler, logRequests) diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/web/connection.py --- a/tools/python/xen/web/connection.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/web/connection.py Tue Nov 28 10:23:34 2006 +0000 @@ -24,6 +24,8 @@ import fcntl from errno import EAGAIN, EINTR, EWOULDBLOCK +from xen.xend.XendLogging import log + """General classes to support server and client sockets, without specifying what kind of socket they are. There are subclasses for TCP and unix-domain sockets (see tcp.py and unix.py). @@ -76,7 +78,7 @@ class SocketListener: Accepts connections and runs a thread for each one. """ - def __init__(self, protocol_class, hosts_allow = ''): + def __init__(self, protocol_class): self.protocol_class = protocol_class self.sock = self.createSocket() threading.Thread(target=self.main).start() @@ -111,3 +113,15 @@ class SocketListener: break finally: self.close() + + +def hostAllowed(addrport, hosts_allowed): + if hosts_allowed is None: + return True + else: + fqdn = socket.getfqdn(addrport[0]) + for h in hosts_allowed: + if h.match(fqdn) or h.match(addrport[0]): + return True + log.warn("Rejected connection from %s (%s).", addrport[0], fqdn) + return False diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/web/tcp.py --- a/tools/python/xen/web/tcp.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/web/tcp.py Tue Nov 28 10:23:34 2006 +0000 @@ -57,20 +57,10 @@ class TCPListener(connection.SocketListe def acceptConnection(self, sock, addrport): addr = addrport[0] - if self.hosts_allow is None: - connection.SocketServerConnection(sock, self.protocol_class) + if connection.hostAllowed(addrport, self.hosts_allow): + connection.SocketServerConnection(sock, self.protocol_class) else: - fqdn = socket.getfqdn(addr) - for h in self.hosts_allow: - if h.match(fqdn) or h.match(addr): - log.debug("Match %s %s", fqdn, h.pattern) - connection.SocketServerConnection(sock, - self.protocol_class) - return - try: - log.warn("Rejected connection from %s:%d (%s) for port %d.", - addr, addrport[1], fqdn, self.port) sock.close() except: pass diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/xend/XendRoot.py --- a/tools/python/xen/xend/XendRoot.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/xend/XendRoot.py Tue Nov 28 10:23:34 2006 +0000 @@ -53,6 +53,9 @@ class XendRoot: """Default level of information to be logged.""" loglevel_default = 'DEBUG' + + """Default Xen-API server configuration. """ + xen_api_server_default = [['unix']] """Default for the flag indicating whether xend should run an http server (deprecated).""" @@ -189,6 +192,12 @@ class XendRoot: except Exception: raise XendError("invalid xend config %s: expected int: %s" % (name, v)) + def get_xen_api_server(self): + """Get the Xen-API server configuration. + """ + return self.get_config_value('xen-api-server', + self.xen_api_server_default) + def get_xend_http_server(self): """Get the flag indicating whether xend should run an http server. """ diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/xend/server/SrvServer.py Tue Nov 28 10:23:34 2006 +0000 @@ -41,6 +41,7 @@ # todo Support command-line args. import fcntl +import re import time import signal from threading import Thread @@ -148,6 +149,29 @@ def create(): log.info('unix path=' + path) servers.add(UnixHttpServer(root, path)) + api_cfg = xroot.get_xen_api_server() + if api_cfg: + try: + addrs = [(str(x[0]).split(':'), + len(x) > 1 and x[1] and map(re.compile, x[1].split(" ")) + or None) + for x in api_cfg] + for addrport, allowed in addrs: + if len(addrport) == 1: + if addrport[0] == 'unix': + servers.add(XMLRPCServer(allowed = allowed)) + else: + servers.add(XMLRPCServer(True, '', int(addrport[0]), + allowed = allowed)) + else: + addr, port = addrport + servers.add(XMLRPCServer(True, addr, int(port), + allowed = allowed)) + except ValueError: + log.error('Xen-API server configuration %s is invalid' % api_cfg) + except TypeError: + log.error('Xen-API server configuration %s is invalid' % api_cfg) + if xroot.get_xend_tcp_xmlrpc_server(): servers.add(XMLRPCServer(True)) diff -r b4baf35cff11 -r 6206685650f5 tools/python/xen/xend/server/XMLRPCServer.py --- a/tools/python/xen/xend/server/XMLRPCServer.py Tue Nov 28 09:51:05 2006 +0000 +++ b/tools/python/xen/xend/server/XMLRPCServer.py Tue Nov 28 10:23:34 2006 +0000 @@ -85,11 +85,12 @@ exclude = ['domain_create', 'domain_rest class XMLRPCServer: def __init__(self, use_tcp=False, host = "localhost", port = 8006, - path = XML_RPC_SOCKET): + path = XML_RPC_SOCKET, hosts_allowed = None): self.use_tcp = use_tcp self.port = port self.host = host self.path = path + self.hosts_allowed = hosts_allowed self.ready = False self.running = True @@ -97,10 +98,18 @@ class XMLRPCServer: def run(self): if self.use_tcp: + log.info("Opening TCP XML-RPC server on %s%d.", + self.host and '%s:' % self.host or + 'all interfaces, port ', + self.port) self.server = TCPXMLRPCServer((self.host, self.port), + self.hosts_allowed, logRequests = False) else: - self.server = UnixXMLRPCServer(self.path, logRequests = False) + log.info("Opening Unix domain socket XML-RPC server on %s:%d.", + self.path) + self.server = UnixXMLRPCServer(self.path, self.hosts_allowed, + logRequests = False) # Register Xen API Functions # ------------------------------------------------------------------- _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |