Signed-off-by: Kurt Garloff diff -uNrp xen-2.0-testing/tools/examples/xend-config.sxp xen-2.0-testing.secure/tools/examples/xend-config.sxp --- xen-2.0-testing/tools/examples/xend-config.sxp 2005-03-21 04:58:08.000000000 +0100 +++ xen-2.0-testing.secure/tools/examples/xend-config.sxp 2005-03-23 13:18:01.167841981 +0100 @@ -11,6 +11,15 @@ # Specifying the empty string '' allows all connections. (xend-address 'localhost') +# Set this to 1 to restrict the access to the xend port +# to connections from a privileged port (<1024); together +# with binding to localhost, this will restrict xen control +# to the root user in domain0. +# Note that the protection is not yet complete, consoles +# are not yet protected. Also, most read-only information +# ist still readable. +(xend-privileged-port 1) + # The port xend should start from when allocating a port # for a domain console. (console-port-base 9600) diff -uNrp xen-2.0-testing/tools/python/xen/xend/XendProtocol.py xen-2.0-testing.secure/tools/python/xen/xend/XendProtocol.py --- xen-2.0-testing/tools/python/xen/xend/XendProtocol.py 2005-03-21 04:58:03.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/XendProtocol.py 2005-03-23 13:13:25.686990578 +0100 @@ -1,6 +1,7 @@ # Copyright (C) 2004 Mike Wray import httplib +import socket import types from encode import * @@ -122,6 +123,43 @@ class XendClientProtocol: """ raise NotImplementedError() +class xenhttpconn(httplib.HTTPConnection): + """A httplib class with slightly modified connect function that + tries to grab a privileged source port. + """ + + def connect(self): + """Connect to the host and port specified in __init__.""" + msg = "getaddrinfo returns an empty list" + for res in socket.getaddrinfo(self.host, self.port, 0, + socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + try: + self.sock = socket.socket(af, socktype, proto) + if self.debuglevel > 0: + print "connect: (%s, %s)" % (self.host, self.port) + # Try to get a src port below 1024 + port = 732 + while port < 1024: + try: + self.sock.bind(("", port)) + except socket.error, msg: + port += 1 + else: + break + self.sock.connect(sa) + except socket.error, msg: + if self.debuglevel > 0: + print 'connect fail:', (self.host, self.port) + if self.sock: + self.sock.close() + self.sock = None + continue + break + if not self.sock: + raise socket.error, msg + + class SynchXendClientProtocol(XendClientProtocol): """A synchronous xend client. This will make a request, wait for the reply and return the result. @@ -137,7 +175,7 @@ class SynchXendClientProtocol(XendClient @param args: request arguments (dict) """ self.request = XendRequest(url, method, args) - conn = httplib.HTTPConnection(url.location()) + conn = xenhttpconn(url.location()) if DEBUG: conn.set_debuglevel(1) conn.request(method, url.fullpath(), self.request.data, self.request.headers) resp = conn.getresponse() diff -uNrp xen-2.0-testing/tools/python/xen/xend/XendRoot.py xen-2.0-testing.secure/tools/python/xen/xend/XendRoot.py --- xen-2.0-testing/tools/python/xen/xend/XendRoot.py 2005-03-21 04:58:04.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/XendRoot.py 2005-03-23 13:18:56.085242803 +0100 @@ -47,6 +47,9 @@ class XendRoot: """Default interface address xend listens at. """ xend_address_default = '' + """Default for xend-privileged """ + xend_privileged_port_default = 1 + """Default port xend serves HTTP at. """ xend_port_default = '8000' @@ -236,6 +239,12 @@ class XendRoot: """ return self.get_config_value('xend-address', self.xend_address_default) + def get_xend_privileged_port(self): + """Get the setting that controls whether xend only accepts connections + from privileged ports. + """ + return self.get_config_value('xend-privileged-port', self.xend_privileged_port_default) + def get_console_address(self): """Get the address xend listens at for its console ports. This defaults to the empty string which allows all hosts to connect. diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvConsole.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvConsole.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvConsole.py 2005-03-21 04:58:07.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvConsole.py 2005-03-23 13:13:25.634999664 +0100 @@ -17,9 +17,6 @@ class SrvConsole(SrvDir): val = self.xc.console_disconnect(self.info.console_port) return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): try: if self.use_sxp(req): @@ -32,7 +29,8 @@ class SrvConsole(SrvDir): req.write('

%s

' % self.info) req.write('

Connect to domain %d

' % (self.info.uri(), self.info.dom)) - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write('') return '' except Exception, ex: diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvDir.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDir.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvDir.py 2005-03-21 04:58:04.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDir.py 2005-03-23 13:19:35.073427804 +0100 @@ -8,6 +8,9 @@ from xen.xend.XendError import XendError from SrvBase import SrvBase +from xen.xend import XendRoot +xroot = XendRoot.instance() + class SrvError(error.ErrorPage): def render(self, request): @@ -84,7 +87,8 @@ class SrvDir(SrvBase): req.write('') self.print_path(req) self.ls(req) - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write('') return '' except Exception, ex: @@ -109,3 +113,22 @@ class SrvDir(SrvBase): def form(self, req): pass + + def render_POST(self, req): + if self.isAuthorized(req): + return self.perform(req) + else: + return self.unauthPage(req, "You need admin power.") + + def isAuthorized(self, req): + return (req.transport.client[1] < 1024 + or not int(xroot.get_xend_privileged_port())) + + def unauthPage(self, req, msg): + msg1 = "

Connected from %s:%i\n" % \ + (req.transport.client[0], req.transport.client[1]) + msg1 += "
Need to connect from privileged port " + msg1 += "or set (xend-privileged 0) in xend-config.sxp\n" + err = SrvError(http.UNAUTHORIZED, "UNAUTHORIZED", msg + msg1) + return err.render(req) + diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvDmesg.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDmesg.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvDmesg.py 2005-03-21 04:58:06.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDmesg.py 2005-03-23 13:13:25.647997393 +0100 @@ -15,10 +15,8 @@ class SrvDmesg(SrvDir): SrvDir.__init__(self) self.xd = XendDmesg.instance() - def render_POST(self, req): - self.perform(req) - def render_GET(self, req): + # No access restriction for now try: if self.use_sxp(req): req.setHeader("Content-Type", "text/plain") diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvDomain.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDomain.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvDomain.py 2005-03-21 04:58:10.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDomain.py 2005-03-23 13:13:25.615003159 +0100 @@ -193,9 +193,6 @@ class SrvDomain(SrvDir): val = fn(req.args, {'dom': self.dom.id}) return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): op = req.args.get('op') if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']: @@ -220,7 +217,8 @@ class SrvDomain(SrvDir): req.write("

")
                 PrettyPrint.prettyprint(self.dom.config, out=req)
                 req.write("
") - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write('') return '' diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvDomainDir.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDomainDir.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvDomainDir.py 2005-03-21 04:58:10.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvDomainDir.py 2005-03-23 13:13:25.597006304 +0100 @@ -116,9 +116,6 @@ class SrvDomainDir(SrvDir): out.close() return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): try: if self.use_sxp(req): @@ -129,7 +126,8 @@ class SrvDomainDir(SrvDir): self.print_path(req) self.ls(req) self.ls_domain(req) - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write("") return '' except Exception, ex: diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvNode.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvNode.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvNode.py 2005-03-21 04:58:09.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvNode.py 2005-03-23 13:14:34.391982867 +0100 @@ -37,9 +37,6 @@ class SrvNode(SrvDir): val = fn(req.args, {}) return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): try: if self.use_sxp(req): @@ -54,8 +51,9 @@ class SrvNode(SrvDir): req.write('') req.write('') return '' diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvVnetDir.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvVnetDir.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvVnetDir.py 2005-03-21 04:58:11.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvVnetDir.py 2005-03-23 13:13:25.641998441 +0100 @@ -18,9 +18,6 @@ class SrvVnet(SrvDir): val = self.xvnet.vnet_delete(self.vnetinfo.id) return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): if self.use_sxp(req): req.setHeader("Content-Type", sxp.mime_type) @@ -32,7 +29,8 @@ class SrvVnet(SrvDir): req.write("
")
             PrettyPrint.prettyprint(self.vnetinfo.sxpr(), out=req)
             req.write("
") - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write('') return '' @@ -71,9 +69,6 @@ class SrvVnetDir(SrvDir): val = fn(req.args, {}) return val - def render_POST(self, req): - return self.perform(req) - def render_GET(self, req): try: if self.use_sxp(req): @@ -84,7 +79,8 @@ class SrvVnetDir(SrvDir): self.print_path(req) self.ls(req) self.ls_vnet(req) - self.form(req) + if self.isAuthorized(req): + self.form(req) req.write("") return '' except Exception, ex: diff -uNrp xen-2.0-testing/tools/python/xen/xend/server/SrvXendLog.py xen-2.0-testing.secure/tools/python/xen/xend/server/SrvXendLog.py --- xen-2.0-testing/tools/python/xen/xend/server/SrvXendLog.py 2005-03-21 04:58:11.000000000 +0100 +++ xen-2.0-testing.secure/tools/python/xen/xend/server/SrvXendLog.py 2005-03-23 13:13:25.654996170 +0100 @@ -18,6 +18,7 @@ class SrvXendLog(SrvDir): self.logfile.encoding = None def render_GET(self, req): + # No access restriction for now try: return self.logfile.render(req) except Exception, ex: