diff options
author | Jack Lloyd <[email protected]> | 2017-12-23 07:54:12 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-12-23 07:57:20 -0500 |
commit | 2d719e51266408bd08f14880d2399c671cbc8a7b (patch) | |
tree | 5d323a2a7119c218e6b683052ae6f8ab3470a356 | |
parent | f40f25f17a2965ca03d42a17599ced5d5f6d46ab (diff) |
Convert TLS server to new style TLS interface (GH #1350)
-rw-r--r-- | src/cli/tls_server.cpp | 149 |
1 files changed, 71 insertions, 78 deletions
diff --git a/src/cli/tls_server.cpp b/src/cli/tls_server.cpp index 6c0b049a2..44c69bf17 100644 --- a/src/cli/tls_server.cpp +++ b/src/cli/tls_server.cpp @@ -23,7 +23,7 @@ namespace Botan_CLI { -class TLS_Server final : public Command +class TLS_Server final : public Command, public Botan::TLS::Callbacks { public: TLS_Server() : Command("tls_server cert key --port=443 --type=tcp --policy= --dump-traces=") @@ -49,7 +49,7 @@ class TLS_Server final : public Command throw CLI_Usage_Error("Invalid transport type '" + transport + "' for TLS"); } - const bool is_tcp = (transport == "tcp"); + m_is_tcp = (transport == "tcp"); std::unique_ptr<Botan::TLS::Policy> policy; const std::string policy_file = get_arg("policy"); @@ -73,23 +73,15 @@ class TLS_Server final : public Command Basic_Credentials_Manager creds(rng(), server_crt, server_key); - auto protocol_chooser = [](const std::vector<std::string>&) -> std::string - { - // we ignore whatever the client sends here - return "echo/1.0"; - }; - output() << "Listening for new connections on " << transport << " port " << port << std::endl; - int server_fd = make_server_socket(is_tcp, port); + int server_fd = make_server_socket(port); while(true) { - int fd; - - if(is_tcp) + if(m_is_tcp) { - fd = ::accept(server_fd, nullptr, nullptr); + m_socket = ::accept(server_fd, nullptr, nullptr); } else { @@ -105,43 +97,16 @@ class TLS_Server final : public Command { throw CLI_Error("Could not connect UDP socket"); } - fd = server_fd; + m_socket = server_fd; } - using namespace std::placeholders; - - auto socket_write = is_tcp ? - std::bind(&TLS_Server::stream_socket_write, this, fd, _1, _2) : - std::bind(&TLS_Server::dgram_socket_write, this, fd, _1, _2); - - std::string s; - std::list<std::string> pending_output; - - auto proc_fn = [&](const uint8_t input[], size_t input_len) - { - for(size_t i = 0; i != input_len; ++i) - { - const char c = static_cast<char>(input[i]); - s += c; - if(c == '\n') - { - pending_output.push_back(s); - s.clear(); - } - } - }; - Botan::TLS::Server server( - socket_write, - proc_fn, - std::bind(&TLS_Server::alert_received, this, _1, _2, _3), - std::bind(&TLS_Server::handshake_complete, this, _1), + *this, session_manager, creds, *policy, rng(), - protocol_chooser, - !is_tcp); + m_is_tcp == false); std::unique_ptr<std::ostream> dump_stream; @@ -160,7 +125,7 @@ class TLS_Server final : public Command try { uint8_t buf[4 * 1024] = { 0 }; - ssize_t got = ::read(fd, buf, sizeof(buf)); + ssize_t got = ::read(m_socket, buf, sizeof(buf)); if(got == -1) { @@ -181,10 +146,10 @@ class TLS_Server final : public Command server.received_data(buf, got); - while(server.is_active() && !pending_output.empty()) + while(server.is_active() && !m_pending_output.empty()) { - std::string output = pending_output.front(); - pending_output.pop_front(); + std::string output = m_pending_output.front(); + m_pending_output.pop_front(); server.send(output); if(output == "quit\n") @@ -196,9 +161,10 @@ class TLS_Server final : public Command catch(std::exception& e) { error_output() << "Connection problem: " << e.what() << std::endl; - if(is_tcp) + if(m_is_tcp) { - ::close(fd); + ::close(m_socket); + m_socket = -1; } } } @@ -208,16 +174,17 @@ class TLS_Server final : public Command error_output() << "Connection failed: " << e.what() << "\n"; } - if(is_tcp) + if(m_is_tcp) { - ::close(fd); + ::close(m_socket); + m_socket = -1; } } } private: - int make_server_socket(bool is_tcp, uint16_t port) + int make_server_socket(uint16_t port) { - const int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM; + const int type = m_is_tcp ? SOCK_STREAM : SOCK_DGRAM; int fd = ::socket(PF_INET, type, 0); if(fd == -1) @@ -239,7 +206,7 @@ class TLS_Server final : public Command throw CLI_Error("server bind failed"); } - if(is_tcp) + if(m_is_tcp) { if(::listen(fd, 100) != 0) { @@ -250,7 +217,7 @@ class TLS_Server final : public Command return fd; } - bool handshake_complete(const Botan::TLS::Session& session) + bool tls_session_established(const Botan::TLS::Session& session) override { output() << "Handshake complete, " << session.version().to_string() << " using " << session.ciphersuite().to_string() << std::endl; @@ -268,48 +235,74 @@ class TLS_Server final : public Command return true; } - void dgram_socket_write(int sockfd, const uint8_t buf[], size_t length) + void tls_record_received(uint64_t, const uint8_t input[], size_t input_len) override { - ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL); - - if(sent == -1) + for(size_t i = 0; i != input_len; ++i) { - error_output() << "Error writing to socket - " << std::strerror(errno) << std::endl; - } - else if(sent != static_cast<ssize_t>(length)) - { - error_output() << "Packet of length " << length << " truncated to " << sent << std::endl; + const char c = static_cast<char>(input[i]); + m_line_buf += c; + if(c == '\n') + { + m_pending_output.push_back(m_line_buf); + m_line_buf.clear(); + } } - } + }; - void stream_socket_write(int sockfd, const uint8_t buf[], size_t length) + void tls_emit_data(const uint8_t buf[], size_t length) override { - while(length) + if(m_is_tcp) { - ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL); + ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL); if(sent == -1) { - if(errno == EINTR) - { - sent = 0; - } - else + error_output() << "Error writing to socket - " << std::strerror(errno) << std::endl; + } + else if(sent != static_cast<ssize_t>(length)) + { + error_output() << "Packet of length " << length << " truncated to " << sent << std::endl; + } + } + else + { + while(length) + { + ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL); + + if(sent == -1) { - throw CLI_Error("Socket write failed"); + if(errno == EINTR) + { + sent = 0; + } + else + { + throw CLI_Error("Socket write failed"); + } } - } - buf += sent; - length -= sent; + buf += sent; + length -= sent; + } } } - void alert_received(Botan::TLS::Alert alert, const uint8_t[], size_t) + void tls_alert(Botan::TLS::Alert alert) override { output() << "Alert: " << alert.type_string() << std::endl; } + std::string tls_server_choose_app_protocol(const std::vector<std::string>&) override + { + // we ignore whatever the client sends here + return "echo/0.1"; + } + + int m_socket = -1; + bool m_is_tcp = false; + std::string m_line_buf; + std::list<std::string> m_pending_output; }; BOTAN_REGISTER_COMMAND("tls_server", TLS_Server); |