@@ -58,9 +58,10 @@ struct qd_tls_t {
58
58
qd_tls_on_secure_cb_t * on_secure_cb ;
59
59
bool tls_has_output ;
60
60
bool tls_error ;
61
- bool output_eos ; // pn_tls_close_output() called
62
- bool input_drained ; // no more decrypted output, raw conn read closed
63
- bool output_flushed ; // encrypt done, raw conn write closed
61
+ bool output_eos ; // pn_tls_close_output() called
62
+ bool raw_read_drained ; // raw conn read closed and all buffer read
63
+ bool input_drained ; // no more decrypted output, raw conn read closed
64
+ bool output_flushed ; // encrypt done, raw conn write closed
64
65
65
66
uint64_t encrypted_output_bytes ;
66
67
uint64_t encrypted_input_bytes ;
@@ -1274,8 +1275,13 @@ int qd_tls_do_io2(qd_tls_t *tls,
1274
1275
if (capacity > 0 && (!pn_tls_is_secure (tls -> tls_session ) || input_data != 0 )) {
1275
1276
size_t pushed = 0 ;
1276
1277
total_octets = 0 ;
1277
- while (pushed < capacity && pn_raw_connection_take_read_buffers (raw_conn , & pn_buf_desc , 1 ) == 1 ) {
1278
- if (pn_buf_desc .size ) {
1278
+ while (pushed < capacity ) {
1279
+ size_t took = pn_raw_connection_take_read_buffers (raw_conn , & pn_buf_desc , 1 );
1280
+ if (took != 1 ) {
1281
+ // No more read buffers available. Now it is safe to check if the raw connection has closed
1282
+ tls -> raw_read_drained = pn_raw_connection_is_read_closed (raw_conn );
1283
+ break ;
1284
+ } else if (pn_buf_desc .size ) {
1279
1285
total_octets += pn_buf_desc .size ;
1280
1286
given = pn_tls_give_decrypt_input_buffers (tls -> tls_session , & pn_buf_desc , 1 );
1281
1287
assert (given == 1 );
@@ -1427,6 +1433,8 @@ int qd_tls_do_io2(qd_tls_t *tls,
1427
1433
return -1 ;
1428
1434
}
1429
1435
1436
+ // check if the output (encrypt) side is done
1437
+ //
1430
1438
if (tls -> output_eos && !pn_tls_is_encrypt_output_pending (tls -> tls_session )) {
1431
1439
// We closed the encrypt side of the TLS connection and we've sent all output
1432
1440
tls -> output_flushed = true;
@@ -1437,9 +1445,12 @@ int qd_tls_do_io2(qd_tls_t *tls,
1437
1445
}
1438
1446
}
1439
1447
1440
- if (pn_tls_is_input_closed (tls -> tls_session )
1441
- || (pn_raw_connection_is_read_closed (raw_conn ) && !pn_tls_is_decrypt_output_pending (tls -> tls_session ))) {
1442
- // TLS will not take any more encrypted input - drain the raw conn input
1448
+ // check for end of input (decrypt done)
1449
+ //
1450
+ if (pn_tls_is_input_closed (tls -> tls_session )) {
1451
+ // TLS clean close signalled by remote. Do not read any more data (prevent truncation attack).
1452
+ //
1453
+ tls -> input_drained = true;
1443
1454
if (!pn_raw_connection_is_read_closed (raw_conn )) {
1444
1455
qd_log (tls -> log_module , QD_LOG_DEBUG ,
1445
1456
"[C%" PRIu64 "] TLS input closed - closing read side of raw connection" , tls -> conn_id );
@@ -1448,8 +1459,12 @@ int qd_tls_do_io2(qd_tls_t *tls,
1448
1459
while (pn_raw_connection_take_read_buffers (raw_conn , & pn_buf_desc , 1 ) == 1 ) {
1449
1460
qd_buffer_free (_pn_buf_desc_take_buffer (& pn_buf_desc ));
1450
1461
}
1451
-
1462
+ } else if (tls -> raw_read_drained && !pn_tls_is_decrypt_output_pending (tls -> tls_session )) {
1463
+ // Unclean close: remote simply dropped the connection. Done reading remaining decrypted output.
1464
+ //
1452
1465
tls -> input_drained = true;
1466
+ qd_log (tls -> log_module , QD_LOG_DEBUG ,
1467
+ "[C%" PRIu64 "] TLS input closed" , tls -> conn_id );
1453
1468
}
1454
1469
1455
1470
return tls -> input_drained && tls -> output_flushed ? QD_TLS_DONE : 0 ;
0 commit comments