aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_channel.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-03-16 17:32:40 +0000
committerlloyd <[email protected]>2012-03-16 17:32:40 +0000
commit1fce3fe2274cf3368e1f29827ed0f41cebba3726 (patch)
tree7a83f1d6d8fcf08dc8120aafba718dd11c1e52b7 /src/tls/tls_channel.cpp
parent4c6327c95bd01de54487b3159b77a5152ed39564 (diff)
parent7371f7c59ae722769fbc0dc810583a0cd0e38877 (diff)
propagate from branch 'net.randombit.botan.tls-state-machine' (head c24b5d6b012131b177d38bddb8b06d73f81f70c4)
to branch 'net.randombit.botan.tls-session-ticket' (head 9977d4c118e1ac26425cef676ebf26cd5b2a470e)
Diffstat (limited to 'src/tls/tls_channel.cpp')
-rw-r--r--src/tls/tls_channel.cpp111
1 files changed, 54 insertions, 57 deletions
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
index 46c6d36cd..f45ce4bda 100644
--- a/src/tls/tls_channel.cpp
+++ b/src/tls/tls_channel.cpp
@@ -6,16 +6,18 @@
*/
#include <botan/tls_channel.h>
-#include <botan/internal/tls_alerts.h>
#include <botan/internal/tls_handshake_state.h>
+#include <botan/internal/tls_messages.h>
#include <botan/internal/assert.h>
#include <botan/loadstor.h>
namespace Botan {
-TLS_Channel::TLS_Channel(std::tr1::function<void (const byte[], size_t)> socket_output_fn,
- std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn,
- std::tr1::function<bool (const TLS_Session&)> handshake_complete) :
+namespace TLS {
+
+Channel::Channel(std::tr1::function<void (const byte[], size_t)> socket_output_fn,
+ std::tr1::function<void (const byte[], size_t, Alert)> proc_fn,
+ std::tr1::function<bool (const Session&)> handshake_complete) :
proc_fn(proc_fn),
handshake_fn(handshake_complete),
writer(socket_output_fn),
@@ -25,13 +27,13 @@ TLS_Channel::TLS_Channel(std::tr1::function<void (const byte[], size_t)> socket_
{
}
-TLS_Channel::~TLS_Channel()
+Channel::~Channel()
{
delete state;
state = 0;
}
-size_t TLS_Channel::received_data(const byte buf[], size_t buf_size)
+size_t Channel::received_data(const byte buf[], size_t buf_size)
{
try
{
@@ -64,7 +66,7 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size)
* following record. Avoid spurious callbacks.
*/
if(record.size() > 0)
- proc_fn(&record[0], record.size(), NULL_ALERT);
+ proc_fn(&record[0], record.size(), Alert());
}
else
{
@@ -79,16 +81,16 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size)
{
Alert alert_msg(record);
- alert_notify(alert_msg.is_fatal(), alert_msg.type());
+ alert_notify(alert_msg);
- proc_fn(0, 0, alert_msg.type());
+ proc_fn(0, 0, alert_msg);
- if(alert_msg.type() == CLOSE_NOTIFY)
+ if(alert_msg.type() == Alert::CLOSE_NOTIFY)
{
if(connection_closed)
reader.reset();
else
- alert(WARNING, CLOSE_NOTIFY); // reply in kind
+ send_alert(Alert(Alert::CLOSE_NOTIFY)); // reply in kind
}
else if(alert_msg.is_fatal())
{
@@ -111,17 +113,22 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size)
}
catch(TLS_Exception& e)
{
- alert(FATAL, e.type());
+ send_alert(Alert(e.type(), true));
throw;
}
catch(Decoding_Error& e)
{
- alert(FATAL, DECODE_ERROR);
+ send_alert(Alert(Alert::DECODE_ERROR, true));
+ throw;
+ }
+ catch(Internal_Error& e)
+ {
+ send_alert(Alert(Alert::INTERNAL_ERROR, true));
throw;
}
catch(std::exception& e)
{
- alert(FATAL, INTERNAL_ERROR);
+ send_alert(Alert(Alert::INTERNAL_ERROR, true));
throw;
}
}
@@ -129,80 +136,68 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size)
/*
* Split up and process handshake messages
*/
-void TLS_Channel::read_handshake(byte rec_type,
- const MemoryRegion<byte>& rec_buf)
+void Channel::read_handshake(byte rec_type,
+ const MemoryRegion<byte>& rec_buf)
{
if(rec_type == HANDSHAKE)
{
if(!state)
- state = new Handshake_State;
- state->queue.write(&rec_buf[0], rec_buf.size());
+ state = new Handshake_State(new Stream_Handshake_Reader);
+ state->handshake_reader()->add_input(&rec_buf[0], rec_buf.size());
}
+ BOTAN_ASSERT(state, "Handshake message recieved without state in place");
+
while(true)
{
Handshake_Type type = HANDSHAKE_NONE;
- MemoryVector<byte> contents;
if(rec_type == HANDSHAKE)
{
- if(state->queue.size() >= 4)
+ if(state->handshake_reader()->have_full_record())
{
- byte head[4] = { 0 };
- state->queue.peek(head, 4);
-
- const size_t length = make_u32bit(0, head[1], head[2], head[3]);
-
- if(state->queue.size() >= length + 4)
- {
- type = static_cast<Handshake_Type>(head[0]);
- contents.resize(length);
- state->queue.read(head, 4);
- state->queue.read(&contents[0], contents.size());
- }
+ std::pair<Handshake_Type, MemoryVector<byte> > msg =
+ state->handshake_reader()->get_next_record();
+ process_handshake_msg(msg.first, msg.second);
}
+ else
+ break;
}
else if(rec_type == CHANGE_CIPHER_SPEC)
{
- if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1)
- type = HANDSHAKE_CCS;
+ if(state->handshake_reader()->empty() && rec_buf.size() == 1 && rec_buf[0] == 1)
+ process_handshake_msg(HANDSHAKE_CCS, MemoryVector<byte>());
else
throw Decoding_Error("Malformed ChangeCipherSpec message");
}
else
throw Decoding_Error("Unknown message type in handshake processing");
- if(type == HANDSHAKE_NONE)
- break;
-
- process_handshake_msg(type, contents);
-
- if(type == HANDSHAKE_CCS || !state)
+ if(type == HANDSHAKE_CCS || !state || !state->handshake_reader()->have_full_record())
break;
}
}
-void TLS_Channel::queue_for_sending(const byte buf[], size_t buf_size)
+void Channel::send(const byte buf[], size_t buf_size)
{
- if(!handshake_completed)
- throw std::runtime_error("Application data cannot be queued before handshake");
+ if(!is_active())
+ throw std::runtime_error("Data cannot be sent on inactive TLS connection");
writer.send(APPLICATION_DATA, buf, buf_size);
}
-void TLS_Channel::alert(Alert_Level alert_level, Alert_Type alert_code)
+void Channel::send_alert(const Alert& alert)
{
- if(alert_code != NULL_ALERT && !connection_closed)
+ if(alert.is_valid() && !connection_closed)
{
try
{
- writer.alert(alert_level, alert_code);
+ writer.send_alert(alert);
}
catch(...) { /* swallow it */ }
}
- if(!connection_closed &&
- (alert_code == CLOSE_NOTIFY || alert_level == FATAL))
+ if(!connection_closed && (alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal()))
{
connection_closed = true;
@@ -213,7 +208,7 @@ void TLS_Channel::alert(Alert_Level alert_level, Alert_Type alert_code)
}
}
-void TLS_Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello)
+void Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello)
{
if(initial_handshake)
{
@@ -222,7 +217,7 @@ void TLS_Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello)
else
{
if(secure_renegotiation != client_hello->secure_renegotiation())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Client changed its mind about secure renegotiation");
}
@@ -233,19 +228,19 @@ void TLS_Channel::Secure_Renegotiation_State::update(Client_Hello* client_hello)
if(initial_handshake)
{
if(!data.empty())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Client sent renegotiation data on initial handshake");
}
else
{
if(data != for_client_hello())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Client sent bad renegotiation data");
}
}
}
-void TLS_Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
+void Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
{
if(initial_handshake)
{
@@ -257,7 +252,7 @@ void TLS_Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
else
{
if(secure_renegotiation != server_hello->secure_renegotiation())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Server changed its mind about secure renegotiation");
}
@@ -268,13 +263,13 @@ void TLS_Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
if(initial_handshake)
{
if(!data.empty())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Server sent renegotiation data on initial handshake");
}
else
{
if(data != for_server_hello())
- throw TLS_Exception(HANDSHAKE_FAILURE,
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Server sent bad renegotiation data");
}
}
@@ -282,7 +277,7 @@ void TLS_Channel::Secure_Renegotiation_State::update(Server_Hello* server_hello)
initial_handshake = false;
}
-void TLS_Channel::Secure_Renegotiation_State::update(Finished* client_finished,
+void Channel::Secure_Renegotiation_State::update(Finished* client_finished,
Finished* server_finished)
{
client_verify = client_finished->verify_data();
@@ -290,3 +285,5 @@ void TLS_Channel::Secure_Renegotiation_State::update(Finished* client_finished,
}
}
+
+}