Blame lang/cpp/src/callbacks.cpp

Packit d7e8d0
/*
Packit d7e8d0
  callbacks.cpp - callback targets for internal use:
Packit d7e8d0
  Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
Packit d7e8d0
  2016 Bundesamt für Sicherheit in der Informationstechnik
Packit d7e8d0
  Software engineering by Intevation GmbH
Packit d7e8d0
Packit d7e8d0
  This file is part of GPGME++.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is free software; you can redistribute it and/or
Packit d7e8d0
  modify it under the terms of the GNU Library General Public
Packit d7e8d0
  License as published by the Free Software Foundation; either
Packit d7e8d0
  version 2 of the License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is distributed in the hope that it will be useful,
Packit d7e8d0
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit d7e8d0
  GNU Library General Public License for more details.
Packit d7e8d0
Packit d7e8d0
  You should have received a copy of the GNU Library General Public License
Packit d7e8d0
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
Packit d7e8d0
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d7e8d0
  Boston, MA 02110-1301, USA.
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
 #include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include "callbacks.h"
Packit d7e8d0
#include "util.h"
Packit d7e8d0
Packit d7e8d0
#include <interfaces/progressprovider.h>
Packit d7e8d0
#include <interfaces/passphraseprovider.h>
Packit d7e8d0
#include <interfaces/dataprovider.h>
Packit d7e8d0
#include <error.h>
Packit d7e8d0
Packit d7e8d0
#include <gpgme.h>
Packit d7e8d0
#include <gpg-error.h>
Packit d7e8d0
Packit d7e8d0
#include <cassert>
Packit d7e8d0
#include <cerrno>
Packit d7e8d0
#include <cstring>
Packit d7e8d0
#include <unistd.h>
Packit d7e8d0
#include <stdlib.h>
Packit d7e8d0
Packit d7e8d0
static inline gpgme_error_t make_err_from_syserror()
Packit d7e8d0
{
Packit d7e8d0
    return gpgme_error_from_syserror();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
using GpgME::ProgressProvider;
Packit d7e8d0
using GpgME::PassphraseProvider;
Packit d7e8d0
using GpgME::DataProvider;
Packit d7e8d0
Packit d7e8d0
void progress_callback(void *opaque, const char *what,
Packit d7e8d0
                       int type, int current, int total)
Packit d7e8d0
{
Packit d7e8d0
    ProgressProvider *provider = static_cast<ProgressProvider *>(opaque);
Packit d7e8d0
    if (provider) {
Packit d7e8d0
        provider->showProgress(what, type, current, total);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* To avoid that a compiler optimizes certain memset calls away, these
Packit d7e8d0
   macros may be used instead. */
Packit d7e8d0
#define wipememory2(_ptr,_set,_len) do { \
Packit d7e8d0
        volatile char *_vptr=(volatile char *)(_ptr); \
Packit d7e8d0
        size_t _vlen=(_len); \
Packit d7e8d0
        while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
Packit d7e8d0
    } while(0)
Packit d7e8d0
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
Packit d7e8d0
Packit d7e8d0
gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, const char *desc,
Packit d7e8d0
                                  int prev_was_bad, int fd)
Packit d7e8d0
{
Packit d7e8d0
    PassphraseProvider *provider = static_cast<PassphraseProvider *>(opaque);
Packit d7e8d0
    bool canceled = false;
Packit d7e8d0
    gpgme_error_t err = GPG_ERR_NO_ERROR;
Packit Service 30b792
    char *passphrase = provider ? provider->getPassphrase(uid_hint, desc, prev_was_bad, canceled) : nullptr ;
Packit d7e8d0
    if (canceled) {
Packit d7e8d0
        err = make_error(GPG_ERR_CANCELED);
Packit d7e8d0
    } else {
Packit d7e8d0
        if (passphrase && *passphrase) {
Packit d7e8d0
            size_t passphrase_length = std::strlen(passphrase);
Packit d7e8d0
            size_t written = 0;
Packit d7e8d0
            do {
Packit d7e8d0
                ssize_t now_written = gpgme_io_write(fd, passphrase + written, passphrase_length - written);
Packit d7e8d0
                if (now_written < 0) {
Packit d7e8d0
                    err = make_err_from_syserror();
Packit d7e8d0
                    break;
Packit d7e8d0
                }
Packit d7e8d0
                written += now_written;
Packit d7e8d0
            } while (written < passphrase_length);
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    if (passphrase && *passphrase) {
Packit d7e8d0
        wipememory(passphrase, std::strlen(passphrase));
Packit d7e8d0
    }
Packit d7e8d0
    free(passphrase);
Packit d7e8d0
    gpgme_io_write(fd, "\n", 1);
Packit d7e8d0
    return err;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_ssize_t
Packit d7e8d0
data_read_callback(void *opaque, void *buf, size_t buflen)
Packit d7e8d0
{
Packit d7e8d0
    DataProvider *provider = static_cast<DataProvider *>(opaque);
Packit d7e8d0
    if (!provider) {
Packit d7e8d0
        gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
Packit d7e8d0
        return -1;
Packit d7e8d0
    }
Packit d7e8d0
    return (gpgme_ssize_t)provider->read(buf, buflen);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_ssize_t
Packit d7e8d0
data_write_callback(void *opaque, const void *buf, size_t buflen)
Packit d7e8d0
{
Packit d7e8d0
    DataProvider *provider = static_cast<DataProvider *>(opaque);
Packit d7e8d0
    if (!provider) {
Packit d7e8d0
        gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
Packit d7e8d0
        return -1;
Packit d7e8d0
    }
Packit d7e8d0
    return (gpgme_ssize_t)provider->write(buf, buflen);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_off_t
Packit d7e8d0
data_seek_callback(void *opaque, gpgme_off_t offset, int whence)
Packit d7e8d0
{
Packit d7e8d0
    DataProvider *provider = static_cast<DataProvider *>(opaque);
Packit d7e8d0
    if (!provider) {
Packit d7e8d0
        gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
Packit d7e8d0
        return -1;
Packit d7e8d0
    }
Packit d7e8d0
    if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
Packit d7e8d0
        gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
Packit d7e8d0
        return -1;
Packit d7e8d0
    }
Packit d7e8d0
    return provider->seek((off_t)offset, whence);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static void data_release_callback(void *opaque)
Packit d7e8d0
{
Packit d7e8d0
    DataProvider *provider = static_cast<DataProvider *>(opaque);
Packit d7e8d0
    if (provider) {
Packit d7e8d0
        provider->release();
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const gpgme_data_cbs GpgME::data_provider_callbacks = {
Packit d7e8d0
    &data_read_callback,
Packit d7e8d0
    &data_write_callback,
Packit d7e8d0
    &data_seek_callback,
Packit d7e8d0
    &data_release_callback
Packit d7e8d0
};