aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-06 20:52:34 +0000
committerlloyd <[email protected]>2012-01-06 20:52:34 +0000
commit8ca42a2f4243954ccfe304fb465cc66c2698b42a (patch)
treee51022f5549fc2a7fe1a0660186bbc135c3fb2c5
parentd9796c5610e0deb63cbf0a52d374c3c5e755c7e4 (diff)
Various example updates. Add a new TLS server example that uses asio
-rw-r--r--doc/examples/asio_tls_server.cpp266
-rw-r--r--doc/examples/self_sig.cpp6
-rw-r--r--doc/examples/tls_client.cpp22
-rw-r--r--doc/examples/tls_server.cpp28
4 files changed, 296 insertions, 26 deletions
diff --git a/doc/examples/asio_tls_server.cpp b/doc/examples/asio_tls_server.cpp
new file mode 100644
index 000000000..9a1c3cefd
--- /dev/null
+++ b/doc/examples/asio_tls_server.cpp
@@ -0,0 +1,266 @@
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <asio.hpp>
+
+#include <botan/tls_server.h>
+#include <botan/x509cert.h>
+#include <botan/pkcs8.h>
+#include <botan/auto_rng.h>
+#include <botan/init.h>
+
+using Botan::byte;
+using asio::ip::tcp;
+
+class tls_server_session : public boost::enable_shared_from_this<tls_server_session>
+ {
+ public:
+ typedef boost::shared_ptr<tls_server_session> pointer;
+
+ static pointer create(asio::io_service& io_service,
+ Botan::TLS_Session_Manager& session_manager,
+ Botan::Credentials_Manager& credentials,
+ Botan::TLS_Policy& policy,
+ Botan::RandomNumberGenerator& rng)
+ {
+ return pointer(
+ new tls_server_session(
+ io_service,
+ session_manager,
+ credentials,
+ policy,
+ rng)
+ );
+ }
+
+ tcp::socket& socket()
+ {
+ return m_socket;
+ }
+
+ void start()
+ {
+ m_socket.async_read_some(
+ asio::buffer(m_read_buf, sizeof(m_read_buf)),
+ boost::bind(&tls_server_session::handle_read, shared_from_this(),
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred));
+ }
+
+ private:
+ tls_server_session(asio::io_service& io_service,
+ Botan::TLS_Session_Manager& session_manager,
+ Botan::Credentials_Manager& credentials,
+ Botan::TLS_Policy& policy,
+ Botan::RandomNumberGenerator& rng) :
+ m_socket(io_service),
+ m_tls(boost::bind(&tls_server_session::tls_output_wanted, this, _1, _2),
+ boost::bind(&tls_server_session::tls_data_recv, this, _1, _2, _3),
+ boost::bind(&tls_server_session::tls_handshake_complete, this, _1),
+ session_manager,
+ credentials,
+ policy,
+ rng)
+ {
+ }
+
+ void handle_read(const asio::error_code& error,
+ size_t bytes_transferred)
+ {
+ if(!error)
+ {
+ m_tls.received_data(m_read_buf, bytes_transferred);
+
+ m_socket.async_read_some(
+ asio::buffer(m_read_buf, sizeof(m_read_buf)),
+ boost::bind(&tls_server_session::handle_read, shared_from_this(),
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred));
+ }
+ else
+ printf("Error in read: %s\n", error.message().c_str());
+ }
+
+ void handle_write(const asio::error_code& error)
+ {
+ if(!error)
+ {
+
+ }
+ else
+ printf("Error in write: %s\n", error.message().c_str());
+ }
+
+ void tls_output_wanted(const byte buf[], size_t buf_len)
+ {
+ memcpy(&m_write_buf[0], buf, buf_len);
+
+ asio::async_write(m_socket,
+ asio::buffer(m_write_buf, buf_len),
+ boost::bind(&tls_server_session::handle_write, this,
+ asio::placeholders::error));
+
+ }
+
+ void tls_data_recv(const byte buf[], size_t buf_len, Botan::u16bit alert_info)
+ {
+ if(buf_len == 0 && alert_info != Botan::NULL_ALERT)
+ printf("Alert: %d\n", alert_info);
+
+ printf("Got %d bytes: ", (int)buf_len);
+ for(size_t i = 0; i != buf_len; ++i)
+ {
+ if(isprint(buf[i]))
+ printf("%c", buf[i]);
+ }
+ printf("\n");
+ }
+
+ bool tls_handshake_complete(const Botan::TLS_Session& session)
+ {
+ printf("handshake complete\n");
+ return true;
+ }
+
+ tcp::socket m_socket;
+
+ Botan::TLS_Server m_tls;
+
+ unsigned char m_read_buf[Botan::MAX_TLS_RECORD_SIZE];
+ unsigned char m_write_buf[Botan::MAX_TLS_RECORD_SIZE];
+ };
+
+class Credentials_Manager_Simple : public Botan::Credentials_Manager
+ {
+ public:
+ Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {}
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context)
+ {
+ const std::string hostname = (context == "" ? "localhost" : context);
+
+ Botan::X509_Certificate cert(hostname + ".crt");
+ Botan::Private_Key* key = Botan::PKCS8::load_key(hostname + ".key", rng);
+
+ certs_and_keys[cert] = key;
+
+ std::vector<Botan::X509_Certificate> certs;
+ certs.push_back(cert);
+ 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;
+ std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
+ };
+
+class Server_TLS_Policy : public Botan::TLS_Policy
+ {
+ public:
+ //bool require_client_auth() const { return true; }
+
+ bool check_cert(const std::vector<Botan::X509_Certificate>& certs) const
+ {
+ for(size_t i = 0; i != certs.size(); ++i)
+ {
+ std::cout << certs[i].to_string();
+ }
+
+ std::cout << "Warning: not checking cert signatures\n";
+
+ return true;
+ }
+ };
+
+class tls_server
+ {
+ public:
+ typedef tls_server_session session;
+
+ tls_server(asio::io_service& io_service, unsigned short port) :
+ m_acceptor(io_service, tcp::endpoint(tcp::v4(), port)),
+ m_creds(m_rng)
+ {
+ session::pointer new_session = make_session();
+
+ m_acceptor.async_accept(
+ new_session->socket(),
+ boost::bind(
+ &tls_server::handle_accept,
+ this,
+ new_session,
+ asio::placeholders::error)
+ );
+ }
+
+ private:
+ session::pointer make_session()
+ {
+ return session::create(
+ m_acceptor.io_service(),
+ m_session_manager,
+ m_creds,
+ m_policy,
+ m_rng
+ );
+ }
+
+ void handle_accept(session::pointer new_session,
+ const asio::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+
+ new_session = make_session();
+
+ m_acceptor.async_accept(
+ new_session->socket(),
+ boost::bind(
+ &tls_server::handle_accept,
+ this,
+ new_session,
+ asio::placeholders::error)
+ );
+ }
+ }
+
+ tcp::acceptor m_acceptor;
+
+ Botan::AutoSeeded_RNG m_rng;
+ Botan::TLS_Session_Manager_In_Memory m_session_manager;
+ Server_TLS_Policy m_policy;
+ Credentials_Manager_Simple m_creds;
+ };
+
+int main()
+ {
+ try
+ {
+ Botan::LibraryInitializer init;
+ asio::io_service io_service;
+
+ unsigned short port = 4433;
+ tls_server server(io_service, port);
+ io_service.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+ }
+
diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp
index 522fad677..7cb159db9 100644
--- a/doc/examples/self_sig.cpp
+++ b/doc/examples/self_sig.cpp
@@ -35,10 +35,10 @@ int main(int argc, char* argv[])
{
AutoSeeded_RNG rng;
- //RSA_PrivateKey key(rng, 2048);
- DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
+ RSA_PrivateKey key(rng, 2048);
+ //DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
- DSA_PrivateKey key(rng, group);
+ //DSA_PrivateKey key(rng, group);
std::ofstream priv_key("private.pem");
priv_key << PKCS8::PEM_encode(key, rng, argv[1]);
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index ee6bcad22..a9d6650c2 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -115,7 +115,9 @@ void process_data(const byte buf[], size_t buf_size, u16bit alert_info)
}
for(size_t i = 0; i != buf_size; ++i)
+ {
printf("%c", buf[i]);
+ }
}
std::string protocol_chooser(const std::vector<std::string>& protocols)
@@ -141,13 +143,10 @@ void doit(RandomNumberGenerator& rng,
creds,
policy,
rng,
- host,
- protocol_chooser);
+ host);
fd_set readfds;
- bool version_reported = false;
-
while(true)
{
FD_ZERO(&readfds);
@@ -159,13 +158,15 @@ void doit(RandomNumberGenerator& rng,
if(client.is_closed())
break;
- if(client.is_active() && !version_reported)
- printf("Negotiated version %04X\n", client.protocol_version());
-
if(FD_ISSET(sockfd, &readfds))
{
- byte buf[1024] = { 0 };
- ssize_t got = read(sockfd, buf, sizeof(buf));
+ byte buf[64] = { 0 };
+
+ size_t to_read = rand() % sizeof(buf);
+ if(to_read == 0)
+ to_read = 1;
+
+ ssize_t got = read(sockfd, buf, to_read);
if(got == 0)
{
@@ -180,7 +181,8 @@ void doit(RandomNumberGenerator& rng,
//printf("socket read %d\n", got);
- client.received_data(buf, got);
+ const size_t needed = client.received_data(buf, got);
+ printf("socket - got %d bytes, need %d\n", got, needed);
}
else if(FD_ISSET(STDIN_FILENO, &readfds))
{
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index 297a7b922..143ba8b64 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -11,6 +11,8 @@
using namespace Botan;
+using namespace std::tr1::placeholders;
+
#include <stdio.h>
#include <string>
#include <iostream>
@@ -28,16 +30,10 @@ class Credentials_Manager_Simple : public Credentials_Manager
{
const std::string hostname = (context == "" ? "localhost" : context);
- //RSA_PrivateKey key(rng, 1024);
- DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024"));
-
- X509_Cert_Options options(
- hostname + "/US/Botan Library/Test Server");
-
- X509_Certificate cert =
- X509::create_self_signed_cert(options, key, "SHA-1", rng);
+ X509_Certificate cert(hostname + ".crt");
+ Private_Key* key = PKCS8::load_key(hostname + ".key", rng);
- certs_and_keys[cert] = PKCS8::copy_key(key, rng);
+ certs_and_keys[cert] = key;
std::vector<X509_Certificate> certs;
certs.push_back(cert);
@@ -72,6 +68,7 @@ class Blocking_TLS_Server
public:
Blocking_TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn,
std::tr1::function<size_t (byte[], size_t)> input_fn,
+ std::vector<std::string>& protocols,
TLS_Session_Manager& sessions,
Credentials_Manager& creds,
TLS_Policy& policy,
@@ -164,7 +161,7 @@ class Blocking_TLS_Server
class Server_TLS_Policy : public TLS_Policy
{
public:
- bool require_client_auth() const { return true; }
+ //bool require_client_auth() const { return true; }
bool check_cert(const std::vector<X509_Certificate>& certs) const
{
@@ -201,18 +198,23 @@ int main(int argc, char* argv[])
Credentials_Manager_Simple creds(rng);
+ std::vector<std::string> protocols;
+ protocols.push_back("spdy/2");
+ protocols.push_back("http/1.0");
+
while(true)
{
try {
printf("Listening for new connection on port %d\n", port);
- Socket* sock = listener.accept();
+ std::auto_ptr<Socket> sock(listener.accept());
printf("Got new connection\n");
Blocking_TLS_Server tls(
std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2, true),
+ protocols,
sessions,
creds,
policy,
@@ -234,6 +236,8 @@ int main(int argc, char* argv[])
line += (char)b;
if(b == '\n')
{
+ //std::cout << line;
+
tls.write(reinterpret_cast<const byte*>(line.data()), line.size());
if(line == "quit\n")
@@ -248,8 +252,6 @@ int main(int argc, char* argv[])
line.clear();
}
}
-
- delete sock;
}
catch(std::exception& e) { printf("Connection problem: %s\n", e.what()); }
}