# 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
|