diff options
Diffstat (limited to 'doc/examples/tls_server.cpp')
-rw-r--r-- | doc/examples/tls_server.cpp | 200 |
1 files changed, 165 insertions, 35 deletions
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp index 153b26d04..727f4c333 100644 --- a/doc/examples/tls_server.cpp +++ b/doc/examples/tls_server.cpp @@ -1,33 +1,140 @@ #include <botan/botan.h> #include <botan/tls_server.h> +#include <botan/hex.h> #include <botan/rsa.h> #include <botan/dsa.h> #include <botan/x509self.h> +#include <botan/secqueue.h> #include "socket.h" +#include "credentials.h" using namespace Botan; +using namespace std::placeholders; + #include <stdio.h> #include <string> #include <iostream> #include <memory> -class Server_TLS_Policy : public TLS_Policy +class Blocking_TLS_Server { public: - bool check_cert(const std::vector<X509_Certificate>& certs) const + Blocking_TLS_Server(std::function<void (const byte[], size_t)> output_fn, + std::function<size_t (byte[], size_t)> input_fn, + std::vector<std::string>& protocols, + TLS::Session_Manager& sessions, + Credentials_Manager& creds, + TLS::Policy& policy, + RandomNumberGenerator& rng) : + input_fn(input_fn), + server( + output_fn, + std::bind(&Blocking_TLS_Server::reader_fn, std::ref(*this), _1, _2, _3), + std::bind(&Blocking_TLS_Server::handshake_complete, std::ref(*this), _1), + sessions, + creds, + policy, + rng, + protocols), + exit(false) + { + read_loop(); + } + + bool handshake_complete(const TLS::Session& session) + { + std::cout << "Handshake complete: " + << session.version().to_string() << " " + << session.ciphersuite().to_string() << " " + << "SessionID: " << hex_encode(session.session_id()) << "\n"; + + if(session.srp_identifier() != "") + std::cout << "SRP identifier: " << session.srp_identifier() << "\n"; + + if(server.next_protocol() != "") + std::cout << "Next protocol: " << server.next_protocol() << "\n"; + + /* + std::vector<X509_Certificate> peer_certs = session.peer_certs(); + if(peer_certs.size()) + std::cout << peer_certs[0].to_string(); + */ + + return true; + } + + size_t read(byte buf[], size_t buf_len) { - for(size_t i = 0; i != certs.size(); ++i) + size_t got = read_queue.read(buf, buf_len); + + while(!exit && !got) { - std::cout << certs[i].to_string(); + read_loop(TLS::TLS_HEADER_SIZE); + got = read_queue.read(buf, buf_len); } - std::cout << "Warning: not checking cert signatures\n"; + return got; + } - return true; + void write(const byte buf[], size_t buf_len) + { + server.send(buf, buf_len); + } + + void close() { server.close(); } + + bool is_active() const { return server.is_active(); } + + TLS::Server& underlying() { return server; } + private: + void read_loop(size_t init_desired = 0) + { + size_t desired = init_desired; + + byte buf[4096]; + while(!exit && (!server.is_active() || desired)) + { + const size_t asking = std::max(sizeof(buf), std::min(desired, static_cast<size_t>(1))); + + const size_t socket_got = input_fn(&buf[0], asking); + + if(socket_got == 0) // eof? + { + close(); + printf("got eof on socket\n"); + exit = true; + } + + desired = server.received_data(&buf[0], socket_got); + } + } + + void reader_fn(const byte buf[], size_t buf_len, TLS::Alert alert) + { + if(alert.is_valid()) + { + printf("Alert %s\n", alert.type_string().c_str()); + //exit = true; + } + + 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"); + + read_queue.write(buf, buf_len); } + + std::function<size_t (byte[], size_t)> input_fn; + TLS::Server server; + SecureQueue read_queue; + bool exit; }; int main(int argc, char* argv[]) @@ -40,59 +147,82 @@ int main(int argc, char* argv[]) try { LibraryInitializer botan_init; - SocketInitializer socket_init; + //SocketInitializer socket_init; AutoSeeded_RNG rng; - //RSA_PrivateKey key(rng, 1024); - DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024")); + Server_Socket listener(port); - X509_Cert_Options options( - "localhost/US/Syn Ack Labs/Mathematical Munitions Dept"); + TLS::Policy policy; - X509_Certificate cert = - X509::create_self_signed_cert(options, key, "SHA-1", rng); + TLS::Session_Manager_In_Memory sessions; - Server_Socket listener(port); + Credentials_Manager_Simple creds(rng); - Server_TLS_Policy policy; + std::vector<std::string> protocols; + + /* + * These are the protocols we advertise to the client, but the + * client will send back whatever it actually plans on talking, + * which may or may not take into account what we advertise. + */ + protocols.push_back("echo/1.0"); + protocols.push_back("echo/1.1"); 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"); - TLS_Server tls( - std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2), - std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2), - policy, - rng, - cert, - key); + Blocking_TLS_Server tls( + std::bind(&Socket::write, std::ref(sock), _1, _2), + std::bind(&Socket::read, std::ref(sock), _1, _2, true), + protocols, + sessions, + creds, + policy, + rng); - std::string hostname = tls.requested_hostname(); + const char* msg = "Welcome to the best echo server evar\n"; + tls.write((const Botan::byte*)msg, strlen(msg)); - if(hostname != "") - printf("Client requested host '%s'\n", hostname.c_str()); + std::string line; - printf("Writing some text\n"); + while(tls.is_active()) + { + byte b; + size_t got = tls.read(&b, 1); - char msg[] = "Foo\nBar\nBaz\nQuux\n"; - tls.write((const Botan::byte*)msg, strlen(msg)); + if(got == 0) + break; + + line += (char)b; + if(b == '\n') + { + //std::cout << line; + + tls.write(reinterpret_cast<const byte*>(line.data()), line.size()); - printf("Now trying a read...\n"); + if(line == "quit\n") + { + tls.close(); + break; + } - char buf[1024] = { 0 }; - u32bit got = tls.read((Botan::byte*)buf, sizeof(buf)-1); - printf("%d: '%s'\n", got, buf); + if(line == "reneg\n") + tls.underlying().renegotiate(false); + else if(line == "RENEG\n") + tls.underlying().renegotiate(true); - tls.close(); + line.clear(); + } + } } - catch(std::exception& e) { printf("%s\n", e.what()); } + catch(std::exception& e) { printf("Connection problem: %s\n", e.what()); } } } catch(std::exception& e) |