1 // Copyright (c) 2017 Ryan Leckey
2 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
7 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8 // SOFTWARE.
9
10 #include "common.h"
11 #include "platform.h"
12 #include "exception.h"
13 #include "constants.h"
14 #include "keys.h"
15 #include "lxml.h"
16
17 #include <xmlsec/xmlenc.h>
18 #include <xmlsec/xmltree.h>
19
20 typedef struct {
21 PyObject_HEAD
22 xmlSecEncCtxPtr handle;
23 PyXmlSec_KeysManager* manager;
24 } PyXmlSec_EncryptionContext;
25
PyXmlSec_EncryptionContext__new__(PyTypeObject * type,PyObject * args,PyObject * kwargs)26 static PyObject* PyXmlSec_EncryptionContext__new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
27 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)PyType_GenericNew(type, args, kwargs);
28 PYXMLSEC_DEBUGF("%p: new enc context", ctx);
29 if (ctx != NULL) {
30 ctx->handle = NULL;
31 ctx->manager = NULL;
32 }
33 return (PyObject*)(ctx);
34 }
35
PyXmlSec_EncryptionContext__init__(PyObject * self,PyObject * args,PyObject * kwargs)36 static int PyXmlSec_EncryptionContext__init__(PyObject* self, PyObject* args, PyObject* kwargs) {
37 static char *kwlist[] = { "manager", NULL};
38
39 PyXmlSec_KeysManager* manager = NULL;
40 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
41
42 PYXMLSEC_DEBUGF("%p: init enc context", self);
43 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:__init__", kwlist, PyXmlSec_KeysManagerConvert, &manager)) {
44 goto ON_FAIL;
45 }
46 ctx->handle = xmlSecEncCtxCreate(manager != NULL ? manager->handle : NULL);
47 if (ctx->handle == NULL) {
48 PyXmlSec_SetLastError("failed to create the encryption context");
49 goto ON_FAIL;
50 }
51 ctx->manager = manager;
52 PYXMLSEC_DEBUGF("%p: init enc context - ok, manager - %p", self, manager);
53 return 0;
54 ON_FAIL:
55 PYXMLSEC_DEBUGF("%p: init enc context - failed", self);
56 Py_XDECREF(manager);
57 return -1;
58 }
59
PyXmlSec_EncryptionContext__del__(PyObject * self)60 static void PyXmlSec_EncryptionContext__del__(PyObject* self) {
61 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
62
63 PYXMLSEC_DEBUGF("%p: delete enc context", self);
64
65 if (ctx->handle != NULL) {
66 xmlSecEncCtxDestroy(ctx->handle);
67 }
68 // release manager object
69 Py_XDECREF(ctx->manager);
70 Py_TYPE(self)->tp_free(self);
71 }
72
73 static const char PyXmlSec_EncryptionContextKey__doc__[] = "Encryption key.\n";
PyXmlSec_EncryptionContextKeyGet(PyObject * self,void * closure)74 static PyObject* PyXmlSec_EncryptionContextKeyGet(PyObject* self, void* closure) {
75 PyXmlSec_EncryptionContext* ctx = ((PyXmlSec_EncryptionContext*)self);
76 PyXmlSec_Key* key;
77
78 if (ctx->handle->encKey == NULL) {
79 Py_RETURN_NONE;
80 }
81
82 key = PyXmlSec_NewKey();
83 key->handle = ctx->handle->encKey;
84 key->is_own = 0;
85 return (PyObject*)key;
86 }
87
PyXmlSec_EncryptionContextKeySet(PyObject * self,PyObject * value,void * closure)88 static int PyXmlSec_EncryptionContextKeySet(PyObject* self, PyObject* value, void* closure) {
89 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
90 PyXmlSec_Key* key;
91
92 PYXMLSEC_DEBUGF("%p, %p", self, value);
93
94 if (value == NULL) { // key deletion
95 if (ctx->handle->encKey != NULL) {
96 xmlSecKeyDestroy(ctx->handle->encKey);
97 ctx->handle->encKey = NULL;
98 }
99 return 0;
100 }
101
102 if (!PyObject_IsInstance(value, (PyObject*)PyXmlSec_KeyType)) {
103 PyErr_SetString(PyExc_TypeError, "instance of *xmlsec.Key* expected.");
104 return -1;
105 }
106
107 key = (PyXmlSec_Key*)value;
108 if (key->handle == NULL) {
109 PyErr_SetString(PyExc_TypeError, "empty key.");
110 return -1;
111 }
112
113 if (ctx->handle->encKey != NULL) {
114 xmlSecKeyDestroy(ctx->handle->encKey);
115 }
116
117 ctx->handle->encKey = xmlSecKeyDuplicate(key->handle);
118 if (ctx->handle->encKey == NULL) {
119 PyXmlSec_SetLastError("failed to duplicate key");
120 return -1;
121 }
122 return 0;
123 }
124
125 static const char PyXmlSec_EncryptionContextReset__doc__[] = \
126 "reset() -> None\n"\
127 "Reset this context, user settings are not touched.\n";
PyXmlSec_EncryptionContextReset(PyObject * self,PyObject * args,PyObject * kwargs)128 static PyObject* PyXmlSec_EncryptionContextReset(PyObject* self, PyObject* args, PyObject* kwargs) {
129 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
130
131 PYXMLSEC_DEBUGF("%p: reset context - start", self);
132 Py_BEGIN_ALLOW_THREADS;
133 xmlSecEncCtxReset(ctx->handle);
134 PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle);
135 Py_END_ALLOW_THREADS;
136 PYXMLSEC_DEBUGF("%p: reset context - ok", self);
137 Py_RETURN_NONE;
138 }
139
140 static const char PyXmlSec_EncryptionContextEncryptBinary__doc__[] = \
141 "encrypt_binary(template, data) -> lxml.etree._Element\n"
142 "Encrypts binary ``data`` according to ``EncryptedData`` template ``template``.\n\n"
143 ".. note:: ``template`` is modified in place.\n\n"
144 ":param template: the pointer to :xml:`<enc:EncryptedData/>` template node\n"
145 ":type template: :class:`lxml.etree._Element`\n"
146 ":param data: the data\n"
147 ":type data: :class:`bytes`\n"
148 ":return: the resulting :xml:`<enc:EncryptedData/>` subtree\n"
149 ":rtype: :class:`lxml.etree._Element`";
PyXmlSec_EncryptionContextEncryptBinary(PyObject * self,PyObject * args,PyObject * kwargs)150 static PyObject* PyXmlSec_EncryptionContextEncryptBinary(PyObject* self, PyObject* args, PyObject* kwargs) {
151 static char *kwlist[] = { "template", "data", NULL};
152
153 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
154 PyXmlSec_LxmlElementPtr template = NULL;
155 const char* data = NULL;
156 Py_ssize_t data_size = 0;
157 int rv;
158
159 PYXMLSEC_DEBUGF("%p: encrypt_binary - start", self);
160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s#:encrypt_binary", kwlist,
161 PyXmlSec_LxmlElementConverter, &template, &data, &data_size))
162 {
163 goto ON_FAIL;
164 }
165
166 Py_BEGIN_ALLOW_THREADS;
167 rv = xmlSecEncCtxBinaryEncrypt(ctx->handle, template->_c_node, (const xmlSecByte*)data, (xmlSecSize)data_size);
168 PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle);
169 Py_END_ALLOW_THREADS;
170
171 if (rv < 0) {
172 PyXmlSec_SetLastError("failed to encrypt binary");
173 goto ON_FAIL;
174 }
175 Py_INCREF(template);
176 PYXMLSEC_DEBUGF("%p: encrypt_binary - ok", self);
177
178 return (PyObject*)template;
179 ON_FAIL:
180 PYXMLSEC_DEBUGF("%p: encrypt_binary - fail", self);
181 return NULL;
182 }
183
184 // release the replaced nodes in a way safe for `lxml`
PyXmlSec_ClearReplacedNodes(xmlSecEncCtxPtr ctx,PyXmlSec_LxmlDocumentPtr doc)185 static void PyXmlSec_ClearReplacedNodes(xmlSecEncCtxPtr ctx, PyXmlSec_LxmlDocumentPtr doc) {
186 PyXmlSec_LxmlElementPtr* elem;
187 // release the replaced nodes in a way safe for `lxml`
188 xmlNodePtr n = ctx->replacedNodeList;
189 xmlNodePtr nn;
190
191 while (n != NULL) {
192 PYXMLSEC_DEBUGF("clear replaced node %p", n);
193 nn = n->next;
194 // if n has references, it will not be deleted
195 elem = PyXmlSec_elementFactory(doc, n);
196 if (NULL == elem)
197 xmlFreeNode(n);
198 else
199 Py_DECREF(elem);
200 n = nn;
201 }
202 ctx->replacedNodeList = NULL;
203 }
204
205 static const char PyXmlSec_EncryptionContextEncryptXml__doc__[] = \
206 "encrypt_xml(template, node) -> lxml.etree._Element\n"
207 "Encrypts ``node`` using ``template``.\n\n"
208 ".. note:: The ``\"Type\"`` attribute of ``template`` decides whether ``node`` itself "
209 "(``http://www.w3.org/2001/04/xmlenc#Element``) or its content (``http://www.w3.org/2001/04/xmlenc#Content``) is encrypted.\n"
210 " It must have one of these two values (or an exception is raised).\n"
211 " The operation modifies the tree and removes replaced nodes.\n\n"
212 ":param template: the pointer to :xml:`<enc:EncryptedData/>` template node\n\n"
213 ":type template: :class:`lxml.etree._Element`\n"
214 ":param node: the pointer to node for encryption\n\n"
215 ":type node: :class:`lxml.etree._Element`\n"
216 ":return: the pointer to newly created :xml:`<enc:EncryptedData/>` node\n"
217 ":rtype: :class:`lxml.etree._Element`";
PyXmlSec_EncryptionContextEncryptXml(PyObject * self,PyObject * args,PyObject * kwargs)218 static PyObject* PyXmlSec_EncryptionContextEncryptXml(PyObject* self, PyObject* args, PyObject* kwargs) {
219 static char *kwlist[] = { "template", "node", NULL};
220
221 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
222 PyXmlSec_LxmlElementPtr template = NULL;
223 PyXmlSec_LxmlElementPtr node = NULL;
224 xmlNodePtr xnew_node = NULL;
225 xmlChar* tmpType = NULL;
226 int rv = 0;
227
228 PYXMLSEC_DEBUGF("%p: encrypt_xml - start", self);
229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:encrypt_xml", kwlist,
230 PyXmlSec_LxmlElementConverter, &template, PyXmlSec_LxmlElementConverter, &node))
231 {
232 goto ON_FAIL;
233 }
234 tmpType = xmlGetProp(template->_c_node, XSTR("Type"));
235 if (tmpType == NULL || !(xmlStrEqual(tmpType, xmlSecTypeEncElement) || xmlStrEqual(tmpType, xmlSecTypeEncContent))) {
236 PyErr_SetString(PyXmlSec_Error, "unsupported `Type`, it should be `element` or `content`");
237 goto ON_FAIL;
238 }
239
240 // `xmlSecEncCtxXmlEncrypt` will replace the subtree rooted
241 // at `node._c_node` or its children by an extended subtree rooted at "c_node".
242 // We set `XMLSEC_ENC_RETURN_REPLACED_NODE` to prevent deallocation
243 // of the replaced node. This is important as `node` is still referencing it
244 ctx->handle->flags = XMLSEC_ENC_RETURN_REPLACED_NODE;
245
246 // try to do all actions whithin single python-free section
247 // rv has the following codes, 1 - failed to copy node, -1 - op failed, 0 - success
248 Py_BEGIN_ALLOW_THREADS;
249 if (template->_doc->_c_doc != node->_doc->_c_doc) {
250 // `xmlSecEncCtxEncrypt` expects *template* to belong to the document of *node*
251 // if this is not the case, we copy the `libxml2` subtree there.
252 xnew_node = xmlDocCopyNode(template->_c_node, node->_doc->_c_doc, 1); // recursive
253 if (xnew_node == NULL) {
254 rv = 1;
255 }
256 }
257 if (rv == 0 && xmlSecEncCtxXmlEncrypt(ctx->handle, xnew_node != NULL ? xnew_node: template->_c_node, node->_c_node) < 0) {
258 rv = -1;
259 if (xnew_node != NULL) {
260 xmlFreeNode(xnew_node);
261 xnew_node = NULL;
262 }
263 }
264 PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle);
265 Py_END_ALLOW_THREADS;
266
267 PyXmlSec_ClearReplacedNodes(ctx->handle, node->_doc);
268 if (NULL != PyErr_Occurred()) {
269 goto ON_FAIL;
270 }
271
272 if (rv != 0) {
273 if (rv > 0) {
274 PyErr_SetString(PyXmlSec_InternalError, "could not copy template tree");
275 } else {
276 PyXmlSec_SetLastError("failed to encrypt xml");
277 }
278 goto ON_FAIL;
279 }
280
281 xmlFree(tmpType);
282
283 PYXMLSEC_DEBUGF("%p: encrypt_xml - ok", self);
284 return (PyObject*)PyXmlSec_elementFactory(node->_doc, xnew_node != NULL ? xnew_node : template->_c_node);
285 ON_FAIL:
286 PYXMLSEC_DEBUGF("%p: encrypt_xml - fail", self);
287 xmlFree(tmpType);
288 return NULL;
289 }
290
291 static const char PyXmlSec_EncryptionContextEncryptUri__doc__[] = \
292 "encrypt_uri(template, uri) -> lxml.etree._Element\n"
293 "Encrypts binary data obtained from ``uri`` according to ``template``.\n\n"
294 ".. note:: ``template`` is modified in place.\n\n"
295 ":param template: the pointer to :xml:`<enc:EncryptedData/>` template node\n"
296 ":type template: :class:`lxml.etree._Element`\n"
297 ":param uri: the URI\n"
298 ":type uri: :class:`str`\n"
299 ":return: the resulting :xml:`<enc:EncryptedData/>` subtree\n"
300 ":rtype: :class:`lxml.etree._Element`";
PyXmlSec_EncryptionContextEncryptUri(PyObject * self,PyObject * args,PyObject * kwargs)301 static PyObject* PyXmlSec_EncryptionContextEncryptUri(PyObject* self, PyObject* args, PyObject* kwargs) {
302 static char *kwlist[] = { "template", "uri", NULL};
303
304 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
305 PyXmlSec_LxmlElementPtr template = NULL;
306 const char* uri = NULL;
307 int rv;
308
309 PYXMLSEC_DEBUGF("%p: encrypt_uri - start", self);
310 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s:encrypt_uri", kwlist, PyXmlSec_LxmlElementConverter, &template, &uri)) {
311 goto ON_FAIL;
312 }
313
314 Py_BEGIN_ALLOW_THREADS;
315 rv = xmlSecEncCtxUriEncrypt(ctx->handle, template->_c_node, (const xmlSecByte*)uri);
316 PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle);
317 Py_END_ALLOW_THREADS;
318
319 if (rv < 0) {
320 PyXmlSec_SetLastError("failed to encrypt URI");
321 goto ON_FAIL;
322 }
323 PYXMLSEC_DEBUGF("%p: encrypt_uri - ok", self);
324 Py_INCREF(template);
325 return (PyObject*)template;
326 ON_FAIL:
327 PYXMLSEC_DEBUGF("%p: encrypt_uri - fail", self);
328 return NULL;
329 }
330
331 static const char PyXmlSec_EncryptionContextDecrypt__doc__[] = \
332 "decrypt(node)\n"
333 "Decrypts ``node`` (an ``EncryptedData`` or ``EncryptedKey`` element) and returns the result. "
334 "The decryption may result in binary data or an XML subtree. "
335 "In the former case, the binary data is returned. In the latter case, "
336 "the input tree is modified and a reference to the decrypted XML subtree is returned.\n"
337 "If the operation modifies the tree, it removes replaced nodes.\n\n"
338 ":param node: the pointer to :xml:`<enc:EncryptedData/>` or :xml:`<enc:EncryptedKey/>` node\n"
339 ":type node: :class:`lxml.etree._Element`\n"
340 ":return: depends on input parameters\n"
341 ":rtype: :class:`lxml.etree._Element` or :class:`bytes`";
PyXmlSec_EncryptionContextDecrypt(PyObject * self,PyObject * args,PyObject * kwargs)342 static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* args, PyObject* kwargs) {
343 static char *kwlist[] = { "node", NULL};
344
345 PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
346 PyXmlSec_LxmlElementPtr node = NULL;
347
348 PyObject* node_num = NULL;
349 PyObject* parent = NULL;
350
351 PyObject* tmp;
352 xmlNodePtr root;
353 xmlNodePtr xparent;
354 int rv;
355 xmlChar* ttype;
356 int notContent;
357
358 PYXMLSEC_DEBUGF("%p: decrypt - start", self);
359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:decrypt", kwlist, PyXmlSec_LxmlElementConverter, &node)) {
360 goto ON_FAIL;
361 }
362
363 xparent = node->_c_node->parent;
364 if (xparent != NULL && !PyXmlSec_IsElement(xparent)) {
365 xparent = NULL;
366 }
367
368 if (xparent != NULL) {
369 parent = (PyObject*)PyXmlSec_elementFactory(node->_doc, xparent);
370 if (parent == NULL) {
371 PyErr_SetString(PyXmlSec_InternalError, "failed to construct parent");
372 goto ON_FAIL;
373 }
374 // get index of node
375 node_num = PyObject_CallMethod(parent, "index", "O", node);
376 PYXMLSEC_DEBUGF("parent: %p, %p", parent, node_num);
377 }
378
379 Py_BEGIN_ALLOW_THREADS;
380 ctx->handle->flags = XMLSEC_ENC_RETURN_REPLACED_NODE;
381 ctx->handle->mode = xmlSecCheckNodeName(node->_c_node, xmlSecNodeEncryptedKey, xmlSecEncNs) ? xmlEncCtxModeEncryptedKey : xmlEncCtxModeEncryptedData;
382 PYXMLSEC_DEBUGF("mode: %d", ctx->handle->mode);
383 rv = xmlSecEncCtxDecrypt(ctx->handle, node->_c_node);
384 PYXMLSEC_DUMP(xmlSecEncCtxDebugDump, ctx->handle);
385 Py_END_ALLOW_THREADS;
386
387 PyXmlSec_ClearReplacedNodes(ctx->handle, node->_doc);
388
389 if (rv < 0) {
390 PyXmlSec_SetLastError("failed to decrypt");
391 goto ON_FAIL;
392 }
393
394 if (!ctx->handle->resultReplaced) {
395 Py_XDECREF(node_num);
396 Py_XDECREF(parent);
397 PYXMLSEC_DEBUGF("%p: binary.decrypt - ok", self);
398 return PyBytes_FromStringAndSize(
399 (const char*)xmlSecBufferGetData(ctx->handle->result),
400 (Py_ssize_t)xmlSecBufferGetSize(ctx->handle->result)
401 );
402 }
403
404 if (xparent != NULL) {
405 ttype = xmlGetProp(node->_c_node, XSTR("Type"));
406 notContent = (ttype == NULL || !xmlStrEqual(ttype, xmlSecTypeEncContent));
407 xmlFree(ttype);
408
409 if (notContent) {
410 tmp = PyObject_GetItem(parent, node_num);
411 if (tmp == NULL) goto ON_FAIL;
412 Py_DECREF(parent);
413 parent = tmp;
414 }
415 Py_DECREF(node_num);
416 PYXMLSEC_DEBUGF("%p: parent.decrypt - ok", self);
417 return parent;
418 }
419
420 // root has been replaced
421 root = xmlDocGetRootElement(node->_doc->_c_doc);
422 if (root == NULL) {
423 PyErr_SetString(PyXmlSec_Error, "decryption resulted in a non well formed document");
424 goto ON_FAIL;
425 }
426
427 Py_XDECREF(node_num);
428 Py_XDECREF(parent);
429
430 PYXMLSEC_DEBUGF("%p: decrypt - ok", self);
431 return (PyObject*)PyXmlSec_elementFactory(node->_doc, root);
432
433 ON_FAIL:
434 PYXMLSEC_DEBUGF("%p: decrypt - fail", self);
435 Py_XDECREF(node_num);
436 Py_XDECREF(parent);
437 return NULL;
438 }
439
440 static PyGetSetDef PyXmlSec_EncryptionContextGetSet[] = {
441 {
442 "key",
443 (getter)PyXmlSec_EncryptionContextKeyGet,
444 (setter)PyXmlSec_EncryptionContextKeySet,
445 (char*)PyXmlSec_EncryptionContextKey__doc__,
446 NULL
447 },
448 {NULL} /* Sentinel */
449 };
450
451 static PyMethodDef PyXmlSec_EncryptionContextMethods[] = {
452 {
453 "reset",
454 (PyCFunction)PyXmlSec_EncryptionContextReset,
455 METH_NOARGS,
456 PyXmlSec_EncryptionContextReset__doc__,
457 },
458 {
459 "encrypt_binary",
460 (PyCFunction)PyXmlSec_EncryptionContextEncryptBinary,
461 METH_VARARGS|METH_KEYWORDS,
462 PyXmlSec_EncryptionContextEncryptBinary__doc__,
463 },
464 {
465 "encrypt_xml",
466 (PyCFunction)PyXmlSec_EncryptionContextEncryptXml,
467 METH_VARARGS|METH_KEYWORDS,
468 PyXmlSec_EncryptionContextEncryptXml__doc__
469 },
470 {
471 "encrypt_uri",
472 (PyCFunction)PyXmlSec_EncryptionContextEncryptUri,
473 METH_VARARGS|METH_KEYWORDS,
474 PyXmlSec_EncryptionContextEncryptUri__doc__
475 },
476 {
477 "decrypt",
478 (PyCFunction)PyXmlSec_EncryptionContextDecrypt,
479 METH_VARARGS|METH_KEYWORDS,
480 PyXmlSec_EncryptionContextDecrypt__doc__
481 },
482 {NULL, NULL} /* sentinel */
483 };
484
485 static PyTypeObject _PyXmlSec_EncryptionContextType = {
486 PyVarObject_HEAD_INIT(NULL, 0)
487 STRINGIFY(MODULE_NAME) ".EncryptionContext", /* tp_name */
488 sizeof(PyXmlSec_EncryptionContext), /* tp_basicsize */
489 0, /* tp_itemsize */
490 PyXmlSec_EncryptionContext__del__, /* tp_dealloc */
491 0, /* tp_print */
492 0, /* tp_getattr */
493 0, /* tp_setattr */
494 0, /* tp_reserved */
495 0, /* tp_repr */
496 0, /* tp_as_number */
497 0, /* tp_as_sequence */
498 0, /* tp_as_mapping */
499 0, /* tp_hash */
500 0, /* tp_call */
501 0, /* tp_str */
502 0, /* tp_getattro */
503 0, /* tp_setattro */
504 0, /* tp_as_buffer */
505 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
506 "XML Encryption implementation", /* tp_doc */
507 0, /* tp_traverse */
508 0, /* tp_clear */
509 0, /* tp_richcompare */
510 0, /* tp_weaklistoffset */
511 0, /* tp_iter */
512 0, /* tp_iternext */
513 PyXmlSec_EncryptionContextMethods, /* tp_methods */
514 0, /* tp_members */
515 PyXmlSec_EncryptionContextGetSet, /* tp_getset */
516 0, /* tp_base */
517 0, /* tp_dict */
518 0, /* tp_descr_get */
519 0, /* tp_descr_set */
520 0, /* tp_dictoffset */
521 PyXmlSec_EncryptionContext__init__, /* tp_init */
522 0, /* tp_alloc */
523 PyXmlSec_EncryptionContext__new__, /* tp_new */
524 0 /* tp_free */
525 };
526
527 PyTypeObject* PyXmlSec_EncryptionContextType = &_PyXmlSec_EncryptionContextType;
528
PyXmlSec_EncModule_Init(PyObject * package)529 int PyXmlSec_EncModule_Init(PyObject* package) {
530 if (PyType_Ready(PyXmlSec_EncryptionContextType) < 0) goto ON_FAIL;
531
532 PYXMLSEC_DEBUGF("%p", PyXmlSec_EncryptionContextType);
533 // since objects is created as static objects, need to increase refcount to prevent deallocate
534 Py_INCREF(PyXmlSec_EncryptionContextType);
535
536 if (PyModule_AddObject(package, "EncryptionContext", (PyObject*)PyXmlSec_EncryptionContextType) < 0) goto ON_FAIL;
537 return 0;
538 ON_FAIL:
539 return -1;
540 }
541