Interdiff:
---
lib/cmdlib.py | 4 +--
lib/constants.py | 3 +-
lib/masterd/instance.py | 47 ++++++++++++++++++++++++++++++
test/ganeti.masterd.instance_unittest.py | 32 +++++++++++++++++++-
4 files changed, 81 insertions(+), 5 deletions(-)
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index a621451..51514d7 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -8873,9 +8873,7 @@ class LUPrepareExport(NoHooksLU):
cert_pem)
return {
- "handshake": (utils.Sha1Hmac(self._cds, constants.RIE_HANDSHAKE,
- salt=salt),
- salt),
+ "handshake": masterd.instance.ComputeRemoteExportHandshake(self._cds),
"x509_key_name": (name, utils.Sha1Hmac(self._cds, name, salt=salt),
salt),
"x509_ca": utils.SignX509Certificate(cert, self._cds, salt),
diff --git a/lib/constants.py b/lib/constants.py
index cf6a656..93f1045 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -333,7 +333,8 @@ LOCKS_APPEND = 'append'
INSTANCE_CREATE = "create"
INSTANCE_IMPORT = "import"
-# Remote import/export handshake message
+# Remote import/export handshake message and version
+RIE_VERSION = 0
RIE_HANDSHAKE = "Hi, I'm Ganeti"
# Remote import/export certificate validity in seconds
diff --git a/lib/masterd/instance.py b/lib/masterd/instance.py
index 7e95b0d..f48e01b 100644
--- a/lib/masterd/instance.py
+++ b/lib/masterd/instance.py
@@ -1105,3 +1105,50 @@ class ExportInstanceHelper:
assert len(self._removed_snaps) == len(self._instance.disks)
for idx in range(len(self._instance.disks)):
self._RemoveSnapshot(idx)
+
+
+def _GetImportExportHandshakeMessage(version):
+ """Returns the handshake message for a RIE protocol version.
+
+ @type version: number
+
+ """
+ return "%s:%s" % (version, constants.RIE_HANDSHAKE)
+
+
+def ComputeRemoteExportHandshake(cds):
+ """Computes the remote import/export handshake.
+
+ @type cds: string
+ @param cds: Cluster domain secret
+
+ """
+ salt = utils.GenerateSecret(8)
+ msg = _GetImportExportHandshakeMessage(constants.RIE_VERSION)
+ return (constants.RIE_VERSION, utils.Sha1Hmac(cds, msg, salt=salt), salt)
+
+
+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
diff --git a/test/ganeti.masterd.instance_unittest.py
b/test/ganeti.masterd.instance_unittest.py
index 05b0183..0c74def 100755
--- a/test/ganeti.masterd.instance_unittest.py
+++ b/test/ganeti.masterd.instance_unittest.py
@@ -25,11 +25,13 @@ import os
import sys
import unittest
+from ganeti import constants
from ganeti import utils
from ganeti import masterd
from ganeti.masterd.instance import \
- ImportExportTimeouts, _TimeoutExpired, _DiskImportExportBase
+ ImportExportTimeouts, _TimeoutExpired, _DiskImportExportBase, \
+ ComputeRemoteExportHandshake, CheckRemoteExportHandshake
import testutils
@@ -56,5 +58,33 @@ class TestMisc(unittest.TestCase):
None, None, None, None, None, None, None)
+class TestRieHandshake(unittest.TestCase):
+ def test(self):
+ cds = "cd-secret"
+ hs = ComputeRemoteExportHandshake(cds)
+ self.assertEqual(len(hs), 3)
+ self.assertEqual(hs[0], constants.RIE_VERSION)
+
+ self.assertEqual(CheckRemoteExportHandshake(cds, hs), None)
+
+ def testCheckErrors(self):
+ self.assert_(CheckRemoteExportHandshake(None, None))
+ self.assert_(CheckRemoteExportHandshake("", ""))
+ self.assert_(CheckRemoteExportHandshake("", ("xyz", "foo")))
+
+ def testCheckWrongHash(self):
+ cds = "cd-secret999"
+ self.assert_(CheckRemoteExportHandshake(cds, (0, "fakehash", "xyz")))
+
+ def testCheckWrongVersion(self):
+ version = 14887
+ self.assertNotEqual(version, constants.RIE_VERSION)
+ cds = "c28ac99"
+ salt = "a19cf8cc06"
+ msg = "%s:%s" % (version, constants.RIE_HANDSHAKE)
+ hs = (version, utils.Sha1Hmac(cds, msg, salt=salt), salt)
+ self.assert_(CheckRemoteExportHandshake(cds, hs))
+
+
if __name__ == "__main__":
testutils.GanetiTestProgram()
--
1.7.0.4