dont use cppcodec
[ghsmtp.git] / TLS-OpenSSL.cpp
blob611de165fceb277f937049c65cef526a2362413a
1 #include "TLS-OpenSSL.hpp"
3 #include <iomanip>
4 #include <span>
5 #include <string>
7 #include <openssl/err.h>
8 #include <openssl/rand.h>
10 #include <openssl/x509.h>
11 #include <openssl/x509v3.h>
13 #include <gflags/gflags.h>
14 #include <glog/logging.h>
16 #define FMT_STRING_ALIAS 1
17 #include <fmt/format.h>
19 #include "DNS.hpp"
20 #include "POSIX.hpp"
21 #include "osutil.hpp"
23 DEFINE_bool(support_all_tls_versions,
24 false,
25 "lift restrictions on TLS versions");
27 // <https://tools.ietf.org/html/rfc7919>
28 // <https://wiki.mozilla.org/Security/Server_Side_TLS#DHE_handshake_and_dhparam>
29 constexpr char ffdhe4096[] = R"(
30 -----BEGIN DH PARAMETERS-----
31 MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
32 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
33 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
34 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
35 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
36 ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
37 7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
38 nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
39 8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
40 iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
41 zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
42 -----END DH PARAMETERS-----
43 )";
45 // convert binary input into a std::string of hex digits
47 auto bin2hexstring(std::span<unsigned char const> const data) -> std::string
49 std::string ret;
50 ret.reserve(2 * data.size());
52 for (auto const& ch : data) {
53 auto const lo = ch & 0xF;
54 auto const hi = (ch >> 4) & 0xF;
56 auto constexpr hex_digits = "0123456789abcdef";
58 ret += hex_digits[static_cast<int>(hi)];
59 ret += hex_digits[static_cast<int>(lo)];
62 return ret;
65 TLS::TLS(std::function<void(void)> read_hook)
66 : read_hook_(read_hook)
70 TLS::~TLS()
72 for (auto& ctx : cert_ctx_) {
73 if (ctx.ctx) {
74 SSL_CTX_free(ctx.ctx);
77 if (ssl_) {
78 SSL_free(ssl_);
82 struct session_context {
85 static int session_context_index = -1;
87 static int verify_callback(int preverify_ok, X509_STORE_CTX* ctx)
89 auto const cert = X509_STORE_CTX_get_current_cert(ctx);
90 if (cert == nullptr)
91 return 1;
93 auto err = X509_STORE_CTX_get_error(ctx);
95 // auto const ssl = reinterpret_cast<SSL*>(
96 // X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
98 CHECK_GE(session_context_index, 0);
100 // auto unused = reinterpret_cast<session_context*>(SSL_get_ex_data(ssl,
101 // session_context_index));
103 auto const depth = X509_STORE_CTX_get_error_depth(ctx);
105 char buf[256];
106 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
108 if (depth > Config::cert_verify_depth) {
109 preverify_ok = 0;
110 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
111 X509_STORE_CTX_set_error(ctx, err);
113 if (!preverify_ok) {
114 LOG(INFO) << "verify error:num=" << err << ':'
115 << X509_verify_cert_error_string(err) << ": depth=" << depth
116 << ':' << buf;
118 else {
119 LOG(INFO) << "preverify_ok; depth=" << depth << " subject_name=«" << buf
120 << "»";
123 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
124 if (cert) {
125 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
126 LOG(INFO) << "issuer=" << buf;
128 else {
129 LOG(INFO) << "issuer=<unknown>";
133 return 1; // always continue
136 static int ssl_servername_callback(SSL* s, int* ad, void* arg)
138 auto cert_ctx_ptr
139 = CHECK_NOTNULL(static_cast<std::vector<TLS::per_cert_ctx>*>(arg));
140 auto const& cert_ctx = *cert_ctx_ptr;
142 auto const servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
144 if (servername && *servername) {
145 LOG(INFO) << "servername requested " << servername;
146 for (auto const& ctx : cert_ctx) {
147 if (auto const& c = std::find(begin(ctx.cn), end(ctx.cn), servername);
148 c != end(ctx.cn)) {
149 if (size(cert_ctx) > 1)
150 SSL_set_SSL_CTX(s, ctx.ctx);
151 return SSL_TLSEXT_ERR_OK;
154 LOG(INFO) << "no cert found for server " << servername;
155 return SSL_TLSEXT_ERR_ALERT_WARNING;
158 // LOG(INFO) << "no specific server name requested";
159 return SSL_TLSEXT_ERR_OK;
162 bool TLS::starttls_client(fs::path config_path,
163 int fd_in,
164 int fd_out,
165 char const* client_name,
166 char const* server_name,
167 DNS::RR_collection const& tlsa_rrs,
168 bool enforce_dane,
169 std::chrono::milliseconds timeout)
171 SSL_load_error_strings();
172 SSL_library_init();
174 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
176 auto const method = CHECK_NOTNULL(SSLv23_client_method());
178 if (client_name) {
179 auto const certs = osutil::list_directory(config_path, Config::cert_fn_re);
181 CHECK_GE(certs.size(), 1) << "no client cert(s) found";
183 for (auto const& cert : certs) {
185 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
186 std::vector<Domain> cn;
188 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
190 // // Allow any old and crufty protocol version.
191 // if (FLAGS_support_all_tls_versions) {
192 // CHECK_GT(SSL_CTX_set_min_proto_version(ctx, 0), 0)
193 // << "unable to set min proto version";
194 // }
196 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
197 << "unable to enable DANE on SSL context";
199 // you'd think if it's the default, you'd not have to call this
200 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
202 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx, cert.string().c_str()),
204 << "Can't load certificate chain file " << cert;
206 auto const key = fs::path(cert).replace_extension(Config::key_ext);
208 if (fs::exists(key)) {
210 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx, key.string().c_str(),
211 SSL_FILETYPE_PEM),
213 << "Can't load private key file " << key;
215 CHECK(SSL_CTX_check_private_key(ctx))
216 << "SSL_CTX_check_private_key failed for " << key;
219 SSL_CTX_set_verify_depth(ctx, Config::cert_verify_depth + 1);
220 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
221 verify_callback);
223 //.......................................................
225 auto const x509 = CHECK_NOTNULL(SSL_CTX_get0_certificate(ctx));
227 X509_NAME* subj = X509_get_subject_name(x509);
229 int lastpos = -1;
230 for (;;) {
231 lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, lastpos);
232 if (lastpos == -1)
233 break;
234 auto e = X509_NAME_get_entry(subj, lastpos);
235 ASN1_STRING* d = X509_NAME_ENTRY_get_data(e);
236 auto str = ASN1_STRING_get0_data(d);
237 // LOG(INFO) << "client cert found for " << str;
238 cn.emplace_back(reinterpret_cast<const char*>(str));
241 auto subject_alt_names = static_cast<GENERAL_NAMES*>(
242 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr));
244 for (int i = 0; i < sk_GENERAL_NAME_num(subject_alt_names); ++i) {
246 GENERAL_NAME* gen = sk_GENERAL_NAME_value(subject_alt_names, i);
248 if (gen->type == GEN_URI || gen->type == GEN_EMAIL) {
249 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
251 std::string const str(
252 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
253 ASN1_STRING_length(asn1_str));
255 LOG(INFO) << "email or uri alt name " << str;
257 else if (gen->type == GEN_DNS) {
258 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
260 std::string str(
261 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
262 ASN1_STRING_length(asn1_str));
264 if (find(begin(cn), end(cn), str) == end(cn)) {
265 // LOG(INFO) << "additional name found " << str;
266 cn.emplace_back(str);
268 else {
269 // LOG(INFO) << "duplicate name " << str << " ignored";
272 else if (gen->type == GEN_IPADD) {
273 unsigned char* p = gen->d.ip->data;
274 if (gen->d.ip->length == 4) {
275 auto const ip = fmt::format(FMT_STRING("{:d}.{:d}.{:d}.{:d}"), p[0],
276 p[1], p[2], p[3]);
277 LOG(INFO) << "alt name IP4 address " << ip;
279 else if (gen->d.ip->length == 16) {
280 LOG(ERROR) << "IPv6 not implemented";
282 else {
283 LOG(ERROR) << "unknown IP type";
286 else {
287 LOG(ERROR) << "unknown alt name type";
291 GENERAL_NAMES_free(subject_alt_names);
293 //.......................................................
295 if (std::find(begin(cn), end(cn), client_name) != end(cn)) {
296 // LOG(INFO) << "**** using cert for " << client_name;
297 cert_ctx_.emplace_back(ctx, cn);
302 if (cert_ctx_.empty()) {
303 LOG(INFO) << "no cert found for client " << client_name;
305 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
306 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
307 << "unable to enable DANE on SSL context";
309 // you'd think if it's the default, you'd not have to call this
310 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
312 SSL_CTX_set_verify_depth(ctx, Config::cert_verify_depth + 1);
313 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
314 verify_callback);
316 LOG(INFO) << "**** using no client cert";
318 std::vector<Domain> cn;
319 cert_ctx_.emplace_back(ctx, cn);
322 ssl_ = CHECK_NOTNULL(SSL_new(cert_ctx_.back().ctx));
324 SSL_set_rfd(ssl_, fd_in);
325 SSL_set_wfd(ssl_, fd_out);
327 // LOG(INFO) << "tlsa_rrs.size() == " << tlsa_rrs.size();
329 if (tlsa_rrs.size()) {
330 CHECK_GE(SSL_dane_enable(ssl_, server_name), 0)
331 << "SSL_dane_enable() failed";
332 LOG(INFO) << "SSL_dane_enable(ssl_, " << server_name << ")";
334 else {
335 CHECK_EQ(SSL_set1_host(ssl_, server_name), 1);
337 // SSL_set_tlsext_host_name(ssl_, server_name);
338 // same as:
339 CHECK_EQ(SSL_ctrl(ssl_, SSL_CTRL_SET_TLSEXT_HOSTNAME,
340 TLSEXT_NAMETYPE_host_name,
341 const_cast<char*>(server_name)),
343 // LOG(INFO) << "SSL_set1_host and SSL_set_tlsext_host_name " <<
344 // server_name;
347 // No partial label wildcards
348 SSL_set_hostflags(ssl_, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
350 auto usable_TLSA_records = 0;
352 for (auto const& tlsa_rr : tlsa_rrs) {
353 if (std::holds_alternative<DNS::RR_TLSA>(tlsa_rr)) {
354 auto const rp = std::get<DNS::RR_TLSA>(tlsa_rr);
355 auto data = rp.assoc_data();
356 auto rc = SSL_dane_tlsa_add(ssl_, rp.cert_usage(), rp.selector(),
357 rp.matching_type(), data.data(), data.size());
359 if (rc < 0) {
360 auto const cp = bin2hexstring(data);
361 LOG(ERROR) << "SSL_dane_tlsa_add() failed.";
362 LOG(ERROR) << "failed record: " << rp.cert_usage() << " "
363 << rp.selector() << " " << rp.matching_type() << " " << cp;
365 else if (rc == 0) {
366 auto const cp = bin2hexstring(data);
367 LOG(ERROR) << "unusable TLSA record: " << rp.cert_usage() << " "
368 << rp.selector() << " " << rp.matching_type() << " " << cp;
370 else {
371 // auto const cp = bin2hexstring(data);
372 // LOG(INFO) << "added TLSA record: " << rp.cert_usage() << " "
373 // << rp.selector() << " " << rp.matching_type() << " " << cp;
374 ++usable_TLSA_records;
379 // CHECK_EQ(SSL_set_tlsext_host_name(ssl_, server_name), 1);
380 // same as:
381 // CHECK_EQ(SSL_ctrl(ssl_, SSL_CTRL_SET_TLSEXT_HOSTNAME,
382 // TLSEXT_NAMETYPE_host_name,
383 // const_cast<char*>(server_name)),
384 // 1);
385 // LOG(INFO) << "SSL_set_tlsext_host_name == " << server_name;
387 if (session_context_index < 0) {
388 session_context_index =
389 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
391 session_context context;
392 SSL_set_ex_data(ssl_, session_context_index, &context);
394 auto const start = std::chrono::system_clock::now();
396 ERR_clear_error();
398 int rc;
399 while ((rc = SSL_connect(ssl_)) < 0) {
401 auto const now = std::chrono::system_clock::now();
403 CHECK(now < (start + timeout)) << "starttls timed out";
405 auto time_left = std::chrono::duration_cast<std::chrono::milliseconds>(
406 (start + timeout) - now);
408 int n_get_err;
409 switch (n_get_err = SSL_get_error(ssl_, rc)) {
410 case SSL_ERROR_WANT_READ:
411 CHECK(POSIX::input_ready(fd_in, time_left))
412 << "starttls timed out on input_ready";
413 ERR_clear_error();
414 continue; // try SSL_accept again
416 case SSL_ERROR_WANT_WRITE:
417 CHECK(POSIX::output_ready(fd_out, time_left))
418 << "starttls timed out on output_ready";
419 ERR_clear_error();
420 continue; // try SSL_accept again
422 case SSL_ERROR_SYSCALL:
423 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
424 [[fallthrough]];
426 default: ssl_error(n_get_err);
430 if (SSL_get_verify_result(ssl_) == X509_V_OK) {
431 LOG(INFO) << "server certificate verified";
432 verified_ = true;
434 char const* const peername = SSL_get0_peername(ssl_);
435 if (peername != nullptr) {
436 // Name checks were in scope and matched the peername
437 verified_peername_ = peername;
438 LOG(INFO) << "verified peername: " << peername;
440 else {
441 LOG(INFO) << "no verified peername";
444 EVP_PKEY* mspki = nullptr;
445 int depth = SSL_get0_dane_authority(ssl_, nullptr, &mspki);
446 if (depth >= 0) {
448 uint8_t usage, selector, mtype;
449 const unsigned char* certdata;
450 size_t certdata_len;
452 SSL_get0_dane_tlsa(ssl_, &usage, &selector, &mtype, &certdata,
453 &certdata_len);
455 LOG(INFO) << "DANE TLSA " << unsigned(usage) << " " << unsigned(selector)
456 << " " << unsigned(mtype) << " ["
457 << bin2hexstring({certdata, 6}) << "...] "
458 << ((mspki != nullptr) ? "TA public key verified certificate"
459 : depth ? "matched TA certificate"
460 : "matched EE certificate")
461 << " at depth " << depth;
463 else if (usable_TLSA_records && enforce_dane) {
464 LOG(WARNING) << "enforcing DANE; failing starttls";
465 return false;
468 else {
469 LOG(WARNING) << "server certificate failed to verify";
472 return true;
475 bool TLS::starttls_server(fs::path config_path,
476 int fd_in,
477 int fd_out,
478 std::chrono::milliseconds timeout)
480 SSL_load_error_strings();
481 SSL_library_init();
483 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
485 auto const method = CHECK_NOTNULL(SSLv23_server_method());
487 auto const bio =
488 CHECK_NOTNULL(BIO_new_mem_buf(const_cast<char*>(ffdhe4096), -1));
490 auto const certs = osutil::list_directory(config_path, Config::cert_fn_re);
492 CHECK_GE(certs.size(), 1) << "no server cert(s) found";
494 for (auto const& cert : certs) {
496 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
497 std::vector<Domain> names;
499 SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
500 SSL_CTX_clear_options(ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
502 // Allow any old and crufty protocol version.
503 // if (FLAGS_support_all_tls_versions) {
504 // CHECK_GT(SSL_CTX_set_min_proto_version(ctx, 0), 0)
505 // << "unable to set min proto version";
506 // }
508 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
509 << "unable to enable DANE on SSL context";
511 // you'd think if it's the default, you'd not have to call this
512 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
514 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx, cert.string().c_str()), 0)
515 << "Can't load certificate chain file " << cert;
517 auto const key = fs::path(cert).replace_extension(Config::key_ext);
519 if (fs::exists(key)) {
521 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx, key.string().c_str(),
522 SSL_FILETYPE_PEM),
524 << "Can't load private key file " << key;
526 CHECK(SSL_CTX_check_private_key(ctx))
527 << "SSL_CTX_check_private_key failed for " << key;
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,
533 verify_callback);
535 // SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback);
536 // same as:
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_);
542 // same as:
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);
554 int lastpos = -1;
555 for (;;) {
556 lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, lastpos);
557 if (lastpos == -1)
558 break;
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;
576 // } else {
577 // // the OID translated to a NID which implies that the OID has a
578 // known
579 // // sn/ln
580 // const char* c_ext_name = CHECK_NOTNULL(OBJ_nid2ln(nid));
581 // LOG(INFO) << "extension " << c_ext_name;
582 // }
583 // }
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;
595 std::string str(
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;
604 std::string str(
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);
612 else {
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) {
619 auto const ip = fmt::format(FMT_STRING("{:d}.{:d}.{:d}.{:d}"), p[0],
620 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) {
625 // FIXME!
626 LOG(ERROR) << "IPv6 not implemented";
628 else {
629 LOG(ERROR) << "unknown IP type";
632 else {
633 LOG(ERROR) << "unknown alt name type";
637 GENERAL_NAMES_free(subject_alt_names);
639 //.......................................................
641 cert_ctx_.emplace_back(ctx, names);
644 BIO_free(bio);
646 ssl_ = CHECK_NOTNULL(SSL_new(cert_ctx_.back().ctx));
648 SSL_set_rfd(ssl_, fd_in);
649 SSL_set_wfd(ssl_, fd_out);
651 if (session_context_index < 0) {
652 session_context_index =
653 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
655 session_context context;
656 SSL_set_ex_data(ssl_, session_context_index, &context);
658 auto const start = std::chrono::system_clock::now();
660 ERR_clear_error();
662 int rc;
663 while ((rc = SSL_accept(ssl_)) < 0) {
665 auto const now = std::chrono::system_clock::now();
667 CHECK(now < (start + timeout)) << "starttls timed out";
669 auto const time_left =
670 std::chrono::duration_cast<std::chrono::milliseconds>(
671 (start + timeout) - now);
673 int n_get_err;
674 switch (n_get_err = SSL_get_error(ssl_, rc)) {
675 case SSL_ERROR_WANT_READ:
676 CHECK(POSIX::input_ready(fd_in, time_left))
677 << "starttls timed out on input_ready";
678 ERR_clear_error();
679 continue; // try SSL_accept again
681 case SSL_ERROR_WANT_WRITE:
682 CHECK(POSIX::output_ready(fd_out, time_left))
683 << "starttls timed out on output_ready";
684 ERR_clear_error();
685 continue; // try SSL_accept again
687 case SSL_ERROR_SYSCALL:
688 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
689 [[fallthrough]];
691 default: ssl_error(n_get_err);
695 if (auto const peer_cert = SSL_get_peer_certificate(ssl_); peer_cert) {
696 if (SSL_get_verify_result(ssl_) == X509_V_OK) {
697 LOG(INFO) << "client certificate verified";
698 verified_ = true;
700 char const* const peername = SSL_get0_peername(ssl_);
701 if (peername != nullptr) {
702 // name checks were in scope and matched the peername
703 verified_peername_ = peername;
704 LOG(INFO) << "verified peername: " << peername;
706 else {
707 LOG(INFO) << "no verified peername";
710 EVP_PKEY* mspki = nullptr;
711 int depth = SSL_get0_dane_authority(ssl_, nullptr, &mspki);
712 if (depth >= 0) {
714 uint8_t usage, selector, mtype;
715 const unsigned char* certdata;
716 size_t certdata_len;
718 SSL_get0_dane_tlsa(ssl_, &usage, &selector, &mtype, &certdata,
719 &certdata_len);
721 LOG(INFO) << "DANE TLSA " << usage << " " << selector << " " << mtype
722 << " [" << bin2hexstring({certdata, 6}) << "...] "
723 << ((mspki != nullptr) ? "TA public key verified certificate"
724 : depth ? "matched TA certificate"
725 : "matched EE certificate")
726 << " at depth " << depth;
729 else {
730 LOG(WARNING) << "client certificate failed to verify";
733 else {
734 // LOG(INFO) << "no client certificate offerd to us";
737 return true;
740 std::string TLS::info() const
742 // same as SSL_CIPHER_get_version() below
743 // info << SSL_get_version(ssl_);
745 auto const c = SSL_get_current_cipher(ssl_);
746 if (c) {
747 int alg_bits;
748 int bits = SSL_CIPHER_get_bits(c, &alg_bits);
749 return fmt::format("version={} cipher={} bits={}/{}{}",
750 SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c), bits,
751 alg_bits, (verified_ ? " verified" : ""));
754 return "";
757 std::streamsize TLS::io_tls_(char const* fn,
758 std::function<int(SSL*, void*, int)> io_fnc,
759 char* s,
760 std::streamsize n,
761 std::chrono::milliseconds timeout,
762 bool& t_o)
764 auto const start = std::chrono::system_clock::now();
765 auto const end_time = start + timeout;
767 ERR_clear_error();
769 int n_ret;
770 while ((n_ret = io_fnc(ssl_, static_cast<void*>(s), static_cast<int>(n)))
771 < 0) {
772 auto const now = std::chrono::system_clock::now();
773 if (now > end_time) {
774 LOG(WARNING) << fn << " timed out";
775 t_o = true;
776 return static_cast<std::streamsize>(-1);
779 auto const time_left
780 = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - now);
782 int n_get_err;
783 switch (n_get_err = SSL_get_error(ssl_, n_ret)) {
784 case SSL_ERROR_WANT_READ: {
785 int fd = SSL_get_rfd(ssl_);
786 CHECK_NE(-1, fd);
787 read_hook_();
788 if (POSIX::input_ready(fd, time_left)) {
789 ERR_clear_error();
790 continue; // try io_fnc again
792 LOG(WARNING) << fn << " timed out";
793 t_o = true;
794 return static_cast<std::streamsize>(-1);
797 case SSL_ERROR_WANT_WRITE: {
798 int fd = SSL_get_wfd(ssl_);
799 CHECK_NE(-1, fd);
800 if (POSIX::output_ready(fd, time_left)) {
801 ERR_clear_error();
802 continue; // try io_fnc again
804 LOG(WARNING) << fn << " timed out";
805 t_o = true;
806 return static_cast<std::streamsize>(-1);
809 case SSL_ERROR_SYSCALL:
810 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
811 [[fallthrough]];
813 default: ssl_error(n_get_err);
817 // The strange (and never before seen) case of 0 return.
818 if (0 == n_ret) {
819 int n_get_err;
820 switch (n_get_err = SSL_get_error(ssl_, n_ret)) {
821 case SSL_ERROR_NONE: LOG(INFO) << fn << " returned SSL_ERROR_NONE"; break;
823 case SSL_ERROR_ZERO_RETURN:
824 // This is a close, not at all sure this is the right thing to do.
825 LOG(INFO) << fn << " returned SSL_ERROR_ZERO_RETURN";
826 break;
828 default: LOG(INFO) << fn << " returned zero"; ssl_error(n_get_err);
832 return static_cast<std::streamsize>(n_ret);
835 void TLS::ssl_error(int n_get_err)
837 LOG(WARNING) << "n_get_err == " << n_get_err;
838 switch (n_get_err) {
839 case SSL_ERROR_NONE: LOG(WARNING) << "SSL_ERROR_NONE"; break;
840 case SSL_ERROR_ZERO_RETURN: LOG(WARNING) << "SSL_ERROR_ZERO_RETURN"; break;
841 case SSL_ERROR_WANT_READ: LOG(WARNING) << "SSL_ERROR_WANT_READ"; break;
842 case SSL_ERROR_WANT_WRITE: LOG(WARNING) << "SSL_ERROR_WANT_WRITE"; break;
843 case SSL_ERROR_WANT_CONNECT: LOG(WARNING) << "SSL_ERROR_WANT_CONNECT"; break;
844 case SSL_ERROR_WANT_ACCEPT: LOG(WARNING) << "SSL_ERROR_WANT_ACCEPT"; break;
845 case SSL_ERROR_WANT_X509_LOOKUP:
846 LOG(WARNING) << "SSL_ERROR_WANT_X509_LOOKUP";
847 break;
848 case SSL_ERROR_SSL: LOG(WARNING) << "SSL_ERROR_SSL"; break;
850 unsigned long er;
851 while (0 != (er = ERR_get_error()))
852 LOG(WARNING) << ERR_error_string(er, nullptr);
853 LOG(WARNING) << "fatal OpenSSL error";
854 exit(1);