blob: 06b5dc1ae290bc51c0c9ffa6189f1069dec9bd76 [file] [log] [blame]
Adrien Béraud612b55b2023-05-29 10:42:04 -04001/*
2 * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
3 *
4 * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#pragma once
22
23//#include "security_const.h"
24//#include "noncopyable.h"
25
26#include <opendht/crypto.h>
27
28#include <string>
29#include <vector>
30#include <map>
31#include <set>
32#include <future>
33#include <mutex>
34
35namespace crypto = ::dht::crypto;
36
37namespace dht {
38namespace log {
39class Logger;
40}
41}
42
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040043namespace dhtnet {
Adrien Béraud612b55b2023-05-29 10:42:04 -040044
45using Logger = dht::log::Logger;
46namespace tls {
47
48enum class TrustStatus { UNTRUSTED = 0, TRUSTED };
49TrustStatus trustStatusFromStr(const char* str);
50const char* statusToStr(TrustStatus s);
51
52/**
53 * Global certificate store.
54 * Stores system root CAs and any other encountred certificate
55 */
56class CertificateStore
57{
58public:
59 explicit CertificateStore(const std::string& accountId, std::shared_ptr<Logger> logger);
60
61 std::vector<std::string> getPinnedCertificates() const;
62 /**
63 * Return certificate (with full chain)
64 */
65 std::shared_ptr<crypto::Certificate> getCertificate(const std::string& cert_id);
66 std::shared_ptr<crypto::Certificate> getCertificateLegacy(const std::string& dataDir, const std::string& cert_id);
67
68 std::shared_ptr<crypto::Certificate> findCertificateByName(
69 const std::string& name, crypto::NameType type = crypto::NameType::UNKNOWN) const;
70 std::shared_ptr<crypto::Certificate> findCertificateByUID(const std::string& uid) const;
71 std::shared_ptr<crypto::Certificate> findIssuer(
72 const std::shared_ptr<crypto::Certificate>& crt) const;
73
74 std::vector<std::string> pinCertificate(const std::vector<uint8_t>& crt,
75 bool local = true) noexcept;
76 std::vector<std::string> pinCertificate(crypto::Certificate&& crt, bool local = true);
77 std::vector<std::string> pinCertificate(const std::shared_ptr<crypto::Certificate>& crt,
78 bool local = true);
79 bool unpinCertificate(const std::string&);
80
81 void pinCertificatePath(const std::string& path,
82 std::function<void(const std::vector<std::string>&)> cb = {});
83 unsigned unpinCertificatePath(const std::string&);
84
85 bool setTrustedCertificate(const std::string& id, TrustStatus status);
86 std::vector<gnutls_x509_crt_t> getTrustedCertificates() const;
87
88 void pinRevocationList(const std::string& id,
89 const std::shared_ptr<dht::crypto::RevocationList>& crl);
90 void pinRevocationList(const std::string& id, dht::crypto::RevocationList&& crl)
91 {
92 pinRevocationList(id,
93 std::make_shared<dht::crypto::RevocationList>(
94 std::forward<dht::crypto::RevocationList>(crl)));
95 }
96 void pinOcspResponse(const dht::crypto::Certificate& cert);
97
98 void loadRevocations(crypto::Certificate& crt) const;
99
100 const std::shared_ptr<Logger>& logger() const {
101 return logger_;
102 }
103
104private:
105 //NON_COPYABLE(CertificateStore);
106
107
108 unsigned loadLocalCertificates();
109 void pinRevocationList(const std::string& id, const dht::crypto::RevocationList& crl);
110 std::shared_ptr<Logger> logger_;
111
112 const std::string certPath_;
113 const std::string crlPath_;
114 const std::string ocspPath_;
115
116 mutable std::mutex lock_;
117 std::map<std::string, std::shared_ptr<crypto::Certificate>> certs_;
118 std::map<std::string, std::vector<std::weak_ptr<crypto::Certificate>>> paths_;
119
120 // globally trusted certificates (root CAs)
121 std::vector<std::shared_ptr<crypto::Certificate>> trustedCerts_;
122};
123
124/**
125 * Keeps track of the allowed and trust status of certificates
126 * Trusted is the status of top certificates we trust to build our
127 * certificate chain: root CAs and other configured CAs.
128 *
129 * Allowed is the status of certificates we accept for incoming
130 * connections.
131 */
132class TrustStore
133{
134public:
135 explicit TrustStore(CertificateStore& certStore)
136 : certStore_(certStore)
137 {}
138
139 enum class PermissionStatus { UNDEFINED = 0, ALLOWED, BANNED };
140
141 static PermissionStatus statusFromStr(const char* str);
142 static const char* statusToStr(PermissionStatus s);
143
144 bool addRevocationList(dht::crypto::RevocationList&& crl);
145
146 bool setCertificateStatus(const std::string& cert_id, const PermissionStatus status);
147 bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert,
148 PermissionStatus status,
149 bool local = true);
150
151 PermissionStatus getCertificateStatus(const std::string& cert_id) const;
152
153 std::vector<std::string> getCertificatesByStatus(PermissionStatus status) const;
154
155 /**
156 * Check that the certificate is allowed (valid and permited) for contact.
157 * Valid means the certificate chain matches with our CA list,
158 * has valid signatures, expiration dates etc.
159 * Permited means at least one of the certificate in the chain is
160 * ALLOWED (if allowPublic is false), and none is BANNED.
161 *
162 * @param crt the end certificate of the chain to check
163 * @param allowPublic if false, requires at least one ALLOWED certificate.
164 * (not required otherwise). In any case a BANNED
165 * certificate means permission refusal.
166 * @return true if the certificate is valid and permitted.
167 */
168 bool isAllowed(const crypto::Certificate& crt, bool allowPublic = false);
169
170private:
171 TrustStore(const TrustStore& o) = delete;
172 TrustStore& operator=(const TrustStore& o) = delete;
173 TrustStore(TrustStore&& o) = delete;
174 TrustStore& operator=(TrustStore&& o) = delete;
175
176 void updateKnownCerts();
177 bool setCertificateStatus(std::shared_ptr<crypto::Certificate> cert,
178 const std::string& cert_id,
179 const TrustStore::PermissionStatus status,
180 bool local);
181 void setStoreCertStatus(const crypto::Certificate& crt, bool status);
182 void rebuildTrust();
183
184 struct Status
185 {
186 bool allowed;
187 };
188
189 // unknown certificates with known status
190 mutable std::recursive_mutex mutex_;
191 std::map<std::string, Status> unknownCertStatus_;
192 std::map<std::string, std::pair<std::shared_ptr<crypto::Certificate>, Status>> certStatus_;
193 dht::crypto::TrustList allowed_;
194 CertificateStore& certStore_;
195};
196
197} // namespace tls
198} // namespace jami