still must match obs first
[ghsmtp.git] / TLS-OpenSSL.cpp
blob0489270b424033948616bdb79b8c18ebb17d81ec
1 #include "TLS-OpenSSL.hpp"
3 #include <iomanip>
4 #include <string>
6 #include <openssl/err.h>
7 #include <openssl/rand.h>
9 #include <openssl/x509.h>
10 #include <openssl/x509v3.h>
12 #include <gflags/gflags.h>
13 #include <glog/logging.h>
15 #define FMT_STRING_ALIAS 1
16 #include <fmt/format.h>
18 #include "DNS.hpp"
19 #include "POSIX.hpp"
20 #include "osutil.hpp"
22 DEFINE_bool(support_all_tls_versions,
23 false,
24 "lift restrictions on TLS versions");
26 // <https://tools.ietf.org/html/rfc7919>
27 // <https://wiki.mozilla.org/Security/Server_Side_TLS#DHE_handshake_and_dhparam>
28 constexpr char ffdhe4096[] = R"(
29 -----BEGIN DH PARAMETERS-----
30 MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
31 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
32 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
33 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
34 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
35 ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
36 7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
37 nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
38 8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
39 iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
40 zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
41 -----END DH PARAMETERS-----
42 )";
44 // convert binary input into a std::string of hex digits
46 auto bin2hexstring(uint8_t const* data, size_t length)
48 std::string ret;
49 ret.reserve(2 * length);
51 for (size_t n = 0u; n < length; ++n) {
52 auto const ch = data[n];
54 auto const lo = ch & 0xF;
55 auto const hi = (ch >> 4) & 0xF;
57 auto constexpr hex_digits = "0123456789abcdef";
59 ret += hex_digits[hi];
60 ret += hex_digits[lo];
63 return ret;
66 TLS::TLS(std::function<void(void)> read_hook)
67 : read_hook_(read_hook)
71 TLS::~TLS()
73 for (auto& ctx : cert_ctx_) {
74 if (ctx.ctx) {
75 SSL_CTX_free(ctx.ctx);
78 if (ssl_) {
79 SSL_free(ssl_);
83 struct session_context {
86 static int session_context_index = -1;
88 static int verify_callback(int preverify_ok, X509_STORE_CTX* ctx)
90 auto const cert = X509_STORE_CTX_get_current_cert(ctx);
91 if (cert == nullptr)
92 return 1;
94 auto err = X509_STORE_CTX_get_error(ctx);
96 // auto const ssl = reinterpret_cast<SSL*>(
97 // X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
99 CHECK_GE(session_context_index, 0);
101 // auto unused = reinterpret_cast<session_context*>(SSL_get_ex_data(ssl,
102 // session_context_index));
104 auto const depth = X509_STORE_CTX_get_error_depth(ctx);
106 char buf[256];
107 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
109 if (depth > Config::cert_verify_depth) {
110 preverify_ok = 0;
111 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
112 X509_STORE_CTX_set_error(ctx, err);
114 if (!preverify_ok) {
115 LOG(INFO) << "verify error:num=" << err << ':'
116 << X509_verify_cert_error_string(err) << ": depth=" << depth
117 << ':' << buf;
119 else {
120 LOG(INFO) << "preverify_ok; depth=" << depth << " subject_name=«" << buf
121 << "»";
124 if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
125 if (cert) {
126 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
127 LOG(INFO) << "issuer=" << buf;
129 else {
130 LOG(INFO) << "issuer=<unknown>";
134 return 1; // always continue
137 static int ssl_servername_callback(SSL* s, int* ad, void* arg)
139 auto cert_ctx_ptr
140 = CHECK_NOTNULL(static_cast<std::vector<TLS::per_cert_ctx>*>(arg));
141 auto const& cert_ctx = *cert_ctx_ptr;
143 auto const servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
145 if (servername && *servername) {
146 LOG(INFO) << "servername requested " << servername;
147 for (auto const& ctx : cert_ctx) {
148 if (auto const& c = std::find(begin(ctx.cn), end(ctx.cn), servername);
149 c != end(ctx.cn)) {
150 if (size(cert_ctx) > 1)
151 SSL_set_SSL_CTX(s, ctx.ctx);
152 return SSL_TLSEXT_ERR_OK;
155 LOG(INFO) << "no cert found for server " << servername;
156 return SSL_TLSEXT_ERR_ALERT_WARNING;
159 // LOG(INFO) << "no specific server name requested";
160 return SSL_TLSEXT_ERR_OK;
163 bool TLS::starttls_client(fs::path config_path,
164 int fd_in,
165 int fd_out,
166 char const* client_name,
167 char const* server_name,
168 DNS::RR_collection const& tlsa_rrs,
169 bool enforce_dane,
170 std::chrono::milliseconds timeout)
172 SSL_load_error_strings();
173 SSL_library_init();
175 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
177 auto const method = CHECK_NOTNULL(SSLv23_client_method());
179 if (client_name) {
180 auto const certs = osutil::list_directory(config_path, Config::cert_fn_re);
182 CHECK_GE(certs.size(), 1) << "no client cert(s) found";
184 for (auto const& cert : certs) {
186 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
187 std::vector<Domain> cn;
189 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
191 // // Allow any old and crufty protocol version.
192 // if (FLAGS_support_all_tls_versions) {
193 // CHECK_GT(SSL_CTX_set_min_proto_version(ctx, 0), 0)
194 // << "unable to set min proto version";
195 // }
197 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
198 << "unable to enable DANE on SSL context";
200 // you'd think if it's the default, you'd not have to call this
201 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
203 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx, cert.string().c_str()),
205 << "Can't load certificate chain file " << cert;
207 auto const key = fs::path(cert).replace_extension(Config::key_ext);
209 if (fs::exists(key)) {
211 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx, key.string().c_str(),
212 SSL_FILETYPE_PEM),
214 << "Can't load private key file " << key;
216 CHECK(SSL_CTX_check_private_key(ctx))
217 << "SSL_CTX_check_private_key failed for " << key;
220 SSL_CTX_set_verify_depth(ctx, Config::cert_verify_depth + 1);
221 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
222 verify_callback);
224 //.......................................................
226 auto const x509 = CHECK_NOTNULL(SSL_CTX_get0_certificate(ctx));
228 X509_NAME* subj = X509_get_subject_name(x509);
230 int lastpos = -1;
231 for (;;) {
232 lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, lastpos);
233 if (lastpos == -1)
234 break;
235 auto e = X509_NAME_get_entry(subj, lastpos);
236 ASN1_STRING* d = X509_NAME_ENTRY_get_data(e);
237 auto str = ASN1_STRING_get0_data(d);
238 // LOG(INFO) << "client cert found for " << str;
239 cn.emplace_back(reinterpret_cast<const char*>(str));
242 auto subject_alt_names = static_cast<GENERAL_NAMES*>(
243 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr));
245 for (int i = 0; i < sk_GENERAL_NAME_num(subject_alt_names); ++i) {
247 GENERAL_NAME* gen = sk_GENERAL_NAME_value(subject_alt_names, i);
249 if (gen->type == GEN_URI || gen->type == GEN_EMAIL) {
250 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
252 std::string const str(
253 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
254 ASN1_STRING_length(asn1_str));
256 LOG(INFO) << "email or uri alt name " << str;
258 else if (gen->type == GEN_DNS) {
259 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
261 std::string str(
262 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
263 ASN1_STRING_length(asn1_str));
265 if (find(begin(cn), end(cn), str) == end(cn)) {
266 // LOG(INFO) << "additional name found " << str;
267 cn.emplace_back(str);
269 else {
270 // LOG(INFO) << "duplicate name " << str << " ignored";
273 else if (gen->type == GEN_IPADD) {
274 unsigned char* p = gen->d.ip->data;
275 if (gen->d.ip->length == 4) {
276 auto const ip = fmt::format(FMT_STRING("{:d}.{:d}.{:d}.{:d}"), p[0],
277 p[1], p[2], p[3]);
278 LOG(INFO) << "alt name IP4 address " << ip;
280 else if (gen->d.ip->length == 16) {
281 LOG(ERROR) << "IPv6 not implemented";
283 else {
284 LOG(ERROR) << "unknown IP type";
287 else {
288 LOG(ERROR) << "unknown alt name type";
292 GENERAL_NAMES_free(subject_alt_names);
294 //.......................................................
296 if (std::find(begin(cn), end(cn), client_name) != end(cn)) {
297 // LOG(INFO) << "**** using cert for " << client_name;
298 cert_ctx_.emplace_back(ctx, cn);
303 if (cert_ctx_.empty()) {
304 LOG(INFO) << "no cert found for client " << client_name;
306 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
307 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
308 << "unable to enable DANE on SSL context";
310 // you'd think if it's the default, you'd not have to call this
311 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
313 SSL_CTX_set_verify_depth(ctx, Config::cert_verify_depth + 1);
314 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
315 verify_callback);
317 LOG(INFO) << "**** using no client cert";
319 std::vector<Domain> cn;
320 cert_ctx_.emplace_back(ctx, cn);
323 ssl_ = CHECK_NOTNULL(SSL_new(cert_ctx_.back().ctx));
325 SSL_set_rfd(ssl_, fd_in);
326 SSL_set_wfd(ssl_, fd_out);
328 // LOG(INFO) << "tlsa_rrs.size() == " << tlsa_rrs.size();
330 if (tlsa_rrs.size()) {
331 CHECK_GE(SSL_dane_enable(ssl_, server_name), 0)
332 << "SSL_dane_enable() failed";
333 LOG(INFO) << "SSL_dane_enable(ssl_, " << server_name << ")";
335 else {
336 CHECK_EQ(SSL_set1_host(ssl_, server_name), 1);
338 // SSL_set_tlsext_host_name(ssl_, server_name);
339 // same as:
340 CHECK_EQ(SSL_ctrl(ssl_, SSL_CTRL_SET_TLSEXT_HOSTNAME,
341 TLSEXT_NAMETYPE_host_name,
342 const_cast<char*>(server_name)),
344 // LOG(INFO) << "SSL_set1_host and SSL_set_tlsext_host_name " <<
345 // server_name;
348 // No partial label wildcards
349 SSL_set_hostflags(ssl_, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
351 auto usable_TLSA_records = 0;
353 for (auto const& tlsa_rr : tlsa_rrs) {
354 if (std::holds_alternative<DNS::RR_TLSA>(tlsa_rr)) {
355 auto const rp = std::get<DNS::RR_TLSA>(tlsa_rr);
356 auto data = rp.assoc_data();
357 auto rc = SSL_dane_tlsa_add(ssl_, rp.cert_usage(), rp.selector(),
358 rp.matching_type(), data.data(), data.size());
360 if (rc < 0) {
361 auto const cp = bin2hexstring(data.data(), data.size());
362 LOG(ERROR) << "SSL_dane_tlsa_add() failed.";
363 LOG(ERROR) << "failed record: " << rp.cert_usage() << " "
364 << rp.selector() << " " << rp.matching_type() << " " << cp;
366 else if (rc == 0) {
367 auto const cp = bin2hexstring(data.data(), data.size());
368 LOG(ERROR) << "unusable TLSA record: " << rp.cert_usage() << " "
369 << rp.selector() << " " << rp.matching_type() << " " << cp;
371 else {
372 // auto const cp = bin2hexstring(data.data(), data.size());
373 // LOG(INFO) << "added TLSA record: " << rp.cert_usage() << " "
374 // << rp.selector() << " " << rp.matching_type() << " " << cp;
375 ++usable_TLSA_records;
380 // CHECK_EQ(SSL_set_tlsext_host_name(ssl_, server_name), 1);
381 // same as:
382 // CHECK_EQ(SSL_ctrl(ssl_, SSL_CTRL_SET_TLSEXT_HOSTNAME,
383 // TLSEXT_NAMETYPE_host_name,
384 // const_cast<char*>(server_name)),
385 // 1);
386 // LOG(INFO) << "SSL_set_tlsext_host_name == " << server_name;
388 if (session_context_index < 0) {
389 session_context_index =
390 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
392 session_context context;
393 SSL_set_ex_data(ssl_, session_context_index, &context);
395 auto const start = std::chrono::system_clock::now();
397 ERR_clear_error();
399 int rc;
400 while ((rc = SSL_connect(ssl_)) < 0) {
402 auto const now = std::chrono::system_clock::now();
404 CHECK(now < (start + timeout)) << "starttls timed out";
406 auto time_left = std::chrono::duration_cast<std::chrono::milliseconds>(
407 (start + timeout) - now);
409 int n_get_err;
410 switch (n_get_err = SSL_get_error(ssl_, rc)) {
411 case SSL_ERROR_WANT_READ:
412 CHECK(POSIX::input_ready(fd_in, time_left))
413 << "starttls timed out on input_ready";
414 ERR_clear_error();
415 continue; // try SSL_accept again
417 case SSL_ERROR_WANT_WRITE:
418 CHECK(POSIX::output_ready(fd_out, time_left))
419 << "starttls timed out on output_ready";
420 ERR_clear_error();
421 continue; // try SSL_accept again
423 case SSL_ERROR_SYSCALL:
424 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
425 [[fallthrough]];
427 default: ssl_error(n_get_err);
431 if (SSL_get_verify_result(ssl_) == X509_V_OK) {
432 LOG(INFO) << "server certificate verified";
433 verified_ = true;
435 char const* const peername = SSL_get0_peername(ssl_);
436 if (peername != nullptr) {
437 // Name checks were in scope and matched the peername
438 verified_peername_ = peername;
439 LOG(INFO) << "verified peername: " << peername;
441 else {
442 LOG(INFO) << "no verified peername";
445 EVP_PKEY* mspki = nullptr;
446 int depth = SSL_get0_dane_authority(ssl_, nullptr, &mspki);
447 if (depth >= 0) {
449 uint8_t usage, selector, mtype;
450 const unsigned char* certdata;
451 size_t certdata_len;
453 SSL_get0_dane_tlsa(ssl_, &usage, &selector, &mtype, &certdata,
454 &certdata_len);
456 LOG(INFO) << "DANE TLSA " << unsigned(usage) << " " << unsigned(selector)
457 << " " << unsigned(mtype) << " [" << bin2hexstring(certdata, 6)
458 << "...] "
459 << ((mspki != nullptr) ? "TA public key verified certificate"
460 : depth ? "matched TA certificate"
461 : "matched EE certificate")
462 << " at depth " << depth;
464 else if (usable_TLSA_records && enforce_dane) {
465 LOG(WARNING) << "enforcing DANE; failing starttls";
466 return false;
469 else {
470 LOG(WARNING) << "server certificate failed to verify";
473 return true;
476 bool TLS::starttls_server(fs::path config_path,
477 int fd_in,
478 int fd_out,
479 std::chrono::milliseconds timeout)
481 SSL_load_error_strings();
482 SSL_library_init();
484 CHECK(RAND_status()); // Be sure the PRNG has been seeded with enough data.
486 auto const method = CHECK_NOTNULL(SSLv23_server_method());
488 auto const bio =
489 CHECK_NOTNULL(BIO_new_mem_buf(const_cast<char*>(ffdhe4096), -1));
491 auto const certs = osutil::list_directory(config_path, Config::cert_fn_re);
493 CHECK_GE(certs.size(), 1) << "no server cert(s) found";
495 for (auto const& cert : certs) {
497 auto ctx = CHECK_NOTNULL(SSL_CTX_new(method));
498 std::vector<Domain> names;
500 SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
501 SSL_CTX_clear_options(ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
503 // Allow any old and crufty protocol version.
504 // if (FLAGS_support_all_tls_versions) {
505 // CHECK_GT(SSL_CTX_set_min_proto_version(ctx, 0), 0)
506 // << "unable to set min proto version";
507 // }
509 CHECK_GT(SSL_CTX_dane_enable(ctx), 0)
510 << "unable to enable DANE on SSL context";
512 // you'd think if it's the default, you'd not have to call this
513 CHECK_EQ(SSL_CTX_set_default_verify_paths(ctx), 1);
515 CHECK_GT(SSL_CTX_use_certificate_chain_file(ctx, cert.string().c_str()), 0)
516 << "Can't load certificate chain file " << cert;
518 auto const key = fs::path(cert).replace_extension(Config::key_ext);
520 if (fs::exists(key)) {
522 CHECK_GT(SSL_CTX_use_PrivateKey_file(ctx, key.string().c_str(),
523 SSL_FILETYPE_PEM),
525 << "Can't load private key file " << key;
527 CHECK(SSL_CTX_check_private_key(ctx))
528 << "SSL_CTX_check_private_key failed for " << key;
531 SSL_CTX_set_verify_depth(ctx, Config::cert_verify_depth + 1);
533 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
534 verify_callback);
536 // SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback);
537 // same as:
538 SSL_CTX_callback_ctrl(
539 ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,
540 reinterpret_cast<void (*)()>(ssl_servername_callback));
542 // SSL_CTX_set_tlsext_servername_arg(ctx, &cert_ctx_);
543 // same as:
544 SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0,
545 reinterpret_cast<void*>(&cert_ctx_));
547 // SSL_CTX_dane_set_flags(ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
549 //.......................................................
551 auto const x509 = CHECK_NOTNULL(SSL_CTX_get0_certificate(ctx));
553 X509_NAME* subj = X509_get_subject_name(x509);
555 int lastpos = -1;
556 for (;;) {
557 lastpos = X509_NAME_get_index_by_NID(subj, NID_commonName, lastpos);
558 if (lastpos == -1)
559 break;
560 auto e = X509_NAME_get_entry(subj, lastpos);
561 ASN1_STRING* d = X509_NAME_ENTRY_get_data(e);
562 auto str = ASN1_STRING_get0_data(d);
563 // LOG(INFO) << "server cert found for " << str;
564 names.emplace_back(reinterpret_cast<const char*>(str));
567 // auto ext_stack = X509_get0_extensions(x509);
568 // for (int i = 0; i < sk_X509_EXTENSION_num(ext_stack); i++) {
569 // X509_EXTENSION* ext
570 // = CHECK_NOTNULL(sk_X509_EXTENSION_value(ext_stack, i));
571 // ASN1_OBJECT* asn1_obj =
572 // CHECK_NOTNULL(X509_EXTENSION_get_object(ext)); unsigned nid =
573 // OBJ_obj2nid(asn1_obj); if (nid == NID_undef) {
574 // // no lookup found for the provided OID so nid came back as
575 // undefined. char extname[256]; OBJ_obj2txt(extname, sizeof(extname),
576 // asn1_obj, 1); LOG(INFO) << "undef extension name is " << extname;
577 // } else {
578 // // the OID translated to a NID which implies that the OID has a
579 // known
580 // // sn/ln
581 // const char* c_ext_name = CHECK_NOTNULL(OBJ_nid2ln(nid));
582 // LOG(INFO) << "extension " << c_ext_name;
583 // }
584 // }
586 auto subject_alt_names = static_cast<GENERAL_NAMES*>(
587 X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr));
589 for (int i = 0; i < sk_GENERAL_NAME_num(subject_alt_names); ++i) {
591 GENERAL_NAME* gen = sk_GENERAL_NAME_value(subject_alt_names, i);
593 if (gen->type == GEN_URI || gen->type == GEN_EMAIL) {
594 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
596 std::string str(
597 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
598 ASN1_STRING_length(asn1_str));
600 LOG(INFO) << "email or uri alt name " << str;
602 else if (gen->type == GEN_DNS) {
603 ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
605 std::string str(
606 reinterpret_cast<char const*>(ASN1_STRING_get0_data(asn1_str)),
607 ASN1_STRING_length(asn1_str));
609 if (find(begin(names), end(names), str) == end(names)) {
610 // LOG(INFO) << "additional name found " << str;
611 names.emplace_back(str);
613 else {
614 // LOG(INFO) << "duplicate name " << str << " ignored";
617 else if (gen->type == GEN_IPADD) {
618 unsigned char* p = gen->d.ip->data;
619 if (gen->d.ip->length == 4) {
620 auto const ip = fmt::format(FMT_STRING("{:d}.{:d}.{:d}.{:d}"), p[0],
621 p[1], p[2], p[3]);
622 LOG(INFO) << "alt name IP4 address " << ip;
623 names.emplace_back(ip);
625 else if (gen->d.ip->length == 16) {
626 // FIXME!
627 LOG(ERROR) << "IPv6 not implemented";
629 else {
630 LOG(ERROR) << "unknown IP type";
633 else {
634 LOG(ERROR) << "unknown alt name type";
638 GENERAL_NAMES_free(subject_alt_names);
640 //.......................................................
642 cert_ctx_.emplace_back(ctx, names);
645 BIO_free(bio);
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();
661 ERR_clear_error();
663 int rc;
664 while ((rc = SSL_accept(ssl_)) < 0) {
666 auto const now = std::chrono::system_clock::now();
668 CHECK(now < (start + timeout)) << "starttls timed out";
670 auto const time_left =
671 std::chrono::duration_cast<std::chrono::milliseconds>(
672 (start + timeout) - now);
674 int n_get_err;
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";
679 ERR_clear_error();
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";
685 ERR_clear_error();
686 continue; // try SSL_accept again
688 case SSL_ERROR_SYSCALL:
689 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
690 [[fallthrough]];
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";
699 verified_ = true;
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;
707 else {
708 LOG(INFO) << "no verified peername";
711 EVP_PKEY* mspki = nullptr;
712 int depth = SSL_get0_dane_authority(ssl_, nullptr, &mspki);
713 if (depth >= 0) {
715 uint8_t usage, selector, mtype;
716 const unsigned char* certdata;
717 size_t certdata_len;
719 SSL_get0_dane_tlsa(ssl_, &usage, &selector, &mtype, &certdata,
720 &certdata_len);
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;
730 else {
731 LOG(WARNING) << "client certificate failed to verify";
734 else {
735 // LOG(INFO) << "no client certificate offerd to us";
738 return true;
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_);
747 if (c) {
748 int alg_bits;
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" : ""));
755 return "";
758 std::streamsize TLS::io_tls_(char const* fn,
759 std::function<int(SSL*, void*, int)> io_fnc,
760 char* s,
761 std::streamsize n,
762 std::chrono::milliseconds timeout,
763 bool& t_o)
765 auto const start = std::chrono::system_clock::now();
766 auto const end_time = start + timeout;
768 ERR_clear_error();
770 int n_ret;
771 while ((n_ret = io_fnc(ssl_, static_cast<void*>(s), static_cast<int>(n)))
772 < 0) {
773 auto const now = std::chrono::system_clock::now();
774 if (now > end_time) {
775 LOG(WARNING) << fn << " timed out";
776 t_o = true;
777 return static_cast<std::streamsize>(-1);
780 auto const time_left
781 = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - now);
783 int n_get_err;
784 switch (n_get_err = SSL_get_error(ssl_, n_ret)) {
785 case SSL_ERROR_WANT_READ: {
786 int fd = SSL_get_rfd(ssl_);
787 CHECK_NE(-1, fd);
788 read_hook_();
789 if (POSIX::input_ready(fd, time_left)) {
790 ERR_clear_error();
791 continue; // try io_fnc again
793 LOG(WARNING) << fn << " timed out";
794 t_o = true;
795 return static_cast<std::streamsize>(-1);
798 case SSL_ERROR_WANT_WRITE: {
799 int fd = SSL_get_wfd(ssl_);
800 CHECK_NE(-1, fd);
801 if (POSIX::output_ready(fd, time_left)) {
802 ERR_clear_error();
803 continue; // try io_fnc again
805 LOG(WARNING) << fn << " timed out";
806 t_o = true;
807 return static_cast<std::streamsize>(-1);
810 case SSL_ERROR_SYSCALL:
811 LOG(WARNING) << "errno == " << errno << ": " << strerror(errno);
812 [[fallthrough]];
814 default: ssl_error(n_get_err);
818 // The strange (and never before seen) case of 0 return.
819 if (0 == n_ret) {
820 int n_get_err;
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";
827 break;
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;
839 switch (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";
848 break;
849 case SSL_ERROR_SSL: LOG(WARNING) << "SSL_ERROR_SSL"; break;
851 unsigned long er;
852 while (0 != (er = ERR_get_error()))
853 LOG(WARNING) << ERR_error_string(er, nullptr);
854 LOG(FATAL) << "fatal OpenSSL error";