aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cmd/credentials.h303
-rw-r--r--src/cmd/tls_client.cpp4
-rw-r--r--src/cmd/tls_proxy.cpp154
-rw-r--r--src/cmd/tls_server.cpp53
4 files changed, 119 insertions, 395 deletions
diff --git a/src/cmd/credentials.h b/src/cmd/credentials.h
index c67fe22e3..b5ee701f3 100644
--- a/src/cmd/credentials.h
+++ b/src/cmd/credentials.h
@@ -27,277 +27,134 @@ inline bool value_exists(const std::vector<std::string>& vec,
return false;
}
-class Credentials_Manager_Simple : public Botan::Credentials_Manager
+class Basic_Credentials_Manager : public Credentials_Manager
{
public:
- Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) :
- rng(rng)
+ Basic_Credentials_Manager()
{
- try
- {
- m_certstores.push_back(new Botan::Certificate_Store_In_Memory("/usr/share/ca-certificates"));
- }
- catch(...) {}
+
}
- std::string srp_identifier(const std::string& type,
- const std::string& hostname)
+ Basic_Credentials_Manager(RandomNumberGenerator& rng,
+ const std::string& server_crt,
+ const std::string& server_key)
{
- if(type == "tls-client" && hostname == "srp-host")
- return "user";
- return "";
+ Certificate_Info cert;
+
+ cert.key.reset(PKCS8::load_key(server_key, rng));
+
+ DataSource_Stream in(server_crt);
+ while(!in.end_of_data())
+ {
+ try
+ {
+ cert.certs.push_back(X509_Certificate(in));
+ }
+ catch(std::exception& e)
+ {
+
+ }
+ }
+
+ // TODO: attempt to validate chain ourselves
+
+ m_creds.push_back(cert);
}
- bool attempt_srp(const std::string& type,
- const std::string& hostname)
+ void load_certstores()
{
- if(hostname == "srp-host" && (type == "tls-client" || type == "tls-server"))
- return true;
- return false;
+ try
+ {
+ // TODO: make path configurable
+ const std::vector<std::string> paths = { "/usr/share/ca-certificates" };
+
+ for(auto&& path : paths)
+ {
+ std::shared_ptr<Certificate_Store> cs(new Certificate_Store_In_Memory(path));
+ m_certstores.push_back(cs);
+ }
+ }
+ catch(std::exception& e)
+ {
+ //std::cout << e.what() << "\n";
+ }
}
std::vector<Botan::Certificate_Store*>
trusted_certificate_authorities(const std::string& type,
const std::string& /*hostname*/)
{
- // don't ask for client cert
+ std::vector<Botan::Certificate_Store*> v;
+
+ // don't ask for client certs
if(type == "tls-server")
- return std::vector<Botan::Certificate_Store*>();
+ return v;
- return m_certstores;
+ for(auto&& cs : m_certstores)
+ v.push_back(cs.get());
+
+ return v;
}
void verify_certificate_chain(
const std::string& type,
const std::string& purported_hostname,
- const std::vector<Botan::X509_Certificate>& cert_chain)
+ const std::vector<X509_Certificate>& cert_chain)
{
try
{
- Botan::Credentials_Manager::verify_certificate_chain(type,
- purported_hostname,
- cert_chain);
+ Credentials_Manager::verify_certificate_chain(type,
+ purported_hostname,
+ cert_chain);
}
catch(std::exception& e)
{
- std::cout << "Certificate verification failed - " << e.what() << " - but will ignore\n";
+ std::cout << e.what() << "\n";
+ //throw;
}
}
- std::string srp_password(const std::string& type,
- const std::string& hostname,
- const std::string& identifier)
- {
- if(type == "tls-client" && hostname == "srp-host" && identifier == "user")
- return "password";
-
- return "";
- }
-
- bool srp_verifier(const std::string& /*type*/,
- const std::string& context,
- const std::string& identifier,
- std::string& group_id,
- Botan::BigInt& verifier,
- std::vector<Botan::byte>& salt,
- bool generate_fake_on_unknown)
+ std::vector<X509_Certificate> cert_chain(
+ const std::vector<std::string>& algos,
+ const std::string& type,
+ const std::string& hostname)
{
-
- std::string pass = srp_password("tls-client", context, identifier);
- if(pass == "")
+ for(auto&& i : m_creds)
{
- if(!generate_fake_on_unknown)
- return false;
-
- pass.resize(16);
- rng.randomize(reinterpret_cast<byte*>(&pass[0]), pass.size());
- }
-
- group_id = "modp/srp/2048";
-
- salt.resize(16);
- rng.randomize(&salt[0], salt.size());
+ if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end())
+ continue;
- verifier = Botan::generate_srp6_verifier(identifier,
- pass,
- salt,
- group_id,
- "SHA-1");
+ if(hostname != "" && !i.certs[0].matches_dns_name(hostname))
+ continue;
- return true;
- }
-
- std::string psk_identity_hint(const std::string&,
- const std::string&)
- {
- return "";
- }
-
- std::string psk_identity(const std::string&, const std::string&,
- const std::string& identity_hint)
- {
- std::cout << "Server sent PSK identity_hint " << identity_hint << "\n";
- return "Client_identity";
- }
-
- Botan::SymmetricKey psk(const std::string& type, const std::string& context,
- const std::string& identity)
- {
- if(type == "tls-server" && context == "session-ticket")
- {
- if(session_ticket_key.length() == 0)
- session_ticket_key = Botan::SymmetricKey(rng, 32);
- return session_ticket_key;
+ return i.certs;
}
- if(identity == "Client_identity")
- return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527");
- if(identity == "lloyd")
- return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630");
-
- throw Botan::Internal_Error("No PSK set for " + identity);
+ return std::vector<X509_Certificate>();
}
- std::pair<Botan::X509_Certificate,Botan::Private_Key*>
- load_or_make_cert(const std::string& hostname,
- const std::string& key_type,
- Botan::RandomNumberGenerator& rng)
+ Private_Key* private_key_for(const X509_Certificate& cert,
+ const std::string& /*type*/,
+ const std::string& /*context*/)
{
- using namespace Botan;
-
- const std::string key_fsname_prefix = hostname + "." + key_type + ".";
- const std::string key_file_name = key_fsname_prefix + "key";
- const std::string cert_file_name = key_fsname_prefix + "crt";
-
- try
+ for(auto&& i : m_creds)
{
- X509_Certificate cert(cert_file_name);
- Private_Key* key = PKCS8::load_key(key_file_name, rng);
-
- //std::cout << "Loaded existing key/cert from " << cert_file_name << " and " << key_file_name << "\n";
-
- return std::make_pair(cert, key);
+ if(cert == i.certs[0])
+ return i.key.get();
}
- catch(...) {}
-
- // Failed. Instead, make a new one
-
- std::cout << "Creating new certificate for identifier '" << hostname << "'\n";
-
- X509_Cert_Options opts;
-
- opts.common_name = hostname;
- opts.country = "US";
- opts.email = "root@" + hostname;
- opts.dns = hostname;
-
- std::unique_ptr<Private_Key> key;
- if(key_type == "rsa")
- key.reset(new RSA_PrivateKey(rng, 1024));
- else if(key_type == "dsa")
- key.reset(new DSA_PrivateKey(rng, DL_Group("dsa/jce/1024")));
- else if(key_type == "ecdsa")
- key.reset(new ECDSA_PrivateKey(rng, EC_Group("secp256r1")));
- else
- throw std::runtime_error("Don't know what to do about key type '" + key_type + "'");
-
- X509_Certificate cert =
- X509::create_self_signed_cert(opts, *key, "SHA-1", rng);
-
- // Now save both
- std::cout << "Saving new " << key_type << " key to " << key_file_name << "\n";
- std::ofstream key_file(key_file_name.c_str());
- key_file << PKCS8::PEM_encode(*key, rng, "");
- key_file.close();
-
- std::cout << "Saving new " << key_type << " cert to " << key_file_name << "\n";
- std::ofstream cert_file(cert_file_name.c_str());
- cert_file << cert.PEM_encode() << "\n";
- cert_file.close();
-
- return std::make_pair(cert, key.release());
+ return nullptr;
}
- std::vector<Botan::X509_Certificate> cert_chain(
- const std::vector<std::string>& cert_key_types,
- const std::string& type,
- const std::string& context)
+ private:
+ struct Certificate_Info
{
- using namespace Botan;
-
std::vector<X509_Certificate> certs;
+ std::shared_ptr<Private_Key> key;
+ };
- try
- {
- if(type == "tls-server")
- {
- const std::string hostname = (context == "" ? "localhost" : context);
-
- if(hostname == "nosuchname")
- return std::vector<Botan::X509_Certificate>();
-
- for(auto i : certs_and_keys)
- {
- if(hostname != "" && !i.first.matches_dns_name(hostname))
- continue;
-
- if(!value_exists(cert_key_types, i.second->algo_name()))
- continue;
-
- certs.push_back(i.first);
- }
-
- if(!certs.empty())
- return certs;
-
- std::string key_name = "";
-
- if(value_exists(cert_key_types, "RSA"))
- key_name = "rsa";
- else if(value_exists(cert_key_types, "DSA"))
- key_name = "dsa";
- else if(value_exists(cert_key_types, "ECDSA"))
- key_name = "ecdsa";
-
- std::pair<X509_Certificate, Private_Key*> cert_and_key =
- load_or_make_cert(hostname, key_name, rng);
-
- certs_and_keys[cert_and_key.first] = cert_and_key.second;
- certs.push_back(cert_and_key.first);
- }
- else if(type == "tls-client")
- {
- X509_Certificate cert("user-rsa.crt");
- Private_Key* key = PKCS8::load_key("user-rsa.key", rng);
-
- certs_and_keys[cert] = key;
- certs.push_back(cert);
- }
- }
- catch(std::exception& e)
- {
- std::cout << e.what() << "\n";
- }
-
- return certs;
- }
-
- Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
- const std::string& /*type*/,
- const std::string& /*context*/)
- {
- return certs_and_keys[cert];
- }
-
- private:
- Botan::RandomNumberGenerator& rng;
-
- Botan::SymmetricKey session_ticket_key;
-
- std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
-
- std::vector<Botan::Certificate_Store*> m_certstores;
+ std::vector<Certificate_Info> m_creds;
+ std::vector<std::shared_ptr<Certificate_Store>> m_certstores;
};
#endif
diff --git a/src/cmd/tls_client.cpp b/src/cmd/tls_client.cpp
index d10c46ba4..74607469f 100644
--- a/src/cmd/tls_client.cpp
+++ b/src/cmd/tls_client.cpp
@@ -6,7 +6,7 @@
#include "apps.h"
-#if defined(BOTAN_HAS_TLS)
+#if defined(BOTAN_HAS_TLS) && !defined(BOTAN_TARGET_OS_IS_WINDOWS)
#include <botan/tls_client.h>
#include <botan/pkcs8.h>
#include <botan/hex.h>
@@ -161,7 +161,7 @@ int tls_client(int argc, char* argv[])
TLS::Session_Manager_In_Memory session_manager(rng);
#endif
- Credentials_Manager_Simple creds(rng);
+ Basic_Credentials_Manager creds;
std::string host = argv[1];
u32bit port = argc >= 3 ? Botan::to_u32bit(argv[2]) : 443;
diff --git a/src/cmd/tls_proxy.cpp b/src/cmd/tls_proxy.cpp
index 867e2280e..94ce28636 100644
--- a/src/cmd/tls_proxy.cpp
+++ b/src/cmd/tls_proxy.cpp
@@ -29,23 +29,25 @@
#include <botan/tls_session_manager_sqlite.h>
#endif
+#include "credentials.h"
+
using boost::asio::ip::tcp;
namespace Botan {
namespace {
-void log_exception(const char* where, const std::exception& e)
+inline void log_exception(const char* where, const std::exception& e)
{
std::cout << where << ' ' << e.what() << std::endl;
}
-void log_error(const char* where, const boost::system::error_code& error)
+inline void log_error(const char* where, const boost::system::error_code& error)
{
std::cout << where << ' ' << error.message() << std::endl;
}
-void log_binary_message(const char* where, const byte buf[], size_t buf_len)
+inline void log_binary_message(const char* where, const byte buf[], size_t buf_len)
{
//std::cout << where << ' ' << hex_encode(buf, buf_len) << std::endl;
}
@@ -167,12 +169,13 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio
}
m_p2s.clear();
- tls_proxy_write_to_server(nullptr, 0); // initiate another write if needed
+ proxy_write_to_server(nullptr, 0); // initiate another write if needed
}
void tls_client_write_to_proxy(const byte buf[], size_t buf_len)
{
- tls_proxy_write_to_server(buf, buf_len);
+ // Immediately bounce message to server
+ proxy_write_to_server(buf, buf_len);
}
void tls_proxy_write_to_client(const byte buf[], size_t buf_len)
@@ -197,7 +200,7 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio
}
}
- void tls_proxy_write_to_server(const byte buf[], size_t buf_len)
+ void proxy_write_to_server(const byte buf[], size_t buf_len)
{
if(buf_len > 0)
m_p2s_pending.insert(m_p2s_pending.end(), buf, buf + buf_len);
@@ -271,11 +274,9 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio
log_error("Server connection", ec);
return;
}
- //std::cout << "Connected to " << endpoint->host_name() << ' '
- //<< endpoint->service_name() << "\n";
- tls_proxy_write_to_server(nullptr, 0);
server_read(boost::system::error_code(), 0); // start read loop
+ proxy_write_to_server(nullptr, 0);
});
return true;
}
@@ -392,139 +393,6 @@ size_t choose_thread_count()
return 2;
}
-class Proxy_Credentials_Manager : public Credentials_Manager
- {
- public:
- Proxy_Credentials_Manager(RandomNumberGenerator& rng,
- const std::string& server_crt,
- const std::string& server_key)
- {
- try
- {
- Certificate_Info cert;
-
-
- try
- {
- cert.key.reset(PKCS8::load_key(server_key, rng));
- }
- catch(std::exception& e)
- {
- log_exception("Loading server key", e);
- throw; // fatal
- }
-
- try
- {
- DataSource_Stream in(server_crt);
- while(!in.end_of_data())
- cert.certs.push_back(X509_Certificate(in));
- }
- catch(std::exception& e)
- {
- log_exception("Loading certs", e);
- }
-
- // TODO: attempt to validate chain ourselves
-
- m_creds.push_back(cert);
- }
- catch(std::exception& e)
- {
- log_exception("Loading server key", e);
- throw; // fatal
- }
-
- try
- {
- // TODO: make path configurable
- std::shared_ptr<Certificate_Store> cs(new Certificate_Store_In_Memory("/usr/share/ca-certificates"));
- m_certstores.push_back(cs);
- }
- catch(std::exception& e)
- {
- log_exception("Loading CA certs", e);
- //throw; // not fatal
- }
- }
-
- std::vector<Botan::Certificate_Store*>
- trusted_certificate_authorities(const std::string& type,
- const std::string& /*hostname*/)
- {
- std::vector<Botan::Certificate_Store*> v;
-
- // don't ask for client certs
- if(type == "tls-server")
- return v;
-
- for(auto&& cs : m_certstores)
- v.push_back(cs.get());
-
- return v;
- }
-
- void verify_certificate_chain(
- const std::string& type,
- const std::string& purported_hostname,
- const std::vector<X509_Certificate>& cert_chain)
- {
- try
- {
- Credentials_Manager::verify_certificate_chain(type,
- purported_hostname,
- cert_chain);
- }
- catch(std::exception& e)
- {
- std::cout << "Certificate validation failure: " << e.what() << "\n";
- throw;
- }
- }
-
- std::vector<X509_Certificate> cert_chain(
- const std::vector<std::string>& algos,
- const std::string& type,
- const std::string& hostname)
- {
- for(auto&& i : m_creds)
- {
- if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end())
- continue;
-
- if(hostname != "" && !i.certs[0].matches_dns_name(hostname))
- continue;
-
- return i.certs;
- }
-
- return std::vector<X509_Certificate>();
- }
-
- Private_Key* private_key_for(const X509_Certificate& cert,
- const std::string& /*type*/,
- const std::string& /*context*/)
- {
- for(auto&& i : m_creds)
- {
- if(cert == i.certs[0])
- return i.key.get();
- }
-
- return nullptr;
- }
-
- private:
- struct Certificate_Info
- {
- std::vector<X509_Certificate> certs;
- std::shared_ptr<Private_Key> key;
- };
-
- std::vector<Certificate_Info> m_creds;
- std::vector<std::shared_ptr<Certificate_Store>> m_certstores;
- };
-
int tls_proxy(int argc, char* argv[])
{
if(argc != 6)
@@ -543,7 +411,7 @@ int tls_proxy(int argc, char* argv[])
const size_t num_threads = choose_thread_count(); // make configurable
AutoSeeded_RNG rng;
- Proxy_Credentials_Manager creds(rng, server_crt, server_key);
+ Basic_Credentials_Manager creds(rng, server_crt, server_key);
TLS::Policy policy; // TODO: Read policy from text file
diff --git a/src/cmd/tls_server.cpp b/src/cmd/tls_server.cpp
index ae51ff55b..fc8499be1 100644
--- a/src/cmd/tls_server.cpp
+++ b/src/cmd/tls_server.cpp
@@ -1,4 +1,5 @@
/*
+* TLS echo server using BSD sockets
* (C) 2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -6,7 +7,7 @@
#include "apps.h"
-#if defined(BOTAN_HAS_TLS)
+#if defined(BOTAN_HAS_TLS) && !defined(BOTAN_TARGET_OS_IS_WINDOWS)
#include <botan/tls_server.h>
#include <botan/hex.h>
@@ -38,9 +39,9 @@ using namespace std::placeholders;
namespace {
-int make_server_socket(const std::string& transport, u16bit port)
+int make_server_socket(bool is_tcp, u16bit port)
{
- int type = (transport == "tcp") ? SOCK_STREAM : SOCK_DGRAM;
+ const int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM;
int fd = ::socket(PF_INET, type, 0);
if(fd == -1)
@@ -60,7 +61,7 @@ int make_server_socket(const std::string& transport, u16bit port)
throw std::runtime_error("server bind failed");
}
- if(transport != "udp")
+ if(is_tcp)
{
if(::listen(fd, 100) != 0)
{
@@ -98,22 +99,19 @@ void dgram_socket_write(int sockfd, const byte buf[], size_t length)
void stream_socket_write(int sockfd, const byte buf[], size_t length)
{
- size_t offset = 0;
-
while(length)
{
- ssize_t sent = ::send(sockfd, (const char*)buf + offset,
- length, MSG_NOSIGNAL);
+ ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);
if(sent == -1)
{
if(errno == EINTR)
sent = 0;
else
- throw std::runtime_error("Socket::write: Socket write failed");
+ throw std::runtime_error("Socket write failed");
}
- offset += sent;
+ buf += sent;
length -= sent;
}
}
@@ -125,13 +123,18 @@ void alert_received(TLS::Alert alert, const byte[], size_t)
int tls_server(int argc, char* argv[])
{
- int port = 4433;
- std::string transport = "tcp";
+ if(argc != 4 && argc != 5)
+ {
+ std::cout << "Usage: " << argv[0] << " server.crt server.key port [tcp|udp]\n";
+ return 1;
+ }
+
+ const std::string server_crt = argv[1];
+ const std::string server_key = argv[2];
+ const int port = to_u32bit(argv[3]);
+ const std::string transport = (argc >= 5) ? argv[4] : "tcp";
- if(argc >= 2)
- port = to_u32bit(argv[1]);
- if(argc >= 3)
- transport = argv[2];
+ const bool is_tcp = (transport == "tcp");
try
{
@@ -141,7 +144,7 @@ int tls_server(int argc, char* argv[])
TLS::Session_Manager_In_Memory session_manager(rng);
- Credentials_Manager_Simple creds(rng);
+ Basic_Credentials_Manager creds(rng, server_crt, server_key);
/*
* These are the protocols we advertise to the client, but the
@@ -152,7 +155,7 @@ int tls_server(int argc, char* argv[])
std::cout << "Listening for new connections on " << transport << " port " << port << "\n";
- int server_fd = make_server_socket(transport, port);
+ int server_fd = make_server_socket(is_tcp, port);
while(true)
{
@@ -160,7 +163,7 @@ int tls_server(int argc, char* argv[])
{
int fd;
- if(transport == "tcp")
+ if(is_tcp)
fd = ::accept(server_fd, nullptr, nullptr);
else
{
@@ -179,16 +182,12 @@ int tls_server(int argc, char* argv[])
std::cout << "New connection received\n";
- auto socket_write =
- (transport == "tcp") ?
- std::bind(stream_socket_write, fd, _1, _2) :
- std::bind(dgram_socket_write, fd, _1, _2);
+ auto socket_write = is_tcp ? std::bind(stream_socket_write, fd, _1, _2) :
+ std::bind(dgram_socket_write, fd, _1, _2);
std::string s;
std::list<std::string> pending_output;
- pending_output.push_back("Welcome to the best echo server evar\n");
-
auto proc_fn = [&](const byte input[], size_t input_len)
{
for(size_t i = 0; i != input_len; ++i)
@@ -212,7 +211,7 @@ int tls_server(int argc, char* argv[])
policy,
rng,
protocols,
- (transport != "tcp"));
+ !is_tcp);
while(!server.is_closed())
{
@@ -244,7 +243,7 @@ int tls_server(int argc, char* argv[])
}
}
- if(transport == "tcp")
+ if(is_tcp)
::close(fd);
}