Line data Source code
1 : /*
2 : # Copyright (C) 2016 g10 Code GmbH
3 : # Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
4 : # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
5 : #
6 : # This library is free software; you can redistribute it and/or
7 : # modify it under the terms of the GNU Lesser General Public
8 : # License as published by the Free Software Foundation; either
9 : # version 2.1 of the License, or (at your option) any later version.
10 : #
11 : # This library is distributed in the hope that it will be useful,
12 : # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : # Lesser General Public License for more details.
15 : #
16 : # You should have received a copy of the GNU Lesser General Public
17 : # License along with this library; if not, write to the Free Software
18 : # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 : */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include <assert.h>
26 : #include <stdio.h>
27 : #include <gpgme.h>
28 : #include <stdlib.h>
29 : #include <string.h>
30 : #include "Python.h"
31 :
32 : #include "helpers.h"
33 : #include "private.h"
34 :
35 : /* Flag specifying whether this is an in-tree build. */
36 : int gpg_in_tree_build =
37 : #if IN_TREE_BUILD
38 : 1
39 : #else
40 : 0
41 : #endif
42 : ;
43 :
44 : static PyObject *GPGMEError = NULL;
45 :
46 128 : void _gpg_exception_init(void) {
47 128 : if (GPGMEError == NULL) {
48 : PyObject *errors;
49 8 : PyObject *from_list = PyList_New(0);
50 8 : errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
51 : PyEval_GetLocals(), from_list, 1);
52 8 : Py_XDECREF(from_list);
53 8 : if (errors) {
54 8 : GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
55 8 : Py_XINCREF(GPGMEError);
56 : }
57 : }
58 128 : }
59 :
60 : static PyObject *
61 0 : _gpg_raise_exception(gpgme_error_t err)
62 : {
63 : PyObject *e;
64 :
65 0 : _gpg_exception_init();
66 0 : if (GPGMEError == NULL)
67 0 : return PyErr_Format(PyExc_RuntimeError, "Got gpgme_error_t %d", err);
68 :
69 0 : e = PyObject_CallFunction(GPGMEError, "l", (long) err);
70 0 : if (e == NULL)
71 : return NULL;
72 :
73 0 : PyErr_SetObject(GPGMEError, e);
74 0 : Py_DECREF(e);
75 :
76 : return NULL; /* raise */
77 : }
78 :
79 8 : gpgme_error_t _gpg_exception2code(void) {
80 8 : gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
81 8 : if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
82 0 : PyObject *type = 0, *value = 0, *traceback = 0;
83 0 : PyObject *error = 0;
84 0 : PyErr_Fetch(&type, &value, &traceback);
85 0 : PyErr_NormalizeException(&type, &value, &traceback);
86 0 : error = PyObject_GetAttrString(value, "error");
87 0 : err_status = PyLong_AsLong(error);
88 0 : Py_DECREF(error);
89 0 : PyErr_Restore(type, value, traceback);
90 : }
91 8 : return err_status;
92 : }
93 :
94 : /* Exception support for callbacks. */
95 : #define EXCINFO "_callback_excinfo"
96 :
97 54 : static void _gpg_stash_callback_exception(PyObject *weak_self)
98 : {
99 : PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
100 :
101 54 : PyErr_Fetch(&ptype, &pvalue, &ptraceback);
102 54 : excinfo = PyTuple_New(3);
103 54 : PyTuple_SetItem(excinfo, 0, ptype);
104 :
105 54 : if (pvalue)
106 54 : PyTuple_SetItem(excinfo, 1, pvalue);
107 : else {
108 0 : Py_INCREF(Py_None);
109 0 : PyTuple_SetItem(excinfo, 1, Py_None);
110 : }
111 :
112 54 : if (ptraceback)
113 44 : PyTuple_SetItem(excinfo, 2, ptraceback);
114 : else {
115 10 : Py_INCREF(Py_None);
116 10 : PyTuple_SetItem(excinfo, 2, Py_None);
117 : }
118 :
119 54 : self = PyWeakref_GetObject(weak_self);
120 : /* self only has a borrowed reference. */
121 54 : if (self == Py_None) {
122 : /* This should not happen, as even if we're called from the data
123 : release callback triggered from the wrappers destructor, the
124 : object is still alive and hence the weak reference still refers
125 : to the object. However, in case this ever changes, not seeing
126 : any exceptions is worse than having a little extra code, so
127 : here we go. */
128 0 : fprintf(stderr,
129 : "Error occurred in callback, but the wrapper object "
130 : "has been deallocated.\n");
131 0 : PyErr_Restore(ptype, pvalue, ptraceback);
132 0 : PyErr_Print();
133 : }
134 : else
135 54 : PyObject_SetAttrString(self, EXCINFO, excinfo);
136 54 : Py_DECREF(excinfo);
137 54 : }
138 :
139 24 : PyObject *gpg_raise_callback_exception(PyObject *self)
140 : {
141 24 : PyGILState_STATE state = PyGILState_Ensure();
142 : PyObject *ptype, *pvalue, *ptraceback, *excinfo;
143 :
144 24 : if (! PyObject_HasAttrString(self, EXCINFO))
145 : goto leave;
146 :
147 24 : excinfo = PyObject_GetAttrString(self, EXCINFO);
148 24 : if (! PyTuple_Check(excinfo))
149 : {
150 0 : Py_DECREF(excinfo);
151 : goto leave;
152 : }
153 :
154 24 : ptype = PyTuple_GetItem(excinfo, 0);
155 24 : Py_INCREF(excinfo);
156 :
157 24 : pvalue = PyTuple_GetItem(excinfo, 1);
158 24 : if (pvalue == Py_None)
159 : pvalue = NULL;
160 : else
161 24 : Py_INCREF(pvalue);
162 :
163 24 : ptraceback = PyTuple_GetItem(excinfo, 2);
164 24 : if (ptraceback == Py_None)
165 : ptraceback = NULL;
166 : else
167 14 : Py_INCREF(ptraceback);
168 :
169 : /* We now have references for the extracted items. */
170 24 : Py_DECREF(excinfo);
171 :
172 : /* Clear the exception information. It is important to do this
173 : before setting the error, because setting the attribute may
174 : execute python code, and the runtime system raises a SystemError
175 : if an exception is set but values are returned. */
176 24 : Py_INCREF(Py_None);
177 24 : PyObject_SetAttrString(self, EXCINFO, Py_None);
178 :
179 : /* Restore exception. */
180 24 : PyErr_Restore(ptype, pvalue, ptraceback);
181 24 : PyGILState_Release(state);
182 24 : return NULL; /* Raise exception. */
183 :
184 : leave:
185 0 : Py_INCREF(Py_None);
186 0 : PyGILState_Release(state);
187 0 : return Py_None;
188 : }
189 : #undef EXCINFO
190 :
191 : /* Argument conversion. */
192 :
193 : /* Convert object to a pointer to gpgme type, generic version. */
194 : PyObject *
195 193 : _gpg_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
196 : {
197 193 : PyObject *pyname = NULL, *pypointer = NULL;
198 193 : pyname = PyObject_GetAttrString(input, "_ctype");
199 193 : if (pyname && PyUnicode_Check(pyname))
200 : {
201 193 : PyObject *encoded = PyUnicode_AsUTF8String(pyname);
202 193 : if (strcmp(PyBytes_AsString(encoded), objtype) != 0)
203 : {
204 0 : PyErr_Format(PyExc_TypeError,
205 : "arg %d: Expected value of type %s, but got %s",
206 : argnum, objtype, PyBytes_AsString(encoded));
207 0 : Py_DECREF(encoded);
208 0 : Py_DECREF(pyname);
209 : return NULL;
210 : }
211 193 : Py_DECREF(encoded);
212 : }
213 : else
214 : return NULL;
215 :
216 193 : Py_DECREF(pyname);
217 193 : pypointer = PyObject_GetAttrString(input, "wrapped");
218 193 : if (pypointer == NULL) {
219 0 : PyErr_Format(PyExc_TypeError,
220 : "arg %d: Use of uninitialized Python object %s",
221 : argnum, objtype);
222 0 : return NULL;
223 : }
224 : return pypointer;
225 : }
226 :
227 : /* Convert object to a pointer to gpgme type, version for data
228 : objects. Constructs a wrapper Python on the fly e.g. for file-like
229 : objects with a fileno method, returning it in WRAPPER. This object
230 : must be de-referenced when no longer needed. */
231 : PyObject *
232 270 : _gpg_obj2gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
233 : PyObject **bytesio, Py_buffer *view)
234 : {
235 : gpgme_error_t err;
236 : PyObject *data;
237 : PyObject *fd;
238 :
239 : /* See if it is a file-like object with file number. */
240 270 : fd = PyObject_CallMethod(input, "fileno", NULL);
241 270 : if (fd) {
242 18 : err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
243 18 : Py_DECREF(fd);
244 18 : if (err)
245 0 : return _gpg_raise_exception (err);
246 :
247 18 : return _gpg_wrap_gpgme_data_t(*wrapper);
248 : }
249 : else
250 252 : PyErr_Clear();
251 :
252 : /* No? Maybe it implements the buffer protocol. */
253 252 : data = PyObject_CallMethod(input, "getbuffer", NULL);
254 252 : if (data)
255 : {
256 : /* Save a reference to input, which seems to be a BytesIO
257 : object. */
258 2 : Py_INCREF(input);
259 2 : *bytesio = input;
260 : }
261 : else
262 : {
263 250 : PyErr_Clear();
264 :
265 : /* No, but maybe the user supplied a buffer object? */
266 250 : data = input;
267 : }
268 :
269 : /* Do we have a buffer object? */
270 252 : if (PyObject_CheckBuffer(data))
271 : {
272 59 : if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
273 : return NULL;
274 :
275 59 : if (data != input)
276 2 : Py_DECREF(data);
277 :
278 : assert (view->obj);
279 : assert (view->ndim == 1);
280 : assert (view->shape == NULL);
281 : assert (view->strides == NULL);
282 : assert (view->suboffsets == NULL);
283 :
284 59 : err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
285 59 : if (err)
286 0 : return _gpg_raise_exception (err);
287 :
288 59 : return _gpg_wrap_gpgme_data_t(*wrapper);
289 : }
290 :
291 : /* As last resort we assume it is a wrapped data object. */
292 193 : if (PyObject_HasAttrString(data, "_ctype"))
293 193 : return _gpg_obj2gpgme_t(data, "gpgme_data_t", argnum);
294 :
295 0 : return PyErr_Format(PyExc_TypeError,
296 : "arg %d: expected gpg.Data, file, or an object "
297 : "implementing the buffer protocol, got %s",
298 0 : argnum, data->ob_type->tp_name);
299 : }
300 :
301 :
302 :
303 : PyObject *
304 139 : _gpg_wrap_result(PyObject *fragile, const char *classname)
305 : {
306 : static PyObject *results;
307 : PyObject *class;
308 : PyObject *replacement;
309 :
310 139 : if (results == NULL)
311 : {
312 28 : PyObject *from_list = PyList_New(0);
313 28 : if (from_list == NULL)
314 : return NULL;
315 :
316 28 : results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
317 : PyEval_GetLocals(), from_list, 1);
318 28 : Py_DECREF(from_list);
319 :
320 28 : if (results == NULL)
321 : return NULL;
322 : }
323 :
324 139 : class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
325 139 : if (class == NULL)
326 : return NULL;
327 :
328 139 : replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
329 139 : Py_DECREF(class);
330 139 : return replacement;
331 : }
332 :
333 :
334 :
335 : /* Callback support. */
336 18 : static gpgme_error_t pyPassphraseCb(void *hook,
337 : const char *uid_hint,
338 : const char *passphrase_info,
339 : int prev_was_bad,
340 : int fd) {
341 18 : PyGILState_STATE state = PyGILState_Ensure();
342 18 : PyObject *pyhook = (PyObject *) hook;
343 18 : PyObject *self = NULL;
344 18 : PyObject *func = NULL;
345 18 : PyObject *args = NULL;
346 18 : PyObject *retval = NULL;
347 18 : PyObject *dataarg = NULL;
348 18 : PyObject *encoded = NULL;
349 18 : gpgme_error_t err_status = 0;
350 :
351 18 : _gpg_exception_init();
352 :
353 : assert (PyTuple_Check(pyhook));
354 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
355 18 : self = PyTuple_GetItem(pyhook, 0);
356 18 : func = PyTuple_GetItem(pyhook, 1);
357 18 : if (PyTuple_Size(pyhook) == 3) {
358 4 : dataarg = PyTuple_GetItem(pyhook, 2);
359 4 : args = PyTuple_New(4);
360 : } else {
361 14 : args = PyTuple_New(3);
362 : }
363 :
364 18 : if (uid_hint == NULL)
365 : {
366 18 : Py_INCREF(Py_None);
367 18 : PyTuple_SetItem(args, 0, Py_None);
368 : }
369 : else
370 0 : PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
371 : "strict"));
372 18 : if (PyErr_Occurred()) {
373 0 : Py_DECREF(args);
374 : err_status = gpg_error(GPG_ERR_GENERAL);
375 : goto leave;
376 : }
377 :
378 18 : PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
379 18 : PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
380 18 : if (dataarg) {
381 4 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
382 4 : PyTuple_SetItem(args, 3, dataarg);
383 : }
384 :
385 18 : retval = PyObject_CallObject(func, args);
386 18 : Py_DECREF(args);
387 18 : if (PyErr_Occurred()) {
388 4 : err_status = _gpg_exception2code();
389 : } else {
390 14 : if (!retval) {
391 0 : if (write(fd, "\n", 1) < 0) {
392 0 : err_status = gpgme_error_from_syserror ();
393 0 : _gpg_raise_exception (err_status);
394 : }
395 : } else {
396 : char *buf;
397 : size_t len;
398 14 : if (PyBytes_Check(retval))
399 6 : buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
400 8 : else if (PyUnicode_Check(retval))
401 : {
402 : Py_ssize_t ssize;
403 6 : encoded = PyUnicode_AsUTF8String(retval);
404 6 : if (encoded == NULL)
405 : {
406 : err_status = gpg_error(GPG_ERR_GENERAL);
407 0 : goto leave;
408 : }
409 6 : if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
410 : {
411 : err_status = gpg_error(GPG_ERR_GENERAL);
412 : goto leave;
413 : }
414 : assert (! buf || ssize >= 0);
415 6 : len = (size_t) ssize;
416 : }
417 : else
418 : {
419 2 : PyErr_Format(PyExc_TypeError,
420 : "expected str or bytes from passphrase callback, got %s",
421 : retval->ob_type->tp_name);
422 2 : err_status = gpg_error(GPG_ERR_GENERAL);
423 2 : goto leave;
424 : }
425 :
426 12 : if (write(fd, buf, len) < 0) {
427 0 : err_status = gpgme_error_from_syserror ();
428 0 : _gpg_raise_exception (err_status);
429 : }
430 12 : if (! err_status && write(fd, "\n", 1) < 0) {
431 0 : err_status = gpgme_error_from_syserror ();
432 0 : _gpg_raise_exception (err_status);
433 : }
434 :
435 12 : Py_DECREF(retval);
436 : }
437 : }
438 :
439 : leave:
440 18 : if (err_status)
441 6 : _gpg_stash_callback_exception(self);
442 :
443 18 : Py_XDECREF(encoded);
444 18 : PyGILState_Release(state);
445 18 : return err_status;
446 : }
447 :
448 : PyObject *
449 156 : gpg_set_passphrase_cb(PyObject *self, PyObject *cb) {
450 156 : PyGILState_STATE state = PyGILState_Ensure();
451 : PyObject *wrapped;
452 : gpgme_ctx_t ctx;
453 :
454 156 : wrapped = PyObject_GetAttrString(self, "wrapped");
455 156 : if (wrapped == NULL)
456 : {
457 : assert (PyErr_Occurred ());
458 0 : PyGILState_Release(state);
459 0 : return NULL;
460 : }
461 :
462 156 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
463 156 : Py_DECREF(wrapped);
464 156 : if (ctx == NULL)
465 : {
466 33 : if (cb == Py_None)
467 : goto out;
468 : else
469 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
470 : }
471 :
472 123 : if (cb == Py_None) {
473 79 : gpgme_set_passphrase_cb(ctx, NULL, NULL);
474 79 : PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
475 79 : goto out;
476 : }
477 :
478 44 : if (! PyTuple_Check(cb))
479 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
480 44 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
481 0 : return PyErr_Format(PyExc_TypeError,
482 : "cb must be a tuple of size 2 or 3");
483 :
484 44 : gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
485 : (void *) cb);
486 44 : PyObject_SetAttrString(self, "_passphrase_cb", cb);
487 :
488 : out:
489 156 : Py_INCREF(Py_None);
490 156 : PyGILState_Release(state);
491 156 : return Py_None;
492 : }
493 :
494 53 : static void pyProgressCb(void *hook, const char *what, int type, int current,
495 : int total) {
496 53 : PyGILState_STATE state = PyGILState_Ensure();
497 53 : PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
498 53 : PyObject *pyhook = (PyObject *) hook;
499 53 : PyObject *self = NULL;
500 :
501 : assert (PyTuple_Check(pyhook));
502 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
503 53 : self = PyTuple_GetItem(pyhook, 0);
504 53 : func = PyTuple_GetItem(pyhook, 1);
505 53 : if (PyTuple_Size(pyhook) == 3) {
506 21 : dataarg = PyTuple_GetItem(pyhook, 2);
507 21 : args = PyTuple_New(5);
508 : } else {
509 32 : args = PyTuple_New(4);
510 : }
511 :
512 53 : PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
513 : "strict"));
514 53 : if (PyErr_Occurred()) {
515 0 : _gpg_stash_callback_exception(self);
516 0 : Py_DECREF(args);
517 0 : PyGILState_Release(state);
518 53 : return;
519 : }
520 53 : PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
521 53 : PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
522 53 : PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
523 53 : if (dataarg) {
524 21 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
525 21 : PyTuple_SetItem(args, 4, dataarg);
526 : }
527 :
528 53 : retval = PyObject_CallObject(func, args);
529 53 : if (PyErr_Occurred())
530 32 : _gpg_stash_callback_exception(self);
531 53 : Py_DECREF(args);
532 53 : Py_XDECREF(retval);
533 53 : PyGILState_Release(state);
534 : }
535 :
536 : PyObject *
537 116 : gpg_set_progress_cb(PyObject *self, PyObject *cb) {
538 116 : PyGILState_STATE state = PyGILState_Ensure();
539 : PyObject *wrapped;
540 : gpgme_ctx_t ctx;
541 :
542 116 : wrapped = PyObject_GetAttrString(self, "wrapped");
543 116 : if (wrapped == NULL)
544 : {
545 : assert (PyErr_Occurred ());
546 0 : PyGILState_Release(state);
547 0 : return NULL;
548 : }
549 :
550 116 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
551 116 : Py_DECREF(wrapped);
552 116 : if (ctx == NULL)
553 : {
554 33 : if (cb == Py_None)
555 : goto out;
556 : else
557 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
558 : }
559 :
560 83 : if (cb == Py_None) {
561 79 : gpgme_set_progress_cb(ctx, NULL, NULL);
562 79 : PyObject_SetAttrString(self, "_progress_cb", Py_None);
563 79 : goto out;
564 : }
565 :
566 4 : if (! PyTuple_Check(cb))
567 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
568 4 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
569 0 : return PyErr_Format(PyExc_TypeError,
570 : "cb must be a tuple of size 2 or 3");
571 :
572 4 : gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
573 4 : PyObject_SetAttrString(self, "_progress_cb", cb);
574 :
575 : out:
576 116 : Py_INCREF(Py_None);
577 116 : PyGILState_Release(state);
578 116 : return Py_None;
579 : }
580 :
581 : /* Status callbacks. */
582 12 : static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
583 : const char *args) {
584 12 : PyGILState_STATE state = PyGILState_Ensure();
585 12 : gpgme_error_t err = 0;
586 12 : PyObject *pyhook = (PyObject *) hook;
587 12 : PyObject *self = NULL;
588 12 : PyObject *func = NULL;
589 12 : PyObject *dataarg = NULL;
590 12 : PyObject *pyargs = NULL;
591 12 : PyObject *retval = NULL;
592 :
593 : assert (PyTuple_Check(pyhook));
594 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
595 12 : self = PyTuple_GetItem(pyhook, 0);
596 12 : func = PyTuple_GetItem(pyhook, 1);
597 12 : if (PyTuple_Size(pyhook) == 3) {
598 10 : dataarg = PyTuple_GetItem(pyhook, 2);
599 10 : pyargs = PyTuple_New(3);
600 : } else {
601 2 : pyargs = PyTuple_New(2);
602 : }
603 :
604 12 : if (keyword)
605 12 : PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
606 : "strict"));
607 : else
608 : {
609 0 : Py_INCREF(Py_None);
610 0 : PyTuple_SetItem(pyargs, 0, Py_None);
611 : }
612 12 : PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
613 : "strict"));
614 12 : if (PyErr_Occurred()) {
615 0 : err = gpg_error(GPG_ERR_GENERAL);
616 0 : Py_DECREF(pyargs);
617 : goto leave;
618 : }
619 :
620 12 : if (dataarg) {
621 10 : Py_INCREF(dataarg);
622 10 : PyTuple_SetItem(pyargs, 2, dataarg);
623 : }
624 :
625 12 : retval = PyObject_CallObject(func, pyargs);
626 12 : if (PyErr_Occurred())
627 2 : err = _gpg_exception2code();
628 12 : Py_DECREF(pyargs);
629 12 : Py_XDECREF(retval);
630 :
631 : leave:
632 12 : if (err)
633 2 : _gpg_stash_callback_exception(self);
634 12 : PyGILState_Release(state);
635 12 : return err;
636 : }
637 :
638 : PyObject *
639 116 : gpg_set_status_cb(PyObject *self, PyObject *cb) {
640 116 : PyGILState_STATE state = PyGILState_Ensure();
641 : PyObject *wrapped;
642 : gpgme_ctx_t ctx;
643 :
644 116 : wrapped = PyObject_GetAttrString(self, "wrapped");
645 116 : if (wrapped == NULL)
646 : {
647 : assert (PyErr_Occurred ());
648 0 : PyGILState_Release(state);
649 0 : return NULL;
650 : }
651 :
652 116 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
653 116 : Py_DECREF(wrapped);
654 116 : if (ctx == NULL)
655 : {
656 33 : if (cb == Py_None)
657 : goto out;
658 : else
659 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
660 : }
661 :
662 83 : if (cb == Py_None) {
663 79 : gpgme_set_status_cb(ctx, NULL, NULL);
664 79 : PyObject_SetAttrString(self, "_status_cb", Py_None);
665 79 : goto out;
666 : }
667 :
668 4 : if (! PyTuple_Check(cb))
669 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
670 4 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
671 0 : return PyErr_Format(PyExc_TypeError,
672 : "cb must be a tuple of size 2 or 3");
673 :
674 4 : gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
675 4 : PyObject_SetAttrString(self, "_status_cb", cb);
676 :
677 : out:
678 116 : Py_INCREF(Py_None);
679 116 : PyGILState_Release(state);
680 116 : return Py_None;
681 : }
682 :
683 :
684 :
685 : /* Interact callbacks. */
686 : gpgme_error_t
687 110 : _gpg_interact_cb(void *opaque, const char *keyword,
688 : const char *args, int fd)
689 : {
690 110 : PyGILState_STATE state = PyGILState_Ensure();
691 110 : PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
692 : PyObject *py_keyword;
693 110 : PyObject *pyopaque = (PyObject *) opaque;
694 110 : gpgme_error_t err_status = 0;
695 110 : PyObject *self = NULL;
696 :
697 110 : _gpg_exception_init();
698 :
699 : assert (PyTuple_Check(pyopaque));
700 : assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
701 110 : self = PyTuple_GetItem(pyopaque, 0);
702 110 : func = PyTuple_GetItem(pyopaque, 1);
703 110 : if (PyTuple_Size(pyopaque) == 3) {
704 74 : dataarg = PyTuple_GetItem(pyopaque, 2);
705 74 : pyargs = PyTuple_New(3);
706 : } else {
707 36 : pyargs = PyTuple_New(2);
708 : }
709 :
710 110 : if (keyword)
711 110 : py_keyword = PyUnicode_FromString(keyword);
712 : else
713 : {
714 0 : Py_INCREF(Py_None);
715 0 : py_keyword = Py_None;
716 : }
717 :
718 110 : PyTuple_SetItem(pyargs, 0, py_keyword);
719 110 : PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
720 110 : if (dataarg) {
721 74 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
722 74 : PyTuple_SetItem(pyargs, 2, dataarg);
723 : }
724 :
725 110 : retval = PyObject_CallObject(func, pyargs);
726 110 : Py_DECREF(pyargs);
727 110 : if (PyErr_Occurred()) {
728 2 : err_status = _gpg_exception2code();
729 : } else {
730 108 : if (fd>=0 && retval && PyUnicode_Check(retval)) {
731 38 : PyObject *encoded = NULL;
732 : char *buffer;
733 : Py_ssize_t size;
734 :
735 38 : encoded = PyUnicode_AsUTF8String(retval);
736 38 : if (encoded == NULL)
737 : {
738 : err_status = gpg_error(GPG_ERR_GENERAL);
739 0 : goto leave;
740 : }
741 38 : if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
742 : {
743 0 : Py_DECREF(encoded);
744 : err_status = gpg_error(GPG_ERR_GENERAL);
745 : goto leave;
746 : }
747 :
748 38 : if (write(fd, buffer, size) < 0) {
749 0 : err_status = gpgme_error_from_syserror ();
750 0 : _gpg_raise_exception (err_status);
751 : }
752 38 : if (! err_status && write(fd, "\n", 1) < 0) {
753 0 : err_status = gpgme_error_from_syserror ();
754 0 : _gpg_raise_exception (err_status);
755 : }
756 38 : Py_DECREF(encoded);
757 : }
758 : }
759 : leave:
760 110 : if (err_status)
761 2 : _gpg_stash_callback_exception(self);
762 :
763 110 : Py_XDECREF(retval);
764 110 : PyGILState_Release(state);
765 110 : return err_status;
766 : }
767 :
768 :
769 :
770 : /* Data callbacks. */
771 :
772 : /* Read up to SIZE bytes into buffer BUFFER from the data object with
773 : the handle HOOK. Return the number of characters read, 0 on EOF
774 : and -1 on error. If an error occurs, errno is set. */
775 64 : static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
776 : {
777 64 : PyGILState_STATE state = PyGILState_Ensure();
778 : ssize_t result;
779 64 : PyObject *pyhook = (PyObject *) hook;
780 64 : PyObject *self = NULL;
781 64 : PyObject *func = NULL;
782 64 : PyObject *dataarg = NULL;
783 64 : PyObject *pyargs = NULL;
784 64 : PyObject *retval = NULL;
785 :
786 : assert (PyTuple_Check(pyhook));
787 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
788 :
789 64 : self = PyTuple_GetItem(pyhook, 0);
790 64 : func = PyTuple_GetItem(pyhook, 1);
791 64 : if (PyTuple_Size(pyhook) == 6) {
792 6 : dataarg = PyTuple_GetItem(pyhook, 5);
793 6 : pyargs = PyTuple_New(2);
794 : } else {
795 58 : pyargs = PyTuple_New(1);
796 : }
797 :
798 64 : PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
799 64 : if (dataarg) {
800 6 : Py_INCREF(dataarg);
801 6 : PyTuple_SetItem(pyargs, 1, dataarg);
802 : }
803 :
804 64 : retval = PyObject_CallObject(func, pyargs);
805 64 : Py_DECREF(pyargs);
806 64 : if (PyErr_Occurred()) {
807 2 : _gpg_stash_callback_exception(self);
808 2 : result = -1;
809 2 : goto leave;
810 : }
811 :
812 62 : if (! PyBytes_Check(retval)) {
813 2 : PyErr_Format(PyExc_TypeError,
814 : "expected bytes from read callback, got %s",
815 : retval->ob_type->tp_name);
816 2 : _gpg_stash_callback_exception(self);
817 2 : result = -1;
818 2 : goto leave;
819 : }
820 :
821 60 : if (PyBytes_Size(retval) > size) {
822 0 : PyErr_Format(PyExc_TypeError,
823 : "expected %zu bytes from read callback, got %zu",
824 : size, PyBytes_Size(retval));
825 0 : _gpg_stash_callback_exception(self);
826 0 : result = -1;
827 0 : goto leave;
828 : }
829 :
830 60 : memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
831 60 : result = PyBytes_Size(retval);
832 :
833 : leave:
834 64 : Py_XDECREF(retval);
835 64 : PyGILState_Release(state);
836 64 : return result;
837 : }
838 :
839 : /* Write up to SIZE bytes from buffer BUFFER to the data object with
840 : the handle HOOK. Return the number of characters written, or -1
841 : on error. If an error occurs, errno is set. */
842 60 : static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
843 : {
844 60 : PyGILState_STATE state = PyGILState_Ensure();
845 : ssize_t result;
846 60 : PyObject *pyhook = (PyObject *) hook;
847 60 : PyObject *self = NULL;
848 60 : PyObject *func = NULL;
849 60 : PyObject *dataarg = NULL;
850 60 : PyObject *pyargs = NULL;
851 60 : PyObject *retval = NULL;
852 :
853 : assert (PyTuple_Check(pyhook));
854 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
855 :
856 60 : self = PyTuple_GetItem(pyhook, 0);
857 60 : func = PyTuple_GetItem(pyhook, 2);
858 60 : if (PyTuple_Size(pyhook) == 6) {
859 4 : dataarg = PyTuple_GetItem(pyhook, 5);
860 4 : pyargs = PyTuple_New(2);
861 : } else {
862 56 : pyargs = PyTuple_New(1);
863 : }
864 :
865 60 : PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
866 60 : if (dataarg) {
867 4 : Py_INCREF(dataarg);
868 4 : PyTuple_SetItem(pyargs, 1, dataarg);
869 : }
870 :
871 60 : retval = PyObject_CallObject(func, pyargs);
872 60 : Py_DECREF(pyargs);
873 60 : if (PyErr_Occurred()) {
874 2 : _gpg_stash_callback_exception(self);
875 2 : result = -1;
876 2 : goto leave;
877 : }
878 :
879 : #if PY_MAJOR_VERSION < 3
880 29 : if (PyInt_Check(retval))
881 26 : result = PyInt_AsSsize_t(retval);
882 : else
883 : #endif
884 32 : if (PyLong_Check(retval))
885 30 : result = PyLong_AsSsize_t(retval);
886 : else {
887 2 : PyErr_Format(PyExc_TypeError,
888 : "expected int from write callback, got %s",
889 : retval->ob_type->tp_name);
890 2 : _gpg_stash_callback_exception(self);
891 2 : result = -1;
892 : }
893 :
894 : leave:
895 60 : Py_XDECREF(retval);
896 60 : PyGILState_Release(state);
897 60 : return result;
898 : }
899 :
900 : /* Set the current position from where the next read or write starts
901 : in the data object with the handle HOOK to OFFSET, relativ to
902 : WHENCE. Returns the new offset in bytes from the beginning of the
903 : data object. */
904 8 : static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
905 : {
906 8 : PyGILState_STATE state = PyGILState_Ensure();
907 : off_t result;
908 8 : PyObject *pyhook = (PyObject *) hook;
909 8 : PyObject *self = NULL;
910 8 : PyObject *func = NULL;
911 8 : PyObject *dataarg = NULL;
912 8 : PyObject *pyargs = NULL;
913 8 : PyObject *retval = NULL;
914 :
915 : assert (PyTuple_Check(pyhook));
916 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
917 :
918 8 : self = PyTuple_GetItem(pyhook, 0);
919 8 : func = PyTuple_GetItem(pyhook, 3);
920 8 : if (PyTuple_Size(pyhook) == 6) {
921 4 : dataarg = PyTuple_GetItem(pyhook, 5);
922 4 : pyargs = PyTuple_New(3);
923 : } else {
924 4 : pyargs = PyTuple_New(2);
925 : }
926 :
927 : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
928 8 : PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
929 : #else
930 : PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
931 : #endif
932 8 : PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
933 8 : if (dataarg) {
934 4 : Py_INCREF(dataarg);
935 4 : PyTuple_SetItem(pyargs, 2, dataarg);
936 : }
937 :
938 8 : retval = PyObject_CallObject(func, pyargs);
939 8 : Py_DECREF(pyargs);
940 8 : if (PyErr_Occurred()) {
941 2 : _gpg_stash_callback_exception(self);
942 2 : result = -1;
943 2 : goto leave;
944 : }
945 :
946 : #if PY_MAJOR_VERSION < 3
947 3 : if (PyInt_Check(retval))
948 0 : result = PyInt_AsLong(retval);
949 : else
950 : #endif
951 6 : if (PyLong_Check(retval))
952 : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
953 4 : result = PyLong_AsLongLong(retval);
954 : #else
955 : result = PyLong_AsLong(retval);
956 : #endif
957 : else {
958 2 : PyErr_Format(PyExc_TypeError,
959 : "expected int from seek callback, got %s",
960 : retval->ob_type->tp_name);
961 2 : _gpg_stash_callback_exception(self);
962 2 : result = -1;
963 : }
964 :
965 : leave:
966 8 : Py_XDECREF(retval);
967 8 : PyGILState_Release(state);
968 8 : return result;
969 : }
970 :
971 : /* Close the data object with the handle HOOK. */
972 14 : static void pyDataReleaseCb(void *hook)
973 : {
974 14 : PyGILState_STATE state = PyGILState_Ensure();
975 14 : PyObject *pyhook = (PyObject *) hook;
976 14 : PyObject *self = NULL;
977 14 : PyObject *func = NULL;
978 14 : PyObject *dataarg = NULL;
979 14 : PyObject *pyargs = NULL;
980 14 : PyObject *retval = NULL;
981 :
982 : assert (PyTuple_Check(pyhook));
983 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
984 :
985 14 : self = PyTuple_GetItem(pyhook, 0);
986 14 : func = PyTuple_GetItem(pyhook, 4);
987 14 : if (PyTuple_Size(pyhook) == 6) {
988 8 : dataarg = PyTuple_GetItem(pyhook, 5);
989 8 : pyargs = PyTuple_New(1);
990 : } else {
991 6 : pyargs = PyTuple_New(0);
992 : }
993 :
994 14 : if (dataarg) {
995 8 : Py_INCREF(dataarg);
996 8 : PyTuple_SetItem(pyargs, 0, dataarg);
997 : }
998 :
999 14 : retval = PyObject_CallObject(func, pyargs);
1000 14 : Py_XDECREF(retval);
1001 14 : Py_DECREF(pyargs);
1002 14 : if (PyErr_Occurred())
1003 0 : _gpg_stash_callback_exception(self);
1004 14 : PyGILState_Release(state);
1005 14 : }
1006 :
1007 : PyObject *
1008 20 : gpg_data_new_from_cbs(PyObject *self,
1009 : PyObject *pycbs,
1010 : gpgme_data_t *r_data)
1011 : {
1012 20 : PyGILState_STATE state = PyGILState_Ensure();
1013 : static struct gpgme_data_cbs cbs = {
1014 : pyDataReadCb,
1015 : pyDataWriteCb,
1016 : pyDataSeekCb,
1017 : pyDataReleaseCb,
1018 : };
1019 : gpgme_error_t err;
1020 :
1021 20 : if (! PyTuple_Check(pycbs))
1022 0 : return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
1023 20 : if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
1024 0 : return PyErr_Format(PyExc_TypeError,
1025 : "pycbs must be a tuple of size 5 or 6");
1026 :
1027 20 : err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
1028 20 : if (err)
1029 0 : return _gpg_raise_exception(err);
1030 :
1031 20 : PyObject_SetAttrString(self, "_data_cbs", pycbs);
1032 :
1033 20 : Py_INCREF(Py_None);
1034 20 : PyGILState_Release(state);
1035 20 : return Py_None;
1036 : }
1037 :
1038 :
1039 :
1040 : /* The assuan callbacks. */
1041 :
1042 : gpgme_error_t
1043 4 : _gpg_assuan_data_cb (void *hook, const void *data, size_t datalen)
1044 : {
1045 4 : PyGILState_STATE state = PyGILState_Ensure();
1046 4 : gpgme_error_t err = 0;
1047 4 : PyObject *pyhook = (PyObject *) hook;
1048 4 : PyObject *self = NULL;
1049 4 : PyObject *func = NULL;
1050 4 : PyObject *py_data = NULL;
1051 4 : PyObject *retval = NULL;
1052 :
1053 : assert (PyTuple_Check(pyhook));
1054 : assert (PyTuple_Size(pyhook) == 2);
1055 4 : self = PyTuple_GetItem(pyhook, 0);
1056 4 : func = PyTuple_GetItem(pyhook, 1);
1057 : assert (PyCallable_Check(func));
1058 :
1059 4 : py_data = PyBytes_FromStringAndSize(data, datalen);
1060 4 : if (py_data == NULL)
1061 : {
1062 0 : err = _gpg_exception2code();
1063 0 : goto leave;
1064 : }
1065 :
1066 4 : retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
1067 4 : if (PyErr_Occurred())
1068 0 : err = _gpg_exception2code();
1069 4 : Py_DECREF(py_data);
1070 4 : Py_XDECREF(retval);
1071 :
1072 : leave:
1073 4 : if (err)
1074 0 : _gpg_stash_callback_exception(self);
1075 4 : PyGILState_Release(state);
1076 4 : return err;
1077 : }
1078 :
1079 : gpgme_error_t
1080 0 : _gpg_assuan_inquire_cb (void *hook, const char *name, const char *args,
1081 : gpgme_data_t *r_data)
1082 : {
1083 0 : PyGILState_STATE state = PyGILState_Ensure();
1084 0 : gpgme_error_t err = 0;
1085 0 : PyObject *pyhook = (PyObject *) hook;
1086 0 : PyObject *self = NULL;
1087 0 : PyObject *func = NULL;
1088 0 : PyObject *py_name = NULL;
1089 0 : PyObject *py_args = NULL;
1090 0 : PyObject *retval = NULL;
1091 :
1092 : assert (PyTuple_Check(pyhook));
1093 : assert (PyTuple_Size(pyhook) == 2);
1094 0 : self = PyTuple_GetItem(pyhook, 0);
1095 0 : func = PyTuple_GetItem(pyhook, 1);
1096 : assert (PyCallable_Check(func));
1097 :
1098 0 : py_name = PyUnicode_FromString(name);
1099 0 : if (py_name == NULL)
1100 : {
1101 0 : err = _gpg_exception2code();
1102 0 : goto leave;
1103 : }
1104 :
1105 0 : py_args = PyUnicode_FromString(args);
1106 0 : if (py_args == NULL)
1107 : {
1108 0 : err = _gpg_exception2code();
1109 0 : goto leave;
1110 : }
1111 :
1112 0 : retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
1113 0 : if (PyErr_Occurred())
1114 0 : err = _gpg_exception2code();
1115 0 : Py_XDECREF(retval);
1116 :
1117 : /* FIXME: Returning data is not yet implemented. */
1118 0 : *r_data = NULL;
1119 :
1120 : leave:
1121 0 : Py_XDECREF(py_name);
1122 0 : Py_XDECREF(py_args);
1123 0 : if (err)
1124 0 : _gpg_stash_callback_exception(self);
1125 0 : PyGILState_Release(state);
1126 0 : return err;
1127 : }
1128 :
1129 : gpgme_error_t
1130 2 : _gpg_assuan_status_cb (void *hook, const char *status, const char *args)
1131 : {
1132 2 : PyGILState_STATE state = PyGILState_Ensure();
1133 2 : gpgme_error_t err = 0;
1134 2 : PyObject *pyhook = (PyObject *) hook;
1135 2 : PyObject *self = NULL;
1136 2 : PyObject *func = NULL;
1137 2 : PyObject *py_status = NULL;
1138 2 : PyObject *py_args = NULL;
1139 2 : PyObject *retval = NULL;
1140 :
1141 : assert (PyTuple_Check(pyhook));
1142 : assert (PyTuple_Size(pyhook) == 2);
1143 2 : self = PyTuple_GetItem(pyhook, 0);
1144 2 : func = PyTuple_GetItem(pyhook, 1);
1145 : assert (PyCallable_Check(func));
1146 :
1147 2 : py_status = PyUnicode_FromString(status);
1148 2 : if (py_status == NULL)
1149 : {
1150 0 : err = _gpg_exception2code();
1151 0 : goto leave;
1152 : }
1153 :
1154 2 : py_args = PyUnicode_FromString(args);
1155 2 : if (py_args == NULL)
1156 : {
1157 0 : err = _gpg_exception2code();
1158 0 : goto leave;
1159 : }
1160 :
1161 2 : retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
1162 2 : if (PyErr_Occurred())
1163 0 : err = _gpg_exception2code();
1164 2 : Py_XDECREF(retval);
1165 :
1166 : leave:
1167 2 : Py_XDECREF(py_status);
1168 2 : Py_XDECREF(py_args);
1169 2 : if (err)
1170 0 : _gpg_stash_callback_exception(self);
1171 2 : PyGILState_Release(state);
1172 2 : return err;
1173 : }
|