370919 | 2002-03-20 | Martin Nilsson | | #pike __REAL_VERSION__
|
18c01f | 2004-01-25 | Martin Nilsson | | #pragma strict_types
|
e1fb09 | 2014-02-14 | Martin Nilsson | | #require constant(SSL.Cipher)
|
370919 | 2002-03-20 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
f5bb03 | 2001-09-17 | Martin Nilsson | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
f5bb03 | 2001-09-17 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
565b33 | 2014-05-17 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
fc7f09 | 2014-06-01 | Martin Nilsson | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
fc7f09 | 2014-06-01 | Martin Nilsson | |
|
c79dc1 | 2001-06-14 | Pär Svensson | |
|
4f5e1d | 2003-01-27 | Martin Nilsson | | import .Constants;
|
91f9c7 | 2014-05-15 | Martin Nilsson | | #define State .State
|
c65c58 | 2014-05-15 | Martin Nilsson | | #define Session .Session
|
dc90a5 | 2014-05-15 | Martin Nilsson | | #define Context .Context
|
7d5500 | 2014-11-24 | Martin Nilsson | | #define Buffer .Buffer
|
33ef43 | 1997-03-13 | Niels Möller | |
|
813b39 | 2000-08-04 | Andreas Sigfridsson | | #ifdef SSL3_DEBUG
|
624414 | 2003-01-27 | Martin Nilsson | | #define SSL3_DEBUG_MSG(X ...) werror(X)
|
813b39 | 2000-08-04 | Andreas Sigfridsson | | #else /*! SSL3_DEBUG */
|
624414 | 2003-01-27 | Martin Nilsson | | #define SSL3_DEBUG_MSG(X ...)
|
813b39 | 2000-08-04 | Andreas Sigfridsson | | #endif /* SSL3_DEBUG */
|
c65c58 | 2014-05-15 | Martin Nilsson | | Session session;
|
dc90a5 | 2014-05-15 | Martin Nilsson | | Context context;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
91f9c7 | 2014-05-15 | Martin Nilsson | | State pending_read_state;
State pending_write_state;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
5e3a14 | 2014-04-30 | Martin Nilsson | | int handshake_state;
|
fab1c6 | 2014-11-22 | Henrik Grubbström (Grubba) | | int reuse;
|
33ef43 | 1997-03-13 | Niels Möller | |
constant CERT_none = 0;
constant CERT_requested = 1;
|
b1b57a | 1997-03-17 | Niels Möller | | constant CERT_received = 2;
|
33ef43 | 1997-03-13 | Niels Möller | | constant CERT_no_certificate = 3;
int certificate_state;
|
da1209 | 1998-08-26 | Niels Möller | | int expect_change_cipher;
|
87740f | 2011-01-10 | Henrik Grubbström (Grubba) | |
int secure_renegotiation;
|
2d4060 | 2014-05-16 | Martin Nilsson | | string(8bit) client_verify_data = "";
string(8bit) server_verify_data = "";
|
ca9498 | 2013-12-08 | Henrik Grubbström (Grubba) | |
|
87740f | 2011-01-10 | Henrik Grubbström (Grubba) | |
|
2f77da | 2013-11-23 | Henrik Grubbström (Grubba) | |
.Cipher.KeyExchange ke;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
68b67e | 2014-04-05 | Henrik Grubbström (Grubba) | | ProtocolVersion version;
ProtocolVersion client_version;
|
88cfa1 | 2005-10-28 | H. William Welliver III | |
|
f5bb03 | 2001-09-17 | Martin Nilsson | |
|
2d4060 | 2014-05-16 | Martin Nilsson | | string(8bit) client_random;
string(8bit) server_random;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
08afc7 | 2014-05-01 | Martin Nilsson | | #define Packet .Packet
|
7f45cf | 2014-05-15 | Martin Nilsson | | #define Alert .Alert
|
47f84c | 2014-04-12 | Henrik Grubbström (Grubba) | |
|
2d4060 | 2014-05-16 | Martin Nilsson | | Alert alert(int(1..2) level, int(8bit) description,
|
7f45cf | 2014-05-15 | Martin Nilsson | | string|void message)
|
47f84c | 2014-04-12 | Henrik Grubbström (Grubba) | | {
return context->alert_factory(this, level, description, version,
|
74b5eb | 2014-04-24 | Martin Nilsson | | message);
|
47f84c | 2014-04-12 | Henrik Grubbström (Grubba) | | }
|
9eb76c | 2014-11-24 | Martin Nilsson | | Buffer get_signature_algorithms()
|
47c33a | 2014-04-13 | Henrik Grubbström (Grubba) | | {
|
7d5500 | 2014-11-24 | Martin Nilsson | | Buffer sign_algs = Buffer();
|
cec12e | 2014-07-07 | Henrik Grubbström (Grubba) | | foreach(context->get_signature_algorithms(), [int hash, int sign])
|
ef87a8 | 2014-05-20 | Martin Nilsson | | {
|
16d2f1 | 2014-11-21 | Martin Nilsson | | sign_algs->add_int(hash, 1);
sign_algs->add_int(sign, 1);
|
47c33a | 2014-04-13 | Henrik Grubbström (Grubba) | | }
|
9eb76c | 2014-11-24 | Martin Nilsson | | return sign_algs;
|
47c33a | 2014-04-13 | Henrik Grubbström (Grubba) | | }
|
c79dc1 | 2001-06-14 | Pär Svensson | | #ifdef SSL3_PROFILING
|
bc15c2 | 2014-05-02 | Martin Nilsson | | System.Timer timer = System.Timer();
|
c79dc1 | 2001-06-14 | Pär Svensson | | void addRecord(int t,int s) {
|
bc15c2 | 2014-05-02 | Martin Nilsson | | Stdio.stdout.write("time: %.6f sender: %d type: %s\n", timer->get(), s,
fmt_constant(t, "HANDSHAKE"));
|
c79dc1 | 2001-06-14 | Pär Svensson | | }
#endif
|
2d4060 | 2014-05-16 | Martin Nilsson | | string(8bit) handshake_messages;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
09f63c | 2014-11-25 | Martin Nilsson | | Packet handshake_packet(int(8bit) type, string(8bit)|Buffer data)
|
33ef43 | 1997-03-13 | Niels Möller | | {
|
c79dc1 | 2001-06-14 | Pär Svensson | | #ifdef SSL3_PROFILING
addRecord(type,1);
#endif
|
09f63c | 2014-11-25 | Martin Nilsson | | string(8bit) str;
if(stringp(data))
str = [string(8bit)]data;
else
str = ([object(Buffer)]data)->read();
str = sprintf("%1c%3H", type, str);
handshake_messages += str;
|
33ef43 | 1997-03-13 | Niels Möller | |
|
09f63c | 2014-11-25 | Martin Nilsson | | Packet packet = Packet(version, PACKET_handshake, str);
|
33ef43 | 1997-03-13 | Niels Möller | | return packet;
}
|
b6345f | 2004-01-23 | Martin Nilsson | | Packet change_cipher_packet()
|
33ef43 | 1997-03-13 | Niels Möller | | {
|
4d1537 | 2014-11-25 | Martin Nilsson | | return Packet(version, PACKET_change_cipher_spec, "\001");
|
33ef43 | 1997-03-13 | Niels Möller | | }
|
2d4060 | 2014-05-16 | Martin Nilsson | | string(8bit) hash_messages(string(8bit) sender)
|
33ef43 | 1997-03-13 | Niels Möller | | {
|
8ccdd8 | 2014-11-25 | Martin Nilsson | | string(8bit) hash;
|
68b67e | 2014-04-05 | Henrik Grubbström (Grubba) | | if(version == PROTOCOL_SSL_3_0) {
|
044964 | 2014-11-27 | Martin Nilsson | | string(8bit) data = handshake_messages + sender;
|
2a87c8 | 2014-11-26 | Martin Nilsson | | hash = .Cipher.MACmd5(session->master_secret)->hash(data) +
.Cipher.MACsha(session->master_secret)->hash(data);
|
aa77d5 | 2001-04-18 | Pär Svensson | | }
|
68b67e | 2014-04-05 | Henrik Grubbström (Grubba) | | else if(version <= PROTOCOL_TLS_1_1) {
|
8ccdd8 | 2014-11-25 | Martin Nilsson | | hash = session->cipher_spec->prf(session->master_secret, sender,
|
0791b1 | 2013-11-24 | Henrik Grubbström (Grubba) | | Crypto.MD5.hash(handshake_messages)+
Crypto.SHA1.hash(handshake_messages), 12);
|
68b67e | 2014-04-05 | Henrik Grubbström (Grubba) | | } else if(version >= PROTOCOL_TLS_1_2) {
|
8ccdd8 | 2014-11-25 | Martin Nilsson | | hash = session->cipher_spec->prf(session->master_secret, sender,
|
b492c8 | 2014-11-25 | Martin Nilsson | | session->cipher_spec->hash
->hash(handshake_messages), 12);
|
aa77d5 | 2001-04-18 | Pär Svensson | | }
|
8ccdd8 | 2014-11-25 | Martin Nilsson | |
return hash;
|
33ef43 | 1997-03-13 | Niels Möller | | }
|
2d4060 | 2014-05-16 | Martin Nilsson | | Packet certificate_packet(array(string(8bit)) certificates)
|
88cfa1 | 2005-10-28 | H. William Welliver III | | {
|
09f63c | 2014-11-25 | Martin Nilsson | | return handshake_packet(HANDSHAKE_certificate,
Buffer()->add_string_array(certificates, 3, 3));
|
88cfa1 | 2005-10-28 | H. William Welliver III | | }
|
2e19a4 | 2014-12-30 | Henrik Grubbström (Grubba) | | Packet certificate_verify_packet()
{
SSL3_DEBUG_MSG("SSL.Connection: CERTIFICATE_VERIFY\n"
"%O: handshake_messages: %d bytes.\n",
this_object(), sizeof(handshake_messages));
Buffer struct = Buffer();
session->cipher_spec->sign(session, handshake_messages, struct);
return handshake_packet(HANDSHAKE_certificate_verify, struct);
}
|
09f63c | 2014-11-25 | Martin Nilsson | | Packet heartbeat_packet(Buffer s)
|
978f57 | 2014-04-14 | Henrik Grubbström (Grubba) | | {
|
09f63c | 2014-11-25 | Martin Nilsson | | return Packet(version, PACKET_heartbeat, s->read());
|
978f57 | 2014-04-14 | Henrik Grubbström (Grubba) | | }
protected Crypto.AES heartbeat_encode;
protected Crypto.AES heartbeat_decode;
Packet heartbleed_packet()
{
if (!heartbeat_encode) {
heartbeat_encode = Crypto.AES();
heartbeat_decode = Crypto.AES();
string(8bit) heartbeat_key = random_string(16);
heartbeat_encode->set_encrypt_key(heartbeat_key);
heartbeat_decode->set_decrypt_key(heartbeat_key);
}
|
7d5500 | 2014-11-24 | Martin Nilsson | | Buffer hb_msg = Buffer();
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add_int(HEARTBEAT_MESSAGE_request, 1);
hb_msg->add_int(16, 2);
|
978f57 | 2014-04-14 | Henrik Grubbström (Grubba) | | int now = gethrtime();
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add(heartbeat_encode->crypt(sprintf("%8c%8c", now, 0)));
|
978f57 | 2014-04-14 | Henrik Grubbström (Grubba) | |
|
09f63c | 2014-11-25 | Martin Nilsson | | return heartbeat_packet(hb_msg);
|
978f57 | 2014-04-14 | Henrik Grubbström (Grubba) | | }
|
0f48d7 | 2014-12-21 | Martin Nilsson | |
|
f591dd | 2004-01-29 | H. William Welliver III | |
|
b6345f | 2004-01-23 | Martin Nilsson | | int verify_certificate_chain(array(string) certs)
|
7e7821 | 2004-01-23 | H. William Welliver III | | {
|
0f48d7 | 2014-12-21 | Martin Nilsson | |
|
526a40 | 2004-01-30 | H. William Welliver III | | if(!context->verify_certificates)
return 1;
|
0f48d7 | 2014-12-21 | Martin Nilsson | |
|
88cfa1 | 2005-10-28 | H. William Welliver III | |
if((context->auth_level < AUTHLEVEL_require) && !sizeof(certs))
return 1;
|
0f48d7 | 2014-12-21 | Martin Nilsson | |
|
868f71 | 2012-05-20 | Martin Nilsson | |
|
0f48d7 | 2014-12-21 | Martin Nilsson | | if(!sizeof(certs))
|
88cfa1 | 2005-10-28 | H. William Welliver III | | return 0;
|
09aa4f | 2013-12-04 | Martin Nilsson | |
|
526a40 | 2004-01-30 | H. William Welliver III | | if(sizeof(context->authorities_cache))
|
7e7821 | 2004-01-23 | H. William Welliver III | | {
|
9cade8 | 2014-02-15 | Martin Nilsson | | string r=Standards.X509.decode_certificate(certs[-1])->issuer
|
09aa4f | 2013-12-04 | Martin Nilsson | | ->get_der();
int issuer_known = 0;
foreach(context->authorities_cache, string c)
|
7e7821 | 2004-01-23 | H. William Welliver III | | {
|
09aa4f | 2013-12-04 | Martin Nilsson | | if(r == c)
|
526a40 | 2004-01-30 | H. William Welliver III | | {
issuer_known = 1;
break;
}
|
7e7821 | 2004-01-23 | H. William Welliver III | | }
|
526a40 | 2004-01-30 | H. William Welliver III | | if(issuer_known==0)
{
return 0;
}
|
f591dd | 2004-01-29 | H. William Welliver III | | }
|
765567 | 2004-01-27 | H. William Welliver III | |
|
7e7821 | 2004-01-23 | H. William Welliver III | |
|
765567 | 2004-01-27 | H. William Welliver III | |
|
d13f3f | 2013-11-24 | Henrik Grubbström (Grubba) | | mapping result =
|
81bef2 | 2013-12-04 | Martin Nilsson | | Standards.X509.verify_certificate_chain(certs,
context->trusted_issuers_cache,
|
d13f3f | 2013-11-24 | Henrik Grubbström (Grubba) | | context->require_trust);
|
765567 | 2004-01-27 | H. William Welliver III | | if(result->verified)
|
f591dd | 2004-01-29 | H. William Welliver III | | {
|
81bef2 | 2013-12-04 | Martin Nilsson | |
|
f591dd | 2004-01-29 | H. William Welliver III | | session->cert_data = result;
|
765567 | 2004-01-27 | H. William Welliver III | | return 1;
|
f591dd | 2004-01-29 | H. William Welliver III | | }
|
7e7821 | 2004-01-23 | H. William Welliver III | |
|
868f71 | 2012-05-20 | Martin Nilsson | | return 0;
|
7e7821 | 2004-01-23 | H. William Welliver III | | }
|
aa77d5 | 2001-04-18 | Pär Svensson | |
|
f5bb03 | 2001-09-17 | Martin Nilsson | |
|
4c0c47 | 2013-10-27 | Henrik Grubbström (Grubba) | |
|
3a5f8e | 2010-02-21 | Stephen R. van den Berg | |
|
5f883e | 2008-09-05 | Martin Stjernholm | |
|
2d4060 | 2014-05-16 | Martin Nilsson | | int(-1..1) handle_handshake(int type, string(8bit) data, string(8bit) raw);
|
33ef43 | 1997-03-13 | Niels Möller | |
|
4ceceb | 2014-05-05 | Henrik Grubbström (Grubba) | |
|
6262d4 | 2011-12-15 | Henrik Grubbström (Grubba) | |
|
dc90a5 | 2014-05-15 | Martin Nilsson | | protected void create(Context ctx)
|
33ef43 | 1997-03-13 | Niels Möller | | {
|
91f9c7 | 2014-05-15 | Martin Nilsson | | current_read_state = State(this);
current_write_state = State(this);
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
f466b6 | 2014-04-04 | Henrik Grubbström (Grubba) | | if ((ctx->max_version < PROTOCOL_SSL_3_0) ||
(ctx->max_version > PROTOCOL_TLS_MAX)) {
ctx->max_version = PROTOCOL_TLS_MAX;
|
6262d4 | 2011-12-15 | Henrik Grubbström (Grubba) | | }
|
f466b6 | 2014-04-04 | Henrik Grubbström (Grubba) | | if (ctx->min_version < PROTOCOL_SSL_3_0) {
ctx->min_version = PROTOCOL_SSL_3_0;
} else if (ctx->min_version > ctx->max_version) {
ctx->min_version = ctx->max_version;
|
6262d4 | 2011-12-15 | Henrik Grubbström (Grubba) | | }
|
68b67e | 2014-04-05 | Henrik Grubbström (Grubba) | | version = ctx->max_version;
|
a30079 | 2003-10-24 | Martin Stjernholm | | context = ctx;
|
84b90d | 2014-05-04 | Martin Nilsson | | }
|
91f9c7 | 2014-05-15 | Martin Nilsson | | State current_read_state;
State current_write_state;
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | string(8bit) left_over;
|
84b90d | 2014-05-04 | Martin Nilsson | | Packet packet;
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | |
|
84b90d | 2014-05-04 | Martin Nilsson | | int sent;
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | |
ConnectionState state = CONNECTION_handshaking;
|
84b90d | 2014-05-04 | Martin Nilsson | |
function(object,int|object,string:void) alert_callback;
constant PRI_alert = 1;
constant PRI_urgent = 2;
constant PRI_application = 3;
|
7f45cf | 2014-05-15 | Martin Nilsson | | protected ADT.Queue alert_q = ADT.Queue();
protected ADT.Queue urgent_q = ADT.Queue();
protected ADT.Queue application_q = ADT.Queue();
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | |
string describe_state()
{
if (!state) return "ready";
array(string) res = ({});
if (state & CONNECTION_handshaking) res += ({ "handshaking" });
if (state & CONNECTION_local_failing) {
if (state & CONNECTION_local_fatal) {
res += ({ "local_fatal" });
} else {
res += ({ "local_failing" });
}
}
if (state & CONNECTION_local_closing) {
if (state & CONNECTION_local_closed) {
res += ({ "local_closed" });
} else {
res += ({ "local_closing" });
}
}
if (state & CONNECTION_peer_fatal) res += ({ "peer_fatal" });
if (state & CONNECTION_peer_closed) res += ({ "peer_closed" });
return res * "|";
}
|
423a55 | 2014-08-01 | Henrik Grubbström (Grubba) | | protected string _sprintf(int t)
{
if (t == 'O') return sprintf("SSL.Connection(%s)", describe_state());
}
|
84b90d | 2014-05-04 | Martin Nilsson | |
void set_alert_callback(function(object,int|object,string:void) callback)
{
alert_callback = callback;
}
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | protected Packet recv_packet(string(8bit) data)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | string(8bit)|Packet res;
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
938d51 | 2014-05-16 | Martin Nilsson | |
|
84b90d | 2014-05-04 | Martin Nilsson | | if (left_over || !packet)
{
|
6dfd42 | 2014-08-07 | Martin Nilsson | | packet = Packet(version, 2048);
res = packet->recv( (left_over || "") + data);
|
84b90d | 2014-05-04 | Martin Nilsson | | }
else
|
6dfd42 | 2014-08-07 | Martin Nilsson | | res = packet->recv(data);
|
84b90d | 2014-05-04 | Martin Nilsson | |
if (stringp(res))
{
left_over = [string]res;
if (current_read_state) {
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection->recv_packet(): version=0x%x\n",
|
84b90d | 2014-05-04 | Martin Nilsson | | version);
|
6dfd42 | 2014-08-07 | Martin Nilsson | | return current_read_state->decrypt_packet(packet);
|
84b90d | 2014-05-04 | Martin Nilsson | | } else {
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection->recv_packet(): current_read_state is zero!\n");
|
84b90d | 2014-05-04 | Martin Nilsson | | return 0;
}
}
else
left_over = 0;
return [object]res;
}
|
31e650 | 2014-05-16 | Martin Nilsson | | void send_packet(Packet packet, int|void priority)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_local_closing) {
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection->send_packet: ignoring packet after close\n");
|
84b90d | 2014-05-04 | Martin Nilsson | | return;
}
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (packet->content_type == PACKET_alert) {
if (packet->level == ALERT_fatal) {
state = [int(0..0)|ConnectionState](state | CONNECTION_local_failing);
} else if (packet->description == ALERT_close_notify) {
state = [int(0..0)|ConnectionState](state | CONNECTION_local_closing);
}
}
|
84b90d | 2014-05-04 | Martin Nilsson | |
if (!priority)
priority = ([ PACKET_alert : PRI_alert,
PACKET_change_cipher_spec : PRI_urgent,
PACKET_handshake : PRI_urgent,
PACKET_heartbeat : PRI_urgent,
|
b492c8 | 2014-11-25 | Martin Nilsson | | PACKET_application_data : PRI_application
])[packet->content_type];
|
5c4191 | 2014-08-24 | Henrik Grubbström (Grubba) | |
if ((packet->content_type == PACKET_handshake) &&
(priority == PRI_application)) {
expect_change_cipher = 0;
certificate_state = 0;
state = [int(0..0)|ConnectionState](state | CONNECTION_handshaking);
handshake_state = STATE_wait_for_hello;
}
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection->send_packet: type %d, pri %d, %O\n",
|
31e650 | 2014-05-16 | Martin Nilsson | | packet->content_type, priority, packet->fragment[..5]);
|
84b90d | 2014-05-04 | Martin Nilsson | | switch (priority)
{
default:
error( "Internal error\n" );
case PRI_alert:
|
7f45cf | 2014-05-15 | Martin Nilsson | | alert_q->put(packet);
|
84b90d | 2014-05-04 | Martin Nilsson | | break;
case PRI_urgent:
|
7f45cf | 2014-05-15 | Martin Nilsson | | urgent_q->put(packet);
|
84b90d | 2014-05-04 | Martin Nilsson | | break;
case PRI_application:
|
7f45cf | 2014-05-15 | Martin Nilsson | | application_q->put(packet);
|
84b90d | 2014-05-04 | Martin Nilsson | | break;
}
}
|
02bb9d | 2014-07-13 | Henrik Grubbström (Grubba) | |
int query_write_queue_size()
{
return sizeof(alert_q) + sizeof(urgent_q) + sizeof(application_q);
}
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
02bb9d | 2014-07-13 | Henrik Grubbström (Grubba) | |
|
84b90d | 2014-05-04 | Martin Nilsson | | string|int to_write()
{
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_local_fatal)
|
84b90d | 2014-05-04 | Martin Nilsson | | return -1;
|
7f45cf | 2014-05-15 | Martin Nilsson | | Packet packet = [object(Packet)](alert_q->get() || urgent_q->get() ||
application_q->get());
|
84b90d | 2014-05-04 | Martin Nilsson | | if (!packet) {
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | return (state & CONNECTION_local_closing) ? 1 : "";
|
84b90d | 2014-05-04 | Martin Nilsson | | }
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: writing packet of type %d, %O\n",
|
84b90d | 2014-05-04 | Martin Nilsson | | packet->content_type, packet->fragment[..6]);
if (packet->content_type == PACKET_alert)
{
if (packet->level == ALERT_fatal) {
|
6fda6f | 2014-10-14 | Henrik Grubbström (Grubba) | | state = [int(0..0)|ConnectionState](state | CONNECTION_local_fatal |
CONNECTION_peer_closed);
|
84b90d | 2014-05-04 | Martin Nilsson | |
if (session) {
context->purge_session(session);
}
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | } else if (packet->description == ALERT_close_notify) {
state = [int(0..0)|ConnectionState](state | CONNECTION_local_closed);
|
84b90d | 2014-05-04 | Martin Nilsson | | }
}
|
3455b8 | 2014-11-20 | Martin Nilsson | | string res = current_write_state->encrypt_packet(packet, context)->send();
|
84b90d | 2014-05-04 | Martin Nilsson | | if (packet->content_type == PACKET_change_cipher_spec)
current_write_state = pending_write_state;
return res;
}
void send_close()
{
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_warning, ALERT_close_notify,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Closing connection.\n"), PRI_application);
}
|
5c4191 | 2014-08-24 | Henrik Grubbström (Grubba) | |
void send_renegotiate();
|
84b90d | 2014-05-04 | Martin Nilsson | |
int send_streaming_data (string(8bit) data)
{
|
b5c591 | 2014-11-25 | Martin Nilsson | | int size = sizeof(data);
if (!size) return 0;
|
84b90d | 2014-05-04 | Martin Nilsson | | if ((!sent) && (version < PROTOCOL_TLS_1_1) &&
|
b5c591 | 2014-11-25 | Martin Nilsson | | (session->cipher_spec->cipher_type == CIPHER_block) &&
(size>1))
{
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
b5c591 | 2014-11-25 | Martin Nilsson | | send_packet(Packet(version, PACKET_application_data, data[..0]));
data = data[1..];
|
84b90d | 2014-05-04 | Martin Nilsson | | }
|
b5c591 | 2014-11-25 | Martin Nilsson | |
send_packet(Packet(version, PACKET_application_data,
data[..session->max_packet_size-1]));;
|
84b90d | 2014-05-04 | Martin Nilsson | | sent += size;
return size;
}
protected int handle_alert(string s)
{
int level = s[0];
int description = s[1];
if (! (ALERT_levels[level] && ALERT_descriptions[description]))
{
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "invalid alert\n"));
return -1;
}
if (level == ALERT_fatal)
{
|
a03254 | 2014-05-19 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Fatal alert %O\n",
ALERT_descriptions[description]);
|
6fda6f | 2014-10-14 | Henrik Grubbström (Grubba) | | state = [int(0..0)|ConnectionState](state | CONNECTION_peer_fatal |
CONNECTION_peer_closed);
|
9e98b9 | 2014-12-05 | Henrik Grubbström (Grubba) | |
if (session) {
context->purge_session(session);
}
|
84b90d | 2014-05-04 | Martin Nilsson | | return -1;
}
if (description == ALERT_close_notify)
{
|
a03254 | 2014-05-19 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: %O\n", ALERT_descriptions[description]);
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | state = [int(0..0)|ConnectionState](state | CONNECTION_peer_closed);
|
84b90d | 2014-05-04 | Martin Nilsson | | return 1;
}
if (description == ALERT_no_certificate)
{
|
a03254 | 2014-05-19 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: %O\n", ALERT_descriptions[description]);
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
b492c8 | 2014-11-25 | Martin Nilsson | | if ( (certificate_state == CERT_requested) &&
(context->auth_level == AUTHLEVEL_ask) )
|
84b90d | 2014-05-04 | Martin Nilsson | | {
certificate_state = CERT_no_certificate;
return 0;
} else {
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal,
|
84b90d | 2014-05-04 | Martin Nilsson | | ((certificate_state == CERT_requested)
? ALERT_handshake_failure
: ALERT_unexpected_message),
"Certificate required.\n"));
return -1;
}
}
#ifdef SSL3_DEBUG
else
|
a03254 | 2014-05-19 | Martin Nilsson | | werror("SSL.Connection: Received warning alert %O\n",
ALERT_descriptions[description]);
|
84b90d | 2014-05-04 | Martin Nilsson | | #endif
return 0;
}
|
da3381 | 2004-01-14 | H. William Welliver III | |
|
84b90d | 2014-05-04 | Martin Nilsson | | int handle_change_cipher(int c)
{
if (!expect_change_cipher || (c != 1))
{
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Unexpected change cipher!\n"));
return -1;
}
|
33ef43 | 1997-03-13 | Niels Möller | | else
|
813b39 | 2000-08-04 | Andreas Sigfridsson | | {
|
84b90d | 2014-05-04 | Martin Nilsson | | current_read_state = pending_read_state;
expect_change_cipher = 0;
return 0;
}
}
void send_heartbeat()
{
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if ((state != CONNECTION_ready) ||
|
84b90d | 2014-05-04 | Martin Nilsson | | (session->heartbeat_mode != HEARTBEAT_MODE_peer_allowed_to_send)) {
return;
}
|
7d5500 | 2014-11-24 | Martin Nilsson | | Buffer hb_msg = Buffer();
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add_int(HEARTBEAT_MESSAGE_request, 1);
hb_msg->add_int(16, 2);
|
84b90d | 2014-05-04 | Martin Nilsson | | int now = gethrtime();
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add(heartbeat_encode->crypt(sprintf("%8c%8c", now, now)));
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add(random_string(64 - sizeof(hb_msg)));
|
09f63c | 2014-11-25 | Martin Nilsson | | send_packet(heartbeat_packet(hb_msg));
|
84b90d | 2014-05-04 | Martin Nilsson | | }
void handle_heartbeat(string(8bit) s)
{
if (sizeof(s) < 19) return;
|
7d5500 | 2014-11-24 | Martin Nilsson | | Buffer hb_msg = Buffer(s);
|
16d2f1 | 2014-11-21 | Martin Nilsson | | int hb_type = hb_msg->read_int(1);
int hb_len = hb_msg->read_int(2);
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Heartbeat %s (%d bytes)",
|
84b90d | 2014-05-04 | Martin Nilsson | | fmt_constant(hb_type, "HEARTBEAT_MESSAGE"), hb_len);
string(8bit) payload;
int pad_len = 16;
if ((hb_len < 0) || ((hb_len + 16) > sizeof(hb_msg))) {
#ifdef SSL3_SIMULATE_HEARTBLEED
|
16d2f1 | 2014-11-21 | Martin Nilsson | | payload = hb_msg->read();
|
84b90d | 2014-05-04 | Martin Nilsson | | if (sizeof(payload) < hb_len) {
payload = payload + random_string(hb_len - sizeof(payload));
} else {
payload = payload[..hb_len-1];
}
#else
return;
#endif
} else {
|
16d2f1 | 2014-11-21 | Martin Nilsson | | payload = hb_msg->read(hb_len);
|
84b90d | 2014-05-04 | Martin Nilsson | | pad_len = sizeof(hb_msg);
}
switch(hb_type) {
case HEARTBEAT_MESSAGE_request:
|
7d5500 | 2014-11-24 | Martin Nilsson | | hb_msg = Buffer();
|
16d2f1 | 2014-11-21 | Martin Nilsson | | hb_msg->add_int(HEARTBEAT_MESSAGE_response, 1);
hb_msg->add_int(hb_len, 2);
hb_msg->add(payload);
hb_msg->add(random_string(pad_len));
|
09f63c | 2014-11-25 | Martin Nilsson | | send_packet(heartbeat_packet(hb_msg));
|
84b90d | 2014-05-04 | Martin Nilsson | | break;
case HEARTBEAT_MESSAGE_response:
if ((sizeof(payload) == 16) && heartbeat_decode) {
|
7d5500 | 2014-11-24 | Martin Nilsson | | hb_msg = Buffer(heartbeat_decode->crypt(payload));
|
16d2f1 | 2014-11-21 | Martin Nilsson | | int a = hb_msg->read_int(8);
int b = hb_msg->read_int(8);
|
84b90d | 2014-05-04 | Martin Nilsson | | if (a != b) {
if (!b) {
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_insufficient_security,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Peer suffers from a bleeding heart.\n"));
}
break;
}
#ifdef SSL3_DEBUG
int delta = gethrtime() - a;
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Heartbeat roundtrip: %dus\n", delta);
|
84b90d | 2014-05-04 | Martin Nilsson | | #endif
}
break;
default:
break;
}
}
string(8bit) alert_buffer = "";
string(8bit) handshake_buffer = "";
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | |
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | string(8bit)|int got_data(string(8bit) data)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_peer_closed) {
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | |
|
84b90d | 2014-05-04 | Martin Nilsson | | return 1;
}
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | |
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | string(8bit) alert_context = (left_over || "") + data;
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | string(8bit) res = "";
|
84b90d | 2014-05-04 | Martin Nilsson | | Packet packet;
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | while (packet = recv_packet(data))
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | data = "";
|
84b90d | 2014-05-04 | Martin Nilsson | |
if (packet->is_alert)
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Bad received packet\n");
|
84b90d | 2014-05-04 | Martin Nilsson | | if (alert_callback)
alert_callback(packet, current_read_state->seq_num, alert_context);
|
68ac5e | 2014-11-13 | Henrik Grubbström (Grubba) | | if (this && packet)
send_packet(packet);
|
84b90d | 2014-05-04 | Martin Nilsson | | if ((!packet) || (!this) || (packet->level == ALERT_fatal))
return -1;
if (alert_callback)
break;
}
else
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: received packet of type %d\n",
|
84b90d | 2014-05-04 | Martin Nilsson | | packet->content_type);
switch (packet->content_type)
{
case PACKET_alert:
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: ALERT\n");
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
0844c2 | 2014-08-05 | Martin Nilsson | | if( !sizeof(packet->fragment) )
{
send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
"Zero length Alert fragments not allowed.\n"));
return -1;
}
|
84b90d | 2014-05-04 | Martin Nilsson | | int i;
int err = 0;
alert_buffer += packet->fragment;
for (i = 0;
!err && ((sizeof(alert_buffer) - i) >= 2);
i+= 2)
err = handle_alert(alert_buffer[i..i+1]);
alert_buffer = alert_buffer[i..];
if (err)
if (err > 0 && sizeof (res))
return res;
else
return err;
break;
}
case PACKET_change_cipher_spec:
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: CHANGE_CIPHER_SPEC\n");
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
0844c2 | 2014-08-05 | Martin Nilsson | | if( !sizeof(packet->fragment) )
{
send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
"Zero length ChangeCipherSpec fragments not allowed.\n"));
return -1;
}
|
5cbf61 | 2014-08-05 | Martin Nilsson | | foreach(packet->fragment;; int c)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
5cbf61 | 2014-08-05 | Martin Nilsson | | int err = handle_change_cipher(c);
|
84b90d | 2014-05-04 | Martin Nilsson | | SSL3_DEBUG_MSG("tried change_cipher: %d\n", err);
if (err)
return err;
}
break;
}
case PACKET_handshake:
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: HANDSHAKE\n");
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
0844c2 | 2014-08-05 | Martin Nilsson | | if( !sizeof(packet->fragment) )
{
send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
"Zero length Handshake fragments not allowed.\n"));
return -1;
}
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (!(state & CONNECTION_handshaking) &&
!secure_renegotiation) {
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_warning, ALERT_no_renegotiation,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Renegotiation not supported in unsecure mode.\n"));
return -1;
}
if (expect_change_cipher)
{
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Expected change cipher.\n"));
return -1;
}
int err, len;
handshake_buffer += packet->fragment;
while (sizeof(handshake_buffer) >= 4)
{
sscanf(handshake_buffer, "%*c%3c", len);
if (sizeof(handshake_buffer) < (len + 4))
break;
|
6f35e9 | 2014-05-05 | Martin Nilsson | | mixed exception = catch {
err = handle_handshake(handshake_buffer[0],
handshake_buffer[4..len + 3],
handshake_buffer[.. len + 3]);
};
if( exception )
{
|
7d5500 | 2014-11-24 | Martin Nilsson | | if( objectp(exception) && ([object]exception)->buffer_error )
|
6f35e9 | 2014-05-05 | Martin Nilsson | | {
Error.Generic e = [object(Error.Generic)]exception;
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_decode_error,
|
6f35e9 | 2014-05-05 | Martin Nilsson | | e->message()));
return -1;
}
throw(exception);
}
|
84b90d | 2014-05-04 | Martin Nilsson | | handshake_buffer = handshake_buffer[len + 4..];
if (err < 0)
return err;
if (err > 0) {
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | state &= ~CONNECTION_handshaking;
|
84b90d | 2014-05-04 | Martin Nilsson | | }
}
break;
}
case PACKET_application_data:
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: APPLICATION_DATA\n");
|
84b90d | 2014-05-04 | Martin Nilsson | |
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_handshaking)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Handshake not finished yet!\n"));
return -1;
}
res += packet->fragment;
break;
case PACKET_heartbeat:
{
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Heartbeat.\n");
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state != CONNECTION_ready) {
|
84b90d | 2014-05-04 | Martin Nilsson | |
break;
}
if (!session->heartbeat_mode) {
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_warning, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Heart beat mode not enabled.\n"));
break;
}
|
6f35e9 | 2014-05-05 | Martin Nilsson | |
mixed exception = catch {
handle_heartbeat(packet->fragment);
};
if( exception )
{
|
7d5500 | 2014-11-24 | Martin Nilsson | | if( objectp(exception) && ([object]exception)->buffer_error )
|
6f35e9 | 2014-05-05 | Martin Nilsson | | {
Error.Generic e = [object(Error.Generic)]exception;
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_decode_error,
|
6f35e9 | 2014-05-05 | Martin Nilsson | | e->message()));
return -1;
}
throw(exception);
}
|
84b90d | 2014-05-04 | Martin Nilsson | | }
break;
default:
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_handshaking)
|
84b90d | 2014-05-04 | Martin Nilsson | | {
|
7f45cf | 2014-05-15 | Martin Nilsson | | send_packet(alert(ALERT_fatal, ALERT_unexpected_message,
|
84b90d | 2014-05-04 | Martin Nilsson | | "Unexpected message during handshake!\n"));
return -1;
}
|
938d51 | 2014-05-16 | Martin Nilsson | | SSL3_DEBUG_MSG("SSL.Connection: Ignoring packet of type %s\n",
|
84b90d | 2014-05-04 | Martin Nilsson | | fmt_constant(packet->content_type, "PACKET"));
break;
}
}
|
813b39 | 2000-08-04 | Andreas Sigfridsson | | }
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | if (sizeof(res)) return res;
|
2ed01a | 2014-05-23 | Henrik Grubbström (Grubba) | | if (state & CONNECTION_peer_closed) return 1;
|
4eacaa | 2014-05-18 | Henrik Grubbström (Grubba) | | return "";
|
33ef43 | 1997-03-13 | Niels Möller | | }
|