diff options
Diffstat (limited to 'src/tls/tls_server.cpp')
-rw-r--r-- | src/tls/tls_server.cpp | 235 |
1 files changed, 9 insertions, 226 deletions
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 8964be3d7..81ed2c48e 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -1,6 +1,6 @@ /* * TLS Server -* (C) 2004-2010 Jack Lloyd +* (C) 2004-2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -85,40 +85,20 @@ void server_check_state(Handshake_Type new_msg, Handshake_State* state) /* * TLS Server Constructor */ -TLS_Server::TLS_Server(std::tr1::function<size_t (byte[], size_t)> input_fn, - std::tr1::function<void (const byte[], size_t)> output_fn, +TLS_Server::TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn, + std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, const TLS_Policy& policy, RandomNumberGenerator& rng, const X509_Certificate& cert, const Private_Key& cert_key) : - input_fn(input_fn), + TLS_Channel(output_fn, proc_fn), policy(policy), - rng(rng), - writer(output_fn) + rng(rng) { - state = 0; + writer.set_version(TLS_V10); cert_chain.push_back(cert); private_key = PKCS8::copy_key(cert_key, rng); - - try { - active = false; - writer.set_version(TLS_V10); - do_handshake(); - active = true; - } - catch(std::exception& e) - { - if(state) - { - delete state; - state = 0; - } - - writer.alert(FATAL, HANDSHAKE_FAILURE); - throw Stream_IO_Error(std::string("TLS_Server: Handshake failed: ") + - e.what()); - } } /* @@ -126,143 +106,7 @@ TLS_Server::TLS_Server(std::tr1::function<size_t (byte[], size_t)> input_fn, */ TLS_Server::~TLS_Server() { - close(); delete private_key; - delete state; - } - -/* -* Return the peer's certificate chain -*/ -std::vector<X509_Certificate> TLS_Server::peer_cert_chain() const - { - return peer_certs; - } - -/* -* Write to a TLS connection -*/ -void TLS_Server::write(const byte buf[], size_t length) - { - if(!active) - throw Internal_Error("TLS_Server::write called while closed"); - - writer.send(APPLICATION_DATA, buf, length); - } - -/* -* Read from a TLS connection -*/ -size_t TLS_Server::read(byte out[], size_t length) - { - if(!active) - throw Internal_Error("TLS_Server::read called while closed"); - - writer.flush(); - - while(read_buf.size() == 0) - { - state_machine(); - if(active == false) - break; - } - - size_t got = std::min<size_t>(read_buf.size(), length); - read_buf.read(out, got); - return got; - } - -/* -* Check connection status -*/ -bool TLS_Server::is_closed() const - { - if(!active) - return true; - return false; - } - -/* -* Close a TLS connection -*/ -void TLS_Server::close() - { - close(WARNING, CLOSE_NOTIFY); - } - -/* -* Close a TLS connection -*/ -void TLS_Server::close(Alert_Level level, Alert_Type alert_code) - { - if(active) - { - try { - active = false; - writer.alert(level, alert_code); - writer.flush(); - } - catch(...) {} - } - } - -/* -* Iterate the TLS state machine -*/ -void TLS_Server::state_machine() - { - byte rec_type = CONNECTION_CLOSED; - SecureVector<byte> record(1024); - - size_t bytes_needed = reader.get_record(rec_type, record); - - while(bytes_needed) - { - size_t to_get = std::min<size_t>(record.size(), bytes_needed); - size_t got = input_fn(&record[0], to_get); - - if(got == 0) - { - rec_type = CONNECTION_CLOSED; - break; - } - - reader.add_input(&record[0], got); - - bytes_needed = reader.get_record(rec_type, record); - } - - if(rec_type == CONNECTION_CLOSED) - { - active = false; - reader.reset(); - writer.reset(); - } - else if(rec_type == APPLICATION_DATA) - { - if(active) - read_buf.write(&record[0], record.size()); - else - throw Unexpected_Message("Application data before handshake done"); - } - else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC) - read_handshake(rec_type, record); - else if(rec_type == ALERT) - { - Alert alert(record); - - if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY) - { - if(alert.type() == CLOSE_NOTIFY) - writer.alert(WARNING, CLOSE_NOTIFY); - - reader.reset(); - writer.reset(); - active = false; - } - } - else - throw Unexpected_Message("Unknown message type received"); } /* @@ -271,54 +115,10 @@ void TLS_Server::state_machine() void TLS_Server::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()); - } - - while(true) - { - Handshake_Type type = HANDSHAKE_NONE; - SecureVector<byte> contents; - - if(rec_type == HANDSHAKE) - { - if(state->queue.size() >= 4) - { - 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()); - } - } - } - else if(rec_type == CHANGE_CIPHER_SPEC) - { - if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1) - type = HANDSHAKE_CCS; - else - throw Decoding_Error("Malformed ChangeCipherSpec message"); - } - else - throw Decoding_Error("Unknown message type in handshake processing"); + if(rec_type == HANDSHAKE && !state) + state = new Handshake_State; - if(type == HANDSHAKE_NONE) - break; - - process_handshake_msg(type, contents); - - if(type == HANDSHAKE_CCS || !state) - break; - } + TLS_Channel::read_handshake(rec_type, rec_buf); } /* @@ -474,21 +274,4 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, throw Unexpected_Message("Unknown handshake message received"); } -/* -* Perform a server-side TLS handshake -*/ -void TLS_Server::do_handshake() - { - while(true) - { - if(active && !state) - break; - - state_machine(); - - if(!active && !state) - throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Server: Handshake failed"); - } - } - } |