Browse Source

[1351] Use TSIGKeyRing class in xfrin

Also updated said class (added a find(name) without algorithm)
Jelte Jansen 12 years ago
parent
commit
0cf505f04b

+ 6 - 2
src/bin/xfrin/tests/xfrin_test.py

@@ -26,6 +26,7 @@ from xfrin import *
 import xfrin
 import xfrin
 from isc.xfrin.diff import Diff
 from isc.xfrin.diff import Diff
 import isc.log
 import isc.log
+from isc.server_common.tsig_keyring import init_keyring, get_keyring
 # If we use any python library that is basically a wrapper for
 # If we use any python library that is basically a wrapper for
 # a library we use as well (like sqlite3 in our datasources),
 # a library we use as well (like sqlite3 in our datasources),
 # we must make sure we import ours first; If we have special
 # we must make sure we import ours first; If we have special
@@ -139,10 +140,12 @@ class MockCC(MockModuleCCSession):
         if identifier == "zones/use_ixfr":
         if identifier == "zones/use_ixfr":
             return False
             return False
 
 
+    def add_remote_config_by_name(self, name, callback):
+        pass
+
     def get_remote_config_value(self, module, identifier):
     def get_remote_config_value(self, module, identifier):
         if module == 'tsig_keys' and identifier == 'keys':
         if module == 'tsig_keys' and identifier == 'keys':
-            return (['example.com.key.:EvAAsfU2h7uofnmqaTCrhHunGsc=',
-                     'bad.key.:EvAAsfU2h7uofnmqaTCrhHu' ], True)
+            return (['example.com.key.:EvAAsfU2h7uofnmqaTCrhHunGsc='], True)
         else:
         else:
             raise Exception('MockCC requested for unknown config value ' +
             raise Exception('MockCC requested for unknown config value ' +
                             + module + "/" + identifier)
                             + module + "/" + identifier)
@@ -237,6 +240,7 @@ class MockXfrin(Xfrin):
     def _cc_setup(self):
     def _cc_setup(self):
         self._tsig_key = None
         self._tsig_key = None
         self._module_cc = MockCC()
         self._module_cc = MockCC()
+        init_keyring(self._module_cc)
         pass
         pass
 
 
     def _get_db_file(self):
     def _get_db_file(self):

+ 8 - 21
src/bin/xfrin/xfrin.py.in

@@ -34,6 +34,7 @@ from isc.datasrc import DataSourceClient, ZoneFinder
 import isc.net.parse
 import isc.net.parse
 from isc.xfrin.diff import Diff
 from isc.xfrin.diff import Diff
 from isc.server_common.auth_command import auth_loadzone_command
 from isc.server_common.auth_command import auth_loadzone_command
+from isc.server_common.tsig_keyring import init_keyring, get_keyring
 from isc.log_messages.xfrin_messages import *
 from isc.log_messages.xfrin_messages import *
 
 
 isc.log.init("b10-xfrin")
 isc.log.init("b10-xfrin")
@@ -72,8 +73,6 @@ XFROUT_MODULE_NAME = 'Xfrout'
 
 
 # Remote module and identifiers (according to their spec files)
 # Remote module and identifiers (according to their spec files)
 ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
 ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
-TSIG_KEYS_MODULE_NAME = 'tsig_keys'
-TSIG_KEYS_IDENTIFIER = 'keys'
 
 
 REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
 REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
 
 
@@ -1265,24 +1264,12 @@ class ZoneInfo:
     def get_tsig_key(self):
     def get_tsig_key(self):
         if self.tsig_key_name is None:
         if self.tsig_key_name is None:
             return None
             return None
-        key_strings, _ = self._module_cc.get_remote_config_value(
-                                  TSIG_KEYS_MODULE_NAME,
-                                  TSIG_KEYS_IDENTIFIER)
-        # Find the TSIG key in the keyring
-        for possible_key_string in key_strings:
-            try:
-                key = TSIGKey(possible_key_string)
-            except InvalidParameter as ipe:
-                # In theory, bad keys should never end up here (but be refused
-                # by the validator for TSIG keys config. However,
-                # should they do, we simply log and ignore them
-                logger.error(XFRIN_BAD_TSIG_KEY_STRING, possible_key_string)
-            if key.get_key_name() == self.tsig_key_name:
-                return key
-        logger.error(XFRIN_TSIG_KEY_NOT_FOUND, self.tsig_key_name.to_text())
-        errmsg = "TSIG key not found in keyring: " +\
-                 self.tsig_key_name.to_text()
-        raise XfrinZoneInfoException(errmsg)
+        result, key = get_keyring().find(self.tsig_key_name)
+        if result != isc.dns.TSIGKeyRing.SUCCESS:
+            raise XfrinZoneInfoException("TSIG key not found in keyring: " +
+                                         self.tsig_key_name.to_text())
+        else:
+            return key
 
 
     def set_use_ixfr(self, use_ixfr):
     def set_use_ixfr(self, use_ixfr):
         """Set use_ixfr. If set to True, it will use
         """Set use_ixfr. If set to True, it will use
@@ -1337,7 +1324,7 @@ class Xfrin:
         self.config_handler(config_data)
         self.config_handler(config_data)
         self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION,
         self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION,
                                           self._auth_config_handler)
                                           self._auth_config_handler)
-        self._module_cc.add_remote_config_by_name(TSIG_KEYS_MODULE_NAME)
+        init_keyring(self._module_cc)
 
 
     def _cc_check_command(self):
     def _cc_check_command(self):
         '''This is a straightforward wrapper for cc.check_command,
         '''This is a straightforward wrapper for cc.check_command,

+ 6 - 0
src/lib/dns/python/tests/tsigkey_python_test.py

@@ -170,6 +170,12 @@ class TSIGKeyRingTest(unittest.TestCase):
         self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name())
         self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name())
         self.assertEqual(self.secret, key.get_secret())
         self.assertEqual(self.secret, key.get_secret())
 
 
+        (code, key) = self.keyring.find(self.key_name)
+        self.assertEqual(TSIGKeyRing.SUCCESS, code)
+        self.assertEqual(self.key_name, key.get_key_name())
+        self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name())
+        self.assertEqual(self.secret, key.get_secret())
+
         (code, key) = self.keyring.find(Name('different-key.example'),
         (code, key) = self.keyring.find(Name('different-key.example'),
                                         self.sha256_name)
                                         self.sha256_name)
         self.assertEqual(TSIGKeyRing.NOTFOUND, code)
         self.assertEqual(TSIGKeyRing.NOTFOUND, code)

+ 11 - 6
src/lib/dns/python/tsigkey_python.cc

@@ -287,7 +287,9 @@ PyMethodDef TSIGKeyRing_methods[] = {
       METH_VARARGS,
       METH_VARARGS,
       "Remove a TSIGKey for the given name from the TSIGKeyRing." },
       "Remove a TSIGKey for the given name from the TSIGKeyRing." },
     { "find", reinterpret_cast<PyCFunction>(TSIGKeyRing_find), METH_VARARGS,
     { "find", reinterpret_cast<PyCFunction>(TSIGKeyRing_find), METH_VARARGS,
-      "Find a TSIGKey for the given name in the TSIGKeyRing. "
+      "Find a TSIGKey for the given name in the TSIGKeyRing. Optional "
+      "second argument is an algorithm, in which case it only returns "
+      "a key if both match.\n"
       "It returns a tuple of (result_code, key)." },
       "It returns a tuple of (result_code, key)." },
     { NULL, NULL, 0, NULL }
     { NULL, NULL, 0, NULL }
 };
 };
@@ -362,13 +364,16 @@ TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
 PyObject*
 PyObject*
 TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
 TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
     PyObject* key_name;
     PyObject* key_name;
-    PyObject* algorithm_name;
+    PyObject* algorithm_name = NULL;
 
 
-    if (PyArg_ParseTuple(args, "O!O!", &name_type, &key_name,
+    if (PyArg_ParseTuple(args, "O!|O!", &name_type, &key_name,
                          &name_type, &algorithm_name)) {
                          &name_type, &algorithm_name)) {
-        const TSIGKeyRing::FindResult result =
-            self->cppobj->find(PyName_ToName(key_name),
-                               PyName_ToName(algorithm_name));
+        // Can't init TSIGKeyRing::FindResult without actual result,
+        // so use ternary operator
+        TSIGKeyRing::FindResult result = (algorithm_name == NULL) ?
+                    self->cppobj->find(PyName_ToName(key_name)) :
+                    self->cppobj->find(PyName_ToName(key_name),
+                                       PyName_ToName(algorithm_name));
         if (result.key != NULL) {
         if (result.key != NULL) {
             s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
             s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
             if (key == NULL) {
             if (key == NULL) {

+ 9 - 0
src/lib/dns/tests/tsigkey_unittest.cc

@@ -251,6 +251,15 @@ TEST_F(TSIGKeyRingTest, find) {
     const TSIGKeyRing::FindResult result3 = keyring.find(key_name, md5_name);
     const TSIGKeyRing::FindResult result3 = keyring.find(key_name, md5_name);
     EXPECT_EQ(TSIGKeyRing::NOTFOUND, result3.code);
     EXPECT_EQ(TSIGKeyRing::NOTFOUND, result3.code);
     EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result3.key);
     EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result3.key);
+
+    // But with just the name it should work
+    const TSIGKeyRing::FindResult result4(keyring.find(key_name));
+    EXPECT_EQ(TSIGKeyRing::SUCCESS, result1.code);
+    EXPECT_EQ(key_name, result1.key->getKeyName());
+    EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result1.key->getAlgorithmName());
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, secret, secret_len,
+                        result1.key->getSecret(),
+                        result1.key->getSecretLength());
 }
 }
 
 
 TEST_F(TSIGKeyRingTest, findFromSome) {
 TEST_F(TSIGKeyRingTest, findFromSome) {

+ 11 - 1
src/lib/dns/tsigkey.cc

@@ -51,7 +51,7 @@ namespace {
         if (name == TSIGKey::HMACSHA512_NAME()) {
         if (name == TSIGKey::HMACSHA512_NAME()) {
             return (isc::cryptolink::SHA512);
             return (isc::cryptolink::SHA512);
         }
         }
- 
+
         return (isc::cryptolink::UNKNOWN_HASH);
         return (isc::cryptolink::UNKNOWN_HASH);
     }
     }
 }
 }
@@ -270,6 +270,16 @@ TSIGKeyRing::remove(const Name& key_name) {
 }
 }
 
 
 TSIGKeyRing::FindResult
 TSIGKeyRing::FindResult
+TSIGKeyRing::find(const Name& key_name) const {
+    TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
+        impl_->keys.find(key_name);
+    if (found == impl_->keys.end()) {
+        return (FindResult(NOTFOUND, NULL));
+    }
+    return (FindResult(SUCCESS, &((*found).second)));
+}
+
+TSIGKeyRing::FindResult
 TSIGKeyRing::find(const Name& key_name, const Name& algorithm_name) const {
 TSIGKeyRing::find(const Name& key_name, const Name& algorithm_name) const {
     TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
     TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
         impl_->keys.find(key_name);
         impl_->keys.find(key_name);

+ 22 - 0
src/lib/dns/tsigkey.h

@@ -327,6 +327,27 @@ public:
     /// Find a \c TSIGKey for the given name in the \c TSIGKeyRing.
     /// Find a \c TSIGKey for the given name in the \c TSIGKeyRing.
     ///
     ///
     /// It searches the internal storage for a \c TSIGKey whose name is
     /// It searches the internal storage for a \c TSIGKey whose name is
+    /// \c key_name.
+    /// It returns the result in the form of a \c FindResult
+    /// object as follows:
+    /// - \c code: \c SUCCESS if a key is found; otherwise \c NOTFOUND.
+    /// - \c key: A pointer to the found \c TSIGKey object if one is found;
+    /// otherwise \c NULL.
+    ///
+    /// The pointer returned in the \c FindResult object is only valid until
+    /// the corresponding key is removed from the key ring.
+    /// The caller must ensure that the key is held in the key ring while
+    /// it needs to refer to it, or it must make a local copy of the key.
+    ///
+    /// This method never throws an exception.
+    ///
+    /// \param key_name The name of the key to be found.
+    /// \return A \c FindResult object enclosing the search result (see above).
+    FindResult find(const Name& key_name) const;
+
+    /// Find a \c TSIGKey for the given name in the \c TSIGKeyRing.
+    ///
+    /// It searches the internal storage for a \c TSIGKey whose name is
     /// \c key_name and that uses the hash algorithm identified by
     /// \c key_name and that uses the hash algorithm identified by
     /// \c algorithm_name.
     /// \c algorithm_name.
     /// It returns the result in the form of a \c FindResult
     /// It returns the result in the form of a \c FindResult
@@ -346,6 +367,7 @@ public:
     /// \param algorithm_name The name of the algorithm of the found key.
     /// \param algorithm_name The name of the algorithm of the found key.
     /// \return A \c FindResult object enclosing the search result (see above).
     /// \return A \c FindResult object enclosing the search result (see above).
     FindResult find(const Name& key_name, const Name& algorithm_name) const;
     FindResult find(const Name& key_name, const Name& algorithm_name) const;
+
 private:
 private:
     struct TSIGKeyRingImpl;
     struct TSIGKeyRingImpl;
     TSIGKeyRingImpl* impl_;
     TSIGKeyRingImpl* impl_;