Commit acd65a16 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

import/export: Validate remote host/port



The hostname and port received from the remote cluster should
be validated, just in case.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent 28f34048
......@@ -40,6 +40,7 @@ import math
from ganeti import constants
from ganeti import cli
from ganeti import utils
from ganeti import errors
from ganeti import serializer
from ganeti import objects
from ganeti import locking
......@@ -401,6 +402,16 @@ def ParseOptions():
# Won't return
parser.error("Invalid mode: %s" % mode)
# Normalize and check parameters
if options.host is not None:
try:
options.host = utils.HostInfo.NormalizeName(options.host)
except errors.OpPrereqError, err:
parser.error("Invalid hostname '%s': %s" % (options.host, err))
if options.port is not None:
options.port = utils.ValidateServiceName(options.port)
if (options.exp_size is not None and
options.exp_size != constants.IE_CUSTOM_SIZE):
try:
......
......@@ -9100,6 +9100,7 @@ class LUExportInstance(LogicalUnit):
_CheckNodeNotDrained(self, self.dst_node.name)
self._cds = None
self.dest_disk_info = None
self.dest_x509_ca = None
elif self.export_mode == constants.EXPORT_MODE_REMOTE:
......@@ -9139,13 +9140,20 @@ class LUExportInstance(LogicalUnit):
self.dest_x509_ca = cert
# Verify target information
disk_info = []
for idx, disk_data in enumerate(self.op.target_node):
try:
masterd.instance.CheckRemoteExportDiskInfo(cds, idx, disk_data)
(host, port) = masterd.instance.CheckRemoteExportDiskInfo(cds, idx,
disk_data)
except errors.GenericError, err:
raise errors.OpPrereqError("Target info for disk %s: %s" % (idx, err),
errors.ECODE_INVAL)
disk_info.append((host, port))
assert len(disk_info) == len(self.op.target_node)
self.dest_disk_info = disk_info
else:
raise errors.ProgrammerError("Unhandled export mode %r" %
self.export_mode)
......@@ -9236,7 +9244,7 @@ class LUExportInstance(LogicalUnit):
opts = objects.ImportExportOptions(key_name=key_name,
ca_pem=dest_ca_pem)
(fin_resu, dresults) = helper.RemoteExport(opts, self.op.target_node,
(fin_resu, dresults) = helper.RemoteExport(opts, self.dest_disk_info,
timeouts)
finally:
helper.Cleanup()
......
......@@ -1239,8 +1239,8 @@ class ExportInstanceHelper:
ieloop = ImportExportLoop(self._lu)
try:
for idx, (dev, (host, port, _, _)) in enumerate(zip(instance.disks,
disk_info)):
for idx, (dev, (host, port)) in enumerate(zip(instance.disks,
disk_info)):
self._feedback_fn("Sending disk %s to %s:%s" % (idx, host, port))
finished_fn = compat.partial(self._TransferFinished, idx)
ieloop.Add(DiskExport(self._lu, instance.primary_node,
......@@ -1514,7 +1514,8 @@ def CheckRemoteExportDiskInfo(cds, disk_index, disk_info):
if not utils.VerifySha1Hmac(cds, msg, hmac_digest, salt=hmac_salt):
raise errors.GenericError("HMAC is wrong")
return (host, port)
return (utils.HostInfo.NormalizeName(host),
utils.ValidateServiceName(port))
def ComputeRemoteImportDiskInfo(cds, salt, disk_index, host, port):
......
......@@ -111,6 +111,20 @@ class TestRieDiskInfo(unittest.TestCase):
self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
cds, i, di)
def testInvalidHostPort(self):
cds = "3ZoJY8KtGJ"
salt = "drK5oYiHWD"
for host in [",", "...", "Hello World", "`", "!", "#", "\\"]:
di = ComputeRemoteImportDiskInfo(cds, salt, 0, host, 1234)
self.assertRaises(errors.OpPrereqError,
CheckRemoteExportDiskInfo, cds, 0, di)
for port in [-1, 792825908, "HelloWorld!", "`#", "\\\"", "_?_"]:
di = ComputeRemoteImportDiskInfo(cds, salt, 0, "localhost", port)
self.assertRaises(errors.OpPrereqError,
CheckRemoteExportDiskInfo, cds, 0, di)
def testCheckErrors(self):
cds = "0776450535a"
self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
......
......@@ -108,8 +108,21 @@ $impexpd $src_statusfile >/dev/null 2>&1 &&
$impexpd $src_statusfile invalidmode >/dev/null 2>&1 &&
err "daemon-util succeeded with invalid mode"
$impexpd $src_statusfile import --compression=rot13 >/dev/null 2>&1 &&
err "daemon-util succeeded with invalid compression"
for mode in import export; do
$impexpd $src_statusfile $mode --compression=rot13 >/dev/null 2>&1 &&
err "daemon-util succeeded with invalid compression"
for host in '' ' ' ' s p a c e' ... , foo.example.net... \
'some"evil"name' 'x\ny\tmoo'; do
$impexpd $src_statusfile $mode --host="$host" >/dev/null 2>&1 &&
err "daemon-util succeeded with invalid host '$host'"
done
for port in '' ' ' -1234 'some ` port " here'; do
$impexpd $src_statusfile $mode --port="$port" >/dev/null 2>&1 &&
err "daemon-util succeeded with invalid port '$port'"
done
done
upto 'Generate test data'
cat $(get_testfile proc_drbd8.txt) $(get_testfile cert1.pem) > $testdata
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment