1 #include "TLS-OpenSSL.hpp"
6 #include <openssl/err.h>
7 #include <openssl/rand.h>
9 #include <openssl/x509.h>
10 #include <openssl/x509v3.h>
12 #include <glog/logging.h>
14 #define FMT_STRING_ALIAS 1
15 #include <fmt/format.h>
21 // <https://tools.ietf.org/html/rfc7919>
22 // <https://wiki.mozilla.org/Security/Server_Side_TLS#DHE_handshake_and_dhparam>
23 constexpr char ffdhe4096
[] = R
"(
24 -----BEGIN DH PARAMETERS-----
25 MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
26 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
27 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
28 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
29 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
30 ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
31 7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
32 nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
33 8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
34 iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
35 zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
36 -----END DH PARAMETERS-----
39 // convert binary input into a std::string of hex digits
41 auto bin2hexstring(uint8_t const* data
, size_t length
)
44 ret
.reserve(2 * length
);
46 for (size_t n
= 0u; n
< length
; ++n
) {
47 auto const ch
= data
[n
];
49 auto const lo
= ch
& 0xF;
50 auto const hi
= (ch
>> 4) & 0xF;
52 auto constexpr hex_digits
= "0123456789abcdef";
54 ret
+= hex_digits
[hi
];
55 ret
+= hex_digits
[lo
];
61 TLS::TLS(std::function
<void(void)> read_hook
)
62 : read_hook_(read_hook
)
68 for (auto& ctx
: cert_ctx_
) {
70 SSL_CTX_free(ctx
.ctx
);
78 struct session_context
{
81 static int session_context_index
= -1;
83 static int verify_callback(int preverify_ok
, X509_STORE_CTX
* ctx
)
85 auto const cert
= X509_STORE_CTX_get_current_cert(ctx
);
89 auto err
= X509_STORE_CTX_get_error(ctx
);
91 // auto const ssl = reinterpret_cast<SSL*>(
92 // X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
94 CHECK_GE(session_context_index
, 0);
96 // auto unused = reinterpret_cast<session_context*>(SSL_get_ex_data(ssl,
97 // session_context_index));
99 auto const depth
= X509_STORE_CTX_get_error_depth(ctx
);
102 X509_NAME_oneline(X509_get_subject_name(cert
), buf
, sizeof(buf
));
104 if (depth
> Config::cert_verify_depth
) {
106 err
= X509_V_ERR_CERT_CHAIN_TOO_LONG
;
107 X509_STORE_CTX_set_error(ctx
, err
);
110 LOG(INFO
) << "verify error:num=" << err
<< ':'
111 << X509_verify_cert_error_string(err
) << ": depth=" << depth
115 LOG(INFO
) << "preverify_ok; depth=" << depth
<< " subject_name=«" << buf
119 if (!preverify_ok
&& (err
== X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
)) {
121 X509_NAME_oneline(X509_get_issuer_name(cert
), buf
, sizeof(buf
));
122 LOG(INFO
) << "issuer=" << buf
;
125 LOG(INFO
) << "issuer=<unknown>";
129 return 1; // always continue
132 static int ssl_servername_callback(SSL
* s
, int* ad
, void* arg
)
135 = CHECK_NOTNULL(static_cast<std::vector
<TLS::per_cert_ctx
>*>(arg
));
136 auto const& cert_ctx
= *cert_ctx_ptr
;
138 auto const servername
= SSL_get_servername(s
, TLSEXT_NAMETYPE_host_name
);
140 if (servername
&& *servername
) {
141 LOG(INFO
) << "servername requested " << servername
;
142 for (auto const& ctx
: cert_ctx
) {
143 if (auto const& c
= std::find(begin(ctx
.cn
), end(ctx
.cn
), servername
);
145 if (size(cert_ctx
) > 1)
146 SSL_set_SSL_CTX(s
, ctx
.ctx
);
147 return SSL_TLSEXT_ERR_OK
;
150 LOG(INFO
) << "no cert found for server " << servername
;
151 return SSL_TLSEXT_ERR_ALERT_WARNING
;
154 // LOG(INFO) << "no specific server name requested";
155 return SSL_TLSEXT_ERR_OK
;
158 bool TLS::starttls_client(fs::path config_path
,
161 char const* client_name
,
162 char const* server_name
,
163 DNS::RR_collection
const& tlsa_rrs
,
165 std::chrono::milliseconds timeout
)
167 SSL_load_error_strings();
170 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
172 auto const method
= CHECK_NOTNULL(SSLv23_client_method());
175 auto const certs
= osutil::list_directory(config_path
, Config::cert_fn_re
);
177 CHECK_GE(certs
.size(), 1) << "no client cert(s) found";
179 for (auto const& cert
: certs
) {
181 auto ctx
= CHECK_NOTNULL(SSL_CTX_new(method
));
182 std::vector
<Domain
> cn
;
184 SSL_CTX_set_ecdh_auto(ctx
, 1);
186 // SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
188 CHECK_GT(SSL_CTX_dane_enable(ctx
), 0)
189 << "unable to enable DANE on SSL context";
191 // you'd think if it's the default, you'd not have to call this
192 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx
), 1);
194 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx
, cert
.string().c_str()),
196 << "Can't load certificate chain file " << cert
;
198 auto const key
= fs::path(cert
).replace_extension(Config::key_ext
);
200 if (fs::exists(key
)) {
202 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx
, key
.string().c_str(),
205 << "Can't load private key file " << key
;
207 CHECK(SSL_CTX_check_private_key(ctx
))
208 << "SSL_CTX_check_private_key failed for " << key
;
211 SSL_CTX_set_verify_depth(ctx
, Config::cert_verify_depth
+ 1);
212 SSL_CTX_set_verify(ctx
, SSL_VERIFY_PEER
| SSL_VERIFY_CLIENT_ONCE
,
215 //.......................................................
217 auto const x509
= CHECK_NOTNULL(SSL_CTX_get0_certificate(ctx
));
219 X509_NAME
* subj
= X509_get_subject_name(x509
);
223 lastpos
= X509_NAME_get_index_by_NID(subj
, NID_commonName
, lastpos
);
226 auto e
= X509_NAME_get_entry(subj
, lastpos
);
227 ASN1_STRING
* d
= X509_NAME_ENTRY_get_data(e
);
228 auto str
= ASN1_STRING_get0_data(d
);
229 // LOG(INFO) << "client cert found for " << str;
230 cn
.emplace_back(reinterpret_cast<const char*>(str
));
233 auto subject_alt_names
= static_cast<GENERAL_NAMES
*>(
234 X509_get_ext_d2i(x509
, NID_subject_alt_name
, nullptr, nullptr));
236 for (int i
= 0; i
< sk_GENERAL_NAME_num(subject_alt_names
); ++i
) {
238 GENERAL_NAME
* gen
= sk_GENERAL_NAME_value(subject_alt_names
, i
);
240 if (gen
->type
== GEN_URI
|| gen
->type
== GEN_EMAIL
) {
241 ASN1_IA5STRING
* asn1_str
= gen
->d
.uniformResourceIdentifier
;
243 std::string
const str(
244 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str
)),
245 ASN1_STRING_length(asn1_str
));
247 LOG(INFO
) << "email or uri alt name " << str
;
249 else if (gen
->type
== GEN_DNS
) {
250 ASN1_IA5STRING
* asn1_str
= gen
->d
.uniformResourceIdentifier
;
253 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str
)),
254 ASN1_STRING_length(asn1_str
));
256 if (find(begin(cn
), end(cn
), str
) == end(cn
)) {
257 // LOG(INFO) << "additional name found " << str;
258 cn
.emplace_back(str
);
261 // LOG(INFO) << "duplicate name " << str << " ignored";
264 else if (gen
->type
== GEN_IPADD
) {
265 unsigned char* p
= gen
->d
.ip
->data
;
266 if (gen
->d
.ip
->length
== 4) {
267 auto const ip
= fmt::format(fmt("{:d}.{:d}.{:d}.{:d}"), p
[0], p
[1],
269 LOG(INFO
) << "alt name IP4 address " << ip
;
271 else if (gen
->d
.ip
->length
== 16) {
272 LOG(ERROR
) << "IPv6 not implemented";
275 LOG(ERROR
) << "unknown IP type";
279 LOG(ERROR
) << "unknown alt name type";
283 GENERAL_NAMES_free(subject_alt_names
);
285 //.......................................................
287 if (std::find(begin(cn
), end(cn
), client_name
) != end(cn
)) {
288 // LOG(INFO) << "**** using cert for " << client_name;
289 cert_ctx_
.emplace_back(ctx
, cn
);
294 if (cert_ctx_
.empty()) {
295 LOG(INFO
) << "no cert found for client " << client_name
;
297 auto ctx
= CHECK_NOTNULL(SSL_CTX_new(method
));
298 CHECK_GT(SSL_CTX_dane_enable(ctx
), 0)
299 << "unable to enable DANE on SSL context";
301 // you'd think if it's the default, you'd not have to call this
302 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx
), 1);
304 SSL_CTX_set_verify_depth(ctx
, Config::cert_verify_depth
+ 1);
305 SSL_CTX_set_verify(ctx
, SSL_VERIFY_PEER
| SSL_VERIFY_CLIENT_ONCE
,
308 LOG(INFO
) << "**** using no client cert";
310 std::vector
<Domain
> cn
;
311 cert_ctx_
.emplace_back(ctx
, cn
);
314 ssl_
= CHECK_NOTNULL(SSL_new(cert_ctx_
.back().ctx
));
316 char const* const preferred_ciphers
= "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
317 CHECK_EQ(1, SSL_set_cipher_list(ssl_
, preferred_ciphers
));
319 SSL_set_rfd(ssl_
, fd_in
);
320 SSL_set_wfd(ssl_
, fd_out
);
322 // LOG(INFO) << "tlsa_rrs.size() == " << tlsa_rrs.size();
324 if (tlsa_rrs
.size()) {
325 CHECK_GE(SSL_dane_enable(ssl_
, server_name
), 0)
326 << "SSL_dane_enable() failed";
327 LOG(INFO
) << "SSL_dane_enable(ssl_, " << server_name
<< ")";
330 CHECK_EQ(SSL_set1_host(ssl_
, server_name
), 1);
332 // SSL_set_tlsext_host_name(ssl_, server_name);
334 CHECK_EQ(SSL_ctrl(ssl_
, SSL_CTRL_SET_TLSEXT_HOSTNAME
,
335 TLSEXT_NAMETYPE_host_name
,
336 const_cast<char*>(server_name
)),
338 // LOG(INFO) << "SSL_set1_host and SSL_set_tlsext_host_name " <<
342 // No partial label wildcards
343 SSL_set_hostflags(ssl_
, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
);
345 auto usable_TLSA_records
= 0;
347 for (auto const& tlsa_rr
: tlsa_rrs
) {
348 if (std::holds_alternative
<DNS::RR_TLSA
>(tlsa_rr
)) {
349 auto const rp
= std::get
<DNS::RR_TLSA
>(tlsa_rr
);
350 auto data
= rp
.assoc_data();
351 auto rc
= SSL_dane_tlsa_add(ssl_
, rp
.cert_usage(), rp
.selector(),
352 rp
.matching_type(), data
.data(), data
.size());
355 auto const cp
= bin2hexstring(data
.data(), data
.size());
356 LOG(ERROR
) << "SSL_dane_tlsa_add() failed.";
357 LOG(ERROR
) << "failed record: " << rp
.cert_usage() << " "
358 << rp
.selector() << " " << rp
.matching_type() << " " << cp
;
361 auto const cp
= bin2hexstring(data
.data(), data
.size());
362 LOG(ERROR
) << "unusable TLSA record: " << rp
.cert_usage() << " "
363 << rp
.selector() << " " << rp
.matching_type() << " " << cp
;
366 // auto const cp = bin2hexstring(data.data(), data.size());
367 // LOG(INFO) << "added TLSA record: " << rp.cert_usage() << " "
368 // << rp.selector() << " " << rp.matching_type() << " " << cp;
369 ++usable_TLSA_records
;
374 // CHECK_EQ(SSL_set_tlsext_host_name(ssl_, server_name), 1);
376 // CHECK_EQ(SSL_ctrl(ssl_, SSL_CTRL_SET_TLSEXT_HOSTNAME,
377 // TLSEXT_NAMETYPE_host_name,
378 // const_cast<char*>(server_name)),
380 // LOG(INFO) << "SSL_set_tlsext_host_name == " << server_name;
382 if (session_context_index
< 0) {
383 session_context_index
384 = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
386 session_context context
;
387 SSL_set_ex_data(ssl_
, session_context_index
, &context
);
389 auto const start
= std::chrono::system_clock::now();
394 while ((rc
= SSL_connect(ssl_
)) < 0) {
396 auto const now
= std::chrono::system_clock::now();
398 CHECK(now
< (start
+ timeout
)) << "starttls timed out";
400 auto time_left
= std::chrono::duration_cast
<std::chrono::milliseconds
>(
401 (start
+ timeout
) - now
);
404 switch (n_get_err
= SSL_get_error(ssl_
, rc
)) {
405 case SSL_ERROR_WANT_READ
:
406 CHECK(POSIX::input_ready(fd_in
, time_left
))
407 << "starttls timed out on input_ready";
409 continue; // try SSL_accept again
411 case SSL_ERROR_WANT_WRITE
:
412 CHECK(POSIX::output_ready(fd_out
, time_left
))
413 << "starttls timed out on output_ready";
415 continue; // try SSL_accept again
417 case SSL_ERROR_SYSCALL
:
418 LOG(WARNING
) << "errno == " << errno
<< ": " << strerror(errno
);
421 default: ssl_error(n_get_err
);
425 if (SSL_get_verify_result(ssl_
) == X509_V_OK
) {
426 LOG(INFO
) << "server certificate verified";
429 char const* const peername
= SSL_get0_peername(ssl_
);
430 if (peername
!= nullptr) {
431 // Name checks were in scope and matched the peername
432 verified_peername_
= peername
;
433 LOG(INFO
) << "verified peername: " << peername
;
436 LOG(INFO
) << "no verified peername";
439 EVP_PKEY
* mspki
= nullptr;
440 int depth
= SSL_get0_dane_authority(ssl_
, nullptr, &mspki
);
443 uint8_t usage
, selector
, mtype
;
444 const unsigned char* certdata
;
447 SSL_get0_dane_tlsa(ssl_
, &usage
, &selector
, &mtype
, &certdata
,
450 LOG(INFO
) << "DANE TLSA " << unsigned(usage
) << " " << unsigned(selector
)
451 << " " << unsigned(mtype
) << " [" << bin2hexstring(certdata
, 6)
453 << ((mspki
!= nullptr) ? "TA public key verified certificate"
454 : depth
? "matched TA certificate"
455 : "matched EE certificate")
456 << " at depth " << depth
;
458 else if (usable_TLSA_records
&& enforce_dane
) {
459 LOG(WARNING
) << "enforcing DANE; failing starttls";
464 LOG(WARNING
) << "server certificate failed to verify";
470 bool TLS::starttls_server(fs::path config_path
,
473 std::chrono::milliseconds timeout
)
475 SSL_load_error_strings();
478 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
480 auto const method
= CHECK_NOTNULL(SSLv23_server_method());
483 = CHECK_NOTNULL(BIO_new_mem_buf(const_cast<char*>(ffdhe4096
), -1));
485 = CHECK_NOTNULL(PEM_read_bio_DHparams(bio
, nullptr, nullptr, nullptr));
487 auto const certs
= osutil::list_directory(config_path
, Config::cert_fn_re
);
489 CHECK_GE(certs
.size(), 1) << "no server cert(s) found";
491 for (auto const& cert
: certs
) {
493 auto ctx
= CHECK_NOTNULL(SSL_CTX_new(method
));
494 std::vector
<Domain
> names
;
496 SSL_CTX_set_options(ctx
, SSL_OP_CIPHER_SERVER_PREFERENCE
);
497 SSL_CTX_clear_options(ctx
, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
);
499 SSL_CTX_set_ecdh_auto(ctx
, 1);
501 CHECK_GT(SSL_CTX_dane_enable(ctx
), 0)
502 << "unable to enable DANE on SSL context";
504 // you'd think if it's the default, you'd not have to call this
505 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx
), 1);
507 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx
, cert
.string().c_str()), 0)
508 << "Can't load certificate chain file " << cert
;
510 auto const key
= fs::path(cert
).replace_extension(Config::key_ext
);
512 if (fs::exists(key
)) {
514 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx
, key
.string().c_str(),
517 << "Can't load private key file " << key
;
519 CHECK(SSL_CTX_check_private_key(ctx
))
520 << "SSL_CTX_check_private_key failed for " << key
;
523 #pragma GCC diagnostic push
524 #pragma GCC diagnostic ignored "-Wold-style-cast"
526 SSL_CTX_set_tmp_dh(ctx
, dh
);
528 #pragma GCC diagnostic pop
530 SSL_CTX_set_verify_depth(ctx
, Config::cert_verify_depth
+ 1);
532 SSL_CTX_set_verify(ctx
, SSL_VERIFY_PEER
| SSL_VERIFY_CLIENT_ONCE
,
535 // SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback);
537 SSL_CTX_callback_ctrl(
538 ctx
, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
,
539 reinterpret_cast<void (*)()>(ssl_servername_callback
));
541 // SSL_CTX_set_tlsext_servername_arg(ctx, &cert_ctx_);
543 SSL_CTX_ctrl(ctx
, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
, 0,
544 reinterpret_cast<void*>(&cert_ctx_
));
546 // SSL_CTX_dane_set_flags(ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
548 //.......................................................
550 auto const x509
= CHECK_NOTNULL(SSL_CTX_get0_certificate(ctx
));
552 X509_NAME
* subj
= X509_get_subject_name(x509
);
556 lastpos
= X509_NAME_get_index_by_NID(subj
, NID_commonName
, lastpos
);
559 auto e
= X509_NAME_get_entry(subj
, lastpos
);
560 ASN1_STRING
* d
= X509_NAME_ENTRY_get_data(e
);
561 auto str
= ASN1_STRING_get0_data(d
);
562 // LOG(INFO) << "server cert found for " << str;
563 names
.emplace_back(reinterpret_cast<const char*>(str
));
566 // auto ext_stack = X509_get0_extensions(x509);
567 // for (int i = 0; i < sk_X509_EXTENSION_num(ext_stack); i++) {
568 // X509_EXTENSION* ext
569 // = CHECK_NOTNULL(sk_X509_EXTENSION_value(ext_stack, i));
570 // ASN1_OBJECT* asn1_obj =
571 // CHECK_NOTNULL(X509_EXTENSION_get_object(ext)); unsigned nid =
572 // OBJ_obj2nid(asn1_obj); if (nid == NID_undef) {
573 // // no lookup found for the provided OID so nid came back as
574 // undefined. char extname[256]; OBJ_obj2txt(extname, sizeof(extname),
575 // asn1_obj, 1); LOG(INFO) << "undef extension name is " << extname;
577 // // the OID translated to a NID which implies that the OID has a
580 // const char* c_ext_name = CHECK_NOTNULL(OBJ_nid2ln(nid));
581 // LOG(INFO) << "extension " << c_ext_name;
585 auto subject_alt_names
= static_cast<GENERAL_NAMES
*>(
586 X509_get_ext_d2i(x509
, NID_subject_alt_name
, nullptr, nullptr));
588 for (int i
= 0; i
< sk_GENERAL_NAME_num(subject_alt_names
); ++i
) {
590 GENERAL_NAME
* gen
= sk_GENERAL_NAME_value(subject_alt_names
, i
);
592 if (gen
->type
== GEN_URI
|| gen
->type
== GEN_EMAIL
) {
593 ASN1_IA5STRING
* asn1_str
= gen
->d
.uniformResourceIdentifier
;
596 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str
)),
597 ASN1_STRING_length(asn1_str
));
599 LOG(INFO
) << "email or uri alt name " << str
;
601 else if (gen
->type
== GEN_DNS
) {
602 ASN1_IA5STRING
* asn1_str
= gen
->d
.uniformResourceIdentifier
;
605 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str
)),
606 ASN1_STRING_length(asn1_str
));
608 if (find(begin(names
), end(names
), str
) == end(names
)) {
609 // LOG(INFO) << "additional name found " << str;
610 names
.emplace_back(str
);
613 // LOG(INFO) << "duplicate name " << str << " ignored";
616 else if (gen
->type
== GEN_IPADD
) {
617 unsigned char* p
= gen
->d
.ip
->data
;
618 if (gen
->d
.ip
->length
== 4) {
620 = fmt::format(fmt("{:d}.{:d}.{:d}.{:d}"), p
[0], p
[1], p
[2], p
[3]);
621 LOG(INFO
) << "alt name IP4 address " << ip
;
622 names
.emplace_back(ip
);
624 else if (gen
->d
.ip
->length
== 16) {
626 LOG(ERROR
) << "IPv6 not implemented";
629 LOG(ERROR
) << "unknown IP type";
633 LOG(ERROR
) << "unknown alt name type";
637 GENERAL_NAMES_free(subject_alt_names
);
639 //.......................................................
641 cert_ctx_
.emplace_back(ctx
, names
);
647 ssl_
= CHECK_NOTNULL(SSL_new(cert_ctx_
.back().ctx
));
649 SSL_set_rfd(ssl_
, fd_in
);
650 SSL_set_wfd(ssl_
, fd_out
);
652 if (session_context_index
< 0) {
653 session_context_index
654 = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
656 session_context context
;
657 SSL_set_ex_data(ssl_
, session_context_index
, &context
);
659 auto const start
= std::chrono::system_clock::now();
664 while ((rc
= SSL_accept(ssl_
)) < 0) {
666 auto const now
= std::chrono::system_clock::now();
668 CHECK(now
< (start
+ timeout
)) << "starttls timed out";
671 = std::chrono::duration_cast
<std::chrono::milliseconds
>(
672 (start
+ timeout
) - now
);
675 switch (n_get_err
= SSL_get_error(ssl_
, rc
)) {
676 case SSL_ERROR_WANT_READ
:
677 CHECK(POSIX::input_ready(fd_in
, time_left
))
678 << "starttls timed out on input_ready";
680 continue; // try SSL_accept again
682 case SSL_ERROR_WANT_WRITE
:
683 CHECK(POSIX::output_ready(fd_out
, time_left
))
684 << "starttls timed out on output_ready";
686 continue; // try SSL_accept again
688 case SSL_ERROR_SYSCALL
:
689 LOG(WARNING
) << "errno == " << errno
<< ": " << strerror(errno
);
692 default: ssl_error(n_get_err
);
696 if (auto const peer_cert
= SSL_get_peer_certificate(ssl_
); peer_cert
) {
697 if (SSL_get_verify_result(ssl_
) == X509_V_OK
) {
698 LOG(INFO
) << "client certificate verified";
701 char const* const peername
= SSL_get0_peername(ssl_
);
702 if (peername
!= nullptr) {
703 // name checks were in scope and matched the peername
704 verified_peername_
= peername
;
705 LOG(INFO
) << "verified peername: " << peername
;
708 LOG(INFO
) << "no verified peername";
711 EVP_PKEY
* mspki
= nullptr;
712 int depth
= SSL_get0_dane_authority(ssl_
, nullptr, &mspki
);
715 uint8_t usage
, selector
, mtype
;
716 const unsigned char* certdata
;
719 SSL_get0_dane_tlsa(ssl_
, &usage
, &selector
, &mtype
, &certdata
,
722 LOG(INFO
) << "DANE TLSA " << usage
<< " " << selector
<< " " << mtype
723 << " [" << bin2hexstring(certdata
, 6) << "...] "
724 << ((mspki
!= nullptr) ? "TA public key verified certificate"
725 : depth
? "matched TA certificate"
726 : "matched EE certificate")
727 << " at depth " << depth
;
731 LOG(WARNING
) << "client certificate failed to verify";
735 // LOG(INFO) << "no client certificate offerd to us";
741 std::string
TLS::info() const
743 // same as SSL_CIPHER_get_version() below
744 // info << SSL_get_version(ssl_);
746 auto const c
= SSL_get_current_cipher(ssl_
);
749 int bits
= SSL_CIPHER_get_bits(c
, &alg_bits
);
750 return fmt::format("version={} cipher={} bits={}/{}{}",
751 SSL_CIPHER_get_version(c
), SSL_CIPHER_get_name(c
), bits
,
752 alg_bits
, (verified_
? " verified" : ""));
758 std::streamsize
TLS::io_tls_(char const* fn
,
759 std::function
<int(SSL
*, void*, int)> io_fnc
,
762 std::chrono::milliseconds timeout
,
765 auto const start
= std::chrono::system_clock::now();
766 auto const end_time
= start
+ timeout
;
771 while ((n_ret
= io_fnc(ssl_
, static_cast<void*>(s
), static_cast<int>(n
)))
773 auto const now
= std::chrono::system_clock::now();
774 if (now
> end_time
) {
775 LOG(WARNING
) << fn
<< " timed out";
777 return static_cast<std::streamsize
>(-1);
781 = std::chrono::duration_cast
<std::chrono::milliseconds
>(end_time
- now
);
784 switch (n_get_err
= SSL_get_error(ssl_
, n_ret
)) {
785 case SSL_ERROR_WANT_READ
: {
786 int fd
= SSL_get_rfd(ssl_
);
789 if (POSIX::input_ready(fd
, time_left
)) {
791 continue; // try io_fnc again
793 LOG(WARNING
) << fn
<< " timed out";
795 return static_cast<std::streamsize
>(-1);
798 case SSL_ERROR_WANT_WRITE
: {
799 int fd
= SSL_get_wfd(ssl_
);
801 if (POSIX::output_ready(fd
, time_left
)) {
803 continue; // try io_fnc again
805 LOG(WARNING
) << fn
<< " timed out";
807 return static_cast<std::streamsize
>(-1);
810 case SSL_ERROR_SYSCALL
:
811 LOG(WARNING
) << "errno == " << errno
<< ": " << strerror(errno
);
814 default: ssl_error(n_get_err
);
818 // The strange (and never before seen) case of 0 return.
821 switch (n_get_err
= SSL_get_error(ssl_
, n_ret
)) {
822 case SSL_ERROR_NONE
: LOG(INFO
) << fn
<< " returned SSL_ERROR_NONE"; break;
824 case SSL_ERROR_ZERO_RETURN
:
825 // This is a close, not at all sure this is the right thing to do.
826 LOG(INFO
) << fn
<< " returned SSL_ERROR_ZERO_RETURN";
829 default: LOG(INFO
) << fn
<< " returned zero"; ssl_error(n_get_err
);
833 return static_cast<std::streamsize
>(n_ret
);
836 void TLS::ssl_error(int n_get_err
)
838 LOG(WARNING
) << "n_get_err == " << n_get_err
;
840 case SSL_ERROR_NONE
: LOG(WARNING
) << "SSL_ERROR_NONE"; break;
841 case SSL_ERROR_ZERO_RETURN
: LOG(WARNING
) << "SSL_ERROR_ZERO_RETURN"; break;
842 case SSL_ERROR_WANT_READ
: LOG(WARNING
) << "SSL_ERROR_WANT_READ"; break;
843 case SSL_ERROR_WANT_WRITE
: LOG(WARNING
) << "SSL_ERROR_WANT_WRITE"; break;
844 case SSL_ERROR_WANT_CONNECT
: LOG(WARNING
) << "SSL_ERROR_WANT_CONNECT"; break;
845 case SSL_ERROR_WANT_ACCEPT
: LOG(WARNING
) << "SSL_ERROR_WANT_ACCEPT"; break;
846 case SSL_ERROR_WANT_X509_LOOKUP
:
847 LOG(WARNING
) << "SSL_ERROR_WANT_X509_LOOKUP";
849 case SSL_ERROR_SSL
: LOG(WARNING
) << "SSL_ERROR_SSL"; break;
852 while (0 != (er
= ERR_get_error()))
853 LOG(WARNING
) << ERR_error_string(er
, nullptr);
854 LOG(FATAL
) << "fatal OpenSSL error";