1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <config_gpgme.h>
12 #include "SecurityEnvironment.hxx"
13 #include "CertificateImpl.hxx"
15 #include <cppuhelper/supportsservice.hxx>
16 #include <comphelper/servicehelper.hxx>
20 #include <keylistresult.h>
21 #include <xmlsec-wrapper.h>
24 using namespace css::security
;
25 using namespace css::uno
;
26 using namespace css::lang
;
28 SecurityEnvironmentGpg::SecurityEnvironmentGpg()
30 GpgME::Error err
= GpgME::checkEngine(GpgME::OpenPGP
);
32 throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
34 m_ctx
.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP
) );
36 throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
37 m_ctx
->setArmor(false);
40 SecurityEnvironmentGpg::~SecurityEnvironmentGpg()
45 sal_Int64 SAL_CALL
SecurityEnvironmentGpg::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
47 if( aIdentifier
.getLength() == 16 && 0 == memcmp( getUnoTunnelId().getConstArray(), aIdentifier
.getConstArray(), 16 ) ) {
48 return sal::static_int_cast
<sal_Int64
>(reinterpret_cast<sal_uIntPtr
>(this));
53 /* XUnoTunnel extension */
57 class theSecurityEnvironmentUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theSecurityEnvironmentUnoTunnelId
> {};
60 const Sequence
< sal_Int8
>& SecurityEnvironmentGpg::getUnoTunnelId() {
61 return theSecurityEnvironmentUnoTunnelId::get().getSeq();
64 OUString
SecurityEnvironmentGpg::getSecurityEnvironmentInformation()
69 Sequence
< Reference
< XCertificate
> > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly
)
71 CertificateImpl
* xCert
;
72 std::list
< GpgME::Key
> keyList
;
73 std::list
< CertificateImpl
* > certsList
;
75 m_ctx
->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL
);
76 GpgME::Error err
= m_ctx
->startKeyListing("", bPrivateOnly
);
78 GpgME::Key k
= m_ctx
->nextKey(err
);
81 if (!k
.isRevoked() && !k
.isExpired() && !k
.isDisabled() && !k
.isInvalid()) {
82 // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API
83 // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls
87 m_ctx
->endKeyListing();
89 for (auto const& key
: keyList
) {
90 xCert
= new CertificateImpl();
91 xCert
->setCertificate(m_ctx
.get(),key
);
92 certsList
.push_back(xCert
);
95 Sequence
< Reference
< XCertificate
> > xCertificateSequence(certsList
.size());
97 for (auto const& cert
: certsList
) {
98 xCertificateSequence
[i
++] = cert
;
101 return xCertificateSequence
;
104 Sequence
< Reference
< XCertificate
> > SecurityEnvironmentGpg::getPersonalCertificates()
106 return getCertificatesImpl( true );
109 Sequence
< Reference
< XCertificate
> > SecurityEnvironmentGpg::getAllCertificates()
111 return getCertificatesImpl( false );
114 Reference
< XCertificate
> SecurityEnvironmentGpg::getCertificate( const OUString
& keyId
, const Sequence
< sal_Int8
>& /*serialNumber*/ )
116 CertificateImpl
* xCert
=nullptr;
118 //xmlChar* pSignatureValue=xmlNodeGetContent(cur);
119 OString ostr
= OUStringToOString( keyId
, RTL_TEXTENCODING_UTF8
);
120 const xmlChar
* strKeyId
= reinterpret_cast<const xmlChar
*>(ostr
.getStr());
121 if(xmlSecBase64Decode(strKeyId
, const_cast<xmlSecByte
*>(strKeyId
), xmlStrlen(strKeyId
)) < 0)
122 throw RuntimeException("Base64 decode failed");
124 m_ctx
->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL
);
125 GpgME::Error err
= m_ctx
->startKeyListing("", false);
127 GpgME::Key k
= m_ctx
->nextKey(err
);
130 if (!k
.isInvalid() && strcmp(k
.primaryFingerprint(), reinterpret_cast<const char*>(strKeyId
)) == 0) {
131 xCert
= new CertificateImpl();
132 xCert
->setCertificate(m_ctx
.get(), k
);
133 m_ctx
->endKeyListing();
137 m_ctx
->endKeyListing();
142 Sequence
< Reference
< XCertificate
> > SecurityEnvironmentGpg::buildCertificatePath( const Reference
< XCertificate
>& /*begin*/ )
144 return Sequence
< Reference
< XCertificate
> >();
147 Reference
< XCertificate
> SecurityEnvironmentGpg::createCertificateFromRaw( const Sequence
< sal_Int8
>& /*rawCertificate*/ )
152 Reference
< XCertificate
> SecurityEnvironmentGpg::createCertificateFromAscii( const OUString
& /*asciiCertificate*/ )
157 sal_Int32
SecurityEnvironmentGpg::verifyCertificate( const Reference
< XCertificate
>& aCert
,
158 const Sequence
< Reference
< XCertificate
> >& /*intermediateCerts*/ )
160 const CertificateImpl
* xCert
= dynamic_cast<CertificateImpl
*>(aCert
.get());
161 if (xCert
== nullptr) {
162 // Can't find the key locally -> unknown owner
163 return security::CertificateValidity::ISSUER_UNKNOWN
;
166 const GpgME::Key
* key
= xCert
->getCertificate();
167 if (key
->ownerTrust() == GpgME::Key::OwnerTrust::Marginal
||
168 key
->ownerTrust() == GpgME::Key::OwnerTrust::Full
||
169 key
->ownerTrust() == GpgME::Key::OwnerTrust::Ultimate
)
171 return security::CertificateValidity::VALID
;
174 return security::CertificateValidity::ISSUER_UNTRUSTED
;
177 sal_Int32
SecurityEnvironmentGpg::getCertificateCharacters(
178 const Reference
< XCertificate
>& aCert
)
180 const CertificateImpl
* xCert
;
181 Reference
< XUnoTunnel
> xCertTunnel(aCert
, UNO_QUERY_THROW
) ;
182 xCert
= reinterpret_cast<CertificateImpl
*>(sal::static_int_cast
<sal_uIntPtr
>(xCertTunnel
->getSomething(CertificateImpl::getUnoTunnelId()))) ;
183 if (xCert
== nullptr)
184 throw RuntimeException();
186 // we only listed private keys anyway, up in
187 // SecurityEnvironmentGpg::getPersonalCertificates
188 return CertificateCharacters::HAS_PRIVATE_KEY
;
191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */