aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-04 17:11:40 +0000
committerlloyd <[email protected]>2012-01-04 17:11:40 +0000
commit268b336843cf71f8fcb8c68ed67a622c71e3232a (patch)
tree1e6da6458693a5c8040edeb05bc3eef40c93cddf /src
parentc926d5e919245f25d1730f4f4d565f691647e99f (diff)
Split hello.cpp into c_hello.cpp and s_hello.cpp
Add support for NPN on the server side. Server is initialized with the list of protocols it wants to offer, once the handshake completes the client requested protocol is available via a getter.
Diffstat (limited to 'src')
-rw-r--r--src/tls/c_hello.cpp (renamed from src/tls/hello.cpp)180
-rw-r--r--src/tls/info.txt17
-rw-r--r--src/tls/s_hello.cpp201
-rw-r--r--src/tls/tls_extensions.cpp4
-rw-r--r--src/tls/tls_messages.h22
-rw-r--r--src/tls/tls_server.cpp49
-rw-r--r--src/tls/tls_server.h19
-rw-r--r--src/tls/tls_session_manager.cpp2
8 files changed, 271 insertions, 223 deletions
diff --git a/src/tls/hello.cpp b/src/tls/c_hello.cpp
index 8c13cb8f6..3164f30ee 100644
--- a/src/tls/hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -1,5 +1,5 @@
;/*
-* TLS Hello Messages
+* TLS Hello Request and Client Hello Messages
* (C) 2004-2011 Jack Lloyd
*
* Released under the terms of the Botan license
@@ -287,182 +287,4 @@ bool Client_Hello::offered_suite(u16bit ciphersuite) const
return false;
}
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(Record_Writer& writer,
- TLS_Handshake_Hash& hash,
- const TLS_Policy& policy,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
- const std::vector<X509_Certificate>& certs,
- const Client_Hello& c_hello,
- Version_Code ver) :
- s_version(ver),
- m_session_id(rng.random_vec(32)),
- s_random(rng.random_vec(32)),
- m_fragment_size(c_hello.fragment_size()),
- m_secure_renegotiation(client_has_secure_renegotiation),
- m_renegotiation_info(reneg_info),
- m_next_protocol(false)
- {
- bool have_rsa = false, have_dsa = false;
-
- for(size_t i = 0; i != certs.size(); ++i)
- {
- Public_Key* key = certs[i].subject_public_key();
- if(key->algo_name() == "RSA")
- have_rsa = true;
-
- if(key->algo_name() == "DSA")
- have_dsa = true;
- }
-
- suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa, false);
-
- if(suite == 0)
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "Can't agree on a ciphersuite with client");
-
- comp_method = policy.choose_compression(c_hello.compression_methods());
-
- send(writer, hash);
- }
-
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(Record_Writer& writer,
- TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
- const MemoryRegion<byte>& session_id,
- size_t fragment_size,
- u16bit ciphersuite,
- byte compression,
- Version_Code ver) :
- s_version(ver),
- m_session_id(session_id),
- s_random(rng.random_vec(32)),
- suite(ciphersuite),
- comp_method(compression),
- m_fragment_size(fragment_size),
- m_secure_renegotiation(client_has_secure_renegotiation),
- m_renegotiation_info(reneg_info),
- m_next_protocol(false)
- {
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello message
-*/
-MemoryVector<byte> Server_Hello::serialize() const
- {
- MemoryVector<byte> buf;
-
- buf.push_back(static_cast<byte>(s_version >> 8));
- buf.push_back(static_cast<byte>(s_version ));
- buf += s_random;
-
- append_tls_length_value(buf, m_session_id, 1);
-
- buf.push_back(get_byte(0, suite));
- buf.push_back(get_byte(1, suite));
-
- buf.push_back(comp_method);
-
- TLS_Extensions extensions;
-
- if(m_secure_renegotiation)
- extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
-
- if(m_fragment_size != 0)
- extensions.push_back(new Maximum_Fragment_Length(m_fragment_size));
-
- if(m_next_protocol)
- extensions.push_back(new Next_Protocol_Negotiation(m_next_protocols));
-
- buf += extensions.serialize();
-
- return buf;
- }
-
-/*
-* Deserialize a Server Hello message
-*/
-void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
- {
- m_secure_renegotiation = false;
- m_next_protocol = false;
-
- if(buf.size() < 38)
- throw Decoding_Error("Server_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- s_version = static_cast<Version_Code>(reader.get_u16bit());
-
- if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11)
- {
- throw TLS_Exception(PROTOCOL_VERSION,
- "Server_Hello: Unsupported server version");
- }
-
- s_random = reader.get_fixed<byte>(32);
-
- m_session_id = reader.get_range<byte>(1, 0, 32);
-
- suite = reader.get_u16bit();
-
- comp_method = reader.get_byte();
-
- TLS_Extensions extensions(reader);
-
- for(size_t i = 0; i != extensions.count(); ++i)
- {
- TLS_Extension* extn = extensions.at(i);
-
- if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
- {
- // checked by TLS_Client / TLS_Server as they know the handshake state
- m_secure_renegotiation = true;
- m_renegotiation_info = reneg->renegotiation_info();
- }
- else if(Next_Protocol_Negotiation* npn = dynamic_cast<Next_Protocol_Negotiation*>(extn))
- {
- m_next_protocols = npn->protocols();
- m_next_protocol = true;
- }
- }
- }
-
-/*
-* Create a new Server Hello Done message
-*/
-Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
- TLS_Handshake_Hash& hash)
- {
- send(writer, hash);
- }
-
-/*
-* Serialize a Server Hello Done message
-*/
-MemoryVector<byte> Server_Hello_Done::serialize() const
- {
- return MemoryVector<byte>();
- }
-
-/*
-* Deserialize a Server Hello Done message
-*/
-void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
- }
-
}
diff --git a/src/tls/info.txt b/src/tls/info.txt
index 6654c3b80..9473b0ae2 100644
--- a/src/tls/info.txt
+++ b/src/tls/info.txt
@@ -22,34 +22,35 @@ tls_suites.h
<header:internal>
tls_alerts.h
-tls_handshake_hash.h
tls_extensions.h
+tls_handshake_hash.h
+tls_handshake_state.h
tls_messages.h
tls_reader.h
tls_session_key.h
-tls_handshake_state.h
</header:internal>
<source>
+c_hello.cpp
c_kex.cpp
cert_req.cpp
cert_ver.cpp
finished.cpp
-tls_handshake_hash.cpp
-tls_extensions.cpp
-hello.cpp
+next_protocol.cpp
rec_read.cpp
rec_wri.cpp
+s_hello.cpp
s_kex.cpp
-next_protocol.cpp
tls_channel.cpp
tls_client.cpp
+tls_extensions.cpp
+tls_handshake_hash.cpp
+tls_handshake_state.cpp
tls_policy.cpp
tls_server.cpp
-tls_session_key.cpp
tls_session.cpp
+tls_session_key.cpp
tls_session_manager.cpp
-tls_handshake_state.cpp
tls_suites.cpp
</source>
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp
new file mode 100644
index 000000000..5ffb1e7d4
--- /dev/null
+++ b/src/tls/s_hello.cpp
@@ -0,0 +1,201 @@
+;/*
+* TLS Server Hello and Server Hello Done
+* (C) 2004-2011 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_session_key.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/tls_record.h>
+#include <botan/internal/stl_util.h>
+
+namespace Botan {
+
+/*
+* Create a new Server Hello message
+*/
+Server_Hello::Server_Hello(Record_Writer& writer,
+ TLS_Handshake_Hash& hash,
+ Version_Code version,
+ const Client_Hello& c_hello,
+ const std::vector<X509_Certificate>& certs,
+ const TLS_Policy& policy,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng) :
+ s_version(version),
+ m_session_id(rng.random_vec(32)),
+ s_random(rng.random_vec(32)),
+ m_fragment_size(c_hello.fragment_size()),
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(client_has_npn),
+ m_next_protocols(next_protocols)
+ {
+ bool have_rsa = false, have_dsa = false;
+
+ for(size_t i = 0; i != certs.size(); ++i)
+ {
+ Public_Key* key = certs[i].subject_public_key();
+ if(key->algo_name() == "RSA")
+ have_rsa = true;
+
+ if(key->algo_name() == "DSA")
+ have_dsa = true;
+ }
+
+ suite = policy.choose_suite(c_hello.ciphersuites(), have_rsa, have_dsa, false);
+
+ if(suite == 0)
+ throw TLS_Exception(HANDSHAKE_FAILURE,
+ "Can't agree on a ciphersuite with client");
+
+ comp_method = policy.choose_compression(c_hello.compression_methods());
+
+ send(writer, hash);
+ }
+
+/*
+* Create a new Server Hello message
+*/
+Server_Hello::Server_Hello(Record_Writer& writer,
+ TLS_Handshake_Hash& hash,
+ const MemoryRegion<byte>& session_id,
+ Version_Code ver,
+ u16bit ciphersuite,
+ byte compression,
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng) :
+ s_version(ver),
+ m_session_id(session_id),
+ s_random(rng.random_vec(32)),
+ suite(ciphersuite),
+ comp_method(compression),
+ m_fragment_size(max_fragment_size),
+ m_secure_renegotiation(client_has_secure_renegotiation),
+ m_renegotiation_info(reneg_info),
+ m_next_protocol(client_has_npn),
+ m_next_protocols(next_protocols)
+ {
+ send(writer, hash);
+ }
+
+/*
+* Serialize a Server Hello message
+*/
+MemoryVector<byte> Server_Hello::serialize() const
+ {
+ MemoryVector<byte> buf;
+
+ buf.push_back(static_cast<byte>(s_version >> 8));
+ buf.push_back(static_cast<byte>(s_version ));
+ buf += s_random;
+
+ append_tls_length_value(buf, m_session_id, 1);
+
+ buf.push_back(get_byte(0, suite));
+ buf.push_back(get_byte(1, suite));
+
+ buf.push_back(comp_method);
+
+ TLS_Extensions extensions;
+
+ if(m_secure_renegotiation)
+ extensions.push_back(new Renegotation_Extension(m_renegotiation_info));
+
+ if(m_fragment_size != 0)
+ extensions.push_back(new Maximum_Fragment_Length(m_fragment_size));
+
+ if(m_next_protocol)
+ extensions.push_back(new Next_Protocol_Negotiation(m_next_protocols));
+
+ buf += extensions.serialize();
+
+ return buf;
+ }
+
+/*
+* Deserialize a Server Hello message
+*/
+void Server_Hello::deserialize(const MemoryRegion<byte>& buf)
+ {
+ m_secure_renegotiation = false;
+ m_next_protocol = false;
+
+ if(buf.size() < 38)
+ throw Decoding_Error("Server_Hello: Packet corrupted");
+
+ TLS_Data_Reader reader(buf);
+
+ s_version = static_cast<Version_Code>(reader.get_u16bit());
+
+ if(s_version != SSL_V3 && s_version != TLS_V10 && s_version != TLS_V11)
+ {
+ throw TLS_Exception(PROTOCOL_VERSION,
+ "Server_Hello: Unsupported server version");
+ }
+
+ s_random = reader.get_fixed<byte>(32);
+
+ m_session_id = reader.get_range<byte>(1, 0, 32);
+
+ suite = reader.get_u16bit();
+
+ comp_method = reader.get_byte();
+
+ TLS_Extensions extensions(reader);
+
+ for(size_t i = 0; i != extensions.count(); ++i)
+ {
+ TLS_Extension* extn = extensions.at(i);
+
+ if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
+ {
+ // checked by TLS_Client / TLS_Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+ else if(Next_Protocol_Negotiation* npn = dynamic_cast<Next_Protocol_Negotiation*>(extn))
+ {
+ m_next_protocols = npn->protocols();
+ m_next_protocol = true;
+ }
+ }
+ }
+
+/*
+* Create a new Server Hello Done message
+*/
+Server_Hello_Done::Server_Hello_Done(Record_Writer& writer,
+ TLS_Handshake_Hash& hash)
+ {
+ send(writer, hash);
+ }
+
+/*
+* Serialize a Server Hello Done message
+*/
+MemoryVector<byte> Server_Hello_Done::serialize() const
+ {
+ return MemoryVector<byte>();
+ }
+
+/*
+* Deserialize a Server Hello Done message
+*/
+void Server_Hello_Done::deserialize(const MemoryRegion<byte>& buf)
+ {
+ if(buf.size())
+ throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
+ }
+
+}
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index a6ab13f46..c74790ea1 100644
--- a/src/tls/tls_extensions.cpp
+++ b/src/tls/tls_extensions.cpp
@@ -9,8 +9,6 @@
#include <botan/internal/tls_reader.h>
#include <botan/tls_exceptn.h>
-#include <stdio.h>
-
namespace Botan {
namespace {
@@ -244,8 +242,6 @@ Next_Protocol_Negotiation::Next_Protocol_Negotiation(TLS_Data_Reader& reader,
{
const std::string p = reader.get_string(1, 0, 255);
- printf("Protocol option %s\n", p.c_str());
-
if(bytes_remaining < p.size() + 1)
throw Decoding_Error("Bad encoding for next protocol extension");
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index 9c61501c9..67647d5a3 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -154,24 +154,28 @@ class Server_Hello : public Handshake_Message
Server_Hello(Record_Writer& writer,
TLS_Handshake_Hash& hash,
+ Version_Code version,
+ const Client_Hello& other,
+ const std::vector<X509_Certificate>& certs,
const TLS_Policy& policies,
- RandomNumberGenerator& rng,
bool client_has_secure_renegotiation,
const MemoryRegion<byte>& reneg_info,
- const std::vector<X509_Certificate>& certs,
- const Client_Hello& other,
- Version_Code version);
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng);
Server_Hello(Record_Writer& writer,
TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- bool client_has_secure_renegotiation,
- const MemoryRegion<byte>& reneg_info,
const MemoryRegion<byte>& session_id,
- size_t max_fragment_size,
+ Version_Code ver,
u16bit ciphersuite,
byte compression,
- Version_Code ver);
+ size_t max_fragment_size,
+ bool client_has_secure_renegotiation,
+ const MemoryRegion<byte>& reneg_info,
+ bool client_has_npn,
+ const std::vector<std::string>& next_protocols,
+ RandomNumberGenerator& rng);
Server_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); }
private:
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index 109835e4a..729c185df 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -12,8 +12,6 @@
#include <botan/rsa.h>
#include <botan/dh.h>
-#include <stdio.h>
-
namespace Botan {
namespace {
@@ -87,12 +85,14 @@ TLS_Server::TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn
TLS_Session_Manager& session_manager,
Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng) :
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& next_protocols) :
TLS_Channel(output_fn, proc_fn, handshake_fn),
policy(policy),
rng(rng),
session_manager(session_manager),
- creds(creds)
+ creds(creds),
+ m_possible_protocols(next_protocols)
{
}
@@ -154,7 +154,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
{
state->client_hello = new Client_Hello(contents, type);
- client_requested_hostname = state->client_hello->sni_hostname();
+ m_hostname = state->client_hello->sni_hostname();
state->version = choose_version(state->client_hello->version(),
policy.min_version());
@@ -176,14 +176,16 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
state->server_hello = new Server_Hello(
writer,
state->hash,
- rng,
- secure_renegotiation.supported(),
- secure_renegotiation.for_server_hello(),
session_info.session_id(),
+ Version_Code(session_info.version()),
session_info.ciphersuite(),
session_info.compression_method(),
session_info.fragment_size(),
- Version_Code(session_info.version()));
+ secure_renegotiation.supported(),
+ secure_renegotiation.for_server_hello(),
+ state->client_hello->next_protocol_negotiation(),
+ m_possible_protocols,
+ rng);
if(session_info.fragment_size())
writer.set_maximum_fragment_size(session_info.fragment_size());
@@ -214,24 +216,26 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
std::vector<X509_Certificate> server_certs =
creds.cert_chain("",
"tls-server",
- client_requested_hostname);
+ m_hostname);
Private_Key* private_key =
server_certs.empty() ? 0 :
(creds.private_key_for(server_certs[0],
"tls-server",
- client_requested_hostname));
+ m_hostname));
state->server_hello = new Server_Hello(
writer,
state->hash,
+ state->version,
+ *(state->client_hello),
+ server_certs,
policy,
- rng,
secure_renegotiation.supported(),
secure_renegotiation.for_server_hello(),
- server_certs,
- *(state->client_hello),
- state->version);
+ state->client_hello->next_protocol_negotiation(),
+ m_possible_protocols,
+ rng);
if(state->client_hello->fragment_size())
writer.set_maximum_fragment_size(state->client_hello->fragment_size());
@@ -347,10 +351,21 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
}
else if(type == HANDSHAKE_CCS)
{
- state->set_expected_next(FINISHED);
+ if(state->server_hello->next_protocol_negotiation())
+ state->set_expected_next(NEXT_PROTOCOL);
+ else
+ state->set_expected_next(FINISHED);
reader.activate(state->suite, state->keys, SERVER);
}
+ else if(type == NEXT_PROTOCOL)
+ {
+ state->set_expected_next(FINISHED);
+
+ state->next_protocol = new Next_Protocol(contents);
+
+ m_next_protocol = state->next_protocol->protocol();
+ }
else if(type == FINISHED)
{
state->set_expected_next(HANDSHAKE_NONE);
@@ -389,7 +404,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
secure_renegotiation.supported(),
state->server_hello->fragment_size(),
peer_certs,
- client_requested_hostname,
+ m_hostname,
""
);
diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h
index b08d3f7e8..31e0e9ca4 100644
--- a/src/tls/tls_server.h
+++ b/src/tls/tls_server.h
@@ -30,15 +30,24 @@ class BOTAN_DLL TLS_Server : public TLS_Channel
TLS_Session_Manager& session_manager,
Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng);
+ RandomNumberGenerator& rng,
+ const std::vector<std::string>& protocols =
+ std::vector<std::string>());
void renegotiate();
/**
- * Return the server name indicator, if set by the client
+ * Return the server name indicator, if sent by the client
*/
std::string server_name_indicator() const
- { return client_requested_hostname; }
+ { return m_hostname; }
+
+ /**
+ * Return the protocol negotiated with NPN extension
+ */
+ std::string next_protocol() const
+ { return m_next_protocol; }
+
private:
void read_handshake(byte, const MemoryRegion<byte>&);
@@ -49,7 +58,9 @@ class BOTAN_DLL TLS_Server : public TLS_Channel
TLS_Session_Manager& session_manager;
Credentials_Manager& creds;
- std::string client_requested_hostname;
+ std::vector<std::string> m_possible_protocols;
+ std::string m_hostname;
+ std::string m_next_protocol;
};
}
diff --git a/src/tls/tls_session_manager.cpp b/src/tls/tls_session_manager.cpp
index 4a0126fc0..e5ec75c88 100644
--- a/src/tls/tls_session_manager.cpp
+++ b/src/tls/tls_session_manager.cpp
@@ -9,8 +9,6 @@
#include <botan/hex.h>
#include <botan/time.h>
-#include <stdio.h>
-
namespace Botan {
bool TLS_Session_Manager_In_Memory::load_from_session_str(