def testVerifySha1HmacSalt(self): self.assert_( utils.VerifySha1Hmac("TguMTA2K", "", ("17a4adc34d69c0d367d4" "ffbef96fd41d4df7a6e8"), salt="abc9")) self.assert_( utils.VerifySha1Hmac("3YzMxZWE", "Hello World", ("7f264f8114c9066afc9b" "b7636e1786d996d3cc0d"), salt="xyz0"))
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
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()))
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)
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)
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)