tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / xmlsecurity / source / gpg / SecurityEnvironment.cxx
blob371291ab5cd2fd3b94da56632a2b8f6e6194a7f1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "SecurityEnvironment.hxx"
11 #include "CertificateImpl.hxx"
13 #include <com/sun/star/security/CertificateCharacters.hpp>
14 #include <com/sun/star/security/CertificateValidity.hpp>
16 #include <vector>
17 #include <rtl/ref.hxx>
19 #ifdef _WIN32
20 #include <config_folders.h>
21 #include <osl/file.hxx>
22 #include <osl/process.h>
23 #include <rtl/bootstrap.hxx>
24 #include <tools/urlobj.hxx>
25 #endif
27 #include <key.h>
28 #include <keylistresult.h>
29 #include <libxml/xmlstring.h>
30 #include <xmlsec/base64.h>
31 #include <xmlsec/xmlsec.h>
33 #if defined _MSC_VER && defined __clang__
34 #pragma clang diagnostic push
35 #pragma clang diagnostic ignored "-Wundef"
36 #endif
37 #include <gpgme.h>
38 #if defined _MSC_VER && defined __clang__
39 #pragma clang diagnostic pop
40 #endif
41 #include <context.h>
43 using namespace css;
44 using namespace css::security;
45 using namespace css::uno;
46 using namespace css::lang;
48 SecurityEnvironmentGpg::SecurityEnvironmentGpg()
50 #ifdef _WIN32
51 // On Windows, gpgme expects gpgme-w32spawn.exe to be in the same directory as the current
52 // process executable. This assumption might be wrong, e.g., for bundled python, which is
53 // in instdir/program/python-core-x.y.z/bin, while gpgme-w32spawn.exe is in instdir/program.
54 // If we can't find gpgme-w32spawn.exe in the current executable location, then try to find
55 // the spawn executable, and inform gpgme about actual location using gpgme_set_global_flag.
56 [[maybe_unused]] static bool bSpawnPathInitialized = [] {
57 auto accessUrl = [](const INetURLObject& url) {
58 osl::File file(url.GetMainURL(INetURLObject::DecodeMechanism::NONE));
59 return file.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None;
61 OUString sPath;
62 osl_getExecutableFile(&sPath.pData);
63 INetURLObject aPathUrl(sPath);
64 aPathUrl.setName(u"gpgme-w32spawn.exe");
65 if (!accessUrl(aPathUrl))
67 sPath = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/gpgme-w32spawn.exe";
68 rtl::Bootstrap::expandMacros(sPath);
69 aPathUrl.SetURL(sPath);
70 if (accessUrl(aPathUrl))
72 aPathUrl.removeSegment();
73 GpgME::setGlobalFlag("w32-inst-dir",
74 aPathUrl.getFSysPath(FSysStyle::Dos).toUtf8().getStr());
77 return true;
78 }();
79 #endif
80 GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
81 if (err)
82 throw RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr);
84 m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
85 if (m_ctx == nullptr)
86 throw RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr);
87 m_ctx->setArmor(false);
90 SecurityEnvironmentGpg::~SecurityEnvironmentGpg()
94 OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation()
96 return OUString();
99 Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly )
101 std::vector< GpgME::Key > keyList;
103 m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
104 GpgME::Error err = m_ctx->startKeyListing("", bPrivateOnly );
105 while (!err) {
106 GpgME::Key k = m_ctx->nextKey(err);
107 if (err)
108 break;
109 if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) {
110 // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API
111 // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls
112 keyList.push_back(k);
115 m_ctx->endKeyListing();
117 Sequence< Reference< XCertificate > > xCertificateSequence(keyList.size());
118 auto xCertificateSequenceRange = asNonConstRange(xCertificateSequence);
119 int i = 0;
120 for (auto const& key : keyList) {
121 rtl::Reference<CertificateImpl> xCert = new CertificateImpl();
122 xCert->setCertificate(m_ctx, key);
123 xCertificateSequenceRange[i++] = xCert; // fills xCertificateSequence
126 return xCertificateSequence;
129 Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertificates()
131 return getCertificatesImpl( true );
134 Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getAllCertificates()
136 return getCertificatesImpl( false );
139 Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& keyId, const Sequence< sal_Int8 >& /*serialNumber*/ )
141 //xmlChar* pSignatureValue=xmlNodeGetContent(cur);
142 OString ostr = OUStringToOString( keyId , RTL_TEXTENCODING_UTF8 );
143 const xmlChar* strKeyId = reinterpret_cast<const xmlChar*>(ostr.getStr());
144 xmlSecSize nWritten;
145 int nRet = xmlSecBase64Decode_ex(strKeyId, const_cast<xmlSecByte*>(strKeyId), xmlStrlen(strKeyId), &nWritten);
146 if(nRet < 0)
147 throw RuntimeException(u"Base64 decode failed"_ustr);
149 m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
150 GpgME::Error err = m_ctx->startKeyListing("", false);
151 while (!err) {
152 GpgME::Key k = m_ctx->nextKey(err);
153 if (err)
154 break;
155 if (!k.isInvalid() && strcmp(k.primaryFingerprint(), reinterpret_cast<const char*>(strKeyId)) == 0) {
156 rtl::Reference<CertificateImpl> xCert = new CertificateImpl();
157 xCert->setCertificate(m_ctx, k);
158 m_ctx->endKeyListing();
159 return xCert;
162 m_ctx->endKeyListing();
164 return nullptr;
167 Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::buildCertificatePath( const Reference< XCertificate >& /*begin*/ )
169 return Sequence< Reference < XCertificate > >();
172 Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromRaw( const Sequence< sal_Int8 >& /*rawCertificate*/ )
174 return nullptr;
177 Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromAscii( const OUString& /*asciiCertificate*/ )
179 return nullptr;
182 sal_Int32 SecurityEnvironmentGpg::verifyCertificate( const Reference< XCertificate >& aCert,
183 const Sequence< Reference< XCertificate > >& /*intermediateCerts*/ )
185 const CertificateImpl* xCert = dynamic_cast<CertificateImpl*>(aCert.get());
186 if (xCert == nullptr) {
187 // Can't find the key locally -> unknown owner
188 return security::CertificateValidity::ISSUER_UNKNOWN;
191 const GpgME::Key* key = xCert->getCertificate();
192 if (key->ownerTrust() == GpgME::Key::OwnerTrust::Marginal ||
193 key->ownerTrust() == GpgME::Key::OwnerTrust::Full ||
194 key->ownerTrust() == GpgME::Key::OwnerTrust::Ultimate)
196 return security::CertificateValidity::VALID;
199 return security::CertificateValidity::ISSUER_UNTRUSTED;
202 sal_Int32 SecurityEnvironmentGpg::getCertificateCharacters(
203 const Reference< XCertificate >& aCert)
205 if (dynamic_cast<CertificateImpl*>(aCert.get()) == nullptr)
206 throw RuntimeException();
208 // we only listed private keys anyway, up in
209 // SecurityEnvironmentGpg::getPersonalCertificates
210 return CertificateCharacters::HAS_PRIVATE_KEY;
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */