From 93c5d420fcfe275aeff2b3d5ce99629edbe6625d Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Fri, 1 Jul 2016 16:49:06 +0200 Subject: [PATCH] Cpp: Add TofuInfo to signatures * lang/cpp/src/tofuinfo.cpp, lang/cpp/src/tofuinfo.h: New class. * lang/cpp/src/verificationresult.cpp (Signature::tofuInfo): New. (VerificationResult::Private): Handle tofu info. (GpgME::operator<<(std::ostream &os, const Signature &sig)): Include TofuInfo in dump. * lang/cpp/src/verificationresult.h (Signature::tofuInfo): New. * lang/cpp/src/Makefile.am (main_sources, gpgmepp_headers): Add new files. * configure.ac (LIBGPGMEPP_LT_REVISION): Bump for new API. --- configure.ac | 2 +- lang/cpp/src/Makefile.am | 5 +- lang/cpp/src/tofuinfo.cpp | 177 ++++++++++++++++++++++++++++ lang/cpp/src/tofuinfo.h | 126 ++++++++++++++++++++ lang/cpp/src/verificationresult.cpp | 19 +++ lang/cpp/src/verificationresult.h | 13 ++ 6 files changed, 339 insertions(+), 3 deletions(-) create mode 100644 lang/cpp/src/tofuinfo.cpp create mode 100644 lang/cpp/src/tofuinfo.h diff --git a/configure.ac b/configure.ac index 42695403..335a33a9 100644 --- a/configure.ac +++ b/configure.ac @@ -63,7 +63,7 @@ LIBGPGME_LT_REVISION=0 LIBGPGMEPP_LT_CURRENT=6 LIBGPGMEPP_LT_AGE=0 -LIBGPGMEPP_LT_REVISION=0 +LIBGPGMEPP_LT_REVISION=1 LIBQGPGME_LT_CURRENT=6 LIBQGPGME_LT_AGE=0 diff --git a/lang/cpp/src/Makefile.am b/lang/cpp/src/Makefile.am index d3d28ce6..364d2ca8 100644 --- a/lang/cpp/src/Makefile.am +++ b/lang/cpp/src/Makefile.am @@ -32,7 +32,7 @@ main_sources = \ gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \ gpgadduserideditinteractor.cpp defaultassuantransaction.cpp \ scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \ - vfsmountresult.cpp configuration.cpp + vfsmountresult.cpp configuration.cpp tofuinfo.cpp gpgmepp_headers = \ assuanresult.h configuration.h context.h data.h decryptionresult.h \ @@ -43,7 +43,8 @@ gpgmepp_headers = \ gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \ importresult.h keygenerationresult.h key.h keylistresult.h \ notation.h result.h scdgetinfoassuantransaction.h signingresult.h \ - trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h + trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \ + tofuinfo.h private_gpgmepp_headers = \ result_p.h context_p.h util.h callbacks.h data_p.h diff --git a/lang/cpp/src/tofuinfo.cpp b/lang/cpp/src/tofuinfo.cpp new file mode 100644 index 00000000..c27a59ed --- /dev/null +++ b/lang/cpp/src/tofuinfo.cpp @@ -0,0 +1,177 @@ +/* tofuinfo.cpp - wraps gpgme tofu info + Copyright (C) 2016 Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tofuinfo.h" + +#include +#include "util.h" + +class GpgME::TofuInfo::Private +{ +public: + Private() {} + Private(gpgme_tofu_info_t info) + : mInfo(info ? new _gpgme_tofu_info(*info) : nullptr) + { + if (mInfo && mInfo->fpr) { + mInfo->fpr = strdup(mInfo->fpr); + } + if (mInfo && mInfo->address) { + mInfo->address = strdup(mInfo->address); + } + if (mInfo && mInfo->description) { + mInfo->description = strdup(mInfo->description); + } + } + + Private(const Private &other) + : mInfo(other.mInfo) + { + if (mInfo && mInfo->fpr) { + mInfo->fpr = strdup(mInfo->fpr); + } + if (mInfo && mInfo->address) { + mInfo->address = strdup(mInfo->address); + } + if (mInfo && mInfo->description) { + mInfo->description = strdup(mInfo->description); + } + } + + ~Private() + { + if (mInfo) { + std::free(mInfo->fpr); + mInfo->fpr = nullptr; + std::free(mInfo->address); + mInfo->address = nullptr; + std::free(mInfo->description); + mInfo->description = nullptr; + + delete mInfo; + } + } + + gpgme_tofu_info_t mInfo; +}; + +GpgME::TofuInfo::TofuInfo(gpgme_tofu_info_t info) + : d(new Private(info)) +{ +} + +GpgME::TofuInfo::TofuInfo() : d() +{ +} + +bool GpgME::TofuInfo::isNull() const +{ + return !d || !d->mInfo; +} + +GpgME::TofuInfo::Validity GpgME::TofuInfo::validity() const +{ + if (isNull()) { + return ValidityUnknown; + } + switch (d->mInfo->validity) { + case 0: + return Conflict; + case 1: + return NoHistory; + case 2: + return LittleHistory; + case 3: + return BasicHistory; + case 4: + return LargeHistory; + default: + return ValidityUnknown; + } +} + +GpgME::TofuInfo::Policy GpgME::TofuInfo::policy() const +{ + if (isNull()) { + return PolicyUnknown; + } + switch (d->mInfo->policy) { + case GPGME_TOFU_POLICY_NONE: + return PolicyNone; + case GPGME_TOFU_POLICY_AUTO: + return PolicyAuto; + case GPGME_TOFU_POLICY_GOOD: + return PolicyGood; + case GPGME_TOFU_POLICY_BAD: + return PolicyBad; + case GPGME_TOFU_POLICY_ASK: + return PolicyAsk; + case GPGME_TOFU_POLICY_UNKNOWN: + return PolicyUnknown; + } +} + +const char *GpgME::TofuInfo::fingerprint() const +{ + return isNull() ? nullptr : d->mInfo->fpr; +} + +const char *GpgME::TofuInfo::address() const +{ + return isNull() ? nullptr : d->mInfo->address; +} + +const char *GpgME::TofuInfo::description() const +{ + return isNull() ? nullptr : d->mInfo->description; +} + +unsigned short GpgME::TofuInfo::signCount() const +{ + return isNull() ? 0 : d->mInfo->signcount; +} + +unsigned int GpgME::TofuInfo::firstSeen() const +{ + return isNull() ? 0 : d->mInfo->firstseen; +} + +unsigned int GpgME::TofuInfo::lastSeen() const +{ + return isNull() ? 0 : d->mInfo->lastseen; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const GpgME::TofuInfo &info) +{ + os << "GpgME::Signature::TofuInfo("; + if (!info.isNull()) { + os << "\n address: " << protect(info.address()) + << "\n fpr: " << protect(info.fingerprint()) + << "\n desc: " << protect(info.description()) + << "\n validity: " << info.validity() + << "\n policy: " << info.policy() + << "\n signcount: "<< info.signCount() + << "\n firstseen: "<< info.firstSeen() + << "\n lastseen: " << info.lastSeen() + << '\n'; + } + return os << ")"; +} diff --git a/lang/cpp/src/tofuinfo.h b/lang/cpp/src/tofuinfo.h new file mode 100644 index 00000000..c698360f --- /dev/null +++ b/lang/cpp/src/tofuinfo.h @@ -0,0 +1,126 @@ +/* + tofuinfo.h - wraps gpgme tofu info + Copyright (C) 2016 Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_TOFUINFO_H__ +#define __GPGMEPP_TOFUINFO_H__ + +#include "gpgmepp_export.h" + +#include "gpgme.h" + +#include "global.h" + +#include + +namespace GpgME +{ + +class GPGMEPP_EXPORT TofuInfo +{ +public: + TofuInfo(); + explicit TofuInfo(gpgme_tofu_info_t info); + + const TofuInfo &operator=(TofuInfo other) + { + swap(other); + return *this; + } + + void swap(TofuInfo &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + /* @enum Validity + * @brief The TOFU Validity. */ + enum Validity { + /*! Unknown (uninitialized).*/ + ValidityUnknown, + /*! TOFU Conflict.*/ + Conflict, + /*! Key without history.*/ + NoHistory, + /*! Key with too little history.*/ + LittleHistory, + /*! Key with enough history for basic trust.*/ + BasicHistory, + /*! Key with a lot of history.*/ + LargeHistory, + }; + Validity validity() const; + + /* @enum Policy + * @brief The TOFU Validity. */ + enum Policy { + /*! GPGME_TOFU_POLICY_NONE */ + PolicyNone, + /*! GPGME_TOFU_POLICY_AUTO */ + PolicyAuto, + /*! GPGME_TOFU_POLICY_GOOD */ + PolicyGood, + /*! GPGME_TOFU_POLICY_UNKNOWN */ + PolicyUnknown, + /*! GPGME_TOFU_POLICY_BAD */ + PolicyBad, + /*! GPGME_TOFU_POLICY_ASK */ + PolicyAsk, + }; + Policy policy() const; + + /* Number of signatures seen for this binding. Capped at USHRT_MAX. */ + unsigned short signCount() const; + + /* Number of seconds since the first message was verified. */ + unsigned int firstSeen() const; + + /* Number of seconds since the last message was verified. */ + unsigned int lastSeen() const; + + /* Finterprint of the key for this entry. */ + const char *fingerprint() const; + + /* If non-NULL a human readable string summarizing the TOFU data. */ + const char *description() const; + + /* The address of the tofu binding. + * + * If no mail address is set for a User ID this is the name used + * for the user ID. Can be ambiguous when the same mail address or + * name is used in multiple user ids. + */ + const char *address() const; + +private: + class Private; + std::shared_ptr d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const TofuInfo &info); + +} // namespace GpgME + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TofuInfo) +#endif // __GPGMEPP_TOFUINFO_H__ diff --git a/lang/cpp/src/verificationresult.cpp b/lang/cpp/src/verificationresult.cpp index b6fde7da..4bd1a7b1 100644 --- a/lang/cpp/src/verificationresult.cpp +++ b/lang/cpp/src/verificationresult.cpp @@ -24,6 +24,7 @@ #include #include "result_p.h" #include "util.h" +#include "tofuinfo.h" #include @@ -81,6 +82,11 @@ public: } nota.back().push_back(n); } + // copy tofu info: + tinfos.push_back(std::vector()); + for (gpgme_tofu_info_t in = is->tofu; in ; in = in->next) { + tinfos.back().push_back(TofuInfo(in)); + } } } ~Private() @@ -107,6 +113,7 @@ public: std::vector sigs; std::vector< std::vector > nota; + std::vector< std::vector > tinfos; std::vector purls; std::string file_name; }; @@ -363,6 +370,15 @@ std::vector GpgME::Signature::notations() const return result; } +std::vector GpgME::Signature::tofuInfo() const +{ + if (isNull()) { + return std::vector(); + } + + return d->tinfos[idx]; +} + class GpgME::Notation::Private { public: @@ -530,6 +546,9 @@ std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig) const std::vector nota = sig.notations(); std::copy(nota.begin(), nota.end(), std::ostream_iterator(os, "\n")); + const std::vector tinfos = sig.tofuInfo(); + std::copy(tinfos.begin(), tinfos.end(), + std::ostream_iterator(os, "\n")); } return os << ')'; } diff --git a/lang/cpp/src/verificationresult.h b/lang/cpp/src/verificationresult.h index 17f0568b..5a2927f9 100644 --- a/lang/cpp/src/verificationresult.h +++ b/lang/cpp/src/verificationresult.h @@ -40,6 +40,7 @@ namespace GpgME class Error; class Signature; class Notation; +class TofuInfo; class GPGMEPP_EXPORT VerificationResult : public Result { @@ -156,6 +157,18 @@ public: GpgME::Notation notation(unsigned int index) const; std::vector notations() const; + /** List of TOFU stats for this signature. + * + * For each UserID of the key used to create this + * signature a tofu entry is returned. + * + * Warning: Addresses can be ambigous if there are multiple UserID's + * with the same mailbox in a key. + * + * @returns The list of TOFU stats. + */ + std::vector tofuInfo() const; + private: std::shared_ptr d; unsigned int idx;