diff options
author | lloyd <[email protected]> | 2012-03-16 17:32:40 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-03-16 17:32:40 +0000 |
commit | 1fce3fe2274cf3368e1f29827ed0f41cebba3726 (patch) | |
tree | 7a83f1d6d8fcf08dc8120aafba718dd11c1e52b7 /src/tls/tls_channel.cpp | |
parent | 4c6327c95bd01de54487b3159b77a5152ed39564 (diff) | |
parent | 7371f7c59ae722769fbc0dc810583a0cd0e38877 (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.cpp | 111 |
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, } } + +} |