Line data Source code
1 : /*
2 : callbacks.cpp - callback targets for internal use:
3 : Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
4 : 2016 Bundesamt für Sicherheit in der Informationstechnik
5 : Software engineering by Intevation GmbH
6 :
7 : This file is part of GPGME++.
8 :
9 : GPGME++ is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU Library General Public
11 : License as published by the Free Software Foundation; either
12 : version 2 of the License, or (at your option) any later version.
13 :
14 : GPGME++ is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Library General Public License for more details.
18 :
19 : You should have received a copy of the GNU Library General Public License
20 : along with GPGME++; see the file COPYING.LIB. If not, write to the
21 : Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 : Boston, MA 02110-1301, USA.
23 : */
24 :
25 : #ifdef HAVE_CONFIG_H
26 : #include "config.h"
27 : #endif
28 :
29 : #include "callbacks.h"
30 : #include "util.h"
31 :
32 : #include <interfaces/progressprovider.h>
33 : #include <interfaces/passphraseprovider.h>
34 : #include <interfaces/dataprovider.h>
35 : #include <error.h>
36 :
37 : #include <gpgme.h>
38 : #include <gpg-error.h>
39 :
40 : #include <cassert>
41 : #include <cerrno>
42 : #include <cstring>
43 : #include <unistd.h>
44 : #include <stdlib.h>
45 :
46 0 : static inline gpgme_error_t make_err_from_syserror()
47 : {
48 0 : return gpgme_error_from_syserror();
49 : }
50 :
51 : using GpgME::ProgressProvider;
52 : using GpgME::PassphraseProvider;
53 : using GpgME::DataProvider;
54 :
55 26 : void progress_callback(void *opaque, const char *what,
56 : int type, int current, int total)
57 : {
58 26 : ProgressProvider *provider = static_cast<ProgressProvider *>(opaque);
59 26 : if (provider) {
60 26 : provider->showProgress(what, type, current, total);
61 : }
62 26 : }
63 :
64 : /* To avoid that a compiler optimizes certain memset calls away, these
65 : macros may be used instead. */
66 : #define wipememory2(_ptr,_set,_len) do { \
67 : volatile char *_vptr=(volatile char *)(_ptr); \
68 : size_t _vlen=(_len); \
69 : while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
70 : } while(0)
71 : #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
72 :
73 6 : gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, const char *desc,
74 : int prev_was_bad, int fd)
75 : {
76 6 : PassphraseProvider *provider = static_cast<PassphraseProvider *>(opaque);
77 6 : bool canceled = false;
78 6 : gpgme_error_t err = GPG_ERR_NO_ERROR;
79 6 : char *passphrase = provider ? provider->getPassphrase(uid_hint, desc, prev_was_bad, canceled) : 0 ;
80 6 : if (canceled) {
81 0 : err = make_error(GPG_ERR_CANCELED);
82 : } else {
83 6 : if (passphrase && *passphrase) {
84 6 : size_t passphrase_length = std::strlen(passphrase);
85 6 : size_t written = 0;
86 0 : do {
87 6 : ssize_t now_written = gpgme_io_write(fd, passphrase + written, passphrase_length - written);
88 6 : if (now_written < 0) {
89 0 : err = make_err_from_syserror();
90 0 : break;
91 : }
92 6 : written += now_written;
93 6 : } while (written < passphrase_length);
94 : }
95 : }
96 :
97 6 : if (passphrase && *passphrase) {
98 6 : wipememory(passphrase, std::strlen(passphrase));
99 : }
100 6 : free(passphrase);
101 6 : gpgme_io_write(fd, "\n", 1);
102 6 : return err;
103 : }
104 :
105 : static gpgme_ssize_t
106 318 : data_read_callback(void *opaque, void *buf, size_t buflen)
107 : {
108 318 : DataProvider *provider = static_cast<DataProvider *>(opaque);
109 318 : if (!provider) {
110 0 : gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
111 0 : return -1;
112 : }
113 318 : return (gpgme_ssize_t)provider->read(buf, buflen);
114 : }
115 :
116 : static gpgme_ssize_t
117 61 : data_write_callback(void *opaque, const void *buf, size_t buflen)
118 : {
119 61 : DataProvider *provider = static_cast<DataProvider *>(opaque);
120 61 : if (!provider) {
121 0 : gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
122 0 : return -1;
123 : }
124 61 : return (gpgme_ssize_t)provider->write(buf, buflen);
125 : }
126 :
127 : static gpgme_off_t
128 205 : data_seek_callback(void *opaque, gpgme_off_t offset, int whence)
129 : {
130 205 : DataProvider *provider = static_cast<DataProvider *>(opaque);
131 205 : if (!provider) {
132 0 : gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
133 0 : return -1;
134 : }
135 205 : if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
136 0 : gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
137 0 : return -1;
138 : }
139 205 : return provider->seek((off_t)offset, whence);
140 : }
141 :
142 88 : static void data_release_callback(void *opaque)
143 : {
144 88 : DataProvider *provider = static_cast<DataProvider *>(opaque);
145 88 : if (provider) {
146 88 : provider->release();
147 : }
148 88 : }
149 :
150 : const gpgme_data_cbs GpgME::data_provider_callbacks = {
151 : &data_read_callback,
152 : &data_write_callback,
153 : &data_seek_callback,
154 : &data_release_callback
155 24 : };
|