if (!PACKET_forward(&pkt, 1)
/* Save the sequence number: 64 bits, with top 2 bytes = epoch */
|| !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
- || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)
- || PACKET_remaining(&pkt) != 0) {
+ || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
+ /*
+ * We allow data remaining at the end of the packet because there could
+ * be a second record (but we ignore it)
+ */
/* This is an initial ClientHello so the epoch has to be 0 */
if (seq[0] != 0 || seq[1] != 0) {
|| !PACKET_get_net_2(&msgpkt, &msgseq)
|| !PACKET_get_net_3(&msgpkt, &fragoff)
|| !PACKET_get_net_3(&msgpkt, &fraglen)
- || !PACKET_get_sub_packet(&msgpkt, &msgpayload, msglen)
+ || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
|| PACKET_remaining(&msgpkt) != 0) {
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
goto end;
}
- /* We don't support a fragmented ClientHello whilst listening */
- if (fragoff != 0 || fraglen != msglen) {
+ /*
+ * We don't support fragment reassembly for ClientHellos whilst
+ * listening because that would require server side state (which is
+ * against the whole point of the ClientHello/HelloVerifyRequest
+ * mechanism). Instead we only look at the first ClientHello fragment
+ * and require that the cookie must be contained within it.
+ */
+ if (fragoff != 0 || fraglen > msglen) {
+ /* Non initial ClientHello fragment (or bad fragment) */
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
goto end;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
- msglen + DTLS1_HM_HEADER_LENGTH, s,
+ fraglen + DTLS1_HM_HEADER_LENGTH, s,
s->msg_callback_arg);
if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
|| !PACKET_get_length_prefixed_1(&msgpayload, &session)
|| !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
+ /*
+ * Could be malformed or the cookie does not fit within the initial
+ * ClientHello fragment. Either way we can't handle it.
+ */
SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
goto end;
}
s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+
+ if ((tmpclient = BIO_ADDR_new()) == NULL) {
+ SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
/*
* This is unneccessary if rbio and wbio are one and the same - but
- * maybe they're not.
+ * maybe they're not. We ignore errors here - some BIOs do not
+ * support this.
*/
- if ((tmpclient = BIO_ADDR_new()) == NULL
- || BIO_dgram_get_peer(rbio, tmpclient) <= 0
- || BIO_dgram_set_peer(wbio, tmpclient) <= 0) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
- goto end;
+ if(BIO_dgram_get_peer(rbio, tmpclient) > 0) {
+ (void)BIO_dgram_set_peer(wbio, tmpclient);
}
BIO_ADDR_free(tmpclient);
tmpclient = NULL;
*/
ossl_statem_set_hello_verify_done(s);
- if(BIO_dgram_get_peer(rbio, client) <= 0) {
- SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
- return -1;
- }
+ /* Some BIOs may not support this. If we fail we clear the client address */
+ if (BIO_dgram_get_peer(rbio, client) <= 0)
+ BIO_ADDR_clear(client);
ret = 1;
clearpkt = 0;
unsigned int padding = 16; /* Use minimum padding */
if (s->msg_callback)
- s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
+ s->msg_callback(0, s->version, DTLS1_RT_HEARTBEAT,
p, length, s, s->msg_callback_arg);
/* Read type and payload length first */
return -1;
}
- r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
+ r = dtls1_write_bytes(s, DTLS1_RT_HEARTBEAT, buffer, write_length);
if (r >= 0 && s->msg_callback)
- s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
+ s->msg_callback(1, s->version, DTLS1_RT_HEARTBEAT,
buffer, write_length, s, s->msg_callback_arg);
OPENSSL_free(buffer);
unsigned int padding = 16; /* Use minimum padding */
/* Only send if peer supports and accepts HB requests... */
- if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
- s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) {
+ if (!(s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED) ||
+ s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_SEND_REQUESTS) {
SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
return -1;
}
goto err;
}
- ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
+ ret = dtls1_write_bytes(s, DTLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
if (ret >= 0) {
if (s->msg_callback)
- s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
+ s->msg_callback(1, s->version, DTLS1_RT_HEARTBEAT,
buf, 3 + payload + padding,
s, s->msg_callback_arg);