diff --git a/lib/modules/SSL.pmod/ClientConnection.pike b/lib/modules/SSL.pmod/ClientConnection.pike index 30a68259f753683917f64a78f4166ccdb4cf43eb..11da241e91041a22ea29fd3fea5108c1e6eece98 100644 --- a/lib/modules/SSL.pmod/ClientConnection.pike +++ b/lib/modules/SSL.pmod/ClientConnection.pike @@ -233,6 +233,14 @@ protected void create(Context ctx, string(8bit)|void server_name) send_packet(client_hello(server_name)); } +//! Renegotiate the connection (client initiated). +//! +//! Sends a @[client_hello] to force a new round of handshaking. +void send_renegotiate() +{ + send_packet(client_hello(), PRI_application); +} + //! Do handshake processing. Type is one of HANDSHAKE_*, data is the //! contents of the packet, and raw is the raw packet received (needed //! for supporting SSLv2 hello messages). diff --git a/lib/modules/SSL.pmod/Connection.pike b/lib/modules/SSL.pmod/Connection.pike index 5ca17788e8c09846621450da5fe3a48cac062a38..f1f57c3ffcf27aaaebe63ef296b196cbac16c952 100644 --- a/lib/modules/SSL.pmod/Connection.pike +++ b/lib/modules/SSL.pmod/Connection.pike @@ -415,6 +415,22 @@ void send_packet(Packet packet, int|void priority) PACKET_handshake : PRI_urgent, PACKET_heartbeat : PRI_urgent, PACKET_application_data : PRI_application ])[packet->content_type]; + + if ((state & CONNECTION_local_closing) && (priority >= PRI_application)) { + SSL3_DEBUG_MSG("send_packet: Ignoring application packet during close.\n"); + return; + } + + if ((packet->content_type == PACKET_handshake) && + (priority == PRI_application)) { + // Assume the packet is either hello_request or client_hello, + // and that we want to renegotiate. + expect_change_cipher = 0; + certificate_state = 0; + state = [int(0..0)|ConnectionState](state | CONNECTION_handshaking); + handshake_state = STATE_wait_for_hello; + } + SSL3_DEBUG_MSG("SSL.Connection->send_packet: type %d, pri %d, %O\n", packet->content_type, priority, packet->fragment[..5]); switch (priority) @@ -496,6 +512,9 @@ void send_close() "Closing connection.\n"), PRI_application); } +//! Renegotiate the connection. +void send_renegotiate(); + //! Send an application data packet. If the data block is too large //! then as much as possible of the beginning of it is sent. The size //! of the sent data is returned. diff --git a/lib/modules/SSL.pmod/File.pike b/lib/modules/SSL.pmod/File.pike index 0b44631b68c87cdbe91536c52ee71ed4f83787ca..b4ed6cee56c3a5bfb11611f765964193eced1d49 100644 --- a/lib/modules/SSL.pmod/File.pike +++ b/lib/modules/SSL.pmod/File.pike @@ -1027,19 +1027,13 @@ int renegotiate() local_errno = 0; - // FIXME: Change this state with a packet instead so that things - // currently in the queue aren't affect by it. - conn->expect_change_cipher = 0; - conn->certificate_state = 0; - conn->state |= CONNECTION_handshaking; + conn->send_renegotiate(); SSL3_DEBUG_MSG("renegotiate: Installing read/close callbacks.\n"); stream->set_read_callback(ssl_read_callback); stream->set_close_callback(ssl_close_callback); - conn->send_packet(conn->hello_request()); - RETURN (direct_write()); } LEAVE; } diff --git a/lib/modules/SSL.pmod/ServerConnection.pike b/lib/modules/SSL.pmod/ServerConnection.pike index acb286faf87704872e4634daf1ed746e005b08b0..08c95125e73270b9aeac209b54dc8c87e9dc8541 100644 --- a/lib/modules/SSL.pmod/ServerConnection.pike +++ b/lib/modules/SSL.pmod/ServerConnection.pike @@ -151,6 +151,14 @@ Packet certificate_request_packet(Context context) struct->pop_data()); } +//! Renegotiate the connection (server initiated). +//! +//! Sends a @[hello_request] to force a new round of handshaking. +void send_renegotiate() +{ + send_packet(hello_request(), PRI_application); +} + int(0..1) not_ecc_suite(int cipher_suite) { array(int) suite = [array(int)]CIPHER_SUITES[cipher_suite];