aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-04-16 19:00:49 +0000
committerlloyd <[email protected]>2012-04-16 19:00:49 +0000
commitb224e899c8846f17a36dc41c53dd94ba037ada79 (patch)
tree81e2b0391b436b7620ffbeaa15252c75ae3c9039
parentc09b208d5d3ead81ef7ad662f71f55f1e00f61bc (diff)
Add support for TLS heartbeats (RFC 6520). Heartbeat initiations from
the peer are automatically responded to. TLS::Channel::heartbeat can initiate a new heartbeat if the peer allows it. Heartbeat replies are passed back to the application processing function with an Alert value of HEARTBEAT_PAYLOAD (a 'fake' value, 256, which is out of range of the valid TLS alert space), along with the sent payload. The RFC requires us to have no more than one heartbeat 'in flight' at a time, ie without getting a response (or a timeout in the case of DTLS). Currently we do not prevent an application from requesting more.
-rw-r--r--src/tls/c_hello.cpp31
-rw-r--r--src/tls/info.txt2
-rw-r--r--src/tls/rec_read.cpp3
-rw-r--r--src/tls/s_hello.cpp14
-rw-r--r--src/tls/tls_alert.cpp5
-rw-r--r--src/tls/tls_alert.h4
-rw-r--r--src/tls/tls_channel.cpp48
-rw-r--r--src/tls/tls_channel.h14
-rw-r--r--src/tls/tls_client.cpp3
-rw-r--r--src/tls/tls_extensions.cpp3
-rw-r--r--src/tls/tls_extensions.h27
-rw-r--r--src/tls/tls_heartbeats.cpp78
-rw-r--r--src/tls/tls_heartbeats.h40
-rw-r--r--src/tls/tls_magic.h3
-rw-r--r--src/tls/tls_messages.h37
-rw-r--r--src/tls/tls_record.h3
-rw-r--r--src/tls/tls_server.cpp5
17 files changed, 282 insertions, 38 deletions
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp
index d3fff8b00..e52d34bc6 100644
--- a/src/tls/c_hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -77,7 +77,9 @@ Client_Hello::Client_Hello(Record_Writer& writer,
m_secure_renegotiation(true),
m_renegotiation_info(reneg_info),
m_supported_curves(policy.allowed_ecc_curves()),
- m_supports_session_ticket(true)
+ m_supports_session_ticket(true),
+ m_supports_heartbeats(true),
+ m_peer_can_send_heartbeats(true)
{
std::vector<std::string> hashes = policy.allowed_hashes();
std::vector<std::string> sigs = policy.allowed_signature_methods();
@@ -110,7 +112,9 @@ Client_Hello::Client_Hello(Record_Writer& writer,
m_secure_renegotiation(session.secure_renegotiation()),
m_supported_curves(policy.allowed_ecc_curves()),
m_supports_session_ticket(true),
- m_session_ticket(session.session_ticket())
+ m_session_ticket(session.session_ticket()),
+ m_supports_heartbeats(true),
+ m_peer_can_send_heartbeats(true)
{
if(!value_exists(m_suites, session.ciphersuite_code()))
m_suites.push_back(session.ciphersuite_code());
@@ -136,6 +140,8 @@ Client_Hello::Client_Hello(const MemoryRegion<byte>& buf, Handshake_Type type)
m_next_protocol = false;
m_secure_renegotiation = false;
m_supports_session_ticket = false;
+ m_supports_heartbeats = false;
+ m_peer_can_send_heartbeats = false;
m_fragment_size = 0;
if(type == CLIENT_HELLO)
@@ -168,29 +174,24 @@ MemoryVector<byte> Client_Hello::serialize() const
Extensions extensions;
- // Initial handshake
+ // Extensions only used on an initial handshake
if(m_renegotiation_info.empty())
{
- extensions.add(new Renegotation_Extension(m_renegotiation_info));
extensions.add(new Server_Name_Indicator(m_hostname));
extensions.add(new SRP_Identifier(m_srp_identifier));
extensions.add(new Supported_Elliptic_Curves(m_supported_curves));
+ extensions.add(new Heartbeat_Support_Indicator(true));
if(m_version >= Protocol_Version::TLS_V12)
extensions.add(new Signature_Algorithms(m_supported_algos));
if(m_next_protocol)
extensions.add(new Next_Protocol_Notification());
-
- extensions.add(new Session_Ticket(m_session_ticket));
- }
- else
- {
- // renegotiation
- extensions.add(new Renegotation_Extension(m_renegotiation_info));
- extensions.add(new Session_Ticket(m_session_ticket));
}
+ extensions.add(new Renegotation_Extension(m_renegotiation_info));
+ extensions.add(new Session_Ticket(m_session_ticket));
+
buf += extensions.serialize();
return buf;
@@ -338,6 +339,12 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
m_session_ticket = ticket->contents();
}
+ if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>())
+ {
+ m_supports_heartbeats = true;
+ m_peer_can_send_heartbeats = hb->peer_allowed_to_send();
+ }
+
if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>())
{
// checked by TLS_Client / TLS_Server as they know the handshake state
diff --git a/src/tls/info.txt b/src/tls/info.txt
index 229cf658f..77ffb4585 100644
--- a/src/tls/info.txt
+++ b/src/tls/info.txt
@@ -29,6 +29,7 @@ tls_extensions.h
tls_handshake_hash.h
tls_handshake_reader.h
tls_handshake_state.h
+tls_heartbeats.h
tls_messages.h
tls_reader.h
tls_session_key.h
@@ -55,6 +56,7 @@ tls_extensions.cpp
tls_handshake_hash.cpp
tls_handshake_reader.cpp
tls_handshake_state.cpp
+tls_heartbeats.cpp
tls_policy.cpp
tls_server.cpp
tls_session.cpp
diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp
index d1fab4692..5d46ec1fa 100644
--- a/src/tls/rec_read.cpp
+++ b/src/tls/rec_read.cpp
@@ -216,7 +216,8 @@ size_t Record_Reader::add_input(const byte input_array[], size_t input_sz,
if(m_readbuf[0] != CHANGE_CIPHER_SPEC &&
m_readbuf[0] != ALERT &&
m_readbuf[0] != HANDSHAKE &&
- m_readbuf[0] != APPLICATION_DATA)
+ m_readbuf[0] != APPLICATION_DATA &&
+ m_readbuf[0] != HEARTBEAT)
{
throw Unexpected_Message(
"Unknown record type " + to_string(m_readbuf[0]) + " from counterparty");
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp
index bb93108d9..1244dd2d8 100644
--- a/src/tls/s_hello.cpp
+++ b/src/tls/s_hello.cpp
@@ -31,6 +31,7 @@ Server_Hello::Server_Hello(Record_Writer& writer,
bool offer_session_ticket,
bool client_has_npn,
const std::vector<std::string>& next_protocols,
+ bool client_has_heartbeat,
RandomNumberGenerator& rng) :
m_version(ver),
m_session_id(session_id),
@@ -42,7 +43,9 @@ Server_Hello::Server_Hello(Record_Writer& writer,
m_renegotiation_info(reneg_info),
m_next_protocol(client_has_npn),
m_next_protocols(next_protocols),
- m_supports_session_ticket(offer_session_ticket)
+ m_supports_session_ticket(offer_session_ticket),
+ m_supports_heartbeats(client_has_heartbeat),
+ m_peer_can_send_heartbeats(true)
{
hash.update(writer.send(*this));
}
@@ -104,6 +107,12 @@ Server_Hello::Server_Hello(const MemoryRegion<byte>& buf)
throw Decoding_Error("TLS server sent non-empty session ticket extension");
m_supports_session_ticket = true;
}
+
+ if(Heartbeat_Support_Indicator* hb = extensions.get<Heartbeat_Support_Indicator>())
+ {
+ m_supports_heartbeats = true;
+ m_peer_can_send_heartbeats = hb->peer_allowed_to_send();
+ }
}
/*
@@ -126,6 +135,9 @@ MemoryVector<byte> Server_Hello::serialize() const
Extensions extensions;
+ if(m_supports_heartbeats)
+ extensions.add(new Heartbeat_Support_Indicator(m_peer_can_send_heartbeats));
+
if(m_secure_renegotiation)
extensions.add(new Renegotation_Extension(m_renegotiation_info));
diff --git a/src/tls/tls_alert.cpp b/src/tls/tls_alert.cpp
index 2461854e1..83205bb74 100644
--- a/src/tls/tls_alert.cpp
+++ b/src/tls/tls_alert.cpp
@@ -102,7 +102,10 @@ std::string Alert::type_string() const
return "unknown_psk_identity";
case NULL_ALERT:
- return "";
+ return "none";
+
+ case HEARTBEAT_PAYLOAD:
+ return "heartbeat_payload";
}
/*
diff --git a/src/tls/tls_alert.h b/src/tls/tls_alert.h
index 8b4b963f0..3dfff3d29 100644
--- a/src/tls/tls_alert.h
+++ b/src/tls/tls_alert.h
@@ -53,7 +53,9 @@ class BOTAN_DLL Alert
BAD_CERTIFICATE_HASH_VALUE = 114,
UNKNOWN_PSK_IDENTITY = 115,
- NULL_ALERT = 255
+ NULL_ALERT = 255,
+
+ HEARTBEAT_PAYLOAD = 256
};
/**
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
index f45ce4bda..2464d339a 100644
--- a/src/tls/tls_channel.cpp
+++ b/src/tls/tls_channel.cpp
@@ -8,6 +8,7 @@
#include <botan/tls_channel.h>
#include <botan/internal/tls_handshake_state.h>
#include <botan/internal/tls_messages.h>
+#include <botan/internal/tls_heartbeats.h>
#include <botan/internal/assert.h>
#include <botan/loadstor.h>
@@ -23,7 +24,9 @@ Channel::Channel(std::tr1::function<void (const byte[], size_t)> socket_output_f
writer(socket_output_fn),
state(0),
handshake_completed(false),
- connection_closed(false)
+ connection_closed(false),
+ m_peer_supports_heartbeats(false),
+ m_heartbeat_sending_allowed(false)
{
}
@@ -56,7 +59,30 @@ size_t Channel::received_data(const byte buf[], size_t buf_size)
if(buf_size == 0 && needed != 0)
return needed; // need more data to complete record
- if(rec_type == APPLICATION_DATA)
+ if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC)
+ {
+ read_handshake(rec_type, record);
+ }
+ else if(rec_type == HEARTBEAT && m_peer_supports_heartbeats)
+ {
+ Heartbeat_Message heartbeat(record);
+
+ const MemoryRegion<byte>& payload = heartbeat.payload();
+
+ if(heartbeat.is_request() && !state)
+ {
+ Heartbeat_Message response(Heartbeat_Message::RESPONSE,
+ payload, payload.size());
+
+ writer.send(HEARTBEAT, response.contents());
+ }
+ else
+ {
+ // pass up to the application
+ proc_fn(&payload[0], payload.size(), Alert(Alert::HEARTBEAT_PAYLOAD));
+ }
+ }
+ else if(rec_type == APPLICATION_DATA)
{
if(handshake_completed)
{
@@ -73,10 +99,6 @@ size_t Channel::received_data(const byte buf[], size_t buf_size)
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_msg(record);
@@ -178,6 +200,20 @@ void Channel::read_handshake(byte rec_type,
}
}
+void Channel::heartbeat(const byte payload[], size_t payload_size)
+ {
+ if(!is_active())
+ throw std::runtime_error("Heartbeat cannot be sent on inactive TLS connection");
+
+ if(m_heartbeat_sending_allowed)
+ {
+ Heartbeat_Message heartbeat(Heartbeat_Message::REQUEST,
+ payload, payload_size);
+
+ writer.send(HEARTBEAT, heartbeat.contents());
+ }
+ }
+
void Channel::send(const byte buf[], size_t buf_size)
{
if(!is_active())
diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h
index 53af0bdfc..05fb7e82f 100644
--- a/src/tls/tls_channel.h
+++ b/src/tls/tls_channel.h
@@ -58,6 +58,18 @@ class BOTAN_DLL Channel
virtual void renegotiate() = 0;
/**
+ * Attempt to send a heartbeat message (if negotiated with counterparty)
+ * @param payload will be echoed back
+ * @param countents_size size of payload in bytes
+ */
+ void heartbeat(const byte payload[], size_t payload_size);
+
+ /**
+ * Attempt to send a heartbeat message (if negotiated with counterparty)
+ */
+ void heartbeat() { heartbeat(0, 0); }
+
+ /**
* @return certificate chain of the peer (may be empty)
*/
std::vector<X509_Certificate> peer_cert_chain() const { return peer_certs; }
@@ -130,6 +142,8 @@ class BOTAN_DLL Channel
bool handshake_completed;
bool connection_closed;
+ bool m_peer_supports_heartbeats;
+ bool m_heartbeat_sending_allowed;
};
}
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 850d053a2..f6266ee6a 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -188,6 +188,9 @@ void Client::process_handshake_msg(Handshake_Type type,
secure_renegotiation.update(state->server_hello);
+ m_peer_supports_heartbeats = state->server_hello->supports_heartbeats();
+ m_heartbeat_sending_allowed = state->server_hello->peer_can_send_heartbeats();
+
state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());
const bool server_returned_same_session_id =
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index 59ab64374..f1361bbb9 100644
--- a/src/tls/tls_extensions.cpp
+++ b/src/tls/tls_extensions.cpp
@@ -42,6 +42,9 @@ Extension* make_extension(TLS_Data_Reader& reader,
case TLSEXT_NEXT_PROTOCOL:
return new Next_Protocol_Notification(reader, size);
+ case TLSEXT_HEARTBEAT_SUPPORT:
+ return new Heartbeat_Support_Indicator(reader, size);
+
case TLSEXT_SESSION_TICKET:
return new Session_Ticket(reader, size);
diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h
index 6a97d2560..3fe3f7399 100644
--- a/src/tls/tls_extensions.h
+++ b/src/tls/tls_extensions.h
@@ -32,6 +32,7 @@ enum Handshake_Extension_Type {
TLSEXT_EC_POINT_FORMATS = 11,
TLSEXT_SRP_IDENTIFIER = 12,
TLSEXT_SIGNATURE_ALGORITHMS = 13,
+ TLSEXT_HEARTBEAT_SUPPORT = 15,
TLSEXT_SESSION_TICKET = 35,
@@ -309,6 +310,32 @@ class Signature_Algorithms : public Extension
};
/**
+* Heartbeat Extension (RFC 6520)
+*/
+class Heartbeat_Support_Indicator : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_HEARTBEAT_SUPPORT; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ bool peer_allowed_to_send() const { return m_peer_allowed_to_send; }
+
+ MemoryVector<byte> serialize() const;
+
+ bool empty() const { return false; }
+
+ Heartbeat_Support_Indicator(bool peer_allowed_to_send) :
+ m_peer_allowed_to_send(peer_allowed_to_send) {}
+
+ Heartbeat_Support_Indicator(TLS_Data_Reader& reader, u16bit extension_size);
+
+ private:
+ bool m_peer_allowed_to_send;
+ };
+
+/**
* Represents a block of extensions in a hello message
*/
class Extensions
diff --git a/src/tls/tls_heartbeats.cpp b/src/tls/tls_heartbeats.cpp
new file mode 100644
index 000000000..a77d23534
--- /dev/null
+++ b/src/tls/tls_heartbeats.cpp
@@ -0,0 +1,78 @@
+/*
+* TLS Heartbeats
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#include <botan/internal/tls_heartbeats.h>
+#include <botan/internal/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/tls_exceptn.h>
+
+namespace Botan {
+
+namespace TLS {
+
+Heartbeat_Message::Heartbeat_Message(const MemoryRegion<byte>& buf)
+ {
+ TLS_Data_Reader reader(buf);
+
+ const byte type = reader.get_byte();
+
+ if(type != 1 && type != 2)
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Unknown heartbeat message type");
+
+ m_type = static_cast<Type>(type);
+
+ m_payload = reader.get_range<byte>(2, 0, 16*1024);
+
+ // padding follows and is ignored
+ }
+
+Heartbeat_Message::Heartbeat_Message(Type type,
+ const byte payload[],
+ size_t payload_len) :
+ m_type(type),
+ m_payload(payload, payload_len)
+ {
+ }
+
+MemoryVector<byte> Heartbeat_Message::contents() const
+ {
+ MemoryVector<byte> send_buf(3 + m_payload.size() + 16);
+ send_buf[0] = m_type;
+ send_buf[1] = get_byte<u16bit>(0, m_payload.size());
+ send_buf[2] = get_byte<u16bit>(1, m_payload.size());
+ copy_mem(&send_buf[3], &m_payload[0], m_payload.size());
+ // leave padding as all zeros
+
+ return send_buf;
+ }
+
+MemoryVector<byte> Heartbeat_Support_Indicator::serialize() const
+ {
+ MemoryVector<byte> heartbeat(1);
+ heartbeat[0] = (m_peer_allowed_to_send ? 1 : 2);
+ return heartbeat;
+ }
+
+Heartbeat_Support_Indicator::Heartbeat_Support_Indicator(TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+ if(extension_size != 1)
+ throw Decoding_Error("Strange size for heartbeat extension");
+
+ const byte code = reader.get_byte();
+
+ if(code != 1 && code != 2)
+ throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
+ "Unknown heartbeat code " + to_string(code));
+
+ m_peer_allowed_to_send = (code == 1);
+ }
+
+}
+
+}
diff --git a/src/tls/tls_heartbeats.h b/src/tls/tls_heartbeats.h
new file mode 100644
index 000000000..4fa49501b
--- /dev/null
+++ b/src/tls/tls_heartbeats.h
@@ -0,0 +1,40 @@
+/*
+* TLS Heartbeats
+* (C) 2012 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_HEARTBEATS_H__
+#define BOTAN_TLS_HEARTBEATS_H__
+
+#include <botan/secmem.h>
+
+namespace Botan {
+
+namespace TLS {
+
+class Heartbeat_Message
+ {
+ public:
+ enum Type { REQUEST = 1, RESPONSE = 2 };
+
+ MemoryVector<byte> contents() const;
+
+ const MemoryRegion<byte>& payload() const { return m_payload; }
+
+ bool is_request() const { return m_type == REQUEST; }
+
+ Heartbeat_Message(const MemoryRegion<byte>& buf);
+
+ Heartbeat_Message(Type type, const byte payload[], size_t payload_len);
+ private:
+ Type m_type;
+ MemoryVector<byte> m_payload;
+ };
+
+}
+
+}
+
+#endif
diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h
index 6dd50ead2..2972321c9 100644
--- a/src/tls/tls_magic.h
+++ b/src/tls/tls_magic.h
@@ -32,7 +32,8 @@ enum Record_Type {
CHANGE_CIPHER_SPEC = 20,
ALERT = 21,
HANDSHAKE = 22,
- APPLICATION_DATA = 23
+ APPLICATION_DATA = 23,
+ HEARTBEAT = 24,
};
enum Handshake_Type {
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index c8a9382d6..4c2b1b797 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -73,15 +73,10 @@ class Client_Hello : public Handshake_Message
{
public:
Handshake_Type type() const { return CLIENT_HELLO; }
+
Protocol_Version version() const { return m_version; }
- const MemoryVector<byte>& session_id() const { return m_session_id; }
- std::vector<byte> session_id_vector() const
- {
- std::vector<byte> v;
- v.insert(v.begin(), &m_session_id[0], &m_session_id[m_session_id.size()]);
- return v;
- }
+ const MemoryVector<byte>& session_id() const { return m_session_id; }
const std::vector<std::pair<std::string, std::string> >& supported_algos() const
{ return m_supported_algos; }
@@ -114,6 +109,10 @@ class Client_Hello : public Handshake_Message
const MemoryRegion<byte>& session_ticket() const
{ return m_session_ticket; }
+ bool supports_heartbeats() const { return m_supports_heartbeats; }
+
+ bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; }
+
Client_Hello(Record_Writer& writer,
Handshake_Hash& hash,
const Policy& policy,
@@ -155,6 +154,9 @@ class Client_Hello : public Handshake_Message
bool m_supports_session_ticket;
MemoryVector<byte> m_session_ticket;
+
+ bool m_supports_heartbeats;
+ bool m_peer_can_send_heartbeats;
};
/**
@@ -164,17 +166,16 @@ class Server_Hello : public Handshake_Message
{
public:
Handshake_Type type() const { return SERVER_HELLO; }
+
Protocol_Version version() { return m_version; }
+
+ const MemoryVector<byte>& random() const { return m_random; }
+
const MemoryVector<byte>& session_id() const { return m_session_id; }
+
u16bit ciphersuite() const { return m_ciphersuite; }
- byte compression_method() const { return m_comp_method; }
- std::vector<byte> session_id_vector() const
- {
- std::vector<byte> v;
- v.insert(v.begin(), &m_session_id[0], &m_session_id[m_session_id.size()]);
- return v;
- }
+ byte compression_method() const { return m_comp_method; }
bool secure_renegotiation() const { return m_secure_renegotiation; }
@@ -190,7 +191,9 @@ class Server_Hello : public Handshake_Message
const MemoryVector<byte>& renegotiation_info()
{ return m_renegotiation_info; }
- const MemoryVector<byte>& random() const { return m_random; }
+ bool supports_heartbeats() const { return m_supports_heartbeats; }
+
+ bool peer_can_send_heartbeats() const { return m_peer_can_send_heartbeats; }
Server_Hello(Record_Writer& writer,
Handshake_Hash& hash,
@@ -204,6 +207,7 @@ class Server_Hello : public Handshake_Message
bool offer_session_ticket,
bool client_has_npn,
const std::vector<std::string>& next_protocols,
+ bool client_has_heartbeat,
RandomNumberGenerator& rng);
Server_Hello(const MemoryRegion<byte>& buf);
@@ -222,6 +226,9 @@ class Server_Hello : public Handshake_Message
bool m_next_protocol;
std::vector<std::string> m_next_protocols;
bool m_supports_session_ticket;
+
+ bool m_supports_heartbeats;
+ bool m_peer_can_send_heartbeats;
};
/**
diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h
index fb27db5e2..38eae7823 100644
--- a/src/tls/tls_record.h
+++ b/src/tls/tls_record.h
@@ -46,6 +46,9 @@ class BOTAN_DLL Record_Writer
void send(byte type, const byte input[], size_t length);
void send(byte type, byte val) { send(type, &val, 1); }
+ void send(byte type, const MemoryRegion<byte>& input)
+ { send(type, &input[0], input.size()); }
+
MemoryVector<byte> send(class Handshake_Message& msg);
void send_alert(const Alert& alert);
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index 10872a825..c591a45c5 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -286,6 +286,9 @@ void Server::process_handshake_msg(Handshake_Type type,
secure_renegotiation.update(state->client_hello);
+ m_peer_supports_heartbeats = state->client_hello->supports_heartbeats();
+ m_heartbeat_sending_allowed = state->client_hello->peer_can_send_heartbeats();
+
writer.set_version(state->version());
reader.set_version(state->version());
@@ -324,6 +327,7 @@ void Server::process_handshake_msg(Handshake_Type type,
have_session_ticket_key),
state->client_hello->next_protocol_notification(),
m_possible_protocols,
+ state->client_hello->supports_heartbeats(),
rng);
if(session_info.fragment_size())
@@ -395,6 +399,7 @@ void Server::process_handshake_msg(Handshake_Type type,
state->client_hello->supports_session_ticket() && have_session_ticket_key,
state->client_hello->next_protocol_notification(),
m_possible_protocols,
+ state->client_hello->supports_heartbeats(),
rng);
if(state->client_hello->fragment_size())