diff options
author | lloyd <lloyd@randombit.net> | 2011-12-28 01:05:29 +0000 |
---|---|---|
committer | lloyd <lloyd@randombit.net> | 2011-12-28 01:05:29 +0000 |
commit | e2f2809a421c8e9d60217cefdf2503a887e582ca (patch) | |
tree | e724983ce161813c8578599b368d0b612a3a7409 /src | |
parent | 065187289ea2c47f507b99a429dcf62a19d48f30 (diff) |
Partial bits of the server side of client auth. Incomplete.
Pass a session manager to TLS_Client's constructor. Currently unused.
Add time-based session expiration to the in-memory session cache.
Diffstat (limited to 'src')
-rw-r--r-- | src/tls/cert_req.cpp | 17 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 4 | ||||
-rw-r--r-- | src/tls/tls_client.h | 6 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 22 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 50 | ||||
-rw-r--r-- | src/tls/tls_session_state.cpp | 27 |
6 files changed, 87 insertions, 39 deletions
diff --git a/src/tls/cert_req.cpp b/src/tls/cert_req.cpp index 74398a59f..cc77509df 100644 --- a/src/tls/cert_req.cpp +++ b/src/tls/cert_req.cpp @@ -19,14 +19,19 @@ namespace Botan { */ Certificate_Req::Certificate_Req(Record_Writer& writer, HandshakeHash& hash, - const std::vector<X509_Certificate>& certs) + const std::vector<X509_Certificate>& ca_certs, + const std::vector<Certificate_Type>& cert_types) { - for(size_t i = 0; i != certs.size(); ++i) - names.push_back(certs[i].subject_dn()); + for(size_t i = 0; i != ca_certs.size(); ++i) + names.push_back(ca_certs[i].subject_dn()); - // FIXME: should be able to choose what to ask for - types.push_back(RSA_CERT); - types.push_back(DSS_CERT); + if(cert_types.empty()) // default is RSA/DSA is OK + { + types.push_back(RSA_CERT); + types.push_back(DSS_CERT); + } + else + types = cert_types; send(writer, hash); } diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index 5ffe65bf4..dfa5c57df 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -19,11 +19,13 @@ namespace Botan { */ TLS_Client::TLS_Client(std::tr1::function<void (const byte[], size_t)> output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng) : TLS_Channel(output_fn, proc_fn), policy(policy), - rng(rng) + rng(rng), + session_manager(session_manager) { writer.set_version(policy.pref_version()); diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h index 063323c8b..295eb0364 100644 --- a/src/tls/tls_client.h +++ b/src/tls/tls_client.h @@ -9,6 +9,7 @@ #define BOTAN_TLS_CLIENT_H__ #include <botan/tls_channel.h> +#include <botan/tls_session_state.h> #include <vector> namespace Botan { @@ -24,6 +25,7 @@ class BOTAN_DLL TLS_Client : public TLS_Channel */ TLS_Client(std::tr1::function<void (const byte[], size_t)> socket_output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng); @@ -32,10 +34,12 @@ class BOTAN_DLL TLS_Client : public TLS_Channel ~TLS_Client(); private: - void process_handshake_msg(Handshake_Type, const MemoryRegion<byte>&); + void process_handshake_msg(Handshake_Type type, + const MemoryRegion<byte>& contents); const TLS_Policy& policy; RandomNumberGenerator& rng; + TLS_Session_Manager& session_manager; std::vector<std::pair<X509_Certificate, Private_Key*> > certs; }; diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 480864f55..4d172fbcf 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -129,6 +129,9 @@ class Certificate : public HandshakeMessage Handshake_Type type() const { return CERTIFICATE; } std::vector<X509_Certificate> cert_chain() const { return certs; } + size_t count() const { return certs.size(); } + bool empty() const { return certs.empty(); } + Certificate(Record_Writer&, const std::vector<X509_Certificate>&, HandshakeHash&); Certificate(const MemoryRegion<byte>& buf) { deserialize(buf); } @@ -149,12 +152,11 @@ class Certificate_Req : public HandshakeMessage std::vector<Certificate_Type> acceptable_types() const { return types; } std::vector<X509_DN> acceptable_CAs() const { return names; } - /* TODO - Certificate_Req(Record_Writer&, HandshakeHash&, - const X509_Certificate&); - */ - Certificate_Req(Record_Writer&, HandshakeHash&, - const std::vector<X509_Certificate>&); + Certificate_Req(Record_Writer& writer, + HandshakeHash& hash, + const std::vector<X509_Certificate>& allowed_cas, + const std::vector<Certificate_Type>& types = + std::vector<Certificate_Type>()); Certificate_Req(const MemoryRegion<byte>& buf) { deserialize(buf); } private: @@ -173,11 +175,13 @@ class Certificate_Verify : public HandshakeMessage public: Handshake_Type type() const { return CERTIFICATE_VERIFY; } - bool verify(const X509_Certificate&, HandshakeHash&); + bool verify(const X509_Certificate& cert, + HandshakeHash& hash); Certificate_Verify(RandomNumberGenerator& rng, - Record_Writer&, HandshakeHash&, - const Private_Key*); + Record_Writer& writer, + HandshakeHash& hash, + const Private_Key* key); Certificate_Verify(const MemoryRegion<byte>& buf) { deserialize(buf); } private: diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 80f5492cf..e0fdb6ea7 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -149,7 +149,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, if(resuming) { // resume session - state->server_hello = new Server_Hello( rng, writer, @@ -180,11 +179,15 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, } else // new session { - state->server_hello = new Server_Hello(rng, writer, - policy, cert_chain, - *(state->client_hello), - rng.random_vec(32), - state->version, state->hash); + state->server_hello = new Server_Hello( + rng, + writer, + policy, + cert_chain, + *(state->client_hello), + rng.random_vec(32), + state->version, + state->hash); state->suite = CipherSuite(state->server_hello->ciphersuite()); @@ -218,26 +221,39 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->server_hello->random(), state->hash); - state->server_hello_done = new Server_Hello_Done(writer, state->hash); - if(policy.require_client_auth()) { - throw Internal_Error("Client auth not implemented"); - // FIXME: send client auth request here + // FIXME: figure out the allowed CAs/cert types + + state->cert_req = new Certificate_Req(writer, state->hash, + std::vector<X509_Certificate>()); + state->set_expected_next(CERTIFICATE); } - else - state->set_expected_next(CLIENT_KEX); + + /* + * If the client doesn't have a cert they want to use they are + * allowed to send either an empty cert message or proceed + * directly to the client key exchange. + */ + state->set_expected_next(CLIENT_KEX); + + state->server_hello_done = new Server_Hello_Done(writer, state->hash); } } else if(type == CERTIFICATE) { + state->client_certs = new Certificate(contents); + + if(state->client_certs->count() > 1) + throw TLS_Exception(CERTIFICATE_UNKNOWN, + "Client sent more than one certificate"); + state->set_expected_next(CLIENT_KEX); - // FIXME: process this } else if(type == CLIENT_KEX) { - if(state->received_handshake_msg(CERTIFICATE)) + if(state->received_handshake_msg(CERTIFICATE) && !state->client_certs->empty()) state->set_expected_next(CERTIFICATE_VERIFY); else state->set_expected_next(HANDSHAKE_CCS); @@ -255,7 +271,11 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, } else if(type == CERTIFICATE_VERIFY) { - // FIXME: process this + state->client_verify = new Certificate_Verify(contents); + + std::vector<X509_Certificate> client_certs = state->client_certs->cert_chain(); + + const bool ok = state->client_verify->verify(client_certs[0] state->set_expected_next(HANDSHAKE_CCS); } diff --git a/src/tls/tls_session_state.cpp b/src/tls/tls_session_state.cpp index 05d5d2dbb..47c7d8f5f 100644 --- a/src/tls/tls_session_state.cpp +++ b/src/tls/tls_session_state.cpp @@ -9,7 +9,7 @@ #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/asn1_str.h> -#include <ctime> +#include <botan/time.h> namespace Botan { @@ -22,7 +22,7 @@ TLS_Session_Params::TLS_Session_Params(const MemoryRegion<byte>& session_id, const X509_Certificate* cert, const std::string& sni_hostname, const std::string& srp_identity) : - session_start_time(time(0)), + session_start_time(system_time()), session_id(session_id), master_secret(master_secret), version(version), @@ -86,16 +86,25 @@ bool TLS_Session_Manager_In_Memory::find(const MemoryVector<byte>& session_id, TLS_Session_Params& params, Connection_Side side) { - std::map<std::string, TLS_Session_Params>::const_iterator i = + std::map<std::string, TLS_Session_Params>::iterator i = sessions.find(hex_encode(session_id)); - if(i != sessions.end() && i->second.connection_side == side) + if(i == sessions.end()) + return false; + + // session has expired, remove it + const u64bit now = system_time(); + if(i->second.session_start_time + session_lifetime >= now) { - params = i->second; - return true; + sessions.erase(i); + return false; } - return false; + if(i->second.connection_side != side) + return false; + + params = i->second; + return true; } void TLS_Session_Manager_In_Memory::prohibit_resumption(const MemoryVector<byte>& session_id) @@ -111,6 +120,10 @@ void TLS_Session_Manager_In_Memory::save(const TLS_Session_Params& session_data) { if(max_sessions != 0) { + /* + This removes randomly based on ordering of session ids. + Instead, remove oldest first? + */ while(sessions.size() >= max_sessions) sessions.erase(sessions.begin()); } |