aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-12-28 01:05:29 +0000
committerlloyd <[email protected]>2011-12-28 01:05:29 +0000
commite2f2809a421c8e9d60217cefdf2503a887e582ca (patch)
treee724983ce161813c8578599b368d0b612a3a7409
parent065187289ea2c47f507b99a429dcf62a19d48f30 (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.
-rw-r--r--src/tls/cert_req.cpp17
-rw-r--r--src/tls/tls_client.cpp4
-rw-r--r--src/tls/tls_client.h6
-rw-r--r--src/tls/tls_messages.h22
-rw-r--r--src/tls/tls_server.cpp50
-rw-r--r--src/tls/tls_session_state.cpp27
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());
}