Ejemplo n.º 1
0
 def testVerifySha1HmacSalt(self):
     self.assert_(
         utils.VerifySha1Hmac("TguMTA2K",
                              "", ("17a4adc34d69c0d367d4"
                                   "ffbef96fd41d4df7a6e8"),
                              salt="abc9"))
     self.assert_(
         utils.VerifySha1Hmac("3YzMxZWE",
                              "Hello World", ("7f264f8114c9066afc9b"
                                              "b7636e1786d996d3cc0d"),
                              salt="xyz0"))
Ejemplo n.º 2
0
def LoadSignedJson(txt, key):
    """Verify that a given message was signed with the given key, and load it.

  @param txt: json-encoded hmac-signed message
  @param key: the shared hmac key or a callable taking one argument (the key
    selector), which returns the hmac key belonging to the key selector.
    Typical usage is to pass a reference to the get method of a dict.
  @rtype: tuple of original data, string
  @return: original data, salt
  @raises errors.SignatureError: if the message signature doesn't verify

  """
    signed_dict = LoadJson(txt)

    WrapPrivateValues(signed_dict)

    if not isinstance(signed_dict, dict):
        raise errors.SignatureError("Invalid external message")
    try:
        msg = signed_dict["msg"]
        salt = signed_dict["salt"]
        hmac_sign = signed_dict["hmac"]
    except KeyError:
        raise errors.SignatureError("Invalid external message")

    if callable(key):
        # pylint: disable=E1103
        key_selector = signed_dict.get("key_selector", None)
        hmac_key = key(key_selector)
        if not hmac_key:
            raise errors.SignatureError("No key with key selector '%s' found" %
                                        key_selector)
    else:
        key_selector = ""
        hmac_key = key

    if not utils.VerifySha1Hmac(
            hmac_key, msg, hmac_sign, salt=salt + key_selector):
        raise errors.SignatureError("Invalid Signature")

    return LoadJson(msg), salt
Ejemplo n.º 3
0
    def testVerifySha1Hmac(self):
        self.assert_(
            utils.VerifySha1Hmac("", "", ("fbdb1d1b18aa6c08324b"
                                          "7d64b71fb76370690e1d")))
        self.assert_(
            utils.VerifySha1Hmac("TguMTA2K", "", ("f904c2476527c6d3e660"
                                                  "9ab683c66fa0652cb1dc")))

        digest = "ef4f3bda82212ecb2f7ce868888a19092481f1fd"
        self.assert_(utils.VerifySha1Hmac("3YzMxZWE", "Hello World", digest))
        self.assert_(
            utils.VerifySha1Hmac("3YzMxZWE", "Hello World", digest.lower()))
        self.assert_(
            utils.VerifySha1Hmac("3YzMxZWE", "Hello World", digest.upper()))
        self.assert_(
            utils.VerifySha1Hmac("3YzMxZWE", "Hello World", digest.title()))
Ejemplo n.º 4
0
    def CheckPrereq(self):
        """Check prerequisites.

    This checks that the instance and node names are valid.

    """
        self.instance = self.cfg.GetInstanceInfoByName(self.op.instance_name)
        assert self.instance is not None, \
              "Cannot retrieve locked instance %s" % self.op.instance_name
        CheckNodeOnline(self, self.instance.primary_node)

        if (self.op.remove_instance
                and self.instance.admin_state == constants.ADMINST_UP
                and not self.op.shutdown):
            raise errors.OpPrereqError(
                "Can not remove instance without shutting it"
                " down before", errors.ECODE_STATE)

        if self.op.mode == constants.EXPORT_MODE_LOCAL:
            self.dst_node = self.cfg.GetNodeInfo(self.op.target_node_uuid)
            assert self.dst_node is not None

            CheckNodeOnline(self, self.dst_node.uuid)
            CheckNodeNotDrained(self, self.dst_node.uuid)

            self._cds = None
            self.dest_disk_info = None
            self.dest_x509_ca = None

        elif self.op.mode == constants.EXPORT_MODE_REMOTE:
            self.dst_node = None

            if len(self.op.target_node) != len(self.instance.disks):
                raise errors.OpPrereqError(
                    ("Received destination information for %s"
                     " disks, but instance %s has %s disks") %
                    (len(self.op.target_node), self.op.instance_name,
                     len(self.instance.disks)), errors.ECODE_INVAL)

            cds = GetClusterDomainSecret()

            # Check X509 key name
            try:
                (key_name, hmac_digest, hmac_salt) = self.x509_key_name
            except (TypeError, ValueError), err:
                raise errors.OpPrereqError(
                    "Invalid data for X509 key name: %s" % err,
                    errors.ECODE_INVAL)

            if not utils.VerifySha1Hmac(
                    cds, key_name, hmac_digest, salt=hmac_salt):
                raise errors.OpPrereqError("HMAC for X509 key name is wrong",
                                           errors.ECODE_INVAL)

            # Load and verify CA
            try:
                (cert,
                 _) = utils.LoadSignedX509Certificate(self.dest_x509_ca_pem,
                                                      cds)
            except OpenSSL.crypto.Error, err:
                raise errors.OpPrereqError(
                    "Unable to load destination X509 CA (%s)" % (err, ),
                    errors.ECODE_INVAL)
Ejemplo n.º 5
0
    def CheckPrereq(self):
        """Check prerequisites.

    This checks that the instance and node names are valid.

    """
        self.instance = self.cfg.GetInstanceInfoByName(self.op.instance_name)
        assert self.instance is not None, \
              "Cannot retrieve locked instance %s" % self.op.instance_name
        CheckNodeOnline(self, self.instance.primary_node)

        if (self.op.remove_instance
                and self.instance.admin_state == constants.ADMINST_UP
                and not self.op.shutdown):
            raise errors.OpPrereqError(
                "Can not remove instance without shutting it"
                " down before", errors.ECODE_STATE)

        if self.op.mode == constants.EXPORT_MODE_LOCAL:
            self.dst_node = self.cfg.GetNodeInfo(self.op.target_node_uuid)
            assert self.dst_node is not None

            CheckNodeOnline(self, self.dst_node.uuid)
            CheckNodeNotDrained(self, self.dst_node.uuid)

            self._cds = None
            self.dest_disk_info = None
            self.dest_x509_ca = None

        elif self.op.mode == constants.EXPORT_MODE_REMOTE:
            self.dst_node = None

            if len(self.op.target_node) != len(self.instance.disks):
                raise errors.OpPrereqError(
                    ("Received destination information for %s"
                     " disks, but instance %s has %s disks") %
                    (len(self.op.target_node), self.op.instance_name,
                     len(self.instance.disks)), errors.ECODE_INVAL)

            cds = GetClusterDomainSecret()

            # Check X509 key name
            try:
                (key_name, hmac_digest, hmac_salt) = self.x509_key_name
            except (TypeError, ValueError) as err:
                raise errors.OpPrereqError(
                    "Invalid data for X509 key name: %s" % err,
                    errors.ECODE_INVAL)

            if not utils.VerifySha1Hmac(
                    cds, key_name, hmac_digest, salt=hmac_salt):
                raise errors.OpPrereqError("HMAC for X509 key name is wrong",
                                           errors.ECODE_INVAL)

            # Load and verify CA
            try:
                (cert,
                 _) = utils.LoadSignedX509Certificate(self.dest_x509_ca_pem,
                                                      cds)
            except OpenSSL.crypto.Error as err:
                raise errors.OpPrereqError(
                    "Unable to load destination X509 CA (%s)" % (err, ),
                    errors.ECODE_INVAL)

            (errcode, msg) = utils.VerifyX509Certificate(cert, None, None)
            if errcode is not None:
                raise errors.OpPrereqError(
                    "Invalid destination X509 CA (%s)" % (msg, ),
                    errors.ECODE_INVAL)

            self.dest_x509_ca = cert

            # Verify target information
            disk_info = []
            for idx, disk_data in enumerate(self.op.target_node):
                try:
                    (host, port, magic) = \
                      masterd.instance.CheckRemoteExportDiskInfo(cds, idx, disk_data)
                except errors.GenericError as err:
                    raise errors.OpPrereqError(
                        "Target info for disk %s: %s" % (idx, err),
                        errors.ECODE_INVAL)

                disk_info.append((host, port, magic))

            assert len(disk_info) == len(self.op.target_node)
            self.dest_disk_info = disk_info

        else:
            raise errors.ProgrammerError("Unhandled export mode %r" %
                                         self.op.mode)

        # Check prerequisites for zeroing
        if self.op.zero_free_space:
            # Check that user shutdown detection has been enabled
            hvparams = self.cfg.GetClusterInfo().FillHV(self.instance)
            if self.instance.hypervisor == constants.HT_KVM and \
               not hvparams.get(constants.HV_KVM_USER_SHUTDOWN, False):
                raise errors.OpPrereqError(
                    "Instance shutdown detection must be "
                    "enabled for zeroing to work", errors.ECODE_INVAL)

            # Check that the instance is set to boot from the disk
            if constants.HV_BOOT_ORDER in hvparams and \
               hvparams[constants.HV_BOOT_ORDER] != constants.HT_BO_DISK:
                raise errors.OpPrereqError(
                    "Booting from disk must be set for zeroing "
                    "to work", errors.ECODE_INVAL)

            # Check that the zeroing image is set
            if not self.cfg.GetZeroingImage():
                raise errors.OpPrereqError(
                    "A zeroing image must be set for zeroing to"
                    " work", errors.ECODE_INVAL)

            if self.op.zeroing_timeout_fixed is None:
                self.op.zeroing_timeout_fixed = constants.HELPER_VM_STARTUP

            if self.op.zeroing_timeout_per_mib is None:
                self.op.zeroing_timeout_per_mib = constants.ZEROING_TIMEOUT_PER_MIB

        else:
            if (self.op.zeroing_timeout_fixed is not None
                    or self.op.zeroing_timeout_per_mib is not None):
                raise errors.OpPrereqError(
                    "Zeroing timeout options can only be used"
                    " only with the --zero-free-space option",
                    errors.ECODE_INVAL)

        if self.op.long_sleep and not self.op.shutdown:
            raise errors.OpPrereqError(
                "The long sleep option only makes sense when"
                " the instance can be shut down.", errors.ECODE_INVAL)

        self.secondary_nodes = \
          self.cfg.GetInstanceSecondaryNodes(self.instance.uuid)
        self.inst_disks = self.cfg.GetInstanceDisks(self.instance.uuid)

        # Check if the compression tool is whitelisted
        CheckCompressionTool(self, self.op.compress)
Ejemplo n.º 6
0
def CheckRemoteExportHandshake(cds, handshake):
  """Checks the handshake of a remote import/export.

  @type cds: string
  @param cds: Cluster domain secret
  @type handshake: sequence
  @param handshake: Handshake sent by remote peer

  """
  try:
    (version, hmac_digest, hmac_salt) = handshake
  except (TypeError, ValueError), err:
    return "Invalid data: %s" % err

  if not utils.VerifySha1Hmac(cds, _GetImportExportHandshakeMessage(version),
                              hmac_digest, salt=hmac_salt):
    return "Hash didn't match, clusters don't share the same domain secret"

  if version != constants.RIE_VERSION:
    return ("Clusters don't have the same remote import/export protocol"
            " (local=%s, remote=%s)" %
            (constants.RIE_VERSION, version))

  return None


def _GetRieDiskInfoMessage(disk_index, host, port, magic):
  """Returns the hashed text for import/export disk information.

  @type disk_index: number
  @param disk_index: Index of disk (included in hash)