Revision acd65a16

b/daemons/import-export
40 40
from ganeti import constants
41 41
from ganeti import cli
42 42
from ganeti import utils
43
from ganeti import errors
43 44
from ganeti import serializer
44 45
from ganeti import objects
45 46
from ganeti import locking
......
401 402
    # Won't return
402 403
    parser.error("Invalid mode: %s" % mode)
403 404

  
405
  # Normalize and check parameters
406
  if options.host is not None:
407
    try:
408
      options.host = utils.HostInfo.NormalizeName(options.host)
409
    except errors.OpPrereqError, err:
410
      parser.error("Invalid hostname '%s': %s" % (options.host, err))
411

  
412
  if options.port is not None:
413
    options.port = utils.ValidateServiceName(options.port)
414

  
404 415
  if (options.exp_size is not None and
405 416
      options.exp_size != constants.IE_CUSTOM_SIZE):
406 417
    try:
b/lib/cmdlib.py
9100 9100
      _CheckNodeNotDrained(self, self.dst_node.name)
9101 9101

  
9102 9102
      self._cds = None
9103
      self.dest_disk_info = None
9103 9104
      self.dest_x509_ca = None
9104 9105

  
9105 9106
    elif self.export_mode == constants.EXPORT_MODE_REMOTE:
......
9139 9140
      self.dest_x509_ca = cert
9140 9141

  
9141 9142
      # Verify target information
9143
      disk_info = []
9142 9144
      for idx, disk_data in enumerate(self.op.target_node):
9143 9145
        try:
9144
          masterd.instance.CheckRemoteExportDiskInfo(cds, idx, disk_data)
9146
          (host, port) = masterd.instance.CheckRemoteExportDiskInfo(cds, idx,
9147
                                                                    disk_data)
9145 9148
        except errors.GenericError, err:
9146 9149
          raise errors.OpPrereqError("Target info for disk %s: %s" % (idx, err),
9147 9150
                                     errors.ECODE_INVAL)
9148 9151

  
9152
        disk_info.append((host, port))
9153

  
9154
      assert len(disk_info) == len(self.op.target_node)
9155
      self.dest_disk_info = disk_info
9156

  
9149 9157
    else:
9150 9158
      raise errors.ProgrammerError("Unhandled export mode %r" %
9151 9159
                                   self.export_mode)
......
9236 9244
          opts = objects.ImportExportOptions(key_name=key_name,
9237 9245
                                             ca_pem=dest_ca_pem)
9238 9246

  
9239
          (fin_resu, dresults) = helper.RemoteExport(opts, self.op.target_node,
9247
          (fin_resu, dresults) = helper.RemoteExport(opts, self.dest_disk_info,
9240 9248
                                                     timeouts)
9241 9249
      finally:
9242 9250
        helper.Cleanup()
b/lib/masterd/instance.py
1239 1239

  
1240 1240
    ieloop = ImportExportLoop(self._lu)
1241 1241
    try:
1242
      for idx, (dev, (host, port, _, _)) in enumerate(zip(instance.disks,
1243
                                                          disk_info)):
1242
      for idx, (dev, (host, port)) in enumerate(zip(instance.disks,
1243
                                                    disk_info)):
1244 1244
        self._feedback_fn("Sending disk %s to %s:%s" % (idx, host, port))
1245 1245
        finished_fn = compat.partial(self._TransferFinished, idx)
1246 1246
        ieloop.Add(DiskExport(self._lu, instance.primary_node,
......
1514 1514
  if not utils.VerifySha1Hmac(cds, msg, hmac_digest, salt=hmac_salt):
1515 1515
    raise errors.GenericError("HMAC is wrong")
1516 1516

  
1517
  return (host, port)
1517
  return (utils.HostInfo.NormalizeName(host),
1518
          utils.ValidateServiceName(port))
1518 1519

  
1519 1520

  
1520 1521
def ComputeRemoteImportDiskInfo(cds, salt, disk_index, host, port):
b/test/ganeti.masterd.instance_unittest.py
111 111
      self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
112 112
                        cds, i, di)
113 113

  
114
  def testInvalidHostPort(self):
115
    cds = "3ZoJY8KtGJ"
116
    salt = "drK5oYiHWD"
117

  
118
    for host in [",", "...", "Hello World", "`", "!", "#", "\\"]:
119
      di = ComputeRemoteImportDiskInfo(cds, salt, 0, host, 1234)
120
      self.assertRaises(errors.OpPrereqError,
121
                        CheckRemoteExportDiskInfo, cds, 0, di)
122

  
123
    for port in [-1, 792825908, "HelloWorld!", "`#", "\\\"", "_?_"]:
124
      di = ComputeRemoteImportDiskInfo(cds, salt, 0, "localhost", port)
125
      self.assertRaises(errors.OpPrereqError,
126
                        CheckRemoteExportDiskInfo, cds, 0, di)
127

  
114 128
  def testCheckErrors(self):
115 129
    cds = "0776450535a"
116 130
    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
b/test/import-export_unittest.bash
108 108
$impexpd $src_statusfile invalidmode >/dev/null 2>&1 &&
109 109
  err "daemon-util succeeded with invalid mode"
110 110

  
111
$impexpd $src_statusfile import --compression=rot13 >/dev/null 2>&1 &&
112
  err "daemon-util succeeded with invalid compression"
111
for mode in import export; do
112
  $impexpd $src_statusfile $mode --compression=rot13 >/dev/null 2>&1 &&
113
    err "daemon-util succeeded with invalid compression"
114

  
115
  for host in '' '  ' ' s p a c e' ... , foo.example.net... \
116
              'some"evil"name' 'x\ny\tmoo'; do
117
    $impexpd $src_statusfile $mode --host="$host" >/dev/null 2>&1 &&
118
      err "daemon-util succeeded with invalid host '$host'"
119
  done
120

  
121
  for port in '' ' ' -1234 'some ` port " here'; do
122
    $impexpd $src_statusfile $mode --port="$port" >/dev/null 2>&1 &&
123
      err "daemon-util succeeded with invalid port '$port'"
124
  done
125
done
113 126

  
114 127
upto 'Generate test data'
115 128
cat $(get_testfile proc_drbd8.txt) $(get_testfile cert1.pem) > $testdata

Also available in: Unified diff