aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-communicator-tcp.c
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2021-01-25 15:47:10 +0100
committert3sserakt <t3ss@posteo.de>2021-01-25 15:47:10 +0100
commitac71165822501c42b00980db2fb7f5e2144f3d20 (patch)
treecb62e4f7af0f91bdcf50c69bfc0bb901d3059358 /src/transport/gnunet-communicator-tcp.c
parent438aca2f666f0e0648f389774adee01c131da25c (diff)
downloadgnunet-ac71165822501c42b00980db2fb7f5e2144f3d20.tar.gz
gnunet-ac71165822501c42b00980db2fb7f5e2144f3d20.zip
- fixed bug in tcp com challenge logic. added test case for bidirectional test.
Diffstat (limited to 'src/transport/gnunet-communicator-tcp.c')
-rw-r--r--src/transport/gnunet-communicator-tcp.c654
1 files changed, 338 insertions, 316 deletions
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index 0c79fc1b4..ed82dba9f 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -590,6 +590,11 @@ struct Queue
590 struct ChallengeNonceP challenge; 590 struct ChallengeNonceP challenge;
591 591
592 /** 592 /**
593 * Challenge value received. In case of inbound connection we have to remember the value, because we send the challenge back later after we received the GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
594 */
595 struct ChallengeNonceP challenge_received;
596
597 /**
593 * Iteration Context for retrieving the monotonic time send with key for rekeying. 598 * Iteration Context for retrieving the monotonic time send with key for rekeying.
594 */ 599 */
595 struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get; 600 struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get;
@@ -834,7 +839,7 @@ int addrs_lens;
834 * Size of data received without KX challenge played back. 839 * Size of data received without KX challenge played back.
835 */ 840 */
836// TODO remove? 841// TODO remove?
837// size_t unverified_size; 842size_t unverified_size;
838 843
839/** 844/**
840 * Database for peer's HELLOs. 845 * Database for peer's HELLOs.
@@ -1188,23 +1193,6 @@ setup_cipher (const struct GNUNET_HashCode *dh,
1188 0)); 1193 0));
1189} 1194}
1190 1195
1191
1192/**
1193 * Setup cipher of @a queue for decryption.
1194 *
1195 * @param ephemeral ephemeral key we received from the other peer
1196 * @param queue[in,out] queue to initialize decryption cipher for
1197 */
1198static void
1199setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
1200 struct Queue *queue)
1201{
1202 struct GNUNET_HashCode dh;
1203
1204 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, ephemeral, &dh);
1205 setup_cipher (&dh, &my_identity, &queue->in_cipher, &queue->in_hmac);
1206}
1207
1208/** 1196/**
1209 * Callback called when peerstore store operation for rekey monotime value is finished. 1197 * Callback called when peerstore store operation for rekey monotime value is finished.
1210 * @param cls Queue context the store operation was executed. 1198 * @param cls Queue context the store operation was executed.
@@ -1279,6 +1267,23 @@ rekey_monotime_cb (void *cls,
1279} 1267}
1280 1268
1281/** 1269/**
1270 * Setup cipher of @a queue for decryption.
1271 *
1272 * @param ephemeral ephemeral key we received from the other peer
1273 * @param queue[in,out] queue to initialize decryption cipher for
1274 */
1275static void
1276setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
1277 struct Queue *queue)
1278{
1279 struct GNUNET_HashCode dh;
1280
1281 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, ephemeral, &dh);
1282 setup_cipher (&dh, &my_identity, &queue->in_cipher, &queue->in_hmac);
1283}
1284
1285
1286/**
1282 * Handle @a rekey message on @a queue. The message was already 1287 * Handle @a rekey message on @a queue. The message was already
1283 * HMAC'ed, but we should additionally still check the signature. 1288 * HMAC'ed, but we should additionally still check the signature.
1284 * Then we need to stop the old cipher and start afresh. 1289 * Then we need to stop the old cipher and start afresh.
@@ -1416,6 +1421,220 @@ handshake_ack_monotime_cb (void *cls,
1416} 1421}
1417 1422
1418/** 1423/**
1424 * Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
1425 *
1426 * @param tc The TCPConfirmation originally send.
1427 * @param queue The queue context.
1428 */
1429static void
1430send_challenge (struct ChallengeNonceP challenge, struct Queue *queue)
1431{
1432 struct TCPConfirmationAck tca;
1433 struct TcpHandshakeAckSignature thas;
1434
1435 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
1436 "transport",
1437 "sending challenge\n");
1438
1439 tca.header.type = ntohs (
1440 GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK);
1441 tca.header.size = ntohs (sizeof(tca));
1442 tca.challenge = challenge;
1443 tca.sender = my_identity;
1444 tca.monotonic_time =
1445 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1446 thas.purpose.purpose = htonl (
1447 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
1448 thas.purpose.size = htonl (sizeof(thas));
1449 thas.sender = my_identity;
1450 thas.receiver = queue->target;
1451 thas.monotonic_time = tca.monotonic_time;
1452 thas.challenge = tca.challenge;
1453 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1454 &thas,
1455 &tca.sender_sig);
1456 GNUNET_assert (0 ==
1457 gcry_cipher_encrypt (queue->out_cipher,
1458 &queue->cwrite_buf[queue->cwrite_off],
1459 sizeof(tca),
1460 &tca,
1461 sizeof(tca)));
1462 queue->cwrite_off += sizeof(tca);
1463 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
1464 "transport",
1465 "sending challenge done\n");
1466}
1467
1468/**
1469 * Setup cipher for outgoing data stream based on target and
1470 * our ephemeral private key.
1471 *
1472 * @param queue queue to setup outgoing (encryption) cipher for
1473 */
1474static void
1475setup_out_cipher (struct Queue *queue)
1476{
1477 struct GNUNET_HashCode dh;
1478
1479 GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral, &queue->target.public_key, &dh);
1480 /* we don't need the private key anymore, drop it! */
1481 memset (&queue->ephemeral, 0, sizeof(queue->ephemeral));
1482 setup_cipher (&dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1483 queue->rekey_time = GNUNET_TIME_relative_to_absolute (rekey_interval);
1484 queue->rekey_left_bytes =
1485 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, REKEY_MAX_BYTES);
1486}
1487
1488
1489/**
1490 * Inject a `struct TCPRekey` message into the queue's plaintext
1491 * buffer.
1492 *
1493 * @param queue queue to perform rekeying on
1494 */
1495static void
1496inject_rekey (struct Queue *queue)
1497{
1498 struct TCPRekey rekey;
1499 struct TcpRekeySignature thp;
1500
1501 GNUNET_assert (0 == queue->pwrite_off);
1502 memset (&rekey, 0, sizeof(rekey));
1503 GNUNET_CRYPTO_ecdhe_key_create (&queue->ephemeral);
1504 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
1505 rekey.header.size = ntohs (sizeof(rekey));
1506 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral);
1507 rekey.monotonic_time =
1508 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1509 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
1510 thp.purpose.size = htonl (sizeof(thp));
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "inject_rekey size %u\n",
1513 thp.purpose.size);
1514 thp.sender = my_identity;
1515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1516 "sender %s\n",
1517 GNUNET_p2s (&thp.sender.public_key));
1518 thp.receiver = queue->target;
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1520 "receiver %s\n",
1521 GNUNET_p2s (&thp.receiver.public_key));
1522 thp.ephemeral = rekey.ephemeral;
1523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1524 "ephemeral %s\n",
1525 GNUNET_e2s (&thp.ephemeral));
1526 thp.monotonic_time = rekey.monotonic_time;
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1528 "time %s\n",
1529 GNUNET_STRINGS_absolute_time_to_string (
1530 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1531 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1532 &thp,
1533 &rekey.sender_sig);
1534 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1535 /* Encrypt rekey message with 'old' cipher */
1536 GNUNET_assert (0 ==
1537 gcry_cipher_encrypt (queue->out_cipher,
1538 &queue->cwrite_buf[queue->cwrite_off],
1539 sizeof(rekey),
1540 &rekey,
1541 sizeof(rekey)));
1542 queue->cwrite_off += sizeof(rekey);
1543 /* Setup new cipher for successive messages */
1544 gcry_cipher_close (queue->out_cipher);
1545 setup_out_cipher (queue);
1546}
1547
1548/**
1549 * We have been notified that our socket is ready to write.
1550 * Then reschedule this function to be called again once more is available.
1551 *
1552 * @param cls a `struct Queue`
1553 */
1554static void
1555queue_write (void *cls)
1556{
1557 struct Queue *queue = cls;
1558 ssize_t sent;
1559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1560 queue->write_task = NULL;
1561 if (0 != queue->cwrite_off)
1562 {
1563 sent = GNUNET_NETWORK_socket_send (queue->sock,
1564 queue->cwrite_buf,
1565 queue->cwrite_off);
1566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1567 "Sent %lu bytes to TCP queue\n", sent);
1568 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1569 {
1570 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
1571 queue_destroy (queue);
1572 return;
1573 }
1574 if (sent > 0)
1575 {
1576 size_t usent = (size_t) sent;
1577 queue->cwrite_off -= usent;
1578 memmove (queue->cwrite_buf,
1579 &queue->cwrite_buf[usent],
1580 queue->cwrite_off);
1581 reschedule_queue_timeout (queue);
1582 }
1583 }
1584 /* can we encrypt more? (always encrypt full messages, needed
1585 such that #mq_cancel() can work!) */
1586 if ((0 < queue->rekey_left_bytes) &&
1587 (queue->pwrite_off > 0) &&
1588 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
1589 {
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1591 "Encrypting %lu bytes\n", queue->pwrite_off);
1592 GNUNET_assert (0 ==
1593 gcry_cipher_encrypt (queue->out_cipher,
1594 &queue->cwrite_buf[queue->cwrite_off],
1595 queue->pwrite_off,
1596 queue->pwrite_buf,
1597 queue->pwrite_off));
1598 if (queue->rekey_left_bytes > queue->pwrite_off)
1599 queue->rekey_left_bytes -= queue->pwrite_off;
1600 else
1601 queue->rekey_left_bytes = 0;
1602 queue->cwrite_off += queue->pwrite_off;
1603 queue->pwrite_off = 0;
1604 }
1605 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
1606 if (((0 == queue->pwrite_off) &&
1607 ((0 == queue->rekey_left_bytes) ||
1608 (0 ==
1609 GNUNET_TIME_absolute_get_remaining (
1610 queue->rekey_time).rel_value_us))))
1611 {
1612 inject_rekey (queue);
1613 }
1614 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
1615 (GNUNET_YES == queue->mq_awaits_continue))
1616 {
1617 queue->mq_awaits_continue = GNUNET_NO;
1618 GNUNET_MQ_impl_send_continue (queue->mq);
1619 }
1620 /* did we just finish writing 'finish'? */
1621 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
1622 {
1623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1624 "Finishing queue\n");
1625 queue_destroy (queue);
1626 return;
1627 }
1628 /* do we care to write more? */
1629 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
1630 queue->write_task =
1631 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1632 queue->sock,
1633 &queue_write,
1634 queue);
1635}
1636
1637/**
1419 * Test if we have received a full message in plaintext. 1638 * Test if we have received a full message in plaintext.
1420 * If so, handle it. 1639 * If so, handle it.
1421 * 1640 *
@@ -1450,16 +1669,16 @@ try_handle_plaintext (struct Queue *queue)
1450 return 0; /* not even a header */ 1669 return 0; /* not even a header */
1451 } 1670 }
1452 1671
1453 /* if ((-1 != unverified_size) && (unverified_size > INITIAL_CORE_KX_SIZE)) */ 1672 if ((-1 != unverified_size) && (unverified_size > INITIAL_CORE_KX_SIZE))
1454 /* { */ 1673 {
1455 /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, */ 1674 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1456 /* "Already received data of size %lu bigger than KX size %lu!\n", */ 1675 "Already received data of size %lu bigger than KX size %lu!\n",
1457 /* unverified_size, */ 1676 unverified_size,
1458 /* INITIAL_CORE_KX_SIZE); */ 1677 INITIAL_CORE_KX_SIZE);
1459 /* GNUNET_break_op (0); */ 1678 GNUNET_break_op (0);
1460 /* queue_finish (queue); */ 1679 queue_finish (queue);
1461 /* return 0; */ 1680 return 0;
1462 /* } */ 1681 }
1463 1682
1464 type = ntohs (hdr->type); 1683 type = ntohs (hdr->type);
1465 switch (type) 1684 switch (type)
@@ -1520,43 +1739,53 @@ try_handle_plaintext (struct Queue *queue)
1520 queue); 1739 queue);
1521 1740
1522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1523 "Handling plaintext, ack processed!"); 1742 "Handling plaintext, ack processed!\n");
1524 1743
1525 // unverified_size = -1; 1744 if (GNUNET_TRANSPORT_CS_INBOUND == queue->cs)
1526 1745 {
1527 /* char *foreign_addr; */ 1746 send_challenge (queue->challenge_received, queue);
1528 1747 queue->write_task =
1529 /* switch (queue->address->sa_family) */ 1748 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
1530 /* { */ 1749 queue->sock,
1531 /* case AF_INET: */ 1750 &queue_write,
1532 /* GNUNET_asprintf (&foreign_addr, */ 1751 queue);
1533 /* "%s-%s", */ 1752 }
1534 /* COMMUNICATOR_ADDRESS_PREFIX, */ 1753
1535 /* GNUNET_a2s (queue->address, queue->address_len)); */ 1754 unverified_size = -1;
1536 /* break; */ 1755
1537 1756 char *foreign_addr;
1538 /* case AF_INET6: */ 1757
1539 /* GNUNET_asprintf (&foreign_addr, */ 1758 switch (queue->address->sa_family)
1540 /* "%s-%s", */ 1759 {
1541 /* COMMUNICATOR_ADDRESS_PREFIX, */ 1760 case AF_INET:
1542 /* GNUNET_a2s (queue->address, queue->address_len)); */ 1761 GNUNET_asprintf (&foreign_addr,
1543 /* break; */ 1762 "%s-%s",
1544 1763 COMMUNICATOR_ADDRESS_PREFIX,
1545 /* default: */ 1764 GNUNET_a2s (queue->address, queue->address_len));
1546 /* GNUNET_assert (0); */ 1765 break;
1547 /* } */ 1766
1548 1767 case AF_INET6:
1549 /* queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, */ 1768 GNUNET_asprintf (&foreign_addr,
1550 /* &queue->target, */ 1769 "%s-%s",
1551 /* foreign_addr, */ 1770 COMMUNICATOR_ADDRESS_PREFIX,
1552 /* 0 /\* no MTU *\/, */ 1771 GNUNET_a2s (queue->address, queue->address_len));
1553 /* GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, */ 1772 break;
1554 /* 0, /\* Priority *\/ */ 1773
1555 /* queue->nt, */ 1774 default:
1556 /* queue->cs, */ 1775 GNUNET_assert (0);
1557 /* queue->mq); */ 1776 }
1558 1777
1559 /* GNUNET_free (foreign_addr); */ 1778 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
1779 &queue->target,
1780 foreign_addr,
1781 0 /* no MTU */,
1782 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
1783 0, /* Priority */
1784 queue->nt,
1785 queue->cs,
1786 queue->mq);
1787
1788 GNUNET_free (foreign_addr);
1560 1789
1561 size = ntohs (hdr->size); 1790 size = ntohs (hdr->size);
1562 break; 1791 break;
@@ -1633,8 +1862,8 @@ try_handle_plaintext (struct Queue *queue)
1633 return 0; 1862 return 0;
1634 } 1863 }
1635 GNUNET_assert (0 != size); 1864 GNUNET_assert (0 != size);
1636 /* if (-1 != unverified_size) */ 1865 if (-1 != unverified_size)
1637 /* unverified_size += size; */ 1866 unverified_size += size;
1638 return size; 1867 return size;
1639} 1868}
1640 1869
@@ -2043,178 +2272,6 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2043 return in; 2272 return in;
2044} 2273}
2045 2274
2046
2047/**
2048 * Setup cipher for outgoing data stream based on target and
2049 * our ephemeral private key.
2050 *
2051 * @param queue queue to setup outgoing (encryption) cipher for
2052 */
2053static void
2054setup_out_cipher (struct Queue *queue)
2055{
2056 struct GNUNET_HashCode dh;
2057
2058 GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral, &queue->target.public_key, &dh);
2059 /* we don't need the private key anymore, drop it! */
2060 memset (&queue->ephemeral, 0, sizeof(queue->ephemeral));
2061 setup_cipher (&dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
2062 queue->rekey_time = GNUNET_TIME_relative_to_absolute (rekey_interval);
2063 queue->rekey_left_bytes =
2064 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, REKEY_MAX_BYTES);
2065}
2066
2067
2068/**
2069 * Inject a `struct TCPRekey` message into the queue's plaintext
2070 * buffer.
2071 *
2072 * @param queue queue to perform rekeying on
2073 */
2074static void
2075inject_rekey (struct Queue *queue)
2076{
2077 struct TCPRekey rekey;
2078 struct TcpRekeySignature thp;
2079
2080 GNUNET_assert (0 == queue->pwrite_off);
2081 memset (&rekey, 0, sizeof(rekey));
2082 GNUNET_CRYPTO_ecdhe_key_create (&queue->ephemeral);
2083 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
2084 rekey.header.size = ntohs (sizeof(rekey));
2085 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral);
2086 rekey.monotonic_time =
2087 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
2088 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
2089 thp.purpose.size = htonl (sizeof(thp));
2090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2091 "inject_rekey size %u\n",
2092 thp.purpose.size);
2093 thp.sender = my_identity;
2094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2095 "sender %s\n",
2096 GNUNET_p2s (&thp.sender.public_key));
2097 thp.receiver = queue->target;
2098 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2099 "receiver %s\n",
2100 GNUNET_p2s (&thp.receiver.public_key));
2101 thp.ephemeral = rekey.ephemeral;
2102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2103 "ephemeral %s\n",
2104 GNUNET_e2s (&thp.ephemeral));
2105 thp.monotonic_time = rekey.monotonic_time;
2106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2107 "time %s\n",
2108 GNUNET_STRINGS_absolute_time_to_string (
2109 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
2110 GNUNET_CRYPTO_eddsa_sign (my_private_key,
2111 &thp,
2112 &rekey.sender_sig);
2113 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
2114 /* Encrypt rekey message with 'old' cipher */
2115 GNUNET_assert (0 ==
2116 gcry_cipher_encrypt (queue->out_cipher,
2117 &queue->cwrite_buf[queue->cwrite_off],
2118 sizeof(rekey),
2119 &rekey,
2120 sizeof(rekey)));
2121 queue->cwrite_off += sizeof(rekey);
2122 /* Setup new cipher for successive messages */
2123 gcry_cipher_close (queue->out_cipher);
2124 setup_out_cipher (queue);
2125}
2126
2127
2128/**
2129 * We have been notified that our socket is ready to write.
2130 * Then reschedule this function to be called again once more is available.
2131 *
2132 * @param cls a `struct Queue`
2133 */
2134static void
2135queue_write (void *cls)
2136{
2137 struct Queue *queue = cls;
2138 ssize_t sent;
2139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
2140 queue->write_task = NULL;
2141 if (0 != queue->cwrite_off)
2142 {
2143 sent = GNUNET_NETWORK_socket_send (queue->sock,
2144 queue->cwrite_buf,
2145 queue->cwrite_off);
2146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2147 "Sent %lu bytes to TCP queue\n", sent);
2148 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
2149 {
2150 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
2151 queue_destroy (queue);
2152 return;
2153 }
2154 if (sent > 0)
2155 {
2156 size_t usent = (size_t) sent;
2157 queue->cwrite_off -= usent;
2158 memmove (queue->cwrite_buf,
2159 &queue->cwrite_buf[usent],
2160 queue->cwrite_off);
2161 reschedule_queue_timeout (queue);
2162 }
2163 }
2164 /* can we encrypt more? (always encrypt full messages, needed
2165 such that #mq_cancel() can work!) */
2166 if ((0 < queue->rekey_left_bytes) &&
2167 (queue->pwrite_off > 0) &&
2168 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
2169 {
2170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2171 "Encrypting %lu bytes\n", queue->pwrite_off);
2172 GNUNET_assert (0 ==
2173 gcry_cipher_encrypt (queue->out_cipher,
2174 &queue->cwrite_buf[queue->cwrite_off],
2175 queue->pwrite_off,
2176 queue->pwrite_buf,
2177 queue->pwrite_off));
2178 if (queue->rekey_left_bytes > queue->pwrite_off)
2179 queue->rekey_left_bytes -= queue->pwrite_off;
2180 else
2181 queue->rekey_left_bytes = 0;
2182 queue->cwrite_off += queue->pwrite_off;
2183 queue->pwrite_off = 0;
2184 }
2185 // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
2186 if (((0 == queue->pwrite_off) &&
2187 ((0 == queue->rekey_left_bytes) ||
2188 (0 ==
2189 GNUNET_TIME_absolute_get_remaining (
2190 queue->rekey_time).rel_value_us))))
2191 {
2192 inject_rekey (queue);
2193 }
2194 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
2195 (GNUNET_YES == queue->mq_awaits_continue))
2196 {
2197 queue->mq_awaits_continue = GNUNET_NO;
2198 GNUNET_MQ_impl_send_continue (queue->mq);
2199 }
2200 /* did we just finish writing 'finish'? */
2201 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
2202 {
2203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2204 "Finishing queue\n");
2205 queue_destroy (queue);
2206 return;
2207 }
2208 /* do we care to write more? */
2209 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
2210 queue->write_task =
2211 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2212 queue->sock,
2213 &queue_write,
2214 queue);
2215}
2216
2217
2218/** 2275/**
2219 * Signature of functions implementing the sending functionality of a 2276 * Signature of functions implementing the sending functionality of a
2220 * message queue. 2277 * message queue.
@@ -2348,39 +2405,39 @@ boot_queue (struct Queue *queue)
2348 NULL, 2405 NULL,
2349 &mq_error, 2406 &mq_error,
2350 queue); 2407 queue);
2351 { 2408 /* { */
2352 char *foreign_addr; 2409 /* char *foreign_addr; */
2353 2410
2354 switch (queue->address->sa_family) 2411 /* switch (queue->address->sa_family) */
2355 { 2412 /* { */
2356 case AF_INET: 2413 /* case AF_INET: */
2357 GNUNET_asprintf (&foreign_addr, 2414 /* GNUNET_asprintf (&foreign_addr, */
2358 "%s-%s", 2415 /* "%s-%s", */
2359 COMMUNICATOR_ADDRESS_PREFIX, 2416 /* COMMUNICATOR_ADDRESS_PREFIX, */
2360 GNUNET_a2s (queue->address, queue->address_len)); 2417 /* GNUNET_a2s (queue->address, queue->address_len)); */
2361 break; 2418 /* break; */
2362 2419
2363 case AF_INET6: 2420 /* case AF_INET6: */
2364 GNUNET_asprintf (&foreign_addr, 2421 /* GNUNET_asprintf (&foreign_addr, */
2365 "%s-%s", 2422 /* "%s-%s", */
2366 COMMUNICATOR_ADDRESS_PREFIX, 2423 /* COMMUNICATOR_ADDRESS_PREFIX, */
2367 GNUNET_a2s (queue->address, queue->address_len)); 2424 /* GNUNET_a2s (queue->address, queue->address_len)); */
2368 break; 2425 /* break; */
2369 2426
2370 default: 2427 /* default: */
2371 GNUNET_assert (0); 2428 /* GNUNET_assert (0); */
2372 } 2429 /* } */
2373 queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, 2430 /* queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, */
2374 &queue->target, 2431 /* &queue->target, */
2375 foreign_addr, 2432 /* foreign_addr, */
2376 0 /* no MTU */, 2433 /* 0 /\* no MTU *\/, */
2377 GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, 2434 /* GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, */
2378 0, /* Priority */ 2435 /* 0, /\* Priority *\/ */
2379 queue->nt, 2436 /* queue->nt, */
2380 queue->cs, 2437 /* queue->cs, */
2381 queue->mq); 2438 /* queue->mq); */
2382 GNUNET_free (foreign_addr); 2439 /* GNUNET_free (foreign_addr); */
2383 } 2440 /* } */
2384} 2441}
2385 2442
2386 2443
@@ -2595,48 +2652,6 @@ free_proto_queue (struct ProtoQueue *pq)
2595} 2652}
2596 2653
2597/** 2654/**
2598 * Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
2599 *
2600 * @param tc The TCPConfirmation originally send.
2601 * @param queue The queue context.
2602 */
2603static void
2604send_challenge (struct ChallengeNonceP challenge, struct Queue *queue)
2605{
2606 struct TCPConfirmationAck tca;
2607 struct TcpHandshakeAckSignature thas;
2608
2609 GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
2610 "transport",
2611 "sending challenge\n");
2612
2613 tca.header.type = ntohs (
2614 GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK);
2615 tca.header.size = ntohs (sizeof(tca));
2616 tca.challenge = challenge;
2617 tca.sender = my_identity;
2618 tca.monotonic_time =
2619 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
2620 thas.purpose.purpose = htonl (
2621 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
2622 thas.purpose.size = htonl (sizeof(thas));
2623 thas.sender = my_identity;
2624 thas.receiver = queue->target;
2625 thas.monotonic_time = tca.monotonic_time;
2626 thas.challenge = tca.challenge;
2627 GNUNET_CRYPTO_eddsa_sign (my_private_key,
2628 &thas,
2629 &tca.sender_sig);
2630 GNUNET_assert (0 ==
2631 gcry_cipher_encrypt (queue->out_cipher,
2632 &queue->cwrite_buf[queue->cwrite_off],
2633 sizeof(tca),
2634 &tca,
2635 sizeof(tca)));
2636 queue->cwrite_off += sizeof(tca);
2637}
2638
2639/**
2640 * Read from the socket of the proto queue until we have enough data 2655 * Read from the socket of the proto queue until we have enough data
2641 * to upgrade to full queue. 2656 * to upgrade to full queue.
2642 * 2657 *
@@ -2722,7 +2737,8 @@ proto_read_kx (void *cls)
2722 &queue_write, 2737 &queue_write,
2723 queue); 2738 queue);
2724 // TODO To early! Move it somewhere else. 2739 // TODO To early! Move it somewhere else.
2725 // send_challenge (tc, queue); 2740 // send_challenge (tc.challenge, queue);
2741 queue->challenge_received = tc.challenge;
2726 2742
2727 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); 2743 GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
2728 GNUNET_free (pq); 2744 GNUNET_free (pq);
@@ -2853,6 +2869,12 @@ queue_read_kx (void *cls)
2853 return; 2869 return;
2854 } 2870 }
2855 send_challenge (tc.challenge, queue); 2871 send_challenge (tc.challenge, queue);
2872 queue->write_task =
2873 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2874 queue->sock,
2875 &queue_write,
2876 queue);
2877
2856 /* update queue timeout */ 2878 /* update queue timeout */
2857 reschedule_queue_timeout (queue); 2879 reschedule_queue_timeout (queue);
2858 /* prepare to continue with regular read task immediately */ 2880 /* prepare to continue with regular read task immediately */
@@ -2866,7 +2888,7 @@ queue_read_kx (void *cls)
2866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2867 "cread_off set to %lu bytes\n", 2889 "cread_off set to %lu bytes\n",
2868 queue->cread_off); 2890 queue->cread_off);
2869 if (0 < queue->cread_off) 2891 if (0 <= queue->cread_off)
2870 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); 2892 queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
2871} 2893}
2872 2894