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 0 : void _gpg_exception_init(void) {
47 0 : if (GPGMEError == NULL) {
48 : PyObject *errors;
49 0 : PyObject *from_list = PyList_New(0);
50 0 : errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
51 : PyEval_GetLocals(), from_list, 1);
52 0 : Py_XDECREF(from_list);
53 0 : if (errors) {
54 0 : GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
55 0 : Py_XINCREF(GPGMEError);
56 : }
57 : }
58 0 : }
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 0 : gpgme_error_t _gpg_exception2code(void) {
80 0 : gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
81 0 : 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 0 : return err_status;
92 : }
93 :
94 : /* Exception support for callbacks. */
95 : #define EXCINFO "_callback_excinfo"
96 :
97 0 : static void _gpg_stash_callback_exception(PyObject *weak_self)
98 : {
99 : PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
100 :
101 0 : PyErr_Fetch(&ptype, &pvalue, &ptraceback);
102 0 : excinfo = PyTuple_New(3);
103 0 : PyTuple_SetItem(excinfo, 0, ptype);
104 :
105 0 : if (pvalue)
106 0 : PyTuple_SetItem(excinfo, 1, pvalue);
107 : else {
108 0 : Py_INCREF(Py_None);
109 0 : PyTuple_SetItem(excinfo, 1, Py_None);
110 : }
111 :
112 0 : if (ptraceback)
113 0 : PyTuple_SetItem(excinfo, 2, ptraceback);
114 : else {
115 0 : Py_INCREF(Py_None);
116 0 : PyTuple_SetItem(excinfo, 2, Py_None);
117 : }
118 :
119 0 : self = PyWeakref_GetObject(weak_self);
120 : /* self only has a borrowed reference. */
121 0 : 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 0 : PyObject_SetAttrString(self, EXCINFO, excinfo);
136 0 : Py_DECREF(excinfo);
137 0 : }
138 :
139 0 : PyObject *gpg_raise_callback_exception(PyObject *self)
140 : {
141 0 : PyGILState_STATE state = PyGILState_Ensure();
142 : PyObject *ptype, *pvalue, *ptraceback, *excinfo;
143 :
144 0 : if (! PyObject_HasAttrString(self, EXCINFO))
145 : goto leave;
146 :
147 0 : excinfo = PyObject_GetAttrString(self, EXCINFO);
148 0 : if (! PyTuple_Check(excinfo))
149 : {
150 0 : Py_DECREF(excinfo);
151 : goto leave;
152 : }
153 :
154 0 : ptype = PyTuple_GetItem(excinfo, 0);
155 0 : Py_INCREF(excinfo);
156 :
157 0 : pvalue = PyTuple_GetItem(excinfo, 1);
158 0 : if (pvalue == Py_None)
159 : pvalue = NULL;
160 : else
161 0 : Py_INCREF(pvalue);
162 :
163 0 : ptraceback = PyTuple_GetItem(excinfo, 2);
164 0 : if (ptraceback == Py_None)
165 : ptraceback = NULL;
166 : else
167 0 : Py_INCREF(ptraceback);
168 :
169 : /* We now have references for the extracted items. */
170 0 : 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 0 : Py_INCREF(Py_None);
177 0 : PyObject_SetAttrString(self, EXCINFO, Py_None);
178 :
179 : /* Restore exception. */
180 0 : PyErr_Restore(ptype, pvalue, ptraceback);
181 0 : PyGILState_Release(state);
182 0 : 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 0 : _gpg_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
196 : {
197 0 : PyObject *pyname = NULL, *pypointer = NULL;
198 0 : pyname = PyObject_GetAttrString(input, "_ctype");
199 0 : if (pyname && PyUnicode_Check(pyname))
200 : {
201 0 : PyObject *encoded = PyUnicode_AsUTF8String(pyname);
202 0 : 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 0 : Py_DECREF(encoded);
212 : }
213 : else
214 : return NULL;
215 :
216 0 : Py_DECREF(pyname);
217 0 : pypointer = PyObject_GetAttrString(input, "wrapped");
218 0 : 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 0 : _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 0 : fd = PyObject_CallMethod(input, "fileno", NULL);
241 0 : if (fd) {
242 0 : err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
243 0 : Py_DECREF(fd);
244 0 : if (err)
245 0 : return _gpg_raise_exception (err);
246 :
247 0 : return _gpg_wrap_gpgme_data_t(*wrapper);
248 : }
249 : else
250 0 : PyErr_Clear();
251 :
252 : /* No? Maybe it implements the buffer protocol. */
253 0 : data = PyObject_CallMethod(input, "getbuffer", NULL);
254 0 : if (data)
255 : {
256 : /* Save a reference to input, which seems to be a BytesIO
257 : object. */
258 0 : Py_INCREF(input);
259 0 : *bytesio = input;
260 : }
261 : else
262 : {
263 0 : PyErr_Clear();
264 :
265 : /* No, but maybe the user supplied a buffer object? */
266 0 : data = input;
267 : }
268 :
269 : /* Do we have a buffer object? */
270 0 : if (PyObject_CheckBuffer(data))
271 : {
272 0 : if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
273 : return NULL;
274 :
275 0 : if (data != input)
276 0 : 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 0 : err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
285 0 : if (err)
286 0 : return _gpg_raise_exception (err);
287 :
288 0 : return _gpg_wrap_gpgme_data_t(*wrapper);
289 : }
290 :
291 : /* As last resort we assume it is a wrapped data object. */
292 0 : if (PyObject_HasAttrString(data, "_ctype"))
293 0 : return _gpg_obj2gpgme_t(data, "gpgme_data_t", argnum);
294 :
295 0 : return PyErr_Format(PyExc_TypeError,
296 : "arg %d: expected gpg.Data, file, "
297 : "bytes (not string!), or an object "
298 : "implementing the buffer protocol. Got: %s. "
299 : "If you provided a string, try to encode() it.",
300 0 : argnum, data->ob_type->tp_name);
301 : }
302 :
303 :
304 :
305 : PyObject *
306 0 : _gpg_wrap_result(PyObject *fragile, const char *classname)
307 : {
308 : static PyObject *results;
309 : PyObject *class;
310 : PyObject *replacement;
311 :
312 0 : if (results == NULL)
313 : {
314 0 : PyObject *from_list = PyList_New(0);
315 0 : if (from_list == NULL)
316 : return NULL;
317 :
318 0 : results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
319 : PyEval_GetLocals(), from_list, 1);
320 0 : Py_DECREF(from_list);
321 :
322 0 : if (results == NULL)
323 : return NULL;
324 : }
325 :
326 0 : class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
327 0 : if (class == NULL)
328 : return NULL;
329 :
330 0 : replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
331 0 : Py_DECREF(class);
332 : return replacement;
333 : }
334 :
335 :
336 :
337 : /* Callback support. */
338 0 : static gpgme_error_t pyPassphraseCb(void *hook,
339 : const char *uid_hint,
340 : const char *passphrase_info,
341 : int prev_was_bad,
342 : int fd) {
343 0 : PyGILState_STATE state = PyGILState_Ensure();
344 0 : PyObject *pyhook = (PyObject *) hook;
345 0 : PyObject *self = NULL;
346 0 : PyObject *func = NULL;
347 0 : PyObject *args = NULL;
348 0 : PyObject *retval = NULL;
349 0 : PyObject *dataarg = NULL;
350 0 : PyObject *encoded = NULL;
351 0 : gpgme_error_t err_status = 0;
352 :
353 0 : _gpg_exception_init();
354 :
355 : assert (PyTuple_Check(pyhook));
356 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
357 0 : self = PyTuple_GetItem(pyhook, 0);
358 0 : func = PyTuple_GetItem(pyhook, 1);
359 0 : if (PyTuple_Size(pyhook) == 3) {
360 0 : dataarg = PyTuple_GetItem(pyhook, 2);
361 0 : args = PyTuple_New(4);
362 : } else {
363 0 : args = PyTuple_New(3);
364 : }
365 :
366 0 : if (uid_hint == NULL)
367 : {
368 0 : Py_INCREF(Py_None);
369 0 : PyTuple_SetItem(args, 0, Py_None);
370 : }
371 : else
372 0 : PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
373 : "strict"));
374 0 : if (PyErr_Occurred()) {
375 0 : Py_DECREF(args);
376 : err_status = gpg_error(GPG_ERR_GENERAL);
377 : goto leave;
378 : }
379 :
380 0 : PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
381 0 : PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
382 0 : if (dataarg) {
383 0 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
384 0 : PyTuple_SetItem(args, 3, dataarg);
385 : }
386 :
387 0 : retval = PyObject_CallObject(func, args);
388 0 : Py_DECREF(args);
389 0 : if (PyErr_Occurred()) {
390 0 : err_status = _gpg_exception2code();
391 : } else {
392 0 : if (!retval) {
393 0 : if (write(fd, "\n", 1) < 0) {
394 0 : err_status = gpgme_error_from_syserror ();
395 0 : _gpg_raise_exception (err_status);
396 : }
397 : } else {
398 : char *buf;
399 : size_t len;
400 0 : if (PyBytes_Check(retval))
401 0 : buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
402 0 : else if (PyUnicode_Check(retval))
403 : {
404 : Py_ssize_t ssize;
405 0 : encoded = PyUnicode_AsUTF8String(retval);
406 0 : if (encoded == NULL)
407 : {
408 : err_status = gpg_error(GPG_ERR_GENERAL);
409 0 : goto leave;
410 : }
411 0 : if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
412 : {
413 : err_status = gpg_error(GPG_ERR_GENERAL);
414 : goto leave;
415 : }
416 : assert (! buf || ssize >= 0);
417 0 : len = (size_t) ssize;
418 : }
419 : else
420 : {
421 0 : PyErr_Format(PyExc_TypeError,
422 : "expected str or bytes from passphrase callback, got %s",
423 : retval->ob_type->tp_name);
424 0 : err_status = gpg_error(GPG_ERR_GENERAL);
425 0 : goto leave;
426 : }
427 :
428 0 : if (write(fd, buf, len) < 0) {
429 0 : err_status = gpgme_error_from_syserror ();
430 0 : _gpg_raise_exception (err_status);
431 : }
432 0 : if (! err_status && write(fd, "\n", 1) < 0) {
433 0 : err_status = gpgme_error_from_syserror ();
434 0 : _gpg_raise_exception (err_status);
435 : }
436 :
437 0 : Py_DECREF(retval);
438 : }
439 : }
440 :
441 : leave:
442 0 : if (err_status)
443 0 : _gpg_stash_callback_exception(self);
444 :
445 0 : Py_XDECREF(encoded);
446 0 : PyGILState_Release(state);
447 0 : return err_status;
448 : }
449 :
450 : PyObject *
451 0 : gpg_set_passphrase_cb(PyObject *self, PyObject *cb) {
452 0 : PyGILState_STATE state = PyGILState_Ensure();
453 : PyObject *wrapped;
454 : gpgme_ctx_t ctx;
455 :
456 0 : wrapped = PyObject_GetAttrString(self, "wrapped");
457 0 : if (wrapped == NULL)
458 : {
459 : assert (PyErr_Occurred ());
460 0 : PyGILState_Release(state);
461 0 : return NULL;
462 : }
463 :
464 0 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
465 0 : Py_DECREF(wrapped);
466 0 : if (ctx == NULL)
467 : {
468 0 : if (cb == Py_None)
469 : goto out;
470 : else
471 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
472 : }
473 :
474 0 : if (cb == Py_None) {
475 0 : gpgme_set_passphrase_cb(ctx, NULL, NULL);
476 0 : PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
477 0 : goto out;
478 : }
479 :
480 0 : if (! PyTuple_Check(cb))
481 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
482 0 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
483 0 : return PyErr_Format(PyExc_TypeError,
484 : "cb must be a tuple of size 2 or 3");
485 :
486 0 : gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
487 : (void *) cb);
488 0 : PyObject_SetAttrString(self, "_passphrase_cb", cb);
489 :
490 : out:
491 0 : Py_INCREF(Py_None);
492 0 : PyGILState_Release(state);
493 0 : return Py_None;
494 : }
495 :
496 0 : static void pyProgressCb(void *hook, const char *what, int type, int current,
497 : int total) {
498 0 : PyGILState_STATE state = PyGILState_Ensure();
499 0 : PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
500 0 : PyObject *pyhook = (PyObject *) hook;
501 0 : PyObject *self = NULL;
502 :
503 : assert (PyTuple_Check(pyhook));
504 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
505 0 : self = PyTuple_GetItem(pyhook, 0);
506 0 : func = PyTuple_GetItem(pyhook, 1);
507 0 : if (PyTuple_Size(pyhook) == 3) {
508 0 : dataarg = PyTuple_GetItem(pyhook, 2);
509 0 : args = PyTuple_New(5);
510 : } else {
511 0 : args = PyTuple_New(4);
512 : }
513 :
514 0 : PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
515 : "strict"));
516 0 : if (PyErr_Occurred()) {
517 0 : _gpg_stash_callback_exception(self);
518 0 : Py_DECREF(args);
519 0 : PyGILState_Release(state);
520 0 : return;
521 : }
522 0 : PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
523 0 : PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
524 0 : PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
525 0 : if (dataarg) {
526 0 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
527 0 : PyTuple_SetItem(args, 4, dataarg);
528 : }
529 :
530 0 : retval = PyObject_CallObject(func, args);
531 0 : if (PyErr_Occurred())
532 0 : _gpg_stash_callback_exception(self);
533 0 : Py_DECREF(args);
534 0 : Py_XDECREF(retval);
535 0 : PyGILState_Release(state);
536 : }
537 :
538 : PyObject *
539 0 : gpg_set_progress_cb(PyObject *self, PyObject *cb) {
540 0 : PyGILState_STATE state = PyGILState_Ensure();
541 : PyObject *wrapped;
542 : gpgme_ctx_t ctx;
543 :
544 0 : wrapped = PyObject_GetAttrString(self, "wrapped");
545 0 : if (wrapped == NULL)
546 : {
547 : assert (PyErr_Occurred ());
548 0 : PyGILState_Release(state);
549 0 : return NULL;
550 : }
551 :
552 0 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
553 0 : Py_DECREF(wrapped);
554 0 : if (ctx == NULL)
555 : {
556 0 : if (cb == Py_None)
557 : goto out;
558 : else
559 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
560 : }
561 :
562 0 : if (cb == Py_None) {
563 0 : gpgme_set_progress_cb(ctx, NULL, NULL);
564 0 : PyObject_SetAttrString(self, "_progress_cb", Py_None);
565 0 : goto out;
566 : }
567 :
568 0 : if (! PyTuple_Check(cb))
569 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
570 0 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
571 0 : return PyErr_Format(PyExc_TypeError,
572 : "cb must be a tuple of size 2 or 3");
573 :
574 0 : gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
575 0 : PyObject_SetAttrString(self, "_progress_cb", cb);
576 :
577 : out:
578 0 : Py_INCREF(Py_None);
579 0 : PyGILState_Release(state);
580 0 : return Py_None;
581 : }
582 :
583 : /* Status callbacks. */
584 0 : static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
585 : const char *args) {
586 0 : PyGILState_STATE state = PyGILState_Ensure();
587 0 : gpgme_error_t err = 0;
588 0 : PyObject *pyhook = (PyObject *) hook;
589 0 : PyObject *self = NULL;
590 0 : PyObject *func = NULL;
591 0 : PyObject *dataarg = NULL;
592 0 : PyObject *pyargs = NULL;
593 0 : PyObject *retval = NULL;
594 :
595 : assert (PyTuple_Check(pyhook));
596 : assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
597 0 : self = PyTuple_GetItem(pyhook, 0);
598 0 : func = PyTuple_GetItem(pyhook, 1);
599 0 : if (PyTuple_Size(pyhook) == 3) {
600 0 : dataarg = PyTuple_GetItem(pyhook, 2);
601 0 : pyargs = PyTuple_New(3);
602 : } else {
603 0 : pyargs = PyTuple_New(2);
604 : }
605 :
606 0 : if (keyword)
607 0 : PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
608 : "strict"));
609 : else
610 : {
611 0 : Py_INCREF(Py_None);
612 0 : PyTuple_SetItem(pyargs, 0, Py_None);
613 : }
614 0 : PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
615 : "strict"));
616 0 : if (PyErr_Occurred()) {
617 0 : err = gpg_error(GPG_ERR_GENERAL);
618 0 : Py_DECREF(pyargs);
619 : goto leave;
620 : }
621 :
622 0 : if (dataarg) {
623 0 : Py_INCREF(dataarg);
624 0 : PyTuple_SetItem(pyargs, 2, dataarg);
625 : }
626 :
627 0 : retval = PyObject_CallObject(func, pyargs);
628 0 : if (PyErr_Occurred())
629 0 : err = _gpg_exception2code();
630 0 : Py_DECREF(pyargs);
631 0 : Py_XDECREF(retval);
632 :
633 : leave:
634 0 : if (err)
635 0 : _gpg_stash_callback_exception(self);
636 0 : PyGILState_Release(state);
637 0 : return err;
638 : }
639 :
640 : PyObject *
641 0 : gpg_set_status_cb(PyObject *self, PyObject *cb) {
642 0 : PyGILState_STATE state = PyGILState_Ensure();
643 : PyObject *wrapped;
644 : gpgme_ctx_t ctx;
645 :
646 0 : wrapped = PyObject_GetAttrString(self, "wrapped");
647 0 : if (wrapped == NULL)
648 : {
649 : assert (PyErr_Occurred ());
650 0 : PyGILState_Release(state);
651 0 : return NULL;
652 : }
653 :
654 0 : ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
655 0 : Py_DECREF(wrapped);
656 0 : if (ctx == NULL)
657 : {
658 0 : if (cb == Py_None)
659 : goto out;
660 : else
661 0 : return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
662 : }
663 :
664 0 : if (cb == Py_None) {
665 0 : gpgme_set_status_cb(ctx, NULL, NULL);
666 0 : PyObject_SetAttrString(self, "_status_cb", Py_None);
667 0 : goto out;
668 : }
669 :
670 0 : if (! PyTuple_Check(cb))
671 0 : return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
672 0 : if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
673 0 : return PyErr_Format(PyExc_TypeError,
674 : "cb must be a tuple of size 2 or 3");
675 :
676 0 : gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
677 0 : PyObject_SetAttrString(self, "_status_cb", cb);
678 :
679 : out:
680 0 : Py_INCREF(Py_None);
681 0 : PyGILState_Release(state);
682 0 : return Py_None;
683 : }
684 :
685 :
686 :
687 : /* Interact callbacks. */
688 : gpgme_error_t
689 0 : _gpg_interact_cb(void *opaque, const char *keyword,
690 : const char *args, int fd)
691 : {
692 0 : PyGILState_STATE state = PyGILState_Ensure();
693 0 : PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
694 : PyObject *py_keyword;
695 0 : PyObject *pyopaque = (PyObject *) opaque;
696 0 : gpgme_error_t err_status = 0;
697 0 : PyObject *self = NULL;
698 :
699 0 : _gpg_exception_init();
700 :
701 : assert (PyTuple_Check(pyopaque));
702 : assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
703 0 : self = PyTuple_GetItem(pyopaque, 0);
704 0 : func = PyTuple_GetItem(pyopaque, 1);
705 0 : if (PyTuple_Size(pyopaque) == 3) {
706 0 : dataarg = PyTuple_GetItem(pyopaque, 2);
707 0 : pyargs = PyTuple_New(3);
708 : } else {
709 0 : pyargs = PyTuple_New(2);
710 : }
711 :
712 0 : if (keyword)
713 0 : py_keyword = PyUnicode_FromString(keyword);
714 : else
715 : {
716 0 : Py_INCREF(Py_None);
717 0 : py_keyword = Py_None;
718 : }
719 :
720 0 : PyTuple_SetItem(pyargs, 0, py_keyword);
721 0 : PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
722 0 : if (dataarg) {
723 0 : Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
724 0 : PyTuple_SetItem(pyargs, 2, dataarg);
725 : }
726 :
727 0 : retval = PyObject_CallObject(func, pyargs);
728 0 : Py_DECREF(pyargs);
729 0 : if (PyErr_Occurred()) {
730 0 : err_status = _gpg_exception2code();
731 : } else {
732 0 : if (fd>=0 && retval && PyUnicode_Check(retval)) {
733 0 : PyObject *encoded = NULL;
734 : char *buffer;
735 : Py_ssize_t size;
736 :
737 0 : encoded = PyUnicode_AsUTF8String(retval);
738 0 : if (encoded == NULL)
739 : {
740 : err_status = gpg_error(GPG_ERR_GENERAL);
741 0 : goto leave;
742 : }
743 0 : if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
744 : {
745 0 : Py_DECREF(encoded);
746 : err_status = gpg_error(GPG_ERR_GENERAL);
747 : goto leave;
748 : }
749 :
750 0 : if (write(fd, buffer, size) < 0) {
751 0 : err_status = gpgme_error_from_syserror ();
752 0 : _gpg_raise_exception (err_status);
753 : }
754 0 : if (! err_status && write(fd, "\n", 1) < 0) {
755 0 : err_status = gpgme_error_from_syserror ();
756 0 : _gpg_raise_exception (err_status);
757 : }
758 0 : Py_DECREF(encoded);
759 : }
760 : }
761 : leave:
762 0 : if (err_status)
763 0 : _gpg_stash_callback_exception(self);
764 :
765 0 : Py_XDECREF(retval);
766 0 : PyGILState_Release(state);
767 0 : return err_status;
768 : }
769 :
770 :
771 :
772 : /* Data callbacks. */
773 :
774 : /* Read up to SIZE bytes into buffer BUFFER from the data object with
775 : the handle HOOK. Return the number of characters read, 0 on EOF
776 : and -1 on error. If an error occurs, errno is set. */
777 0 : static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
778 : {
779 0 : PyGILState_STATE state = PyGILState_Ensure();
780 : ssize_t result;
781 0 : PyObject *pyhook = (PyObject *) hook;
782 0 : PyObject *self = NULL;
783 0 : PyObject *func = NULL;
784 0 : PyObject *dataarg = NULL;
785 0 : PyObject *pyargs = NULL;
786 0 : PyObject *retval = NULL;
787 :
788 : assert (PyTuple_Check(pyhook));
789 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
790 :
791 0 : self = PyTuple_GetItem(pyhook, 0);
792 0 : func = PyTuple_GetItem(pyhook, 1);
793 0 : if (PyTuple_Size(pyhook) == 6) {
794 0 : dataarg = PyTuple_GetItem(pyhook, 5);
795 0 : pyargs = PyTuple_New(2);
796 : } else {
797 0 : pyargs = PyTuple_New(1);
798 : }
799 :
800 0 : PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
801 0 : if (dataarg) {
802 0 : Py_INCREF(dataarg);
803 0 : PyTuple_SetItem(pyargs, 1, dataarg);
804 : }
805 :
806 0 : retval = PyObject_CallObject(func, pyargs);
807 0 : Py_DECREF(pyargs);
808 0 : if (PyErr_Occurred()) {
809 0 : _gpg_stash_callback_exception(self);
810 0 : result = -1;
811 0 : goto leave;
812 : }
813 :
814 0 : if (! PyBytes_Check(retval)) {
815 0 : PyErr_Format(PyExc_TypeError,
816 : "expected bytes from read callback, got %s",
817 : retval->ob_type->tp_name);
818 0 : _gpg_stash_callback_exception(self);
819 0 : result = -1;
820 0 : goto leave;
821 : }
822 :
823 0 : if (PyBytes_Size(retval) > size) {
824 0 : PyErr_Format(PyExc_TypeError,
825 : "expected %zu bytes from read callback, got %zu",
826 : size, PyBytes_Size(retval));
827 0 : _gpg_stash_callback_exception(self);
828 0 : result = -1;
829 0 : goto leave;
830 : }
831 :
832 0 : memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
833 0 : result = PyBytes_Size(retval);
834 :
835 : leave:
836 0 : Py_XDECREF(retval);
837 0 : PyGILState_Release(state);
838 0 : return result;
839 : }
840 :
841 : /* Write up to SIZE bytes from buffer BUFFER to the data object with
842 : the handle HOOK. Return the number of characters written, or -1
843 : on error. If an error occurs, errno is set. */
844 0 : static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
845 : {
846 0 : PyGILState_STATE state = PyGILState_Ensure();
847 : ssize_t result;
848 0 : PyObject *pyhook = (PyObject *) hook;
849 0 : PyObject *self = NULL;
850 0 : PyObject *func = NULL;
851 0 : PyObject *dataarg = NULL;
852 0 : PyObject *pyargs = NULL;
853 0 : PyObject *retval = NULL;
854 :
855 : assert (PyTuple_Check(pyhook));
856 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
857 :
858 0 : self = PyTuple_GetItem(pyhook, 0);
859 0 : func = PyTuple_GetItem(pyhook, 2);
860 0 : if (PyTuple_Size(pyhook) == 6) {
861 0 : dataarg = PyTuple_GetItem(pyhook, 5);
862 0 : pyargs = PyTuple_New(2);
863 : } else {
864 0 : pyargs = PyTuple_New(1);
865 : }
866 :
867 0 : PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
868 0 : if (dataarg) {
869 0 : Py_INCREF(dataarg);
870 0 : PyTuple_SetItem(pyargs, 1, dataarg);
871 : }
872 :
873 0 : retval = PyObject_CallObject(func, pyargs);
874 0 : Py_DECREF(pyargs);
875 0 : if (PyErr_Occurred()) {
876 0 : _gpg_stash_callback_exception(self);
877 0 : result = -1;
878 0 : goto leave;
879 : }
880 :
881 : #if PY_MAJOR_VERSION < 3
882 0 : if (PyInt_Check(retval))
883 0 : result = PyInt_AsSsize_t(retval);
884 : else
885 : #endif
886 0 : if (PyLong_Check(retval))
887 0 : result = PyLong_AsSsize_t(retval);
888 : else {
889 0 : PyErr_Format(PyExc_TypeError,
890 : "expected int from write callback, got %s",
891 : retval->ob_type->tp_name);
892 0 : _gpg_stash_callback_exception(self);
893 0 : result = -1;
894 : }
895 :
896 : leave:
897 0 : Py_XDECREF(retval);
898 0 : PyGILState_Release(state);
899 0 : return result;
900 : }
901 :
902 : /* Set the current position from where the next read or write starts
903 : in the data object with the handle HOOK to OFFSET, relativ to
904 : WHENCE. Returns the new offset in bytes from the beginning of the
905 : data object. */
906 0 : static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
907 : {
908 0 : PyGILState_STATE state = PyGILState_Ensure();
909 : off_t result;
910 0 : PyObject *pyhook = (PyObject *) hook;
911 0 : PyObject *self = NULL;
912 0 : PyObject *func = NULL;
913 0 : PyObject *dataarg = NULL;
914 0 : PyObject *pyargs = NULL;
915 0 : PyObject *retval = NULL;
916 :
917 : assert (PyTuple_Check(pyhook));
918 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
919 :
920 0 : self = PyTuple_GetItem(pyhook, 0);
921 0 : func = PyTuple_GetItem(pyhook, 3);
922 0 : if (PyTuple_Size(pyhook) == 6) {
923 0 : dataarg = PyTuple_GetItem(pyhook, 5);
924 0 : pyargs = PyTuple_New(3);
925 : } else {
926 0 : pyargs = PyTuple_New(2);
927 : }
928 :
929 : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
930 0 : PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
931 : #else
932 : PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
933 : #endif
934 0 : PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
935 0 : if (dataarg) {
936 0 : Py_INCREF(dataarg);
937 0 : PyTuple_SetItem(pyargs, 2, dataarg);
938 : }
939 :
940 0 : retval = PyObject_CallObject(func, pyargs);
941 0 : Py_DECREF(pyargs);
942 0 : if (PyErr_Occurred()) {
943 0 : _gpg_stash_callback_exception(self);
944 0 : result = -1;
945 0 : goto leave;
946 : }
947 :
948 : #if PY_MAJOR_VERSION < 3
949 0 : if (PyInt_Check(retval))
950 0 : result = PyInt_AsLong(retval);
951 : else
952 : #endif
953 0 : if (PyLong_Check(retval))
954 : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
955 0 : result = PyLong_AsLongLong(retval);
956 : #else
957 : result = PyLong_AsLong(retval);
958 : #endif
959 : else {
960 0 : PyErr_Format(PyExc_TypeError,
961 : "expected int from seek callback, got %s",
962 : retval->ob_type->tp_name);
963 0 : _gpg_stash_callback_exception(self);
964 0 : result = -1;
965 : }
966 :
967 : leave:
968 0 : Py_XDECREF(retval);
969 0 : PyGILState_Release(state);
970 0 : return result;
971 : }
972 :
973 : /* Close the data object with the handle HOOK. */
974 0 : static void pyDataReleaseCb(void *hook)
975 : {
976 0 : PyGILState_STATE state = PyGILState_Ensure();
977 0 : PyObject *pyhook = (PyObject *) hook;
978 0 : PyObject *self = NULL;
979 0 : PyObject *func = NULL;
980 0 : PyObject *dataarg = NULL;
981 0 : PyObject *pyargs = NULL;
982 0 : PyObject *retval = NULL;
983 :
984 : assert (PyTuple_Check(pyhook));
985 : assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
986 :
987 0 : self = PyTuple_GetItem(pyhook, 0);
988 0 : func = PyTuple_GetItem(pyhook, 4);
989 0 : if (PyTuple_Size(pyhook) == 6) {
990 0 : dataarg = PyTuple_GetItem(pyhook, 5);
991 0 : pyargs = PyTuple_New(1);
992 : } else {
993 0 : pyargs = PyTuple_New(0);
994 : }
995 :
996 0 : if (dataarg) {
997 0 : Py_INCREF(dataarg);
998 0 : PyTuple_SetItem(pyargs, 0, dataarg);
999 : }
1000 :
1001 0 : retval = PyObject_CallObject(func, pyargs);
1002 0 : Py_XDECREF(retval);
1003 0 : Py_DECREF(pyargs);
1004 0 : if (PyErr_Occurred())
1005 0 : _gpg_stash_callback_exception(self);
1006 0 : PyGILState_Release(state);
1007 0 : }
1008 :
1009 : PyObject *
1010 0 : gpg_data_new_from_cbs(PyObject *self,
1011 : PyObject *pycbs,
1012 : gpgme_data_t *r_data)
1013 : {
1014 0 : PyGILState_STATE state = PyGILState_Ensure();
1015 : static struct gpgme_data_cbs cbs = {
1016 : pyDataReadCb,
1017 : pyDataWriteCb,
1018 : pyDataSeekCb,
1019 : pyDataReleaseCb,
1020 : };
1021 : gpgme_error_t err;
1022 :
1023 0 : if (! PyTuple_Check(pycbs))
1024 0 : return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
1025 0 : if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
1026 0 : return PyErr_Format(PyExc_TypeError,
1027 : "pycbs must be a tuple of size 5 or 6");
1028 :
1029 0 : err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
1030 0 : if (err)
1031 0 : return _gpg_raise_exception(err);
1032 :
1033 0 : PyObject_SetAttrString(self, "_data_cbs", pycbs);
1034 :
1035 0 : Py_INCREF(Py_None);
1036 0 : PyGILState_Release(state);
1037 0 : return Py_None;
1038 : }
1039 :
1040 :
1041 :
1042 : /* The assuan callbacks. */
1043 :
1044 : gpgme_error_t
1045 0 : _gpg_assuan_data_cb (void *hook, const void *data, size_t datalen)
1046 : {
1047 0 : PyGILState_STATE state = PyGILState_Ensure();
1048 0 : gpgme_error_t err = 0;
1049 0 : PyObject *pyhook = (PyObject *) hook;
1050 0 : PyObject *self = NULL;
1051 0 : PyObject *func = NULL;
1052 0 : PyObject *py_data = NULL;
1053 0 : PyObject *retval = NULL;
1054 :
1055 : assert (PyTuple_Check(pyhook));
1056 : assert (PyTuple_Size(pyhook) == 2);
1057 0 : self = PyTuple_GetItem(pyhook, 0);
1058 0 : func = PyTuple_GetItem(pyhook, 1);
1059 : assert (PyCallable_Check(func));
1060 :
1061 0 : py_data = PyBytes_FromStringAndSize(data, datalen);
1062 0 : if (py_data == NULL)
1063 : {
1064 0 : err = _gpg_exception2code();
1065 0 : goto leave;
1066 : }
1067 :
1068 0 : retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
1069 0 : if (PyErr_Occurred())
1070 0 : err = _gpg_exception2code();
1071 0 : Py_DECREF(py_data);
1072 0 : Py_XDECREF(retval);
1073 :
1074 : leave:
1075 0 : if (err)
1076 0 : _gpg_stash_callback_exception(self);
1077 0 : PyGILState_Release(state);
1078 0 : return err;
1079 : }
1080 :
1081 : gpgme_error_t
1082 0 : _gpg_assuan_inquire_cb (void *hook, const char *name, const char *args,
1083 : gpgme_data_t *r_data)
1084 : {
1085 0 : PyGILState_STATE state = PyGILState_Ensure();
1086 0 : gpgme_error_t err = 0;
1087 0 : PyObject *pyhook = (PyObject *) hook;
1088 0 : PyObject *self = NULL;
1089 0 : PyObject *func = NULL;
1090 0 : PyObject *py_name = NULL;
1091 0 : PyObject *py_args = NULL;
1092 0 : PyObject *retval = NULL;
1093 :
1094 : assert (PyTuple_Check(pyhook));
1095 : assert (PyTuple_Size(pyhook) == 2);
1096 0 : self = PyTuple_GetItem(pyhook, 0);
1097 0 : func = PyTuple_GetItem(pyhook, 1);
1098 : assert (PyCallable_Check(func));
1099 :
1100 0 : py_name = PyUnicode_FromString(name);
1101 0 : if (py_name == NULL)
1102 : {
1103 0 : err = _gpg_exception2code();
1104 0 : goto leave;
1105 : }
1106 :
1107 0 : py_args = PyUnicode_FromString(args);
1108 0 : if (py_args == NULL)
1109 : {
1110 0 : err = _gpg_exception2code();
1111 0 : goto leave;
1112 : }
1113 :
1114 0 : retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
1115 0 : if (PyErr_Occurred())
1116 0 : err = _gpg_exception2code();
1117 0 : Py_XDECREF(retval);
1118 :
1119 : /* FIXME: Returning data is not yet implemented. */
1120 0 : *r_data = NULL;
1121 :
1122 : leave:
1123 0 : Py_XDECREF(py_name);
1124 0 : Py_XDECREF(py_args);
1125 0 : if (err)
1126 0 : _gpg_stash_callback_exception(self);
1127 0 : PyGILState_Release(state);
1128 0 : return err;
1129 : }
1130 :
1131 : gpgme_error_t
1132 0 : _gpg_assuan_status_cb (void *hook, const char *status, const char *args)
1133 : {
1134 0 : PyGILState_STATE state = PyGILState_Ensure();
1135 0 : gpgme_error_t err = 0;
1136 0 : PyObject *pyhook = (PyObject *) hook;
1137 0 : PyObject *self = NULL;
1138 0 : PyObject *func = NULL;
1139 0 : PyObject *py_status = NULL;
1140 0 : PyObject *py_args = NULL;
1141 0 : PyObject *retval = NULL;
1142 :
1143 : assert (PyTuple_Check(pyhook));
1144 : assert (PyTuple_Size(pyhook) == 2);
1145 0 : self = PyTuple_GetItem(pyhook, 0);
1146 0 : func = PyTuple_GetItem(pyhook, 1);
1147 : assert (PyCallable_Check(func));
1148 :
1149 0 : py_status = PyUnicode_FromString(status);
1150 0 : if (py_status == NULL)
1151 : {
1152 0 : err = _gpg_exception2code();
1153 0 : goto leave;
1154 : }
1155 :
1156 0 : py_args = PyUnicode_FromString(args);
1157 0 : if (py_args == NULL)
1158 : {
1159 0 : err = _gpg_exception2code();
1160 0 : goto leave;
1161 : }
1162 :
1163 0 : retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
1164 0 : if (PyErr_Occurred())
1165 0 : err = _gpg_exception2code();
1166 0 : Py_XDECREF(retval);
1167 :
1168 : leave:
1169 0 : Py_XDECREF(py_status);
1170 0 : Py_XDECREF(py_args);
1171 0 : if (err)
1172 0 : _gpg_stash_callback_exception(self);
1173 0 : PyGILState_Release(state);
1174 0 : return err;
1175 : }
|