tsigkey_python.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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. // For each class, we need a struct, a helper functions (init, destroy,
  28. // and static wrappers around the methods we export), a list of methods,
  29. // and a type description
  30. //
  31. // TSIGKey
  32. //
  33. namespace {
  34. // The s_* Class simply covers one instantiation of the object
  35. class s_TSIGKey : public PyObject {
  36. public:
  37. s_TSIGKey() : cppobj(NULL) {};
  38. TSIGKey* cppobj;
  39. };
  40. //
  41. // We declare the functions here, the definitions are below
  42. // the type definition of the object, since both can use the other
  43. //
  44. // General creation and destruction
  45. int TSIGKey_init(s_TSIGKey* self, PyObject* args);
  46. void TSIGKey_destroy(s_TSIGKey* self);
  47. // These are the functions we export
  48. // This is a second version of toText, we need one where the argument
  49. // is a PyObject*, for the str() function in python.
  50. PyObject* TSIGKey_getKeyName(const s_TSIGKey* self);
  51. PyObject* TSIGKey_getAlgorithmName(const s_TSIGKey* self);
  52. PyObject* TSIGKey_getSecret(const s_TSIGKey* self);
  53. PyObject* TSIGKey_toText(const s_TSIGKey* self);
  54. // This list contains the actual set of functions we have in
  55. // python. Each entry has
  56. // 1. Python method name
  57. // 2. Our static function here
  58. // 3. Argument type
  59. // 4. Documentation
  60. PyMethodDef TSIGKey_methods[] = {
  61. { "get_key_name",
  62. reinterpret_cast<PyCFunction>(TSIGKey_getKeyName), METH_NOARGS,
  63. "Return the key name." },
  64. { "get_algorithm_name",
  65. reinterpret_cast<PyCFunction>(TSIGKey_getAlgorithmName), METH_NOARGS,
  66. "Return the algorithm name." },
  67. { "get_secret",
  68. reinterpret_cast<PyCFunction>(TSIGKey_getSecret), METH_NOARGS,
  69. "Return the value of the TSIG secret." },
  70. { "to_text", reinterpret_cast<PyCFunction>(TSIGKey_toText), METH_NOARGS,
  71. "Returns the string representation (name:secret:algorithm)" },
  72. { NULL, NULL, 0, NULL }
  73. };
  74. int
  75. TSIGKey_init(s_TSIGKey* self, PyObject* args) {
  76. try {
  77. const char* str;
  78. if (PyArg_ParseTuple(args, "s", &str)) {
  79. self->cppobj = new TSIGKey(str);
  80. return (0);
  81. }
  82. PyErr_Clear();
  83. const PyObject* key_name;
  84. const PyObject* algorithm_name;
  85. PyObject* bytes_obj;
  86. const char* secret;
  87. Py_ssize_t secret_len;
  88. if (PyArg_ParseTuple(args, "O!O!O", &name_type, &key_name,
  89. &name_type, &algorithm_name, &bytes_obj) &&
  90. PyObject_AsCharBuffer(bytes_obj, &secret, &secret_len) == 0) {
  91. if (secret_len == 0) {
  92. secret = NULL;
  93. }
  94. self->cppobj = new TSIGKey(PyName_ToName(key_name),
  95. PyName_ToName(algorithm_name),
  96. secret, secret_len);
  97. return (0);
  98. }
  99. } catch (const isc::InvalidParameter& ex) {
  100. PyErr_SetString(po_InvalidParameter, ex.what());
  101. return (-1);
  102. } catch (...) {
  103. PyErr_SetString(po_IscException, "Unexpected exception");
  104. return (-1);
  105. }
  106. PyErr_Clear();
  107. PyErr_SetString(PyExc_TypeError,
  108. "Invalid arguments to TSIGKey constructor");
  109. return (-1);
  110. }
  111. void
  112. TSIGKey_destroy(s_TSIGKey* const self) {
  113. delete self->cppobj;
  114. self->cppobj = NULL;
  115. Py_TYPE(self)->tp_free(self);
  116. }
  117. PyObject*
  118. TSIGKey_getKeyName(const s_TSIGKey* const self) {
  119. try {
  120. return (createNameObject(self->cppobj->getKeyName()));
  121. } catch (const exception& ex) {
  122. const string ex_what =
  123. "Failed to get key name of TSIGKey: " + string(ex.what());
  124. PyErr_SetString(po_IscException, ex_what.c_str());
  125. } catch (...) {
  126. PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
  127. "getting key name of TSIGKey");
  128. }
  129. return (NULL);
  130. }
  131. PyObject*
  132. TSIGKey_getAlgorithmName(const s_TSIGKey* const self) {
  133. try {
  134. return (createNameObject(self->cppobj->getAlgorithmName()));
  135. } catch (const exception& ex) {
  136. const string ex_what =
  137. "Failed to get algorithm name of TSIGKey: " + string(ex.what());
  138. PyErr_SetString(po_IscException, ex_what.c_str());
  139. } catch (...) {
  140. PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
  141. "getting algorithm name of TSIGKey");
  142. }
  143. return (NULL);
  144. }
  145. PyObject*
  146. TSIGKey_getSecret(const s_TSIGKey* const self) {
  147. return (Py_BuildValue("y#", self->cppobj->getSecret(),
  148. self->cppobj->getSecretLength()));
  149. }
  150. PyObject*
  151. TSIGKey_toText(const s_TSIGKey* self) {
  152. return (Py_BuildValue("s", self->cppobj->toText().c_str()));
  153. }
  154. } // end of unnamed namespace
  155. namespace isc {
  156. namespace dns {
  157. namespace python {
  158. // This defines the complete type for reflection in python and
  159. // parsing of PyObject* to s_EDNS
  160. // Most of the functions are not actually implemented and NULL here.
  161. PyTypeObject tsigkey_type = {
  162. PyVarObject_HEAD_INIT(NULL, 0)
  163. "pydnspp.TSIGKey",
  164. sizeof(s_TSIGKey), // tp_basicsize
  165. 0, // tp_itemsize
  166. (destructor)TSIGKey_destroy, // tp_dealloc
  167. NULL, // tp_print
  168. NULL, // tp_getattr
  169. NULL, // tp_setattr
  170. NULL, // tp_reserved
  171. NULL, // tp_repr
  172. NULL, // tp_as_number
  173. NULL, // tp_as_sequence
  174. NULL, // tp_as_mapping
  175. NULL, // tp_hash
  176. NULL, // tp_call
  177. NULL, // tp_str
  178. NULL, // tp_getattro
  179. NULL, // tp_setattro
  180. NULL, // tp_as_buffer
  181. Py_TPFLAGS_DEFAULT, // tp_flags
  182. "The TSIGKey class holds a TSIG key along with some related attributes as "
  183. "defined in RFC2845.",
  184. NULL, // tp_traverse
  185. NULL, // tp_clear
  186. NULL, // tp_richcompare
  187. 0, // tp_weaklistoffset
  188. NULL, // tp_iter
  189. NULL, // tp_iternext
  190. TSIGKey_methods, // tp_methods
  191. NULL, // tp_members
  192. NULL, // tp_getset
  193. NULL, // tp_base
  194. NULL, // tp_dict
  195. NULL, // tp_descr_get
  196. NULL, // tp_descr_set
  197. 0, // tp_dictoffset
  198. (initproc)TSIGKey_init, // tp_init
  199. NULL, // tp_alloc
  200. PyType_GenericNew, // tp_new
  201. NULL, // tp_free
  202. NULL, // tp_is_gc
  203. NULL, // tp_bases
  204. NULL, // tp_mro
  205. NULL, // tp_cache
  206. NULL, // tp_subclasses
  207. NULL, // tp_weaklist
  208. NULL, // tp_del
  209. 0 // tp_version_tag
  210. };
  211. bool
  212. PyTSIGKey_Check(PyObject* obj) {
  213. if (obj == NULL) {
  214. isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
  215. }
  216. return (PyObject_TypeCheck(obj, &tsigkey_type));
  217. }
  218. const TSIGKey&
  219. PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj) {
  220. const s_TSIGKey* tsigkey = static_cast<const s_TSIGKey*>(tsigkey_obj);
  221. return (*tsigkey->cppobj);
  222. }
  223. } // namespace python
  224. } // namespace dns
  225. } // namespace isc
  226. //
  227. // End of TSIGKey
  228. //
  229. //
  230. // TSIGKeyRing
  231. //
  232. namespace {
  233. // The s_* Class simply covers one instantiation of the object
  234. class s_TSIGKeyRing : public PyObject {
  235. public:
  236. s_TSIGKeyRing() : cppobj(NULL) {};
  237. TSIGKeyRing* cppobj;
  238. };
  239. //
  240. // We declare the functions here, the definitions are below
  241. // the type definition of the object, since both can use the other
  242. //
  243. int TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args);
  244. void TSIGKeyRing_destroy(s_TSIGKeyRing* self);
  245. PyObject* TSIGKeyRing_size(const s_TSIGKeyRing* self);
  246. PyObject* TSIGKeyRing_add(const s_TSIGKeyRing* self, PyObject* args);
  247. PyObject* TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args);
  248. PyObject* TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args);
  249. PyMethodDef TSIGKeyRing_methods[] = {
  250. { "size", reinterpret_cast<PyCFunction>(TSIGKeyRing_size), METH_NOARGS,
  251. "Return the number of keys stored in the TSIGKeyRing." },
  252. { "add", reinterpret_cast<PyCFunction>(TSIGKeyRing_add), METH_VARARGS,
  253. "Add a TSIGKey to the TSIGKeyRing." },
  254. { "remove", reinterpret_cast<PyCFunction>(TSIGKeyRing_remove),
  255. METH_VARARGS,
  256. "Remove a TSIGKey for the given name from the TSIGKeyRing." },
  257. { "find", reinterpret_cast<PyCFunction>(TSIGKeyRing_find), METH_VARARGS,
  258. "Find a TSIGKey for the given name in the TSIGKeyRing. "
  259. "It returns a tuple of (result_code, key)." },
  260. { NULL, NULL, 0, NULL }
  261. };
  262. int
  263. TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args) {
  264. if (!PyArg_ParseTuple(args, "")) {
  265. PyErr_Clear();
  266. PyErr_SetString(PyExc_TypeError,
  267. "Invalid arguments to TSIGKeyRing constructor");
  268. return (-1);
  269. }
  270. self->cppobj = new(nothrow) TSIGKeyRing();
  271. if (self->cppobj == NULL) {
  272. PyErr_SetString(po_IscException, "Allocating TSIGKeyRing failed");
  273. return (-1);
  274. }
  275. return (0);
  276. }
  277. void
  278. TSIGKeyRing_destroy(s_TSIGKeyRing* self) {
  279. delete self->cppobj;
  280. self->cppobj = NULL;
  281. Py_TYPE(self)->tp_free(self);
  282. }
  283. PyObject*
  284. TSIGKeyRing_size(const s_TSIGKeyRing* const self) {
  285. return (Py_BuildValue("I", self->cppobj->size()));
  286. }
  287. PyObject*
  288. TSIGKeyRing_add(const s_TSIGKeyRing* const self, PyObject* args) {
  289. s_TSIGKey* tsigkey;
  290. if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey)) {
  291. try {
  292. const TSIGKeyRing::Result result =
  293. self->cppobj->add(*tsigkey->cppobj);
  294. return (Py_BuildValue("I", result));
  295. } catch (...) {
  296. PyErr_SetString(po_IscException, "Unexpected exception");
  297. return (NULL);
  298. }
  299. }
  300. PyErr_Clear();
  301. PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add");
  302. return (NULL);
  303. }
  304. PyObject*
  305. TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
  306. PyObject* key_name;
  307. if (PyArg_ParseTuple(args, "O!", &name_type, &key_name)) {
  308. const TSIGKeyRing::Result result =
  309. self->cppobj->remove(PyName_ToName(key_name));
  310. return (Py_BuildValue("I", result));
  311. }
  312. PyErr_Clear();
  313. PyErr_SetString(PyExc_TypeError, "Invalid arguments to TSIGKeyRing.add");
  314. return (NULL);
  315. }
  316. PyObject*
  317. TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
  318. PyObject* key_name;
  319. PyObject* algorithm_name;
  320. if (PyArg_ParseTuple(args, "O!O!", &name_type, &key_name,
  321. &name_type, &algorithm_name)) {
  322. const TSIGKeyRing::FindResult result =
  323. self->cppobj->find(PyName_ToName(key_name),
  324. PyName_ToName(algorithm_name));
  325. if (result.key != NULL) {
  326. s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
  327. if (key == NULL) {
  328. return (NULL);
  329. }
  330. key->cppobj = new(nothrow) TSIGKey(*result.key);
  331. if (key->cppobj == NULL) {
  332. Py_DECREF(key);
  333. PyErr_SetString(po_IscException,
  334. "Allocating TSIGKey object failed");
  335. return (NULL);
  336. }
  337. return (Py_BuildValue("IN", result.code, key));
  338. } else {
  339. return (Py_BuildValue("Is", result.code, NULL));
  340. }
  341. }
  342. return (NULL);
  343. }
  344. } // end of unnamed namespace
  345. namespace isc {
  346. namespace dns {
  347. namespace python {
  348. PyTypeObject tsigkeyring_type = {
  349. PyVarObject_HEAD_INIT(NULL, 0)
  350. "pydnspp.TSIGKeyRing",
  351. sizeof(s_TSIGKeyRing), // tp_basicsize
  352. 0, // tp_itemsize
  353. (destructor)TSIGKeyRing_destroy, // tp_dealloc
  354. NULL, // tp_print
  355. NULL, // tp_getattr
  356. NULL, // tp_setattr
  357. NULL, // tp_reserved
  358. NULL, // tp_repr
  359. NULL, // tp_as_number
  360. NULL, // tp_as_sequence
  361. NULL, // tp_as_mapping
  362. NULL, // tp_hash
  363. NULL, // tp_call
  364. NULL, // tp_str
  365. NULL, // tp_getattro
  366. NULL, // tp_setattro
  367. NULL, // tp_as_buffer
  368. Py_TPFLAGS_DEFAULT, // tp_flags
  369. "A simple repository of a set of TSIGKey objects.",
  370. NULL, // tp_traverse
  371. NULL, // tp_clear
  372. NULL, // tp_richcompare
  373. 0, // tp_weaklistoffset
  374. NULL, // tp_iter
  375. NULL, // tp_iternext
  376. TSIGKeyRing_methods, // tp_methods
  377. NULL, // tp_members
  378. NULL, // tp_getset
  379. NULL, // tp_base
  380. NULL, // tp_dict
  381. NULL, // tp_descr_get
  382. NULL, // tp_descr_set
  383. 0, // tp_dictoffset
  384. (initproc)TSIGKeyRing_init, // tp_init
  385. NULL, // tp_alloc
  386. PyType_GenericNew, // tp_new
  387. NULL, // tp_free
  388. NULL, // tp_is_gc
  389. NULL, // tp_bases
  390. NULL, // tp_mro
  391. NULL, // tp_cache
  392. NULL, // tp_subclasses
  393. NULL, // tp_weaklist
  394. NULL, // tp_del
  395. 0 // tp_version_tag
  396. };
  397. bool
  398. PyTSIGKeyRing_Check(PyObject* obj) {
  399. if (obj == NULL) {
  400. isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
  401. }
  402. return (PyObject_TypeCheck(obj, &tsigkeyring_type));
  403. }
  404. const TSIGKeyRing&
  405. PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj) {
  406. if (tsigkeyring_obj == NULL) {
  407. isc_throw(PyCPPWrapperException,
  408. "obj argument NULL in TSIGKeyRing PyObject conversion");
  409. }
  410. const s_TSIGKeyRing* tsigkeyring =
  411. static_cast<const s_TSIGKeyRing*>(tsigkeyring_obj);
  412. return (*tsigkeyring->cppobj);
  413. }
  414. } // namespace python
  415. } // namespace dns
  416. } // namespace isc