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