Line data Source code
1 : #include "source/extensions/transport_sockets/tls/connection_info_impl_base.h"
2 :
3 : #include "source/common/common/hex.h"
4 :
5 : #include "absl/strings/str_replace.h"
6 : #include "openssl/err.h"
7 : #include "openssl/x509v3.h"
8 :
9 : namespace Envoy {
10 : namespace Extensions {
11 : namespace TransportSockets {
12 : namespace Tls {
13 :
14 0 : bool ConnectionInfoImplBase::peerCertificatePresented() const {
15 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
16 0 : return cert != nullptr;
17 0 : }
18 :
19 0 : absl::Span<const std::string> ConnectionInfoImplBase::uriSanLocalCertificate() const {
20 0 : if (!cached_uri_san_local_certificate_.empty()) {
21 0 : return cached_uri_san_local_certificate_;
22 0 : }
23 :
24 : // The cert object is not owned.
25 0 : X509* cert = SSL_get_certificate(ssl());
26 0 : if (!cert) {
27 0 : ASSERT(cached_uri_san_local_certificate_.empty());
28 0 : return cached_uri_san_local_certificate_;
29 0 : }
30 0 : cached_uri_san_local_certificate_ = Utility::getSubjectAltNames(*cert, GEN_URI);
31 0 : return cached_uri_san_local_certificate_;
32 0 : }
33 :
34 0 : absl::Span<const std::string> ConnectionInfoImplBase::dnsSansLocalCertificate() const {
35 0 : if (!cached_dns_san_local_certificate_.empty()) {
36 0 : return cached_dns_san_local_certificate_;
37 0 : }
38 :
39 0 : X509* cert = SSL_get_certificate(ssl());
40 0 : if (!cert) {
41 0 : ASSERT(cached_dns_san_local_certificate_.empty());
42 0 : return cached_dns_san_local_certificate_;
43 0 : }
44 0 : cached_dns_san_local_certificate_ = Utility::getSubjectAltNames(*cert, GEN_DNS);
45 0 : return cached_dns_san_local_certificate_;
46 0 : }
47 :
48 0 : absl::Span<const std::string> ConnectionInfoImplBase::ipSansLocalCertificate() const {
49 0 : if (!cached_ip_san_local_certificate_.empty()) {
50 0 : return cached_ip_san_local_certificate_;
51 0 : }
52 :
53 0 : X509* cert = SSL_get_certificate(ssl());
54 0 : if (!cert) {
55 0 : ASSERT(cached_ip_san_local_certificate_.empty());
56 0 : return cached_ip_san_local_certificate_;
57 0 : }
58 0 : cached_ip_san_local_certificate_ = Utility::getSubjectAltNames(*cert, GEN_IPADD);
59 0 : return cached_ip_san_local_certificate_;
60 0 : }
61 :
62 0 : const std::string& ConnectionInfoImplBase::sha256PeerCertificateDigest() const {
63 0 : if (!cached_sha_256_peer_certificate_digest_.empty()) {
64 0 : return cached_sha_256_peer_certificate_digest_;
65 0 : }
66 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
67 0 : if (!cert) {
68 0 : ASSERT(cached_sha_256_peer_certificate_digest_.empty());
69 0 : return cached_sha_256_peer_certificate_digest_;
70 0 : }
71 :
72 0 : std::vector<uint8_t> computed_hash(SHA256_DIGEST_LENGTH);
73 0 : unsigned int n;
74 0 : X509_digest(cert.get(), EVP_sha256(), computed_hash.data(), &n);
75 0 : RELEASE_ASSERT(n == computed_hash.size(), "");
76 0 : cached_sha_256_peer_certificate_digest_ = Hex::encode(computed_hash);
77 0 : return cached_sha_256_peer_certificate_digest_;
78 0 : }
79 :
80 0 : const std::string& ConnectionInfoImplBase::sha1PeerCertificateDigest() const {
81 0 : if (!cached_sha_1_peer_certificate_digest_.empty()) {
82 0 : return cached_sha_1_peer_certificate_digest_;
83 0 : }
84 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
85 0 : if (!cert) {
86 0 : ASSERT(cached_sha_1_peer_certificate_digest_.empty());
87 0 : return cached_sha_1_peer_certificate_digest_;
88 0 : }
89 :
90 0 : std::vector<uint8_t> computed_hash(SHA_DIGEST_LENGTH);
91 0 : unsigned int n;
92 0 : X509_digest(cert.get(), EVP_sha1(), computed_hash.data(), &n);
93 0 : RELEASE_ASSERT(n == computed_hash.size(), "");
94 0 : cached_sha_1_peer_certificate_digest_ = Hex::encode(computed_hash);
95 0 : return cached_sha_1_peer_certificate_digest_;
96 0 : }
97 :
98 0 : const std::string& ConnectionInfoImplBase::urlEncodedPemEncodedPeerCertificate() const {
99 0 : if (!cached_url_encoded_pem_encoded_peer_certificate_.empty()) {
100 0 : return cached_url_encoded_pem_encoded_peer_certificate_;
101 0 : }
102 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
103 0 : if (!cert) {
104 0 : ASSERT(cached_url_encoded_pem_encoded_peer_certificate_.empty());
105 0 : return cached_url_encoded_pem_encoded_peer_certificate_;
106 0 : }
107 :
108 0 : bssl::UniquePtr<BIO> buf(BIO_new(BIO_s_mem()));
109 0 : RELEASE_ASSERT(buf != nullptr, "");
110 0 : RELEASE_ASSERT(PEM_write_bio_X509(buf.get(), cert.get()) == 1, "");
111 0 : const uint8_t* output;
112 0 : size_t length;
113 0 : RELEASE_ASSERT(BIO_mem_contents(buf.get(), &output, &length) == 1, "");
114 0 : absl::string_view pem(reinterpret_cast<const char*>(output), length);
115 0 : cached_url_encoded_pem_encoded_peer_certificate_ = absl::StrReplaceAll(
116 0 : pem, {{"\n", "%0A"}, {" ", "%20"}, {"+", "%2B"}, {"/", "%2F"}, {"=", "%3D"}});
117 0 : return cached_url_encoded_pem_encoded_peer_certificate_;
118 0 : }
119 :
120 0 : const std::string& ConnectionInfoImplBase::urlEncodedPemEncodedPeerCertificateChain() const {
121 0 : if (!cached_url_encoded_pem_encoded_peer_cert_chain_.empty()) {
122 0 : return cached_url_encoded_pem_encoded_peer_cert_chain_;
123 0 : }
124 :
125 0 : STACK_OF(X509)* cert_chain = SSL_get_peer_full_cert_chain(ssl());
126 0 : if (cert_chain == nullptr) {
127 0 : ASSERT(cached_url_encoded_pem_encoded_peer_cert_chain_.empty());
128 0 : return cached_url_encoded_pem_encoded_peer_cert_chain_;
129 0 : }
130 :
131 0 : for (uint64_t i = 0; i < sk_X509_num(cert_chain); i++) {
132 0 : X509* cert = sk_X509_value(cert_chain, i);
133 :
134 0 : bssl::UniquePtr<BIO> buf(BIO_new(BIO_s_mem()));
135 0 : RELEASE_ASSERT(buf != nullptr, "");
136 0 : RELEASE_ASSERT(PEM_write_bio_X509(buf.get(), cert) == 1, "");
137 0 : const uint8_t* output;
138 0 : size_t length;
139 0 : RELEASE_ASSERT(BIO_mem_contents(buf.get(), &output, &length) == 1, "");
140 :
141 0 : absl::string_view pem(reinterpret_cast<const char*>(output), length);
142 0 : cached_url_encoded_pem_encoded_peer_cert_chain_ = absl::StrCat(
143 0 : cached_url_encoded_pem_encoded_peer_cert_chain_,
144 0 : absl::StrReplaceAll(
145 0 : pem, {{"\n", "%0A"}, {" ", "%20"}, {"+", "%2B"}, {"/", "%2F"}, {"=", "%3D"}}));
146 0 : }
147 0 : return cached_url_encoded_pem_encoded_peer_cert_chain_;
148 0 : }
149 :
150 0 : absl::Span<const std::string> ConnectionInfoImplBase::uriSanPeerCertificate() const {
151 0 : if (!cached_uri_san_peer_certificate_.empty()) {
152 0 : return cached_uri_san_peer_certificate_;
153 0 : }
154 :
155 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
156 0 : if (!cert) {
157 0 : ASSERT(cached_uri_san_peer_certificate_.empty());
158 0 : return cached_uri_san_peer_certificate_;
159 0 : }
160 0 : cached_uri_san_peer_certificate_ = Utility::getSubjectAltNames(*cert, GEN_URI);
161 0 : return cached_uri_san_peer_certificate_;
162 0 : }
163 :
164 0 : absl::Span<const std::string> ConnectionInfoImplBase::dnsSansPeerCertificate() const {
165 0 : if (!cached_dns_san_peer_certificate_.empty()) {
166 0 : return cached_dns_san_peer_certificate_;
167 0 : }
168 :
169 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
170 0 : if (!cert) {
171 0 : ASSERT(cached_dns_san_peer_certificate_.empty());
172 0 : return cached_dns_san_peer_certificate_;
173 0 : }
174 0 : cached_dns_san_peer_certificate_ = Utility::getSubjectAltNames(*cert, GEN_DNS);
175 0 : return cached_dns_san_peer_certificate_;
176 0 : }
177 :
178 0 : absl::Span<const std::string> ConnectionInfoImplBase::ipSansPeerCertificate() const {
179 0 : if (!cached_ip_san_peer_certificate_.empty()) {
180 0 : return cached_ip_san_peer_certificate_;
181 0 : }
182 :
183 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
184 0 : if (!cert) {
185 0 : ASSERT(cached_ip_san_peer_certificate_.empty());
186 0 : return cached_ip_san_peer_certificate_;
187 0 : }
188 0 : cached_ip_san_peer_certificate_ = Utility::getSubjectAltNames(*cert, GEN_IPADD);
189 0 : return cached_ip_san_peer_certificate_;
190 0 : }
191 :
192 0 : uint16_t ConnectionInfoImplBase::ciphersuiteId() const {
193 0 : const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
194 0 : if (cipher == nullptr) {
195 0 : return 0xffff;
196 0 : }
197 :
198 : // From the OpenSSL docs:
199 : // SSL_CIPHER_get_id returns |cipher|'s id. It may be cast to a |uint16_t| to
200 : // get the cipher suite value.
201 0 : return static_cast<uint16_t>(SSL_CIPHER_get_id(cipher));
202 0 : }
203 :
204 0 : std::string ConnectionInfoImplBase::ciphersuiteString() const {
205 0 : const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
206 0 : if (cipher == nullptr) {
207 0 : return {};
208 0 : }
209 :
210 0 : return SSL_CIPHER_get_name(cipher);
211 0 : }
212 :
213 0 : const std::string& ConnectionInfoImplBase::tlsVersion() const {
214 0 : if (!cached_tls_version_.empty()) {
215 0 : return cached_tls_version_;
216 0 : }
217 0 : cached_tls_version_ = SSL_get_version(ssl());
218 0 : return cached_tls_version_;
219 0 : }
220 :
221 0 : const std::string& ConnectionInfoImplBase::alpn() const {
222 0 : if (alpn_.empty()) {
223 0 : const unsigned char* proto;
224 0 : unsigned int proto_len;
225 0 : SSL_get0_alpn_selected(ssl(), &proto, &proto_len);
226 0 : if (proto != nullptr) {
227 0 : alpn_ = std::string(reinterpret_cast<const char*>(proto), proto_len);
228 0 : }
229 0 : }
230 0 : return alpn_;
231 0 : }
232 :
233 0 : const std::string& ConnectionInfoImplBase::sni() const {
234 0 : if (sni_.empty()) {
235 0 : const char* proto = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
236 0 : if (proto != nullptr) {
237 0 : sni_ = std::string(proto);
238 0 : }
239 0 : }
240 0 : return sni_;
241 0 : }
242 :
243 0 : const std::string& ConnectionInfoImplBase::serialNumberPeerCertificate() const {
244 0 : if (!cached_serial_number_peer_certificate_.empty()) {
245 0 : return cached_serial_number_peer_certificate_;
246 0 : }
247 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
248 0 : if (!cert) {
249 0 : ASSERT(cached_serial_number_peer_certificate_.empty());
250 0 : return cached_serial_number_peer_certificate_;
251 0 : }
252 0 : cached_serial_number_peer_certificate_ = Utility::getSerialNumberFromCertificate(*cert.get());
253 0 : return cached_serial_number_peer_certificate_;
254 0 : }
255 :
256 0 : const std::string& ConnectionInfoImplBase::issuerPeerCertificate() const {
257 0 : if (!cached_issuer_peer_certificate_.empty()) {
258 0 : return cached_issuer_peer_certificate_;
259 0 : }
260 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
261 0 : if (!cert) {
262 0 : ASSERT(cached_issuer_peer_certificate_.empty());
263 0 : return cached_issuer_peer_certificate_;
264 0 : }
265 0 : cached_issuer_peer_certificate_ = Utility::getIssuerFromCertificate(*cert);
266 0 : return cached_issuer_peer_certificate_;
267 0 : }
268 :
269 0 : const std::string& ConnectionInfoImplBase::subjectPeerCertificate() const {
270 0 : if (!cached_subject_peer_certificate_.empty()) {
271 0 : return cached_subject_peer_certificate_;
272 0 : }
273 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
274 0 : if (!cert) {
275 0 : ASSERT(cached_subject_peer_certificate_.empty());
276 0 : return cached_subject_peer_certificate_;
277 0 : }
278 0 : cached_subject_peer_certificate_ = Utility::getSubjectFromCertificate(*cert);
279 0 : return cached_subject_peer_certificate_;
280 0 : }
281 :
282 0 : const std::string& ConnectionInfoImplBase::subjectLocalCertificate() const {
283 0 : if (!cached_subject_local_certificate_.empty()) {
284 0 : return cached_subject_local_certificate_;
285 0 : }
286 0 : X509* cert = SSL_get_certificate(ssl());
287 0 : if (!cert) {
288 0 : ASSERT(cached_subject_local_certificate_.empty());
289 0 : return cached_subject_local_certificate_;
290 0 : }
291 0 : cached_subject_local_certificate_ = Utility::getSubjectFromCertificate(*cert);
292 0 : return cached_subject_local_certificate_;
293 0 : }
294 :
295 0 : absl::optional<SystemTime> ConnectionInfoImplBase::validFromPeerCertificate() const {
296 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
297 0 : if (!cert) {
298 0 : return absl::nullopt;
299 0 : }
300 0 : return Utility::getValidFrom(*cert);
301 0 : }
302 :
303 0 : absl::optional<SystemTime> ConnectionInfoImplBase::expirationPeerCertificate() const {
304 0 : bssl::UniquePtr<X509> cert(SSL_get_peer_certificate(ssl()));
305 0 : if (!cert) {
306 0 : return absl::nullopt;
307 0 : }
308 0 : return Utility::getExpirationTime(*cert);
309 0 : }
310 :
311 0 : const std::string& ConnectionInfoImplBase::sessionId() const {
312 0 : if (!cached_session_id_.empty()) {
313 0 : return cached_session_id_;
314 0 : }
315 0 : SSL_SESSION* session = SSL_get_session(ssl());
316 0 : if (session == nullptr) {
317 0 : ASSERT(cached_session_id_.empty());
318 0 : return cached_session_id_;
319 0 : }
320 :
321 0 : unsigned int session_id_length = 0;
322 0 : const uint8_t* session_id = SSL_SESSION_get_id(session, &session_id_length);
323 0 : cached_session_id_ = Hex::encode(session_id, session_id_length);
324 0 : return cached_session_id_;
325 0 : }
326 :
327 : } // namespace Tls
328 : } // namespace TransportSockets
329 : } // namespace Extensions
330 : } // namespace Envoy
|