diff options
author | lloyd <[email protected]> | 2012-01-06 20:52:34 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-06 20:52:34 +0000 |
commit | 8ca42a2f4243954ccfe304fb465cc66c2698b42a (patch) | |
tree | e51022f5549fc2a7fe1a0660186bbc135c3fb2c5 | |
parent | d9796c5610e0deb63cbf0a52d374c3c5e755c7e4 (diff) |
Various example updates. Add a new TLS server example that uses asio
-rw-r--r-- | doc/examples/asio_tls_server.cpp | 266 | ||||
-rw-r--r-- | doc/examples/self_sig.cpp | 6 | ||||
-rw-r--r-- | doc/examples/tls_client.cpp | 22 | ||||
-rw-r--r-- | doc/examples/tls_server.cpp | 28 |
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()); } } |