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