aboutsummaryrefslogtreecommitdiff
path: root/src/dht/gnunet-service-dht_neighbours.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-07-07 20:29:24 +0200
committerChristian Grothoff <christian@grothoff.org>2022-07-07 20:29:24 +0200
commit3abeb45550e1cbf4939583c9b6ff48335fe6f1a9 (patch)
treea653991a417cc0a683a95d3b61c67e26fb341486 /src/dht/gnunet-service-dht_neighbours.c
parent2906241b6a21d6009a0d195199f3a08e8f4d4e2a (diff)
downloadgnunet-3abeb45550e1cbf4939583c9b6ff48335fe6f1a9.tar.gz
gnunet-3abeb45550e1cbf4939583c9b6ff48335fe6f1a9.zip
implemented new DHT path signing with origin authentication
Diffstat (limited to 'src/dht/gnunet-service-dht_neighbours.c')
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c566
1 files changed, 415 insertions, 151 deletions
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index 2a54f715a..cc7333a9c 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -150,8 +150,12 @@ struct PeerPutMessage
150 */ 150 */
151 struct GNUNET_HashCode key; 151 struct GNUNET_HashCode key;
152 152
153 /* trunc_peer (if truncated) */
154
153 /* put path (if tracked) */ 155 /* put path (if tracked) */
154 156
157 /* sender_sig (if path tracking is on) */
158
155 /* Payload */ 159 /* Payload */
156}; 160};
157 161
@@ -172,9 +176,9 @@ struct PeerResultMessage
172 uint32_t type GNUNET_PACKED; 176 uint32_t type GNUNET_PACKED;
173 177
174 /** 178 /**
175 * Reserved. 179 * Message options, actually an 'enum GNUNET_DHT_RouteOption' value in NBO.
176 */ 180 */
177 uint32_t reserved GNUNET_PACKED; 181 uint32_t options GNUNET_PACKED;
178 182
179 /** 183 /**
180 * Length of the PUT path that follows (if tracked). 184 * Length of the PUT path that follows (if tracked).
@@ -196,10 +200,14 @@ struct PeerResultMessage
196 */ 200 */
197 struct GNUNET_HashCode key; 201 struct GNUNET_HashCode key;
198 202
203 /* trunc_peer (if truncated) */
204
199 /* put path (if tracked) */ 205 /* put path (if tracked) */
200 206
201 /* get path (if tracked) */ 207 /* get path (if tracked) */
202 208
209 /* sender_sig (if path tracking is on) */
210
203 /* Payload */ 211 /* Payload */
204}; 212};
205 213
@@ -537,10 +545,11 @@ sign_path (const void *data,
537 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP), 545 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP),
538 .purpose.size = htonl (sizeof (hs)), 546 .purpose.size = htonl (sizeof (hs)),
539 .expiration_time = GNUNET_TIME_absolute_hton (exp_time), 547 .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
540 .pred = *pred,
541 .succ = *succ 548 .succ = *succ
542 }; 549 };
543 550
551 if (NULL != pred)
552 hs.pred = *pred;
544 GNUNET_CRYPTO_hash (data, 553 GNUNET_CRYPTO_hash (data,
545 data_size, 554 data_size,
546 &hs.h_data); 555 &hs.h_data);
@@ -1314,21 +1323,36 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
1314 struct PeerInfo **targets; 1323 struct PeerInfo **targets;
1315 size_t msize; 1324 size_t msize;
1316 unsigned int skip_count; 1325 unsigned int skip_count;
1326 enum GNUNET_DHT_RouteOption ro = bd->ro;
1317 unsigned int put_path_length = bd->put_path_length; 1327 unsigned int put_path_length = bd->put_path_length;
1328 const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1329 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1330 bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1331 const struct GNUNET_PeerIdentity *trunc_peer
1332 = truncated
1333 ? &bd->trunc_peer
1334 : NULL;
1318 1335
1319 GNUNET_assert (NULL != bf);
1320#if SANITY_CHECKS > 1 1336#if SANITY_CHECKS > 1
1321 if (0 != 1337 unsigned int failure_offset;
1322 GNUNET_DHT_verify_path (bd->data, 1338
1339 failure_offset
1340 = GNUNET_DHT_verify_path (bd->data,
1323 bd->data_size, 1341 bd->data_size,
1324 bd->expiration_time, 1342 bd->expiration_time,
1325 bd->put_path, 1343 trunc_peer,
1326 bd->put_path_length, 1344 put_path,
1327 NULL, 0, /* get_path */ 1345 put_path_length,
1328 &GDS_my_identity)) 1346 NULL, 0, /* get_path */
1347 &GDS_my_identity);
1348 if (0 != failure_offset)
1329 { 1349 {
1330 GNUNET_break_op (0); 1350 GNUNET_break_op (0);
1331 put_path_length = 0; 1351 truncated = true;
1352 trunc_peer = &put_path[failure_offset - 1].pred;
1353 put_path = &put_path[failure_offset];
1354 put_path_length = put_path_length - failure_offset;
1355 ro |= GNUNET_DHT_RO_TRUNCATED;
1332 } 1356 }
1333#endif 1357#endif
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1340,12 +1364,70 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
1340 1364
1341 /* if we got a HELLO, consider it for our own routing table */ 1365 /* if we got a HELLO, consider it for our own routing table */
1342 hello_check (bd); 1366 hello_check (bd);
1367 GNUNET_assert (NULL != bf);
1343 GNUNET_CONTAINER_bloomfilter_add (bf, 1368 GNUNET_CONTAINER_bloomfilter_add (bf,
1344 &GDS_my_identity_hash); 1369 &GDS_my_identity_hash);
1345 GNUNET_STATISTICS_update (GDS_stats, 1370 GNUNET_STATISTICS_update (GDS_stats,
1346 "# PUT requests routed", 1371 "# PUT requests routed",
1347 1, 1372 1,
1348 GNUNET_NO); 1373 GNUNET_NO);
1374 if (bd->data_size
1375 > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
1376 - sizeof(struct PeerPutMessage))
1377 {
1378 GNUNET_break (0);
1379 return GNUNET_SYSERR;
1380 }
1381 msize = bd->data_size + sizeof(struct PeerPutMessage);
1382 if (tracking)
1383 {
1384 if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature)
1385 > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1386 {
1387 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1388 "Discarding message that is too large due to tracking\n");
1389 return GNUNET_NO;
1390 }
1391 msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1392 }
1393 else
1394 {
1395 /* If tracking is disabled, also discard any path we might have
1396 gotten from some broken peer */
1397 GNUNET_break_op (0 == put_path_length);
1398 put_path_length = 0;
1399 }
1400 if (truncated)
1401 msize += sizeof (struct GNUNET_PeerIdentity);
1402 if (msize + put_path_length * sizeof(struct GNUNET_DHT_PathElement)
1403 > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1404 {
1405 unsigned int mlen;
1406 unsigned int ppl;
1407
1408 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1409 "Truncating path that is too large due\n");
1410 mlen = GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE - msize;
1411 if (! truncated)
1412 {
1413 /* We need extra space for the truncation, consider that,
1414 too! */
1415 truncated = true;
1416 mlen -= sizeof (struct GNUNET_PeerIdentity);
1417 msize += sizeof (struct GNUNET_PeerIdentity);
1418 }
1419 /* compute maximum length of path we can keep */
1420 ppl = mlen / sizeof (struct GNUNET_DHT_PathElement);
1421 GNUNET_assert (put_path_length - ppl > 0);
1422 trunc_peer = &put_path[put_path_length - ppl - 1].pred;
1423 put_path = &put_path[put_path_length - ppl];
1424 put_path_length = ppl;
1425 ro |= GNUNET_DHT_RO_TRUNCATED;
1426 }
1427 else
1428 {
1429 msize += bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement);
1430 }
1349 target_count 1431 target_count
1350 = get_target_peers (&bd->key, 1432 = get_target_peers (&bd->key,
1351 bf, 1433 bf,
@@ -1361,28 +1443,14 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
1361 GNUNET_i2s (&GDS_my_identity)); 1443 GNUNET_i2s (&GDS_my_identity));
1362 return GNUNET_NO; 1444 return GNUNET_NO;
1363 } 1445 }
1364 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)
1365 + bd->data_size;
1366 if (msize + sizeof(struct PeerPutMessage)
1367 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1368 {
1369 put_path_length = 0;
1370 msize = bd->data_size;
1371 }
1372 if (msize + sizeof(struct PeerPutMessage)
1373 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1374 {
1375 GNUNET_break (0);
1376 GNUNET_free (targets);
1377 return GNUNET_NO;
1378 }
1379 skip_count = 0; 1446 skip_count = 0;
1380 for (unsigned int i = 0; i < target_count; i++) 1447 for (unsigned int i = 0; i < target_count; i++)
1381 { 1448 {
1382 struct PeerInfo *target = targets[i]; 1449 struct PeerInfo *target = targets[i];
1383 struct PeerPutMessage *ppm; 1450 struct PeerPutMessage *ppm;
1384 char buf[sizeof (*ppm) + msize] GNUNET_ALIGN; 1451 char buf[msize] GNUNET_ALIGN;
1385 struct GNUNET_DHT_PathElement *pp; 1452 struct GNUNET_DHT_PathElement *pp;
1453 void *data;
1386 1454
1387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1388 "Routing PUT for %s after %u hops to %s\n", 1456 "Routing PUT for %s after %u hops to %s\n",
@@ -1393,7 +1461,7 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
1393 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1461 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1394 ppm->header.size = htons (sizeof (buf)); 1462 ppm->header.size = htons (sizeof (buf));
1395 ppm->type = htonl (bd->type); 1463 ppm->type = htonl (bd->type);
1396 ppm->options = htons (bd->ro); 1464 ppm->options = htons (ro);
1397 ppm->hop_count = htons (hop_count + 1); 1465 ppm->hop_count = htons (hop_count + 1);
1398 ppm->desired_replication_level = htons (desired_replication_level); 1466 ppm->desired_replication_level = htons (desired_replication_level);
1399 ppm->put_path_length = htons (put_path_length); 1467 ppm->put_path_length = htons (put_path_length);
@@ -1406,28 +1474,62 @@ GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
1406 ppm->bloomfilter, 1474 ppm->bloomfilter,
1407 DHT_BLOOM_SIZE)); 1475 DHT_BLOOM_SIZE));
1408 ppm->key = bd->key; 1476 ppm->key = bd->key;
1409 pp = (struct GNUNET_DHT_PathElement *) &ppm[1]; 1477 if (truncated)
1478 {
1479 void *tgt = &ppm[1];
1480
1481 GNUNET_memcpy (tgt,
1482 trunc_peer,
1483 sizeof (struct GNUNET_PeerIdentity));
1484 pp = (struct GNUNET_DHT_PathElement *)
1485 (tgt + sizeof (struct GNUNET_PeerIdentity));
1486 }
1487 else
1488 {
1489 pp = (struct GNUNET_DHT_PathElement *) &ppm[1];
1490 }
1410 GNUNET_memcpy (pp, 1491 GNUNET_memcpy (pp,
1411 bd->put_path, 1492 put_path,
1412 sizeof (struct GNUNET_DHT_PathElement) * put_path_length); 1493 sizeof (struct GNUNET_DHT_PathElement) * put_path_length);
1413 /* 0 == put_path_length means path is not being tracked */ 1494 if (tracking)
1414 if (0 != put_path_length)
1415 { 1495 {
1416 /* Note that the signature in 'put_path' was not initialized before, 1496 void *tgt = &pp[put_path_length];
1417 so this is crucial to avoid sending garbage. */ 1497 struct GNUNET_CRYPTO_EddsaSignature last_sig;
1418 sign_path (bd->data, 1498
1419 bd->data_size, 1499 if (0 == put_path_length)
1420 bd->expiration_time, 1500 {
1421 &pp[put_path_length - 1].pred, 1501 /* Note that the signature in 'put_path' was not initialized before,
1422 &target->id, 1502 so this is crucial to avoid sending garbage. */
1423 &pp[put_path_length - 1].sig); 1503 sign_path (bd->data,
1504 bd->data_size,
1505 bd->expiration_time,
1506 trunc_peer,
1507 &target->id,
1508 &last_sig);
1509 }
1510 else
1511 {
1512 sign_path (bd->data,
1513 bd->data_size,
1514 bd->expiration_time,
1515 &pp[put_path_length - 1].pred,
1516 &target->id,
1517 &last_sig);
1518 }
1424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1425 "Signing PUT PATH %u => %s\n", 1520 "Signing PUT PATH %u => %s\n",
1426 put_path_length, 1521 put_path_length,
1427 GNUNET_B2S (&pp[put_path_length - 1].sig)); 1522 GNUNET_B2S (&last_sig));
1523 memcpy (tgt,
1524 &last_sig,
1525 sizeof (last_sig));
1526 data = tgt + sizeof (last_sig);
1428 } 1527 }
1429 1528 else /* ! tracking */
1430 GNUNET_memcpy (&pp[put_path_length], 1529 {
1530 data = &ppm[1];
1531 }
1532 GNUNET_memcpy (data,
1431 bd->data, 1533 bd->data,
1432 bd->data_size); 1534 bd->data_size);
1433 do_send (target, 1535 do_send (target,
@@ -1572,46 +1674,86 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1572 struct GNUNET_DHT_PathElement *paths; 1674 struct GNUNET_DHT_PathElement *paths;
1573 size_t msize; 1675 size_t msize;
1574 unsigned int ppl = bd->put_path_length; 1676 unsigned int ppl = bd->put_path_length;
1575 1677 const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1678 enum GNUNET_DHT_RouteOption ro = bd->ro;
1679 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1680 const struct GNUNET_PeerIdentity *trunc_peer
1681 = truncated
1682 ? &bd->trunc_peer
1683 : NULL;
1684 bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1576#if SANITY_CHECKS > 1 1685#if SANITY_CHECKS > 1
1577 if (0 != 1686 unsigned int failure_offset;
1578 GNUNET_DHT_verify_path (bd->data, 1687
1688 failure_offset
1689 = GNUNET_DHT_verify_path (bd->data,
1579 bd->data_size, 1690 bd->data_size,
1580 bd->expiration_time, 1691 bd->expiration_time,
1581 bd->put_path, 1692 trunc_peer,
1582 bd->put_path_length, 1693 put_path,
1694 ppl,
1583 get_path, 1695 get_path,
1584 get_path_length, 1696 get_path_length,
1585 &GDS_my_identity)) 1697 &GDS_my_identity);
1698 if (0 != failure_offset)
1586 { 1699 {
1700 GNUNET_assert (failure_offset <= ppl + get_path_length);
1587 GNUNET_break_op (0); 1701 GNUNET_break_op (0);
1588 return false; 1702 if (failure_offset < ppl)
1703 {
1704 trunc_peer = &put_path[failure_offset - 1].pred;
1705 put_path += failure_offset;
1706 ppl -= failure_offset;
1707 truncated = true;
1708 ro |= GNUNET_DHT_RO_TRUNCATED;
1709 }
1710 else
1711 {
1712 failure_offset -= ppl;
1713 if (0 == failure_offset)
1714 trunc_peer = &put_path[ppl - 1].pred;
1715 else
1716 trunc_peer = &get_path[failure_offset - 1].pred;
1717 ppl = 0;
1718 put_path = NULL;
1719 truncated = true;
1720 ro |= GNUNET_DHT_RO_TRUNCATED;
1721 get_path += failure_offset;
1722 get_path_length -= failure_offset;
1723 }
1589 } 1724 }
1590#endif 1725#endif
1591 msize = bd->data_size + (get_path_length + ppl) 1726 msize = bd->data_size + sizeof (struct PeerResultMessage);
1592 * sizeof(struct GNUNET_DHT_PathElement); 1727 if (msize > GNUNET_MAX_MESSAGE_SIZE)
1593 if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || 1728 {
1594 (get_path_length > 1729 GNUNET_break_op (0);
1595 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || 1730 return false;
1596 (ppl > 1731 }
1597 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) || 1732 if (truncated)
1598 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE)) 1733 msize += sizeof (struct GNUNET_PeerIdentity);
1734 if (tracking)
1735 msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1736 if (msize < bd->data_size)
1737 {
1738 GNUNET_break_op (0);
1739 return false;
1740 }
1741 if ( (GNUNET_MAX_MESSAGE_SIZE - msize)
1742 / sizeof(struct GNUNET_DHT_PathElement)
1743 < (get_path_length + ppl) )
1599 { 1744 {
1600 ppl = 0;
1601 get_path_length = 0; 1745 get_path_length = 0;
1602 msize = bd->data_size + (get_path_length + ppl) 1746 ppl = 0;
1603 * sizeof(struct GNUNET_DHT_PathElement);
1604 } 1747 }
1605 if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || 1748 if ( (get_path_length > UINT16_MAX) ||
1606 (get_path_length > 1749 (ppl > UINT16_MAX) )
1607 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ||
1608 (ppl >
1609 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ||
1610 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE))
1611 { 1750 {
1612 GNUNET_break (0); 1751 GNUNET_break (0);
1613 return false; 1752 get_path_length = 0;
1753 ppl = 0;
1614 } 1754 }
1755 msize += (get_path_length + ppl)
1756 * sizeof(struct GNUNET_DHT_PathElement);
1615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1616 "Forwarding reply for key %s to peer %s\n", 1758 "Forwarding reply for key %s to peer %s\n",
1617 GNUNET_h2s (query_hash), 1759 GNUNET_h2s (query_hash),
@@ -1622,22 +1764,36 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1622 GNUNET_NO); 1764 GNUNET_NO);
1623 { 1765 {
1624 struct PeerResultMessage *prm; 1766 struct PeerResultMessage *prm;
1625 char buf[sizeof (*prm) + msize] GNUNET_ALIGN; 1767 char buf[msize] GNUNET_ALIGN;
1768 void *data;
1626 1769
1627 prm = (struct PeerResultMessage *) buf; 1770 prm = (struct PeerResultMessage *) buf;
1628 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); 1771 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1629 prm->header.size = htons (sizeof (buf)); 1772 prm->header.size = htons (sizeof (buf));
1630 prm->type = htonl (bd->type); 1773 prm->type = htonl ((uint32_t) bd->type);
1631 prm->reserved = htonl (0); 1774 prm->options = htonl ((uint32_t) ro);
1632 prm->put_path_length = htons (ppl); 1775 prm->put_path_length = htons ((uint16_t) ppl);
1633 prm->get_path_length = htons (get_path_length); 1776 prm->get_path_length = htons ((uint16_t) get_path_length);
1634 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time); 1777 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1635 prm->key = *query_hash; 1778 prm->key = *query_hash;
1636 paths = (struct GNUNET_DHT_PathElement *) &prm[1]; 1779 if (truncated)
1637 if (NULL != bd->put_path) 1780 {
1781 void *tgt = &prm[1];
1782
1783 GNUNET_memcpy (tgt,
1784 trunc_peer,
1785 sizeof (struct GNUNET_PeerIdentity));
1786 paths = (struct GNUNET_DHT_PathElement *)
1787 (tgt + sizeof (struct GNUNET_PeerIdentity));
1788 }
1789 else
1790 {
1791 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1792 }
1793 if (NULL != put_path)
1638 { 1794 {
1639 GNUNET_memcpy (paths, 1795 GNUNET_memcpy (paths,
1640 bd->put_path, 1796 put_path,
1641 ppl * sizeof(struct GNUNET_DHT_PathElement)); 1797 ppl * sizeof(struct GNUNET_DHT_PathElement));
1642 } 1798 }
1643 else 1799 else
@@ -1654,51 +1810,69 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1654 { 1810 {
1655 GNUNET_assert (0 == get_path_length); 1811 GNUNET_assert (0 == get_path_length);
1656 } 1812 }
1657 /* 0 == get_path_length+ppl means path is not being tracked */ 1813 if (tracking)
1658 if (0 != (get_path_length + ppl))
1659 { 1814 {
1815 struct GNUNET_CRYPTO_EddsaSignature sig;
1816 void *tgt = &paths[get_path_length + ppl];
1817 const struct GNUNET_PeerIdentity *pred;
1818
1819 if (ppl + get_path_length > 0)
1820 pred = &paths[ppl + get_path_length - 1].pred;
1821 else if (truncated)
1822 pred = trunc_peer;
1823 else
1824 pred = NULL; /* we are first! */
1660 /* Note that the last signature in 'paths' was not initialized before, 1825 /* Note that the last signature in 'paths' was not initialized before,
1661 so this is crucial to avoid sending garbage. */ 1826 so this is crucial to avoid sending garbage. */
1662 sign_path (bd->data, 1827 sign_path (bd->data,
1663 bd->data_size, 1828 bd->data_size,
1664 bd->expiration_time, 1829 bd->expiration_time,
1665 &paths[ppl + get_path_length - 1].pred, 1830 pred,
1666 &pi->id, 1831 &pi->id,
1667 &paths[ppl + get_path_length - 1].sig); 1832 &sig);
1833 memcpy (tgt,
1834 &sig,
1835 sizeof (sig));
1836 data = tgt + sizeof (sig);
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669 "Signing GET PATH %u/%u of %s => %s\n", 1838 "Signing GET PATH %u/%u of %s => %s\n",
1670 ppl, 1839 ppl,
1671 get_path_length, 1840 get_path_length,
1672 GNUNET_h2s (query_hash), 1841 GNUNET_h2s (query_hash),
1673 GNUNET_B2S (&paths[ppl + get_path_length - 1].sig)); 1842 GNUNET_B2S (&sig));
1674 }
1675 GNUNET_memcpy (&paths[ppl + get_path_length],
1676 bd->data,
1677 bd->data_size);
1678
1679#if SANITY_CHECKS > 1 1843#if SANITY_CHECKS > 1
1680 {
1681 struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
1682
1683 memcpy (xpaths,
1684 &paths[ppl],
1685 get_path_length * sizeof (struct GNUNET_DHT_PathElement));
1686 xpaths[get_path_length].pred = GDS_my_identity;
1687 if (0 !=
1688 GNUNET_DHT_verify_path (bd->data,
1689 bd->data_size,
1690 bd->expiration_time,
1691 paths,
1692 ppl,
1693 xpaths,
1694 get_path_length + 1,
1695 &pi->id))
1696 { 1844 {
1697 GNUNET_break (0); 1845 struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
1698 return false; 1846
1847 memcpy (xpaths,
1848 &paths[ppl],
1849 get_path_length * sizeof (struct GNUNET_DHT_PathElement));
1850 xpaths[get_path_length].sig = sig;
1851 xpaths[get_path_length].pred = GDS_my_identity;
1852 if (0 !=
1853 GNUNET_DHT_verify_path (bd->data,
1854 bd->data_size,
1855 bd->expiration_time,
1856 trunc_peer,
1857 paths,
1858 ppl,
1859 xpaths,
1860 get_path_length + 1,
1861 &pi->id))
1862 {
1863 GNUNET_break (0);
1864 return false;
1865 }
1699 } 1866 }
1700 }
1701#endif 1867#endif
1868 }
1869 else
1870 {
1871 data = &prm[1];
1872 }
1873 GNUNET_memcpy (data,
1874 bd->data,
1875 bd->data_size);
1702 do_send (pi, 1876 do_send (pi,
1703 &prm->header); 1877 &prm->header);
1704 } 1878 }
@@ -1717,15 +1891,30 @@ static enum GNUNET_GenericReturnValue
1717check_dht_p2p_put (void *cls, 1891check_dht_p2p_put (void *cls,
1718 const struct PeerPutMessage *put) 1892 const struct PeerPutMessage *put)
1719{ 1893{
1894 enum GNUNET_DHT_RouteOption ro
1895 = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1896 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1897 bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1720 uint16_t msize = ntohs (put->header.size); 1898 uint16_t msize = ntohs (put->header.size);
1721 uint16_t putlen = ntohs (put->put_path_length); 1899 uint16_t putlen = ntohs (put->put_path_length);
1900 size_t xsize = (has_path
1901 ? sizeof (struct GNUNET_CRYPTO_EddsaSignature)
1902 : 0)
1903 + (truncated
1904 ? sizeof (struct GNUNET_PeerIdentity)
1905 : 0);
1906 size_t var_meta_size
1907 = putlen * sizeof(struct GNUNET_DHT_PathElement)
1908 + xsize;
1722 1909
1723 (void) cls; 1910 (void) cls;
1724 if ( (msize < 1911 if ( (msize <
1725 sizeof(struct PeerPutMessage) 1912 sizeof (struct PeerPutMessage) + var_meta_size) ||
1726 + putlen * sizeof(struct GNUNET_DHT_PathElement)) ||
1727 (putlen > 1913 (putlen >
1728 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ) 1914 (GNUNET_MAX_MESSAGE_SIZE
1915 - sizeof (struct PeerPutMessage)
1916 - xsize)
1917 / sizeof(struct GNUNET_DHT_PathElement)) )
1729 { 1918 {
1730 GNUNET_break_op (0); 1919 GNUNET_break_op (0);
1731 return GNUNET_SYSERR; 1920 return GNUNET_SYSERR;
@@ -1746,27 +1935,49 @@ handle_dht_p2p_put (void *cls,
1746{ 1935{
1747 struct Target *t = cls; 1936 struct Target *t = cls;
1748 struct PeerInfo *peer = t->pi; 1937 struct PeerInfo *peer = t->pi;
1938 enum GNUNET_DHT_RouteOption ro
1939 = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1940 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1941 bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1749 uint16_t msize = ntohs (put->header.size); 1942 uint16_t msize = ntohs (put->header.size);
1943 uint16_t putlen = ntohs (put->put_path_length);
1944 const struct GNUNET_PeerIdentity *trunc_peer
1945 = truncated
1946 ? (const struct GNUNET_PeerIdentity *) &put[1]
1947 : NULL;
1750 const struct GNUNET_DHT_PathElement *put_path 1948 const struct GNUNET_DHT_PathElement *put_path
1751 = (const struct GNUNET_DHT_PathElement *) &put[1]; 1949 = truncated
1752 uint16_t putlen 1950 ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
1753 = ntohs (put->put_path_length); 1951 : (const struct GNUNET_DHT_PathElement *) &put[1];
1952 const struct GNUNET_CRYPTO_EddsaSignature *last_sig
1953 = has_path
1954 ? (const struct GNUNET_CRYPTO_EddsaSignature *) &put_path[putlen]
1955 : NULL;
1956 const char *data
1957 = has_path
1958 ? (const char *) &last_sig[1]
1959 : (const char *) &put_path[putlen];
1960 size_t var_meta_size
1961 = putlen * sizeof(struct GNUNET_DHT_PathElement)
1962 + has_path ? sizeof (*last_sig) : 0
1963 + truncated ? sizeof (*trunc_peer) : 0;
1754 struct GNUNET_DATACACHE_Block bd = { 1964 struct GNUNET_DATACACHE_Block bd = {
1755 .key = put->key, 1965 .key = put->key,
1756 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time), 1966 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1757 .type = ntohl (put->type), 1967 .type = ntohl (put->type),
1758 .ro = (enum GNUNET_DHT_RouteOption) ntohs (put->options), 1968 .ro = ro,
1759 .data_size = msize - (sizeof(*put) 1969 .data_size = msize - sizeof(*put) - var_meta_size,
1760 + putlen * sizeof(struct GNUNET_DHT_PathElement)), 1970 .data = data
1761 .data = &put_path[putlen]
1762 }; 1971 };
1763 1972
1973 if (NULL != trunc_peer)
1974 bd.trunc_peer = *trunc_peer;
1764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1975 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1765 "PUT for `%s' from %s with RO (%s/%s)\n", 1976 "PUT for `%s' from %s with RO (%s/%s)\n",
1766 GNUNET_h2s (&put->key), 1977 GNUNET_h2s (&put->key),
1767 GNUNET_i2s (&peer->id), 1978 GNUNET_i2s (&peer->id),
1768 (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-", 1979 (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1769 (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-"); 1980 has_path ? "R" : "-");
1770 if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) 1981 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
1771 { 1982 {
1772 GNUNET_STATISTICS_update (GDS_stats, 1983 GNUNET_STATISTICS_update (GDS_stats,
@@ -1784,7 +1995,7 @@ handle_dht_p2p_put (void *cls,
1784 GNUNET_break_op (0); 1995 GNUNET_break_op (0);
1785 return; 1996 return;
1786 } 1997 }
1787 if (0 == (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE)) 1998 if (! has_path)
1788 putlen = 0; 1999 putlen = 0;
1789 GNUNET_STATISTICS_update (GDS_stats, 2000 GNUNET_STATISTICS_update (GDS_stats,
1790 "# P2P PUT requests received", 2001 "# P2P PUT requests received",
@@ -1835,7 +2046,7 @@ handle_dht_p2p_put (void *cls,
1835 /* extend 'put path' by sender */ 2046 /* extend 'put path' by sender */
1836 bd.put_path = (const struct GNUNET_DHT_PathElement *) pp; 2047 bd.put_path = (const struct GNUNET_DHT_PathElement *) pp;
1837 bd.put_path_length = putlen + 1; 2048 bd.put_path_length = putlen + 1;
1838 if (0 != (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE)) 2049 if (has_path)
1839 { 2050 {
1840 unsigned int failure_offset; 2051 unsigned int failure_offset;
1841 2052
@@ -1843,10 +2054,7 @@ handle_dht_p2p_put (void *cls,
1843 put_path, 2054 put_path,
1844 putlen * sizeof(struct GNUNET_DHT_PathElement)); 2055 putlen * sizeof(struct GNUNET_DHT_PathElement));
1845 pp[putlen].pred = peer->id; 2056 pp[putlen].pred = peer->id;
1846 /* zero-out signature, not valid until we actually do forward! */ 2057 pp[putlen].sig = *last_sig;
1847 memset (&pp[putlen].sig,
1848 0,
1849 sizeof (pp[putlen].sig));
1850#if SANITY_CHECKS 2058#if SANITY_CHECKS
1851 /* TODO: might want to eventually implement probabilistic 2059 /* TODO: might want to eventually implement probabilistic
1852 load-based path verification, but for now it is all or nothing */ 2060 load-based path verification, but for now it is all or nothing */
@@ -1854,6 +2062,7 @@ handle_dht_p2p_put (void *cls,
1854 = GNUNET_DHT_verify_path (bd.data, 2062 = GNUNET_DHT_verify_path (bd.data,
1855 bd.data_size, 2063 bd.data_size,
1856 bd.expiration_time, 2064 bd.expiration_time,
2065 trunc_peer,
1857 pp, 2066 pp,
1858 putlen + 1, 2067 putlen + 1,
1859 NULL, 0, /* get_path */ 2068 NULL, 0, /* get_path */
@@ -1863,12 +2072,15 @@ handle_dht_p2p_put (void *cls,
1863#endif 2072#endif
1864 if (0 != failure_offset) 2073 if (0 != failure_offset)
1865 { 2074 {
2075 GNUNET_break_op (0);
1866 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2076 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1867 "Recorded put path invalid at offset %u, truncating\n", 2077 "Recorded put path invalid at offset %u, truncating\n",
1868 failure_offset); 2078 failure_offset);
1869 GNUNET_assert (failure_offset <= putlen); 2079 GNUNET_assert (failure_offset <= putlen + 1);
1870 bd.put_path = &pp[failure_offset]; 2080 bd.put_path = &pp[failure_offset];
1871 bd.put_path_length = putlen - failure_offset; 2081 bd.put_path_length = putlen - failure_offset;
2082 bd.ro |= GNUNET_DHT_RO_TRUNCATED;
2083 bd.trunc_peer = pp[failure_offset - 1].pred;
1872 } 2084 }
1873 } 2085 }
1874 else 2086 else
@@ -2218,8 +2430,6 @@ handle_dht_p2p_get (void *cls,
2218 type, 2430 type,
2219 hop_count, 2431 hop_count,
2220 desired_replication_level, 2432 desired_replication_level,
2221 0,
2222 NULL,
2223 &get->key); 2433 &get->key);
2224 } 2434 }
2225 /* clean up; note that 'bg' is owned by routing now! */ 2435 /* clean up; note that 'bg' is owned by routing now! */
@@ -2326,17 +2536,44 @@ handle_dht_p2p_result (void *cls,
2326{ 2536{
2327 struct Target *t = cls; 2537 struct Target *t = cls;
2328 struct PeerInfo *peer = t->pi; 2538 struct PeerInfo *peer = t->pi;
2329 uint16_t msize = ntohs (prm->header.size); 2539 uint16_t msize = ntohs (prm->header.size) - sizeof (*prm);
2540 enum GNUNET_DHT_RouteOption ro
2541 = (enum GNUNET_DHT_RouteOption) ntohl (prm->options);
2542 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
2543 bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
2330 uint16_t get_path_length = ntohs (prm->get_path_length); 2544 uint16_t get_path_length = ntohs (prm->get_path_length);
2545 uint16_t put_path_length = ntohs (prm->put_path_length);
2546 const struct GNUNET_PeerIdentity *trunc_peer
2547 = truncated
2548 ? (const struct GNUNET_PeerIdentity *) &prm[1]
2549 : NULL;
2550 const struct GNUNET_DHT_PathElement *put_path
2551 = truncated
2552 ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
2553 : (const struct GNUNET_DHT_PathElement *) &prm[1];
2554 const struct GNUNET_DHT_PathElement *get_path
2555 = &put_path[put_path_length];
2556 const struct GNUNET_CRYPTO_EddsaSignature *last_sig
2557 = tracked
2558 ? (const struct GNUNET_CRYPTO_EddsaSignature *) &get_path[get_path_length]
2559 : NULL;
2560 const void *data
2561 = tracked
2562 ? (const void *) &last_sig[1]
2563 : (const void *) &get_path[get_path_length];
2564 size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0)
2565 + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0);
2331 struct GNUNET_DATACACHE_Block bd = { 2566 struct GNUNET_DATACACHE_Block bd = {
2332 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time), 2567 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2333 .put_path = (const struct GNUNET_DHT_PathElement *) &prm[1], 2568 .put_path = put_path,
2334 .put_path_length = ntohs (prm->put_path_length), 2569 .put_path_length = put_path_length,
2335 .key = prm->key, 2570 .key = prm->key,
2336 .type = ntohl (prm->type) 2571 .type = ntohl (prm->type),
2572 .ro = ro,
2573 .data = data,
2574 .data_size = msize - vsize - (get_path_length + put_path_length)
2575 * sizeof(struct GNUNET_DHT_PathElement)
2337 }; 2576 };
2338 const struct GNUNET_DHT_PathElement *get_path
2339 = &bd.put_path[bd.put_path_length];
2340 2577
2341 /* parse and validate message */ 2578 /* parse and validate message */
2342 if (GNUNET_TIME_absolute_is_past (bd.expiration_time)) 2579 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
@@ -2347,11 +2584,6 @@ handle_dht_p2p_result (void *cls,
2347 GNUNET_NO); 2584 GNUNET_NO);
2348 return; 2585 return;
2349 } 2586 }
2350 get_path = &bd.put_path[bd.put_path_length];
2351 bd.data = (const void *) &get_path[get_path_length];
2352 bd.data_size = msize - (sizeof(struct PeerResultMessage)
2353 + (get_path_length + bd.put_path_length)
2354 * sizeof(struct GNUNET_DHT_PathElement));
2355 if (GNUNET_OK != 2587 if (GNUNET_OK !=
2356 GNUNET_BLOCK_check_block (GDS_block_context, 2588 GNUNET_BLOCK_check_block (GDS_block_context,
2357 bd.type, 2589 bd.type,
@@ -2385,6 +2617,7 @@ handle_dht_p2p_result (void *cls,
2385 hello_check (&bd); 2617 hello_check (&bd);
2386 2618
2387 /* Need to append 'peer' to 'get_path' */ 2619 /* Need to append 'peer' to 'get_path' */
2620 if (tracked)
2388 { 2621 {
2389 struct GNUNET_DHT_PathElement xget_path[get_path_length + 1]; 2622 struct GNUNET_DHT_PathElement xget_path[get_path_length + 1];
2390 struct GNUNET_DHT_PathElement *gp = xget_path; 2623 struct GNUNET_DHT_PathElement *gp = xget_path;
@@ -2394,9 +2627,10 @@ handle_dht_p2p_result (void *cls,
2394 get_path, 2627 get_path,
2395 get_path_length * sizeof(struct GNUNET_DHT_PathElement)); 2628 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2396 xget_path[get_path_length].pred = peer->id; 2629 xget_path[get_path_length].pred = peer->id;
2397 memset (&xget_path[get_path_length].sig, 2630 /* use memcpy(), as last_sig may not be aligned */
2398 0, 2631 memcpy (&xget_path[get_path_length].sig,
2399 sizeof (xget_path[get_path_length].sig)); 2632 last_sig,
2633 sizeof (*last_sig));
2400#if SANITY_CHECKS 2634#if SANITY_CHECKS
2401 /* TODO: might want to eventually implement probabilistic 2635 /* TODO: might want to eventually implement probabilistic
2402 load-based path verification, but for now it is all or nothing */ 2636 load-based path verification, but for now it is all or nothing */
@@ -2404,9 +2638,10 @@ handle_dht_p2p_result (void *cls,
2404 = GNUNET_DHT_verify_path (bd.data, 2638 = GNUNET_DHT_verify_path (bd.data,
2405 bd.data_size, 2639 bd.data_size,
2406 bd.expiration_time, 2640 bd.expiration_time,
2407 bd.put_path, 2641 trunc_peer,
2408 bd.put_path_length, 2642 put_path,
2409 xget_path, 2643 put_path_length,
2644 gp,
2410 get_path_length + 1, 2645 get_path_length + 1,
2411 &GDS_my_identity); 2646 &GDS_my_identity);
2412#else 2647#else
@@ -2417,30 +2652,59 @@ handle_dht_p2p_result (void *cls,
2417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2652 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2418 "Recorded path invalid at offset %u, truncating\n", 2653 "Recorded path invalid at offset %u, truncating\n",
2419 failure_offset); 2654 failure_offset);
2420 GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length); 2655 GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length
2421 if (failure_offset >= bd.put_path_length) 2656 + 1);
2422 { 2657 if (failure_offset < bd.put_path_length)
2423 /* failure on get path */
2424 get_path_length -= (failure_offset - bd.put_path_length);
2425 gp = &xget_path[failure_offset - bd.put_path_length];
2426 bd.put_path_length = 0;
2427 }
2428 else
2429 { 2658 {
2430 /* failure on put path */ 2659 /* failure on put path */
2660 trunc_peer = &bd.put_path[failure_offset - 1].pred;
2661 bd.ro |= GNUNET_DHT_RO_TRUNCATED;
2431 bd.put_path = &bd.put_path[failure_offset]; 2662 bd.put_path = &bd.put_path[failure_offset];
2432 bd.put_path_length -= failure_offset; 2663 bd.put_path_length -= failure_offset;
2664 truncated = true;
2665 }
2666 else
2667 {
2668 /* failure on get path */
2669 failure_offset -= bd.put_path_length;
2670 if (0 == failure_offset)
2671 trunc_peer = &bd.put_path[bd.put_path_length - 1].pred;
2672 else
2673 trunc_peer = &gp[failure_offset - 1].pred;
2674 get_path_length -= failure_offset;
2675 gp = &gp[failure_offset];
2676 bd.put_path_length = 0;
2677 bd.put_path = NULL;
2678 bd.ro |= GNUNET_DHT_RO_TRUNCATED;
2679 truncated = true;
2433 } 2680 }
2434 } 2681 }
2435 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2436 "Extending GET path of length %u with %s\n", 2683 "Extending GET path of length %u with %s\n",
2437 get_path_length, 2684 get_path_length,
2438 GNUNET_i2s (&peer->id)); 2685 GNUNET_i2s (&peer->id));
2686 if (truncated)
2687 {
2688 GNUNET_assert (NULL != trunc_peer);
2689 bd.trunc_peer = *trunc_peer;
2690 }
2439 GNUNET_break (process_reply_with_path (&bd, 2691 GNUNET_break (process_reply_with_path (&bd,
2440 &prm->key, 2692 &prm->key,
2441 get_path_length + 1, 2693 get_path_length + 1,
2442 gp)); 2694 gp));
2443 } 2695 }
2696 else
2697 {
2698 if (truncated)
2699 {
2700 GNUNET_assert (NULL != trunc_peer);
2701 bd.trunc_peer = *trunc_peer;
2702 }
2703 GNUNET_break (process_reply_with_path (&bd,
2704 &prm->key,
2705 0,
2706 NULL));
2707 }
2444} 2708}
2445 2709
2446 2710