tsigkey_python.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <Python.h>
  15. #include <stdexcept>
  16. #include <util/python/pycppwrapper_util.h>
  17. #include <dns/name.h>
  18. #include <dns/tsigkey.h>
  19. #include <dns/rdata.h>
  20. #include "pydnspp_common.h"
  21. #include "name_python.h"
  22. #include "tsigkey_python.h"
  23. using namespace std;
  24. using namespace isc::util::python;
  25. using namespace isc::dns;
  26. using namespace isc::dns::python;
  27. //
  28. // Definition of the classes
  29. //
  30. // For each class, we need a struct, a helper functions (init, destroy,
  31. // and static wrappers around the methods we export), a list of methods,
  32. // and a type description
  33. //
  34. // TSIGKey
  35. //
  36. namespace {
  37. // The s_* Class simply covers one instantiation of the object
  38. class s_TSIGKey : public PyObject {
  39. public:
  40. s_TSIGKey() : cppobj(NULL) {};
  41. TSIGKey* cppobj;
  42. };
  43. //
  44. // We declare the functions here, the definitions are below
  45. // the type definition of the object, since both can use the other
  46. //
  47. // General creation and destruction
  48. int TSIGKey_init(s_TSIGKey* self, PyObject* args);
  49. void TSIGKey_destroy(s_TSIGKey* self);
  50. // These are the functions we export
  51. // This is a second version of toText, we need one where the argument
  52. // is a PyObject*, for the str() function in python.
  53. PyObject* TSIGKey_getKeyName(const s_TSIGKey* self);
  54. PyObject* TSIGKey_getAlgorithmName(const s_TSIGKey* self);
  55. PyObject* TSIGKey_getSecret(const s_TSIGKey* self);
  56. PyObject* TSIGKey_toText(const s_TSIGKey* self);
  57. // This list contains the actual set of functions we have in
  58. // python. Each entry has
  59. // 1. Python method name
  60. // 2. Our static function here
  61. // 3. Argument type
  62. // 4. Documentation
  63. PyMethodDef TSIGKey_methods[] = {
  64. { "get_key_name",
  65. reinterpret_cast<PyCFunction>(TSIGKey_getKeyName), METH_NOARGS,
  66. "Return the key name." },
  67. { "get_algorithm_name",
  68. reinterpret_cast<PyCFunction>(TSIGKey_getAlgorithmName), METH_NOARGS,
  69. "Return the algorithm name." },
  70. { "get_secret",
  71. reinterpret_cast<PyCFunction>(TSIGKey_getSecret), METH_NOARGS,
  72. "Return the value of the TSIG secret." },
  73. { "to_text", reinterpret_cast<PyCFunction>(TSIGKey_toText), METH_NOARGS,
  74. "Returns the string representation (name:secret:algorithm)" },
  75. { NULL, NULL, 0, NULL }
  76. };
  77. int
  78. TSIGKey_init(s_TSIGKey* self, PyObject* args) {
  79. try {
  80. const char* str;
  81. if (PyArg_ParseTuple(args, "s", &str)) {
  82. self->cppobj = new TSIGKey(str);
  83. return (0);
  84. }
  85. PyErr_Clear();
  86. const PyObject* key_name;
  87. const PyObject* algorithm_name;
  88. PyObject* bytes_obj;
  89. const char* secret;
  90. Py_ssize_t secret_len;
  91. if (PyArg_ParseTuple(args, "O!O!O", &name_type, &key_name,
  92. &name_type, &algorithm_name, &bytes_obj) &&
  93. PyObject_AsCharBuffer(bytes_obj, &secret, &secret_len) == 0) {
  94. if (secret_len == 0) {
  95. secret = NULL;
  96. }
  97. self->cppobj = new TSIGKey(PyName_ToName(key_name),
  98. PyName_ToName(algorithm_name),
  99. secret, secret_len);
  100. return (0);
  101. }
  102. } catch (const isc::InvalidParameter& ex) {
  103. PyErr_SetString(po_InvalidParameter, ex.what());
  104. return (-1);
  105. } catch (...) {
  106. PyErr_SetString(po_IscException, "Unexpected exception");
  107. return (-1);
  108. }
  109. PyErr_Clear();
  110. PyErr_SetString(PyExc_TypeError,
  111. "Invalid arguments to TSIGKey constructor");
  112. return (-1);
  113. }
  114. void
  115. TSIGKey_destroy(s_TSIGKey* const self) {
  116. delete self->cppobj;
  117. self->cppobj = NULL;
  118. Py_TYPE(self)->tp_free(self);
  119. }
  120. PyObject*
  121. TSIGKey_getKeyName(const s_TSIGKey* const self) {
  122. try {
  123. return (createNameObject(self->cppobj->getKeyName()));
  124. } catch (const exception& ex) {
  125. const string ex_what =
  126. "Failed to get key name of TSIGKey: " + string(ex.what());
  127. PyErr_SetString(po_IscException, ex_what.c_str());
  128. } catch (...) {
  129. PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
  130. "getting key name of TSIGKey");
  131. }
  132. return (NULL);
  133. }
  134. PyObject*
  135. TSIGKey_getAlgorithmName(const s_TSIGKey* const self) {
  136. try {
  137. return (createNameObject(self->cppobj->getAlgorithmName()));
  138. } catch (const exception& ex) {
  139. const string ex_what =
  140. "Failed to get algorithm name of TSIGKey: " + string(ex.what());
  141. PyErr_SetString(po_IscException, ex_what.c_str());
  142. } catch (...) {
  143. PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
  144. "getting algorithm name of TSIGKey");
  145. }
  146. return (NULL);
  147. }
  148. PyObject*
  149. TSIGKey_getSecret(const s_TSIGKey* const self) {
  150. return (Py_BuildValue("y#", self->cppobj->getSecret(),
  151. self->cppobj->getSecretLength()));
  152. }
  153. PyObject*
  154. TSIGKey_toText(const s_TSIGKey* self) {
  155. return (Py_BuildValue("s", self->cppobj->toText().c_str()));
  156. }
  157. } // end of unnamed namespace
  158. namespace isc {
  159. namespace dns {
  160. namespace python {
  161. // This defines the complete type for reflection in python and
  162. // parsing of PyObject* to s_EDNS
  163. // Most of the functions are not actually implemented and NULL here.
  164. PyTypeObject tsigkey_type = {
  165. PyVarObject_HEAD_INIT(NULL, 0)
  166. "pydnspp.TSIGKey",
  167. sizeof(s_TSIGKey), // tp_basicsize
  168. 0, // tp_itemsize
  169. (destructor)TSIGKey_destroy, // tp_dealloc
  170. NULL, // tp_print
  171. NULL, // tp_getattr
  172. NULL, // tp_setattr
  173. NULL, // tp_reserved
  174. NULL, // tp_repr
  175. NULL, // tp_as_number
  176. NULL, // tp_as_sequence
  177. NULL, // tp_as_mapping
  178. NULL, // tp_hash
  179. NULL, // tp_call
  180. NULL, // tp_str
  181. NULL, // tp_getattro
  182. NULL, // tp_setattro
  183. NULL, // tp_as_buffer
  184. Py_TPFLAGS_DEFAULT, // tp_flags
  185. "The TSIGKey class holds a TSIG key along with some related attributes as "
  186. "defined in RFC2845.",
  187. NULL, // tp_traverse
  188. NULL, // tp_clear
  189. NULL, // tp_richcompare
  190. 0, // tp_weaklistoffset
  191. NULL, // tp_iter
  192. NULL, // tp_iternext
  193. TSIGKey_methods, // tp_methods
  194. NULL, // tp_members
  195. NULL, // tp_getset
  196. NULL, // tp_base
  197. NULL, // tp_dict
  198. NULL, // tp_descr_get
  199. NULL, // tp_descr_set
  200. 0, // tp_dictoffset
  201. (initproc)TSIGKey_init, // tp_init
  202. NULL, // tp_alloc
  203. PyType_GenericNew, // tp_new
  204. NULL, // tp_free
  205. NULL, // tp_is_gc
  206. NULL, // tp_bases
  207. NULL, // tp_mro
  208. NULL, // tp_cache
  209. NULL, // tp_subclasses
  210. NULL, // tp_weaklist
  211. NULL, // tp_del
  212. 0 // tp_version_tag
  213. };
  214. // Module Initialization, all statics are initialized here
  215. namespace internal {
  216. bool
  217. initModulePart_TSIGKey(PyObject* mod) {
  218. // We initialize the static description object with PyType_Ready(),
  219. // then add it to the module. This is not just a check! (leaving
  220. // this out results in segmentation faults)
  221. if (PyType_Ready(&tsigkey_type) < 0) {
  222. return (false);
  223. }
  224. void* p = &tsigkey_type;
  225. if (PyModule_AddObject(mod, "TSIGKey", static_cast<PyObject*>(p)) != 0) {
  226. return (false);
  227. }
  228. Py_INCREF(&tsigkey_type);
  229. try {
  230. // Constant class variables
  231. installClassVariable(tsigkey_type, "HMACMD5_NAME",
  232. createNameObject(TSIGKey::HMACMD5_NAME()));
  233. installClassVariable(tsigkey_type, "HMACSHA1_NAME",
  234. createNameObject(TSIGKey::HMACSHA1_NAME()));
  235. installClassVariable(tsigkey_type, "HMACSHA256_NAME",
  236. createNameObject(TSIGKey::HMACSHA256_NAME()));
  237. installClassVariable(tsigkey_type, "HMACSHA224_NAME",
  238. createNameObject(TSIGKey::HMACSHA224_NAME()));
  239. installClassVariable(tsigkey_type, "HMACSHA384_NAME",
  240. createNameObject(TSIGKey::HMACSHA384_NAME()));
  241. installClassVariable(tsigkey_type, "HMACSHA512_NAME",
  242. createNameObject(TSIGKey::HMACSHA512_NAME()));
  243. } catch (const exception& ex) {
  244. const string ex_what =
  245. "Unexpected failure in TSIGKey initialization: " +
  246. string(ex.what());
  247. PyErr_SetString(po_IscException, ex_what.c_str());
  248. return (false);
  249. } catch (...) {
  250. PyErr_SetString(PyExc_SystemError,
  251. "Unexpected failure in TSIGKey initialization");
  252. return (false);
  253. }
  254. return (true);
  255. }
  256. } // end namespace internal
  257. bool
  258. PyTSIGKey_Check(PyObject* obj) {
  259. return (PyObject_TypeCheck(obj, &tsigkey_type));
  260. }
  261. const TSIGKey&
  262. PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj) {
  263. const s_TSIGKey* tsigkey = static_cast<const s_TSIGKey*>(tsigkey_obj);
  264. return (*tsigkey->cppobj);
  265. }
  266. } // namespace python
  267. } // namespace dns
  268. } // namespace isc
  269. //
  270. // End of TSIGKey
  271. //
  272. //
  273. // TSIGKeyRing
  274. //
  275. // The s_* Class simply covers one instantiation of the object
  276. // The s_* Class simply covers one instantiation of the object
  277. namespace {
  278. class s_TSIGKeyRing : public PyObject {
  279. public:
  280. s_TSIGKeyRing() : cppobj(NULL) {};
  281. TSIGKeyRing* cppobj;
  282. };
  283. //
  284. // We declare the functions here, the definitions are below
  285. // the type definition of the object, since both can use the other
  286. //
  287. int TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args);
  288. void TSIGKeyRing_destroy(s_TSIGKeyRing* self);
  289. PyObject* TSIGKeyRing_size(const s_TSIGKeyRing* self);
  290. PyObject* TSIGKeyRing_add(const s_TSIGKeyRing* self, PyObject* args);
  291. PyObject* TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args);
  292. PyObject* TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args);
  293. PyMethodDef TSIGKeyRing_methods[] = {
  294. { "size", reinterpret_cast<PyCFunction>(TSIGKeyRing_size), METH_NOARGS,
  295. "Return the number of keys stored in the TSIGKeyRing." },
  296. { "add", reinterpret_cast<PyCFunction>(TSIGKeyRing_add), METH_VARARGS,
  297. "Add a TSIGKey to the TSIGKeyRing." },
  298. { "remove", reinterpret_cast<PyCFunction>(TSIGKeyRing_remove),
  299. METH_VARARGS,
  300. "Remove a TSIGKey for the given name from the TSIGKeyRing." },
  301. { "find", reinterpret_cast<PyCFunction>(TSIGKeyRing_find), METH_VARARGS,
  302. "Find a TSIGKey for the given name in the TSIGKeyRing. "
  303. "It returns a tuple of (result_code, key)." },
  304. { NULL, NULL, 0, NULL }
  305. };
  306. int
  307. TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args) {
  308. if (!PyArg_ParseTuple(args, "")) {
  309. PyErr_Clear();
  310. PyErr_SetString(PyExc_TypeError,
  311. "Invalid arguments to TSIGKeyRing constructor");
  312. return (-1);
  313. }
  314. self->cppobj = new(nothrow) TSIGKeyRing();
  315. if (self->cppobj == NULL) {
  316. PyErr_SetString(po_IscException, "Allocating TSIGKeyRing failed");
  317. return (-1);
  318. }
  319. return (0);
  320. }
  321. void
  322. TSIGKeyRing_destroy(s_TSIGKeyRing* self) {
  323. delete self->cppobj;
  324. self->cppobj = NULL;
  325. Py_TYPE(self)->tp_free(self);
  326. }
  327. PyObject*
  328. TSIGKeyRing_size(const s_TSIGKeyRing* const self) {
  329. return (Py_BuildValue("I", self->cppobj->size()));
  330. }
  331. PyObject*
  332. TSIGKeyRing_add(const s_TSIGKeyRing* const self, PyObject* args) {
  333. s_TSIGKey* tsigkey;
  334. if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey)) {
  335. try {
  336. const TSIGKeyRing::Result result =
  337. self->cppobj->add(*tsigkey->cppobj);
  338. return (Py_BuildValue("I", result));
  339. } catch (...) {
  340. PyErr_SetString(po_IscException, "Unexpected exception");
  341. return (NULL);
  342. }
  343. }
  344. PyErr_Clear();
  345. PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add");
  346. return (NULL);
  347. }
  348. PyObject*
  349. TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
  350. PyObject* key_name;
  351. if (PyArg_ParseTuple(args, "O!", &name_type, &key_name)) {
  352. const TSIGKeyRing::Result result =
  353. self->cppobj->remove(PyName_ToName(key_name));
  354. return (Py_BuildValue("I", result));
  355. }
  356. PyErr_Clear();
  357. PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add");
  358. return (NULL);
  359. }
  360. PyObject*
  361. TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
  362. PyObject* key_name;
  363. PyObject* algorithm_name;
  364. if (PyArg_ParseTuple(args, "O!O!", &name_type, &key_name,
  365. &name_type, &algorithm_name)) {
  366. const TSIGKeyRing::FindResult result =
  367. self->cppobj->find(PyName_ToName(key_name),
  368. PyName_ToName(algorithm_name));
  369. if (result.key != NULL) {
  370. s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
  371. if (key == NULL) {
  372. return (NULL);
  373. }
  374. key->cppobj = new(nothrow) TSIGKey(*result.key);
  375. if (key->cppobj == NULL) {
  376. Py_DECREF(key);
  377. PyErr_SetString(po_IscException,
  378. "Allocating TSIGKey object failed");
  379. return (NULL);
  380. }
  381. return (Py_BuildValue("IN", result.code, key));
  382. } else {
  383. return (Py_BuildValue("Is", result.code, NULL));
  384. }
  385. }
  386. return (NULL);
  387. }
  388. } // end of unnamed namespace
  389. namespace isc {
  390. namespace dns {
  391. namespace python {
  392. PyTypeObject tsigkeyring_type = {
  393. PyVarObject_HEAD_INIT(NULL, 0)
  394. "pydnspp.TSIGKeyRing",
  395. sizeof(s_TSIGKeyRing), // tp_basicsize
  396. 0, // tp_itemsize
  397. (destructor)TSIGKeyRing_destroy, // tp_dealloc
  398. NULL, // tp_print
  399. NULL, // tp_getattr
  400. NULL, // tp_setattr
  401. NULL, // tp_reserved
  402. NULL, // tp_repr
  403. NULL, // tp_as_number
  404. NULL, // tp_as_sequence
  405. NULL, // tp_as_mapping
  406. NULL, // tp_hash
  407. NULL, // tp_call
  408. NULL, // tp_str
  409. NULL, // tp_getattro
  410. NULL, // tp_setattro
  411. NULL, // tp_as_buffer
  412. Py_TPFLAGS_DEFAULT, // tp_flags
  413. "A simple repository of a set of TSIGKey objects.",
  414. NULL, // tp_traverse
  415. NULL, // tp_clear
  416. NULL, // tp_richcompare
  417. 0, // tp_weaklistoffset
  418. NULL, // tp_iter
  419. NULL, // tp_iternext
  420. TSIGKeyRing_methods, // tp_methods
  421. NULL, // tp_members
  422. NULL, // tp_getset
  423. NULL, // tp_base
  424. NULL, // tp_dict
  425. NULL, // tp_descr_get
  426. NULL, // tp_descr_set
  427. 0, // tp_dictoffset
  428. (initproc)TSIGKeyRing_init, // tp_init
  429. NULL, // tp_alloc
  430. PyType_GenericNew, // tp_new
  431. NULL, // tp_free
  432. NULL, // tp_is_gc
  433. NULL, // tp_bases
  434. NULL, // tp_mro
  435. NULL, // tp_cache
  436. NULL, // tp_subclasses
  437. NULL, // tp_weaklist
  438. NULL, // tp_del
  439. 0 // tp_version_tag
  440. };
  441. namespace internal {
  442. bool
  443. initModulePart_TSIGKeyRing(PyObject* mod) {
  444. if (PyType_Ready(&tsigkeyring_type) < 0) {
  445. return (false);
  446. }
  447. Py_INCREF(&tsigkeyring_type);
  448. void* p = &tsigkeyring_type;
  449. if (PyModule_AddObject(mod, "TSIGKeyRing",
  450. static_cast<PyObject*>(p)) != 0) {
  451. Py_DECREF(&tsigkeyring_type);
  452. return (false);
  453. }
  454. addClassVariable(tsigkeyring_type, "SUCCESS",
  455. Py_BuildValue("I", TSIGKeyRing::SUCCESS));
  456. addClassVariable(tsigkeyring_type, "EXIST",
  457. Py_BuildValue("I", TSIGKeyRing::EXIST));
  458. addClassVariable(tsigkeyring_type, "NOTFOUND",
  459. Py_BuildValue("I", TSIGKeyRing::NOTFOUND));
  460. return (true);
  461. }
  462. } // end namespace internal
  463. bool
  464. PyTSIGKeyRing_Check(PyObject* obj) {
  465. return (PyObject_TypeCheck(obj, &tsigkeyring_type));
  466. }
  467. const TSIGKeyRing&
  468. PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj) {
  469. const s_TSIGKeyRing* tsigkeyring =
  470. static_cast<const s_TSIGKeyRing*>(tsigkeyring_obj);
  471. return (*tsigkeyring->cppobj);
  472. }
  473. } // namespace python
  474. } // namespace dns
  475. } // namespace isc