diff --git a/src/security/certstore.cpp b/src/security/certstore.cpp index c2ff3563d9c9a8c64d470a1520595767779a1046..ec338e4098b491948247e4cf191f9b3b8d7a275d 100644 --- a/src/security/certstore.cpp +++ b/src/security/certstore.cpp @@ -143,15 +143,32 @@ CertificateStore::getPinnedCertificates() const } std::shared_ptr<crypto::Certificate> -CertificateStore::getCertificate(const std::string& k) const -{ +CertificateStore::getCertificate(const std::string& k) +{ + auto getCertificate_ = [this](const std::string& k) -> std::shared_ptr<crypto::Certificate> { + auto cit = certs_.find(k); + if (cit == certs_.cend()) + return {}; + return cit->second; + }; std::unique_lock<std::mutex> l(lock_); - - auto cit = certs_.find(k); - if (cit == certs_.cend()) { - return {}; + auto crt = getCertificate_(k); + // Check if certificate is complete + // If the certificate has been splitted, reconstruct it + auto top_issuer = crt; + while (top_issuer && top_issuer->getUID() != top_issuer->getIssuerUID()) { + if (top_issuer->issuer) { + top_issuer = top_issuer->issuer; + } else if (auto cert = getCertificate_(top_issuer->getIssuerUID())) { + top_issuer->issuer = cert; + top_issuer = cert; + } else { + // In this case, a certificate was not found + JAMI_WARN("Incomplete certificate detected %s", k.c_str()); + break; + } } - return cit->second; + return crt; } std::shared_ptr<crypto::Certificate> diff --git a/src/security/certstore.h b/src/security/certstore.h index 0057d00aaa106180a63f1cef36b0fdd6cd042ca5..d76f5de12d5ae6eb2d43afb7f792ae6229cb4dcb 100644 --- a/src/security/certstore.h +++ b/src/security/certstore.h @@ -53,7 +53,10 @@ public: CertificateStore(); std::vector<std::string> getPinnedCertificates() const; - std::shared_ptr<crypto::Certificate> getCertificate(const std::string& cert_id) const; + /** + * Return certificate (with full chain) + */ + std::shared_ptr<crypto::Certificate> getCertificate(const std::string& cert_id); std::shared_ptr<crypto::Certificate> findCertificateByName( const std::string& name, crypto::NameType type = crypto::NameType::UNKNOWN) const; diff --git a/test/unitTest/certstore.cpp b/test/unitTest/certstore.cpp index 6e59541e2d3ba99a2f763b5e9465ee2f26d8e732..f2fcf210437c176cdd162cf07762399a698af991 100644 --- a/test/unitTest/certstore.cpp +++ b/test/unitTest/certstore.cpp @@ -36,9 +36,11 @@ public: private: void trustStoreTest(); + void getCertificateWithSplitted(); CPPUNIT_TEST_SUITE(CertStoreTest); CPPUNIT_TEST(trustStoreTest); + CPPUNIT_TEST(getCertificateWithSplitted); CPPUNIT_TEST_SUITE_END(); }; @@ -157,6 +159,31 @@ CertStoreTest::trustStoreTest() == 0); } +void +CertStoreTest::getCertificateWithSplitted() +{ + jami::tls::TrustStore trustStore; + auto& certStore = jami::tls::CertificateStore::instance(); + + auto ca = dht::crypto::generateIdentity("test CA"); + auto account = dht::crypto::generateIdentity("test account", ca, 4096, true); + auto device = dht::crypto::generateIdentity("test device", account); + + auto caCert = std::make_shared<dht::crypto::Certificate>(ca.second->toString(false)); + auto accountCert = std::make_shared<dht::crypto::Certificate>(account.second->toString(false)); + auto devicePartialCert = std::make_shared<dht::crypto::Certificate>( + device.second->toString(false)); + + certStore.pinCertificate(caCert); + certStore.pinCertificate(accountCert); + certStore.pinCertificate(devicePartialCert); + + auto fullCert = certStore.getCertificate(device.second->getId().toString()); + CPPUNIT_ASSERT(fullCert->issuer && fullCert->issuer->getUID() == accountCert->getUID()); + CPPUNIT_ASSERT(fullCert->issuer->issuer + && fullCert->issuer->issuer->getUID() == caCert->getUID()); +} + } // namespace test } // namespace jami