Commit 0cf505f0 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[1351] Use TSIGKeyRing class in xfrin

Also updated said class (added a find(name) without algorithm)
parent 669a650e
......@@ -26,6 +26,7 @@ from xfrin import *
import xfrin
from isc.xfrin.diff import Diff
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
# a library we use as well (like sqlite3 in our datasources),
# we must make sure we import ours first; If we have special
......@@ -139,10 +140,12 @@ class MockCC(MockModuleCCSession):
if identifier == "zones/use_ixfr":
return False
def add_remote_config_by_name(self, name, callback):
pass
def get_remote_config_value(self, module, identifier):
if module == 'tsig_keys' and identifier == 'keys':
return (['example.com.key.:EvAAsfU2h7uofnmqaTCrhHunGsc=',
'bad.key.:EvAAsfU2h7uofnmqaTCrhHu' ], True)
return (['example.com.key.:EvAAsfU2h7uofnmqaTCrhHunGsc='], True)
else:
raise Exception('MockCC requested for unknown config value ' +
+ module + "/" + identifier)
......@@ -237,6 +240,7 @@ class MockXfrin(Xfrin):
def _cc_setup(self):
self._tsig_key = None
self._module_cc = MockCC()
init_keyring(self._module_cc)
pass
def _get_db_file(self):
......
......@@ -34,6 +34,7 @@ from isc.datasrc import DataSourceClient, ZoneFinder
import isc.net.parse
from isc.xfrin.diff import Diff
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 *
isc.log.init("b10-xfrin")
......@@ -72,8 +73,6 @@ XFROUT_MODULE_NAME = 'Xfrout'
# Remote module and identifiers (according to their spec files)
ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
TSIG_KEYS_MODULE_NAME = 'tsig_keys'
TSIG_KEYS_IDENTIFIER = 'keys'
REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
......@@ -1265,24 +1264,12 @@ class ZoneInfo:
def get_tsig_key(self):
if self.tsig_key_name is 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):
"""Set use_ixfr. If set to True, it will use
......@@ -1337,7 +1324,7 @@ class Xfrin:
self.config_handler(config_data)
self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION,
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):
'''This is a straightforward wrapper for cc.check_command,
......
......@@ -170,6 +170,12 @@ class TSIGKeyRingTest(unittest.TestCase):
self.assertEqual(TSIGKey.HMACSHA256_NAME, key.get_algorithm_name())
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'),
self.sha256_name)
self.assertEqual(TSIGKeyRing.NOTFOUND, code)
......
......@@ -287,7 +287,9 @@ PyMethodDef TSIGKeyRing_methods[] = {
METH_VARARGS,
"Remove a TSIGKey for the given name from the TSIGKeyRing." },
{ "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)." },
{ NULL, NULL, 0, NULL }
};
......@@ -362,13 +364,16 @@ TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
PyObject*
TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
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)) {
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) {
s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
if (key == NULL) {
......
......@@ -251,6 +251,15 @@ TEST_F(TSIGKeyRingTest, find) {
const TSIGKeyRing::FindResult result3 = keyring.find(key_name, md5_name);
EXPECT_EQ(TSIGKeyRing::NOTFOUND, result3.code);
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) {
......
......@@ -51,7 +51,7 @@ namespace {
if (name == TSIGKey::HMACSHA512_NAME()) {
return (isc::cryptolink::SHA512);
}
return (isc::cryptolink::UNKNOWN_HASH);
}
}
......@@ -269,6 +269,16 @@ TSIGKeyRing::remove(const Name& key_name) {
return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
}
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 {
TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
......
......@@ -324,6 +324,27 @@ public:
/// \c key_name.
Result remove(const Name& key_name);
/// 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.
/// 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
......@@ -346,6 +367,7 @@ public:
/// \param algorithm_name The name of the algorithm of the found key.
/// \return A \c FindResult object enclosing the search result (see above).
FindResult find(const Name& key_name, const Name& algorithm_name) const;
private:
struct TSIGKeyRingImpl;
TSIGKeyRingImpl* impl_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment