diff --git a/src/Conf.cpp b/src/Conf.cpp index 2f06d7eaa..a9432f4b7 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -47,7 +47,7 @@ Conf::Conf() = default; Conf::~Conf() = default; /** - * Return global instance object + * Return global config instance object */ Conf* Conf::instance() { return INSTANCE; } @@ -248,7 +248,7 @@ ConfV2::ConfV2() = default; ConfV2::~ConfV2() = default; /** - * Return global instance object + * @copydoc digidoc::Conf::instance() */ ConfV2* ConfV2::instance() { return dynamic_cast(Conf::instance()); } @@ -277,7 +277,7 @@ ConfV3::ConfV3() = default; ConfV3::~ConfV3() = default; /** - * Return global instance object + * @copydoc digidoc::Conf::instance() */ ConfV3* ConfV3::instance() { return dynamic_cast(Conf::instance()); } @@ -308,7 +308,7 @@ ConfV4::ConfV4() = default; ConfV4::~ConfV4() = default; /** - * Return global instance object + * @copydoc digidoc::Conf::instance() */ ConfV4* ConfV4::instance() { return dynamic_cast(Conf::instance()); } @@ -317,8 +317,37 @@ ConfV4* ConfV4::instance() { return dynamic_cast(Conf::instance()); } */ vector ConfV4::verifyServiceCerts() const { - X509Cert cert = verifyServiceCert(); - if(!cert) - return {}; - return { cert }; + if(X509Cert cert = verifyServiceCert()) + return { cert }; + return {}; +} + +/** + * @class digidoc::ConfV5 + * @brief Verison 5 of configuration class to add additonial parameters. + * + * Conf contains virtual members and is not leaf class we need create + * subclasses to keep binary compatibility + * https://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++#Adding_new_virtual_functions_to_leaf_classes + * @see digidoc::ConfV4 + * @see @ref parameters + */ +/** + * Version 4 config with new parameters + */ +ConfV5::ConfV5() = default; + +ConfV5::~ConfV5() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ +ConfV5* ConfV5::instance() { return dynamic_cast(Conf::instance()); } + +/** + * Gets verify service Certs + */ +vector ConfV5::TSCerts() const +{ + return {}; } diff --git a/src/Conf.h b/src/Conf.h index eee1dbb79..9a44917b7 100644 --- a/src/Conf.h +++ b/src/Conf.h @@ -113,6 +113,19 @@ class DIGIDOCPP_EXPORT ConfV4: public ConfV3 DISABLE_COPY(ConfV4); }; -using ConfCurrent = ConfV4; +class DIGIDOCPP_EXPORT ConfV5: public ConfV4 +{ +public: + ConfV5(); + ~ConfV5() override; + static ConfV5* instance(); + + virtual std::vector TSCerts() const; + +private: + DISABLE_COPY(ConfV5); +}; + +using ConfCurrent = ConfV5; #define CONF(method) (ConfCurrent::instance() ? ConfCurrent::instance()->method() : ConfCurrent().method()) } diff --git a/src/Exports.h b/src/Exports.h index bb7e5f8cc..c337f9e5c 100644 --- a/src/Exports.h +++ b/src/Exports.h @@ -61,5 +61,5 @@ #define DISABLE_COPY(Class) \ Class(const Class &) = delete; \ Class &operator=(const Class &) = delete; \ - Class(Class &&) = delete; \ - Class &operator=(Class &&) = delete + Class(Class &&) DIGIDOCPP_NOEXCEPT = delete; \ + Class &operator=(Class &&) DIGIDOCPP_NOEXCEPT = delete diff --git a/src/XmlConf.cpp b/src/XmlConf.cpp index dedee6db6..3ea8f9115 100644 --- a/src/XmlConf.cpp +++ b/src/XmlConf.cpp @@ -318,6 +318,10 @@ XmlConf::XmlConf(const string &path, const string &schema) : d(make_unique(path, schema.empty() ? File::path(xsdPath(), "conf.xsd") : schema)) {} XmlConf::~XmlConf() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ XmlConf* XmlConf::instance() { return dynamic_cast(Conf::instance()); } /** @@ -333,6 +337,10 @@ XmlConfV2::XmlConfV2(const string &path, const string &schema) : d(make_unique(path, schema.empty() ? File::path(xsdPath(), "conf.xsd") : schema)) {} XmlConfV2::~XmlConfV2() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ XmlConfV2* XmlConfV2::instance() { return dynamic_cast(Conf::instance()); } /** @@ -348,6 +356,10 @@ XmlConfV3::XmlConfV3(const string &path, const string &schema) : d(make_unique(path, schema.empty() ? File::path(xsdPath(), "conf.xsd") : schema)) {} XmlConfV3::~XmlConfV3() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ XmlConfV3* XmlConfV3::instance() { return dynamic_cast(Conf::instance()); } /** @@ -362,35 +374,62 @@ XmlConfV4::XmlConfV4(const string &path, const string &schema) : d(make_unique(path, schema.empty() ? File::path(xsdPath(), "conf.xsd") : schema)) {} XmlConfV4::~XmlConfV4() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ XmlConfV4* XmlConfV4::instance() { return dynamic_cast(Conf::instance()); } +/** + * @class digidoc::XmlConfV5 + * @brief Version 5 of XML Configuration class + * @see digidoc::ConfV5 + */ +/** + * Initialize xml conf from path + */ +XmlConfV5::XmlConfV5(const string &path, const string &schema) + : d(make_unique(path, schema.empty() ? File::path(xsdPath(), "conf.xsd") : schema)) +{} +XmlConfV5::~XmlConfV5() = default; + +/** + * @copydoc digidoc::Conf::instance() + */ +XmlConfV5* XmlConfV5::instance() { return dynamic_cast(Conf::instance()); } + #define GET1(TYPE, PROP) \ TYPE XmlConf::PROP() const { return d->PROP.value(Conf::PROP()); } \ TYPE XmlConfV2::PROP() const { return d->PROP.value(Conf::PROP()); } \ TYPE XmlConfV3::PROP() const { return d->PROP.value(Conf::PROP()); } \ -TYPE XmlConfV4::PROP() const { return d->PROP.value(Conf::PROP()); } +TYPE XmlConfV4::PROP() const { return d->PROP.value(Conf::PROP()); } \ +TYPE XmlConfV5::PROP() const { return d->PROP.value(Conf::PROP()); } #define SET1(TYPE, SET, PROP) \ void XmlConf::SET(TYPE PROP) \ { d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ void XmlConfV2::SET(TYPE PROP) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ +{ d->setUserConf(d->PROP, ConfV2::PROP(), PROP); } \ void XmlConfV3::SET(TYPE PROP) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ +{ d->setUserConf(d->PROP, ConfV3::PROP(), PROP); } \ void XmlConfV4::SET(TYPE PROP) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } +{ d->setUserConf(d->PROP, ConfV4::PROP(), PROP); } \ +void XmlConfV5::SET(TYPE PROP) \ +{ d->setUserConf(d->PROP, ConfV5::PROP(), PROP); } #define SET1CONST(TYPE, SET, PROP) \ void XmlConf::SET(const TYPE &(PROP)) \ { d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ void XmlConfV2::SET(const TYPE &(PROP)) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ +{ d->setUserConf(d->PROP, ConfV2::PROP(), PROP); } \ void XmlConfV3::SET(const TYPE &(PROP)) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } \ +{ d->setUserConf(d->PROP, ConfV3::PROP(), PROP); } \ void XmlConfV4::SET(const TYPE &(PROP)) \ -{ d->setUserConf(d->PROP, Conf::PROP(), PROP); } +{ d->setUserConf(d->PROP, ConfV4::PROP(), PROP); } \ +void XmlConfV5::SET(const TYPE &(PROP)) \ +{ d->setUserConf(d->PROP, ConfV5::PROP(), PROP); } GET1(int, logLevel) GET1(string, logFile) @@ -437,6 +476,12 @@ string XmlConfV4::ocsp(const string &issuer) const return i != d->ocsp.end() ? i->second : Conf::ocsp(issuer); } +string XmlConfV5::ocsp(const string &issuer) const +{ + auto i = d->ocsp.find(issuer); + return i != d->ocsp.end() ? i->second : Conf::ocsp(issuer); +} + /** * @fn void digidoc::XmlConf::setTSLOnlineDigest(bool enable) * Enables/Disables online digest check @@ -454,6 +499,10 @@ string XmlConfV4::ocsp(const string &issuer) const * @fn void digidoc::XmlConfV4::setTSLOnlineDigest(bool enable) * @copydoc digidoc::XmlConf::setTSLOnlineDigest(bool enable) */ +/** + * @fn void digidoc::XmlConfV5::setTSLOnlineDigest(bool enable) + * @copydoc digidoc::XmlConf::setTSLOnlineDigest(bool enable) + */ SET1(bool, setTSLOnlineDigest, TSLOnlineDigest) /** @@ -474,6 +523,10 @@ SET1(bool, setTSLOnlineDigest, TSLOnlineDigest) * @fn void digidoc::XmlConfV4::setTSLTimeOut(int timeOut) * @copydoc digidoc::XmlConf::setTSLTimeOut(int timeOut) */ +/** + * @fn void digidoc::XmlConfV5::setTSLTimeOut(int timeOut) + * @copydoc digidoc::XmlConf::setTSLTimeOut(int timeOut) + */ SET1(int, setTSLTimeOut, TSLTimeOut) /** @@ -495,6 +548,10 @@ SET1(int, setTSLTimeOut, TSLTimeOut) * @fn void digidoc::XmlConfV4::setProxyHost(const std::string &host) * @copydoc digidoc::XmlConf::setProxyHost(const std::string &host) */ +/** + * @fn void digidoc::XmlConfV5::setProxyHost(const std::string &host) + * @copydoc digidoc::XmlConf::setProxyHost(const std::string &host) + */ SET1CONST(string, setProxyHost, proxyHost) /** @@ -516,6 +573,10 @@ SET1CONST(string, setProxyHost, proxyHost) * @fn void digidoc::XmlConfV4::setProxyPort(const std::string &port) * @copydoc digidoc::XmlConf::setProxyPort(const std::string &port) */ +/** + * @fn void digidoc::XmlConfV5::setProxyPort(const std::string &port) + * @copydoc digidoc::XmlConf::setProxyPort(const std::string &port) + */ SET1CONST(string, setProxyPort, proxyPort) /** @@ -537,6 +598,10 @@ SET1CONST(string, setProxyPort, proxyPort) * @fn void digidoc::XmlConfV4::setProxyUser(const std::string &user) * @copydoc digidoc::XmlConf::setProxyUser(const std::string &user) */ +/** + * @fn void digidoc::XmlConfV5::setProxyUser(const std::string &user) + * @copydoc digidoc::XmlConf::setProxyUser(const std::string &user) + */ SET1CONST(string, setProxyUser, proxyUser) /** @@ -558,6 +623,10 @@ SET1CONST(string, setProxyUser, proxyUser) * @fn void digidoc::XmlConfV4::setProxyPass(const std::string &pass) * @copydoc digidoc::XmlConf::setProxyPass(const std::string &pass) */ +/** + * @fn void digidoc::XmlConfV5::setProxyPass(const std::string &pass) + * @copydoc digidoc::XmlConf::setProxyPass(const std::string &pass) + */ SET1CONST(string, setProxyPass, proxyPass) /** @@ -580,6 +649,10 @@ SET1CONST(string, setProxyPass, proxyPass) * @fn void digidoc::XmlConfV4::setPKCS12Cert(const std::string &cert) * @copydoc digidoc::XmlConf::setPKCS12Cert(const std::string &cert) */ +/** + * @fn void digidoc::XmlConfV5::setPKCS12Cert(const std::string &cert) + * @copydoc digidoc::XmlConf::setPKCS12Cert(const std::string &cert) + */ SET1CONST(string, setPKCS12Cert, PKCS12Cert) /** @@ -601,6 +674,10 @@ SET1CONST(string, setPKCS12Cert, PKCS12Cert) * @fn void digidoc::XmlConfV4::setPKCS12Pass(const std::string &pass) * @copydoc digidoc::XmlConf::setPKCS12Pass(const std::string &pass) */ +/** + * @fn void digidoc::XmlConfV5::setPKCS12Pass(const std::string &pass) + * @copydoc digidoc::XmlConf::setPKCS12Pass(const std::string &pass) + */ SET1CONST(string, setPKCS12Pass, PKCS12Pass) /** @@ -622,6 +699,10 @@ SET1CONST(string, setPKCS12Pass, PKCS12Pass) * @fn void digidoc::XmlConfV4::setTSUrl(const std::string &url) * @copydoc digidoc::XmlConf::setTSUrl(const std::string &url) */ +/** + * @fn void digidoc::XmlConfV5::setTSUrl(const std::string &url) + * @copydoc digidoc::XmlConf::setTSUrl(const std::string &url) + */ SET1CONST(string, setTSUrl, TSUrl) /** @@ -631,6 +712,22 @@ SET1CONST(string, setTSUrl, TSUrl) * @param url Target URL to connect Verify service. * @throws Exception exception is thrown if saving a Verify service URL into a user configuration file fails. */ +/** + * @fn void digidoc::XmlConfV2::setVerifyServiceUri(const std::string &url) + * @copydoc digidoc::XmlConf::setVerifyServiceUri(const std::string &url) + */ +/** + * @fn void digidoc::XmlConfV3::setVerifyServiceUri(const std::string &url) + * @copydoc digidoc::XmlConf::setVerifyServiceUri(const std::string &url) + */ +/** + * @fn void digidoc::XmlConfV4::setVerifyServiceUri(const std::string &url) + * @copydoc digidoc::XmlConf::setVerifyServiceUri(const std::string &url) + */ +/** + * @fn void digidoc::XmlConfV5::setVerifyServiceUri(const std::string &url) + * @copydoc digidoc::XmlConf::setVerifyServiceUri(const std::string &url) + */ SET1CONST(string, setVerifyServiceUri, verifyServiceUri) /** @@ -652,6 +749,10 @@ SET1CONST(string, setVerifyServiceUri, verifyServiceUri) * @fn void digidoc::XmlConfV4::setPKCS12Disable(bool disable) * @copydoc digidoc::XmlConf::setPKCS12Disable(bool disable) */ +/** + * @fn void digidoc::XmlConfV5::setPKCS12Disable(bool disable) + * @copydoc digidoc::XmlConf::setPKCS12Disable(bool disable) + */ SET1(bool, setPKCS12Disable, PKCS12Disable) /** @@ -672,6 +773,10 @@ SET1(bool, setPKCS12Disable, PKCS12Disable) * @fn void digidoc::XmlConfV4::setProxyTunnelSSL(bool enable) * @copydoc digidoc::XmlConf::setProxyTunnelSSL(bool enable) */ +/** + * @fn void digidoc::XmlConfV5::setProxyTunnelSSL(bool enable) + * @copydoc digidoc::XmlConf::setProxyTunnelSSL(bool enable) + */ SET1(bool, setProxyTunnelSSL, proxyTunnelSSL) @@ -690,6 +795,11 @@ X509Cert XmlConfV4::verifyServiceCert() const return ConfV4::verifyServiceCert(); } +X509Cert XmlConfV5::verifyServiceCert() const +{ + return ConfV5::verifyServiceCert(); +} + set XmlConfV3::OCSPTMProfiles() const { return d->ocspTMProfiles.empty() ? ConfV3::OCSPTMProfiles() : d->ocspTMProfiles; @@ -700,7 +810,22 @@ set XmlConfV4::OCSPTMProfiles() const return d->ocspTMProfiles.empty() ? ConfV3::OCSPTMProfiles() : d->ocspTMProfiles; } +set XmlConfV5::OCSPTMProfiles() const +{ + return d->ocspTMProfiles.empty() ? ConfV3::OCSPTMProfiles() : d->ocspTMProfiles; +} + vector XmlConfV4::verifyServiceCerts() const { return ConfV4::verifyServiceCerts(); } + +vector XmlConfV5::verifyServiceCerts() const +{ + return ConfV5::verifyServiceCerts(); +} + +vector XmlConfV5::TSCerts() const +{ + return ConfV5::TSCerts(); +} diff --git a/src/XmlConf.h b/src/XmlConf.h index 48902574e..385459839 100644 --- a/src/XmlConf.h +++ b/src/XmlConf.h @@ -82,6 +82,7 @@ class DIGIDOCPP_EXPORT XmlConf: public Conf friend class XmlConfV2; friend class XmlConfV3; friend class XmlConfV4; + friend class XmlConfV5; }; class DIGIDOCPP_EXPORT XmlConfV2: public ConfV2 @@ -252,5 +253,63 @@ class DIGIDOCPP_EXPORT XmlConfV4: public ConfV4 std::unique_ptr d; }; -using XmlConfCurrent = XmlConfV4; +class DIGIDOCPP_EXPORT XmlConfV5: public ConfV5 +{ +public: + explicit XmlConfV5(const std::string &path = {}, const std::string &schema = {}); + ~XmlConfV5() override; + static XmlConfV5* instance(); + + int logLevel() const override; + std::string logFile() const override; + std::string PKCS11Driver() const override; + + std::string proxyHost() const override; + std::string proxyPort() const override; + std::string proxyUser() const override; + std::string proxyPass() const override; + bool proxyForceSSL() const override; + bool proxyTunnelSSL() const override; + + std::string digestUri() const override; + std::string signatureDigestUri() const override; + std::string ocsp(const std::string &issuer) const override; + std::set OCSPTMProfiles() const override; + std::vector TSCerts() const override; + std::string TSUrl() const override; + X509Cert verifyServiceCert() const override; + std::vector verifyServiceCerts() const override; + std::string verifyServiceUri() const override; + + std::string PKCS12Cert() const override; + std::string PKCS12Pass() const override; + bool PKCS12Disable() const override; + + bool TSLAutoUpdate() const override; + std::string TSLCache() const override; + bool TSLOnlineDigest() const override; + int TSLTimeOut() const override; + + virtual void setProxyHost( const std::string &host ); + virtual void setProxyPort( const std::string &port ); + virtual void setProxyUser( const std::string &user ); + virtual void setProxyPass( const std::string &pass ); + virtual void setProxyTunnelSSL( bool enable ); + virtual void setPKCS12Cert( const std::string &cert ); + virtual void setPKCS12Pass( const std::string &pass ); + virtual void setPKCS12Disable( bool disable ); + + virtual void setTSLOnlineDigest( bool enable ); + virtual void setTSLTimeOut( int timeOut ); + + virtual void setTSUrl(const std::string &url); + virtual void setVerifyServiceUri(const std::string &url); + +private: + DISABLE_COPY(XmlConfV5); + + std::unique_ptr d; +}; + +using XmlConfCurrent = XmlConfV5; } diff --git a/src/crypto/OpenSSLHelpers.h b/src/crypto/OpenSSLHelpers.h index fac863244..126a59392 100644 --- a/src/crypto/OpenSSLHelpers.h +++ b/src/crypto/OpenSSLHelpers.h @@ -35,8 +35,9 @@ namespace digidoc { -#define SCOPE2(TYPE, VAR, DATA, FREE) std::unique_ptr VAR(static_cast(DATA), FREE) -#define SCOPE(TYPE, VAR, DATA) SCOPE2(TYPE, VAR, DATA, TYPE##_free) +#define SCOPE_PTR_FREE(TYPE, DATA, FREE) std::unique_ptr(static_cast(DATA), FREE) +#define SCOPE_PTR(TYPE, DATA) SCOPE_PTR_FREE(TYPE, DATA, TYPE##_free) +#define SCOPE(TYPE, VAR, DATA) auto VAR = SCOPE_PTR_FREE(TYPE, DATA, TYPE##_free) template std::vector i2d(T *obj, Func func) diff --git a/src/crypto/PKCS11Signer.cpp b/src/crypto/PKCS11Signer.cpp index c6575c05f..6c4403122 100644 --- a/src/crypto/PKCS11Signer.cpp +++ b/src/crypto/PKCS11Signer.cpp @@ -191,7 +191,7 @@ X509Cert PKCS11Signer::cert() const DEBUG("PKCS11Signer::getCert()"); // If certificate is already selected return it. - if(!!d->sign.certificate) + if(d->sign.certificate) return d->sign.certificate; // Load all slots. diff --git a/src/crypto/TS.cpp b/src/crypto/TS.cpp index 38168a3de..9d888f397 100644 --- a/src/crypto/TS.cpp +++ b/src/crypto/TS.cpp @@ -19,10 +19,10 @@ #include "TS.h" +#include "Conf.h" #include "Container.h" #include "Exception.h" #include "crypto/Connect.h" -#include "crypto/Digest.h" #include "crypto/OpenSSLHelpers.h" #include "crypto/X509CertStore.h" #include "util/DateTime.h" @@ -43,30 +43,30 @@ using namespace std; #if defined(LIBRESSL_VERSION_NUMBER) void *OPENSSL_memdup(const void *data, size_t size) { - void *copy; + void *copy; - if (data == NULL || size == 0 || size >= INT_MAX) - return NULL; + if (data == NULL || size == 0 || size >= INT_MAX) + return NULL; - if ((copy = malloc(size)) == NULL) - return NULL; + if ((copy = malloc(size)) == NULL) + return NULL; - return memcpy(copy, data, size); + return memcpy(copy, data, size); } #endif TS::TS(const string &url, const Digest &digest, const string &useragent) { - SCOPE(TS_REQ, req, TS_REQ_new()); + auto req = SCOPE_PTR(TS_REQ, TS_REQ_new()); TS_REQ_set_version(req.get(), 1); TS_REQ_set_cert_req(req.get(), 1); - SCOPE(X509_ALGOR, algo, X509_ALGOR_new()); + auto algo = SCOPE_PTR(X509_ALGOR, X509_ALGOR_new()); algo->algorithm = OBJ_nid2obj(Digest::toMethod(digest.uri())); algo->parameter = ASN1_TYPE_new(); algo->parameter->type = V_ASN1_NULL; - SCOPE(TS_MSG_IMPRINT, msg_imprint, TS_MSG_IMPRINT_new()); + auto msg_imprint = SCOPE_PTR(TS_MSG_IMPRINT, TS_MSG_IMPRINT_new()); TS_MSG_IMPRINT_set_algo(msg_imprint.get(), algo.get()); vector digestdata = digest.result(); TS_MSG_IMPRINT_set_msg(msg_imprint.get(), digestdata.data(), int(digestdata.size())); @@ -75,20 +75,19 @@ TS::TS(const string &url, const Digest &digest, const string &useragent) #if 0 if(!policy.empty()) { - SCOPE(ASN1_OBJECT, obj, OBJ_txt2obj(policy.c_str(), 0)); + auto obj = SCOPE_PTR(ASN1_OBJECT, OBJ_txt2obj(policy.c_str(), 0)); TS_REQ_set_policy_id(req.get(), obj.get()); } #endif - SCOPE(ASN1_INTEGER, nonce, ASN1_INTEGER_new()); - nonce->length = 20; - nonce->data = (unsigned char*)OPENSSL_malloc(size_t(nonce->length)); + auto nonce = SCOPE_PTR(ASN1_INTEGER, ASN1_INTEGER_new()); + ASN1_STRING_set(nonce.get(), nullptr, 20); nonce->data[0] = 0; while(nonce->data[0] == 0) // Make sure that first byte is not 0x00 RAND_bytes(nonce->data, nonce->length); TS_REQ_set_nonce(req.get(), nonce.get()); - Connect::Result result = Connect(url, "POST", 0, useragent).exec({ + Connect::Result result = Connect(url, "POST", 0, useragent, CONF(TSCerts)).exec({ {"Content-Type", "application/timestamp-query"}, {"Accept", "application/timestamp-reply"}, {"Connection", "Close"}, @@ -111,11 +110,11 @@ TS::TS(const string &url, const Digest &digest, const string &useragent) THROW("Failed to send Time-stamp request"); const unsigned char *p2 = (const unsigned char*)result.content.c_str(); - SCOPE(TS_RESP, resp, d2i_TS_RESP(nullptr, &p2, long(result.content.size()))); + auto resp = SCOPE_PTR(TS_RESP, d2i_TS_RESP(nullptr, &p2, long(result.content.size()))); if(!resp) THROW_OPENSSLEXCEPTION("Failed to parse TS response."); - SCOPE(TS_VERIFY_CTX, ctx, TS_REQ_to_TS_VERIFY_CTX(req.get(), nullptr)); + auto ctx = SCOPE_PTR(TS_VERIFY_CTX, TS_REQ_to_TS_VERIFY_CTX(req.get(), nullptr)); TS_VERIFY_CTX_set_flags(ctx.get(), TS_VFY_VERSION|TS_VFY_NONCE); if(TS_RESP_verify_response(ctx.get(), resp.get()) != 1) THROW_OPENSSLEXCEPTION("Failed to verify TS response."); @@ -139,7 +138,7 @@ TS::TS(const unsigned char *data, size_t size) * * If PKCS7 wrapped TimeStamp parsing fails, try with CMS wrapping */ - SCOPE(BIO, bio, BIO_new_mem_buf((void*)data, int(size))); + auto bio = SCOPE_PTR(BIO, BIO_new_mem_buf((void*)data, int(size))); cms.reset(d2i_CMS_bio(bio.get(), nullptr), CMS_ContentInfo_free); if(!cms || OBJ_obj2nid(CMS_get0_eContentType(cms.get())) != NID_id_smime_ct_TSTInfo) cms.reset(); @@ -166,18 +165,33 @@ X509Cert TS::cert() const return X509Cert(sk_X509_value(signers.get(), 0)); } +auto TS::tstInfo() const +{ + if(d) + return SCOPE_PTR(TS_TST_INFO, PKCS7_to_TS_TST_INFO(d.get())); +#ifndef OPENSSL_NO_CMS + if(cms) + { + auto out = SCOPE_PTR(BIO, CMS_dataInit(cms.get(), nullptr)); + return SCOPE_PTR(TS_TST_INFO, d2i_TS_TST_INFO_bio(out.get(), nullptr)); + } +#endif + return SCOPE_PTR(TS_TST_INFO, nullptr); +} + string TS::digestMethod() const { - SCOPE(TS_TST_INFO, info, tstInfo()); + auto info = tstInfo(); if(!info) return {}; - X509_ALGOR *algo = TS_MSG_IMPRINT_get_algo(TS_TST_INFO_get_msg_imprint(info.get())); - return Digest::toUri(OBJ_obj2nid(algo->algorithm)); + if(X509_ALGOR *algo = TS_MSG_IMPRINT_get_algo(TS_TST_INFO_get_msg_imprint(info.get()))) + return Digest::toUri(OBJ_obj2nid(algo->algorithm)); + return {}; } vector TS::digestValue() const { - SCOPE(TS_TST_INFO, info, tstInfo()); + auto info = tstInfo(); if(!info) return {}; return i2d(TS_MSG_IMPRINT_get_msg(TS_TST_INFO_get_msg_imprint(info.get())), i2d_ASN1_OCTET_STRING); @@ -185,7 +199,7 @@ vector TS::digestValue() const vector TS::messageImprint() const { - SCOPE(TS_TST_INFO, info, tstInfo()); + auto info = tstInfo(); if(!info) return {}; return i2d(TS_TST_INFO_get_msg_imprint(info.get()), i2d_TS_MSG_IMPRINT); @@ -193,25 +207,22 @@ vector TS::messageImprint() const string TS::serial() const { - SCOPE(TS_TST_INFO, info, tstInfo()); + auto info = tstInfo(); if(!info) return {}; - string serial; - SCOPE2(BIGNUM, bn, ASN1_INTEGER_to_BN(TS_TST_INFO_get_serial(info.get()), nullptr), BN_free); - if(bn) + if(auto bn = SCOPE_PTR_FREE(BIGNUM, ASN1_INTEGER_to_BN(TS_TST_INFO_get_serial(info.get()), nullptr), BN_free)) { - char *str = BN_bn2dec(bn.get()); - if(str) - serial = str; - OPENSSL_free(str); + auto openssl_free = [](char *data) { OPENSSL_free(data); }; + if(auto str = unique_ptr(BN_bn2dec(bn.get()), openssl_free)) + return str.get(); } - return serial; + return {}; } string TS::time() const { - SCOPE(TS_TST_INFO, info, tstInfo()); + auto info = tstInfo(); if(!info) return {}; if(const ASN1_GENERALIZEDTIME *t = TS_TST_INFO_get_time(info.get())) @@ -219,28 +230,14 @@ string TS::time() const return {}; } -TS_TST_INFO* TS::tstInfo() const -{ - if(d) - return PKCS7_to_TS_TST_INFO(d.get()); -#ifndef OPENSSL_NO_CMS - if(cms) - { - SCOPE(BIO, out, CMS_dataInit(cms.get(), nullptr)); - return d2i_TS_TST_INFO_bio(out.get(), nullptr); - } -#endif - return nullptr; -} - void TS::verify(const Digest &digest) { vector data = digest.result(); time_t t = util::date::ASN1TimeToTime_t(time()); - SCOPE(X509_STORE, store, X509CertStore::createStore(X509CertStore::TSA, &t)); + auto store = SCOPE_PTR(X509_STORE, X509CertStore::createStore(X509CertStore::TSA, &t)); X509CertStore::instance()->activate(cert()); - SCOPE(X509_STORE_CTX, csc, X509_STORE_CTX_new()); + auto csc = SCOPE_PTR(X509_STORE_CTX, X509_STORE_CTX_new()); if (!csc) THROW_OPENSSLEXCEPTION("Failed to create X509_STORE_CTX"); if(!X509_STORE_CTX_init(csc.get(), store.get(), nullptr, nullptr)) @@ -248,7 +245,7 @@ void TS::verify(const Digest &digest) if(d) { - SCOPE(TS_VERIFY_CTX, ctx, TS_VERIFY_CTX_new()); + auto ctx = SCOPE_PTR(TS_VERIFY_CTX, TS_VERIFY_CTX_new()); TS_VERIFY_CTX_set_flags(ctx.get(), TS_VFY_IMPRINT|TS_VFY_VERSION|TS_VFY_SIGNATURE); TS_VERIFY_CTX_set_imprint(ctx.get(), (unsigned char*)OPENSSL_memdup(data.data(), data.size()), long(data.size())); @@ -268,7 +265,7 @@ void TS::verify(const Digest &digest) #ifndef OPENSSL_NO_CMS else if(cms) { - SCOPE(BIO, out, BIO_new(BIO_s_mem())); + auto out = SCOPE_PTR(BIO, BIO_new(BIO_s_mem())); // Override smime_sign purpose bit because it is actually timestamp X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); X509_VERIFY_PARAM_set1_name(param, "smime_sign"); @@ -279,7 +276,7 @@ void TS::verify(const Digest &digest) if(err != 1) THROW_OPENSSLEXCEPTION("Failed to verify TS response."); - SCOPE(TS_TST_INFO, info, d2i_TS_TST_INFO_bio(out.get(), nullptr)); + auto info = SCOPE_PTR(TS_TST_INFO, d2i_TS_TST_INFO_bio(out.get(), nullptr)); ASN1_OCTET_STRING *msg = TS_MSG_IMPRINT_get_msg(TS_TST_INFO_get_msg_imprint(info.get())); if(data.size() != size_t(ASN1_STRING_length(msg)) || memcmp(data.data(), ASN1_STRING_get0_data(msg), data.size()) != 0) diff --git a/src/crypto/TS.h b/src/crypto/TS.h index 2dfdbeb3b..5998b6bef 100644 --- a/src/crypto/TS.h +++ b/src/crypto/TS.h @@ -20,11 +20,9 @@ #pragma once #include "Digest.h" -#include using PKCS7 = struct pkcs7_st; using CMS_ContentInfo = struct CMS_ContentInfo_st; -using TS_TST_INFO = struct TS_tst_info_st; namespace digidoc { class X509Cert; @@ -32,7 +30,7 @@ class X509Cert; class TS { public: - TS(const std::string &url, const Digest &digest, const std::string &useragent = {}); + TS(const std::string &url, const Digest &digest, const std::string &useragent = {}); TS(const unsigned char *data = nullptr, size_t size = 0); X509Cert cert() const; @@ -46,7 +44,7 @@ class TS operator std::vector() const; private: - TS_TST_INFO* tstInfo() const; + auto tstInfo() const; std::shared_ptr d; std::shared_ptr cms; }; diff --git a/src/crypto/X509Cert.cpp b/src/crypto/X509Cert.cpp index 43f2f6431..f97c91253 100644 --- a/src/crypto/X509Cert.cpp +++ b/src/crypto/X509Cert.cpp @@ -286,6 +286,14 @@ X509Cert::operator std::vector() const return i2d(cert.get(), i2d_X509); } +/** + * Returns true if handle is valid + */ +X509Cert::operator bool() const +{ + return bool(cert); +} + /** * Returns X.509 certificate serial number. * @@ -293,22 +301,15 @@ X509Cert::operator std::vector() const */ string X509Cert::serial() const { - string serial; if(!cert) - return serial; - SCOPE2(BIGNUM, bn, ASN1_INTEGER_to_BN(X509_get_serialNumber(cert.get()), nullptr), BN_free); - if(!!bn) + return {}; + if(auto bn = SCOPE_PTR_FREE(BIGNUM, ASN1_INTEGER_to_BN(X509_get_serialNumber(cert.get()), nullptr), BN_free)) { - char *str = BN_bn2dec(bn.get()); - if(str) - serial = str; - OPENSSL_free(str); + auto openssl_free = [](char *data) { OPENSSL_free(data); }; + if(auto str = unique_ptr(BN_bn2dec(bn.get()), openssl_free)) + return str.get(); } - - if(serial.empty()) - THROW_OPENSSLEXCEPTION("Failed to read certificate serial number from X.509 certificate"); - - return serial; + return {}; } /** @@ -430,7 +431,7 @@ string X509Cert::subjectName(const string &obj) const string X509Cert::toOID(ASN1_OBJECT *obj) const { string oid(80, 0); - oid.resize(size_t(OBJ_obj2txt(&oid[0], int(oid.size()), obj, 1))); + oid.resize(size_t(OBJ_obj2txt(oid.data(), int(oid.size()), obj, 1))); return oid; }; diff --git a/src/crypto/X509Cert.h b/src/crypto/X509Cert.h index 611baeb47..ef7875d94 100644 --- a/src/crypto/X509Cert.h +++ b/src/crypto/X509Cert.h @@ -98,6 +98,7 @@ namespace digidoc operator std::vector() const; X509Cert& operator=(const X509Cert &other); X509Cert& operator=(X509Cert &&other) DIGIDOCPP_NOEXCEPT; + operator bool() const; bool operator !() const; bool operator ==(X509 *other) const; bool operator ==(const X509Cert &other) const; diff --git a/test/libdigidocpp_boost.cpp b/test/libdigidocpp_boost.cpp index 2e0ce14fa..4fb3cf427 100644 --- a/test/libdigidocpp_boost.cpp +++ b/test/libdigidocpp_boost.cpp @@ -128,6 +128,7 @@ BOOST_AUTO_TEST_CASE(parameters) X509Cert c = signer1->cert(); BOOST_CHECK_EQUAL(c, signer1->cert()); BOOST_CHECK_EQUAL(!c, false); + BOOST_CHECK_EQUAL(c, true); BOOST_CHECK_EQUAL(c.serial(), "2"); BOOST_CHECK_EQUAL(c.subjectName("CN"), "signer1");