diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_tunnels.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_tunnels.c | 563 |
1 files changed, 406 insertions, 157 deletions
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c index fb91a4a6a..1e7a8e086 100644 --- a/src/cadet/gnunet-service-cadet_tunnels.c +++ b/src/cadet/gnunet-service-cadet_tunnels.c | |||
@@ -1,21 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013, 2017 GNUnet e.V. | 3 | Copyright (C) 2013, 2017, 2018 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | it under the terms of the GNU General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
7 | by the Free Software Foundation; either version 3, or (at your | 7 | by the Free Software Foundation, either version 3 of the License, |
8 | option) any later version. | 8 | or (at your option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with GNUnet; see the file COPYING. If not, write to the | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | 17 | */ |
20 | /** | 18 | /** |
21 | * @file cadet/gnunet-service-cadet_tunnels.c | 19 | * @file cadet/gnunet-service-cadet_tunnels.c |
@@ -187,6 +185,12 @@ struct CadetTunnelAxolotl | |||
187 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; | 185 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; |
188 | 186 | ||
189 | /** | 187 | /** |
188 | * Last ephemeral public key received from the other peer, | ||
189 | * for duplicate detection. | ||
190 | */ | ||
191 | struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral; | ||
192 | |||
193 | /** | ||
190 | * Time when the current ratchet expires and a new one is triggered | 194 | * Time when the current ratchet expires and a new one is triggered |
191 | * (if @e ratchet_allowed is #GNUNET_YES). | 195 | * (if @e ratchet_allowed is #GNUNET_YES). |
192 | */ | 196 | */ |
@@ -453,6 +457,29 @@ struct CadetTunnel | |||
453 | 457 | ||
454 | 458 | ||
455 | /** | 459 | /** |
460 | * Am I Alice or Betty (some call her Bob), or talking to myself? | ||
461 | * | ||
462 | * @param other the other peer | ||
463 | * @return #GNUNET_YES for Alice, #GNUNET_NO for Betty, #GNUNET_SYSERR if talking to myself | ||
464 | */ | ||
465 | static int | ||
466 | alice_or_betty (const struct GNUNET_PeerIdentity *other) | ||
467 | { | ||
468 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | ||
469 | other)) | ||
470 | return GNUNET_YES; | ||
471 | else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | ||
472 | other)) | ||
473 | return GNUNET_NO; | ||
474 | else | ||
475 | { | ||
476 | GNUNET_break_op (0); | ||
477 | return GNUNET_SYSERR; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
456 | * Connection @a ct is now unready, clear it's ready flag | 483 | * Connection @a ct is now unready, clear it's ready flag |
457 | * and move it from the ready DLL to the busy DLL. | 484 | * and move it from the ready DLL to the busy DLL. |
458 | * | 485 | * |
@@ -1318,6 +1345,8 @@ send_kx (struct CadetTunnel *t, | |||
1318 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; | 1345 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; |
1319 | enum GNUNET_CADET_KX_Flags flags; | 1346 | enum GNUNET_CADET_KX_Flags flags; |
1320 | 1347 | ||
1348 | if (GNUNET_YES != alice_or_betty (GCP_get_id (t->destination))) | ||
1349 | return; /* only Alice may send KX */ | ||
1321 | if ( (NULL == ct) || | 1350 | if ( (NULL == ct) || |
1322 | (GNUNET_NO == ct->is_ready) ) | 1351 | (GNUNET_NO == ct->is_ready) ) |
1323 | ct = get_ready_connection (t); | 1352 | ct = get_ready_connection (t); |
@@ -1331,11 +1360,6 @@ send_kx (struct CadetTunnel *t, | |||
1331 | return; | 1360 | return; |
1332 | } | 1361 | } |
1333 | cc = ct->cc; | 1362 | cc = ct->cc; |
1334 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1335 | "Sending KX on %s via %s in state %s\n", | ||
1336 | GCT_2s (t), | ||
1337 | GCC_2s (cc), | ||
1338 | estate2s (t->estate)); | ||
1339 | env = GNUNET_MQ_msg (msg, | 1363 | env = GNUNET_MQ_msg (msg, |
1340 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); | 1364 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); |
1341 | flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */ | 1365 | flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */ |
@@ -1343,6 +1367,15 @@ send_kx (struct CadetTunnel *t, | |||
1343 | msg->cid = *GCC_get_id (cc); | 1367 | msg->cid = *GCC_get_id (cc); |
1344 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | 1368 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, |
1345 | &msg->ephemeral_key); | 1369 | &msg->ephemeral_key); |
1370 | #if DEBUG_KX | ||
1371 | msg->ephemeral_key_XXX = ax->kx_0; | ||
1372 | msg->private_key_XXX = *my_private_key; | ||
1373 | #endif | ||
1374 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1375 | "Sending KX message to %s with ephemeral %s on CID %s\n", | ||
1376 | GCT_2s (t), | ||
1377 | GNUNET_e2s (&msg->ephemeral_key), | ||
1378 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1346 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | 1379 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, |
1347 | &msg->ratchet_key); | 1380 | &msg->ratchet_key); |
1348 | mark_connection_unready (ct); | 1381 | mark_connection_unready (ct); |
@@ -1356,6 +1389,10 @@ send_kx (struct CadetTunnel *t, | |||
1356 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | 1389 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); |
1357 | GCC_transmit (cc, | 1390 | GCC_transmit (cc, |
1358 | env); | 1391 | env); |
1392 | GNUNET_STATISTICS_update (stats, | ||
1393 | "# KX transmitted", | ||
1394 | 1, | ||
1395 | GNUNET_NO); | ||
1359 | } | 1396 | } |
1360 | 1397 | ||
1361 | 1398 | ||
@@ -1394,11 +1431,6 @@ send_kx_auth (struct CadetTunnel *t, | |||
1394 | } | 1431 | } |
1395 | t->kx_auth_requested = GNUNET_NO; /* clear flag */ | 1432 | t->kx_auth_requested = GNUNET_NO; /* clear flag */ |
1396 | cc = ct->cc; | 1433 | cc = ct->cc; |
1397 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1398 | "Sending KX_AUTH on %s using %s\n", | ||
1399 | GCT_2s (t), | ||
1400 | GCC_2s (ct->cc)); | ||
1401 | |||
1402 | env = GNUNET_MQ_msg (msg, | 1434 | env = GNUNET_MQ_msg (msg, |
1403 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH); | 1435 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH); |
1404 | flags = GNUNET_CADET_KX_FLAG_NONE; | 1436 | flags = GNUNET_CADET_KX_FLAG_NONE; |
@@ -1410,11 +1442,21 @@ send_kx_auth (struct CadetTunnel *t, | |||
1410 | &msg->kx.ephemeral_key); | 1442 | &msg->kx.ephemeral_key); |
1411 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | 1443 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, |
1412 | &msg->kx.ratchet_key); | 1444 | &msg->kx.ratchet_key); |
1445 | #if DEBUG_KX | ||
1446 | msg->kx.ephemeral_key_XXX = ax->kx_0; | ||
1447 | msg->kx.private_key_XXX = *my_private_key; | ||
1448 | msg->r_ephemeral_key_XXX = ax->last_ephemeral; | ||
1449 | #endif | ||
1450 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1451 | "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n", | ||
1452 | GCT_2s (t), | ||
1453 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
1454 | GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel)); | ||
1455 | |||
1413 | /* Compute authenticator (this is the main difference to #send_kx()) */ | 1456 | /* Compute authenticator (this is the main difference to #send_kx()) */ |
1414 | GNUNET_CRYPTO_hash (&ax->RK, | 1457 | GNUNET_CRYPTO_hash (&ax->RK, |
1415 | sizeof (ax->RK), | 1458 | sizeof (ax->RK), |
1416 | &msg->auth); | 1459 | &msg->auth); |
1417 | |||
1418 | /* Compute when to be triggered again; actual job will | 1460 | /* Compute when to be triggered again; actual job will |
1419 | be scheduled via #connection_ready_cb() */ | 1461 | be scheduled via #connection_ready_cb() */ |
1420 | t->kx_retry_delay | 1462 | t->kx_retry_delay |
@@ -1429,9 +1471,12 @@ send_kx_auth (struct CadetTunnel *t, | |||
1429 | if (CADET_TUNNEL_KEY_OK != t->estate) | 1471 | if (CADET_TUNNEL_KEY_OK != t->estate) |
1430 | GCT_change_estate (t, | 1472 | GCT_change_estate (t, |
1431 | CADET_TUNNEL_KEY_AX_AUTH_SENT); | 1473 | CADET_TUNNEL_KEY_AX_AUTH_SENT); |
1432 | |||
1433 | GCC_transmit (cc, | 1474 | GCC_transmit (cc, |
1434 | env); | 1475 | env); |
1476 | GNUNET_STATISTICS_update (stats, | ||
1477 | "# KX_AUTH transmitted", | ||
1478 | 1, | ||
1479 | GNUNET_NO); | ||
1435 | } | 1480 | } |
1436 | 1481 | ||
1437 | 1482 | ||
@@ -1476,66 +1521,57 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax, | |||
1476 | const char salt[] = "CADET Axolotl salt"; | 1521 | const char salt[] = "CADET Axolotl salt"; |
1477 | int am_I_alice; | 1522 | int am_I_alice; |
1478 | 1523 | ||
1479 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | 1524 | if (GNUNET_SYSERR == (am_I_alice = alice_or_betty (pid))) |
1480 | pid)) | ||
1481 | am_I_alice = GNUNET_YES; | ||
1482 | else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | ||
1483 | pid)) | ||
1484 | am_I_alice = GNUNET_NO; | ||
1485 | else | ||
1486 | { | 1525 | { |
1487 | GNUNET_break_op (0); | 1526 | GNUNET_break_op (0); |
1488 | return GNUNET_SYSERR; | 1527 | return GNUNET_SYSERR; |
1489 | } | 1528 | } |
1490 | |||
1491 | if (0 == memcmp (&ax->DHRr, | 1529 | if (0 == memcmp (&ax->DHRr, |
1492 | ratchet_key, | 1530 | ratchet_key, |
1493 | sizeof (*ratchet_key))) | 1531 | sizeof (*ratchet_key))) |
1494 | { | 1532 | { |
1533 | GNUNET_STATISTICS_update (stats, | ||
1534 | "# Ratchet key already known", | ||
1535 | 1, | ||
1536 | GNUNET_NO); | ||
1495 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1537 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1496 | "Ratchet key already known. Ignoring KX.\n"); | 1538 | "Ratchet key already known. Ignoring KX.\n"); |
1497 | return GNUNET_NO; | 1539 | return GNUNET_NO; |
1498 | } | 1540 | } |
1499 | 1541 | ||
1500 | ax->DHRr = *ratchet_key; | 1542 | ax->DHRr = *ratchet_key; |
1501 | 1543 | ax->last_ephemeral = *ephemeral_key; | |
1502 | /* ECDH A B0 */ | 1544 | /* ECDH A B0 */ |
1503 | if (GNUNET_YES == am_I_alice) | 1545 | if (GNUNET_YES == am_I_alice) |
1504 | { | 1546 | { |
1505 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ | 1547 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */ |
1506 | ephemeral_key, /* B0 */ | 1548 | ephemeral_key, /* B0 */ |
1507 | &key_material[0]); | 1549 | &key_material[0]); |
1508 | } | 1550 | } |
1509 | else | 1551 | else |
1510 | { | 1552 | { |
1511 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* B0 */ | 1553 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */ |
1512 | &pid->public_key, /* A */ | 1554 | &pid->public_key, /* A */ |
1513 | &key_material[0]); | 1555 | &key_material[0]); |
1514 | } | 1556 | } |
1515 | |||
1516 | /* ECDH A0 B */ | 1557 | /* ECDH A0 B */ |
1517 | if (GNUNET_YES == am_I_alice) | 1558 | if (GNUNET_YES == am_I_alice) |
1518 | { | 1559 | { |
1519 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* A0 */ | 1560 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */ |
1520 | &pid->public_key, /* B */ | 1561 | &pid->public_key, /* B */ |
1521 | &key_material[1]); | 1562 | &key_material[1]); |
1522 | } | 1563 | } |
1523 | else | 1564 | else |
1524 | { | 1565 | { |
1525 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ | 1566 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */ |
1526 | ephemeral_key, /* B0 */ | 1567 | ephemeral_key, /* A0 */ |
1527 | &key_material[1]); | 1568 | &key_material[1]); |
1528 | |||
1529 | |||
1530 | } | 1569 | } |
1531 | 1570 | ||
1532 | /* ECDH A0 B0 */ | 1571 | /* ECDH A0 B0 */ |
1533 | /* (This is the triple-DH, we could probably safely skip this, | 1572 | GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */ |
1534 | as A0/B0 are already in the key material.) */ | 1573 | ephemeral_key, /* B0 or A0 */ |
1535 | GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* A0 or B0 */ | ||
1536 | ephemeral_key, /* B0 or A0 */ | ||
1537 | &key_material[2]); | 1574 | &key_material[2]); |
1538 | |||
1539 | /* KDF */ | 1575 | /* KDF */ |
1540 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), | 1576 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), |
1541 | salt, sizeof (salt), | 1577 | salt, sizeof (salt), |
@@ -1547,7 +1583,11 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax, | |||
1547 | sizeof (ax->RK))) | 1583 | sizeof (ax->RK))) |
1548 | { | 1584 | { |
1549 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1585 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1550 | "Root key of handshake already known. Ignoring KX.\n"); | 1586 | "Root key already known. Ignoring KX.\n"); |
1587 | GNUNET_STATISTICS_update (stats, | ||
1588 | "# Root key already known", | ||
1589 | 1, | ||
1590 | GNUNET_NO); | ||
1551 | return GNUNET_NO; | 1591 | return GNUNET_NO; |
1552 | } | 1592 | } |
1553 | 1593 | ||
@@ -1592,75 +1632,75 @@ retry_kx (void *cls) | |||
1592 | GCT_2s (t), | 1632 | GCT_2s (t), |
1593 | estate2s (t->estate)); | 1633 | estate2s (t->estate)); |
1594 | switch (t->estate) | 1634 | switch (t->estate) |
1595 | { | ||
1596 | case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */ | ||
1597 | case CADET_TUNNEL_KEY_AX_SENT: /* trying again */ | ||
1598 | send_kx (t, | ||
1599 | NULL, | ||
1600 | &t->ax); | ||
1601 | break; | ||
1602 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1603 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1604 | /* We are responding, so only require reply | ||
1605 | if WE have a channel waiting. */ | ||
1606 | if (NULL != t->unverified_ax) | ||
1607 | { | ||
1608 | /* Send AX_AUTH so we might get this one verified */ | ||
1609 | ax = t->unverified_ax; | ||
1610 | } | ||
1611 | else | ||
1612 | { | ||
1613 | /* How can this be? */ | ||
1614 | GNUNET_break (0); | ||
1615 | ax = &t->ax; | ||
1616 | } | ||
1617 | send_kx_auth (t, | ||
1618 | NULL, | ||
1619 | ax, | ||
1620 | (0 == GCT_count_channels (t)) | ||
1621 | ? GNUNET_NO | ||
1622 | : GNUNET_YES); | ||
1623 | break; | ||
1624 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1625 | /* We are responding, so only require reply | ||
1626 | if WE have a channel waiting. */ | ||
1627 | if (NULL != t->unverified_ax) | ||
1628 | { | ||
1629 | /* Send AX_AUTH so we might get this one verified */ | ||
1630 | ax = t->unverified_ax; | ||
1631 | } | ||
1632 | else | ||
1633 | { | ||
1634 | /* How can this be? */ | ||
1635 | GNUNET_break (0); | ||
1636 | ax = &t->ax; | ||
1637 | } | ||
1638 | send_kx_auth (t, | ||
1639 | NULL, | ||
1640 | ax, | ||
1641 | (0 == GCT_count_channels (t)) | ||
1642 | ? GNUNET_NO | ||
1643 | : GNUNET_YES); | ||
1644 | break; | ||
1645 | case CADET_TUNNEL_KEY_OK: | ||
1646 | /* Must have been the *other* peer asking us to | ||
1647 | respond with a KX_AUTH. */ | ||
1648 | if (NULL != t->unverified_ax) | ||
1649 | { | 1635 | { |
1650 | /* Sending AX_AUTH in response to AX so we might get this one verified */ | 1636 | case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */ |
1651 | ax = t->unverified_ax; | 1637 | case CADET_TUNNEL_KEY_AX_SENT: /* trying again */ |
1652 | } | 1638 | send_kx (t, |
1653 | else | 1639 | NULL, |
1654 | { | 1640 | &t->ax); |
1655 | /* Sending AX_AUTH in response to AX_AUTH */ | 1641 | break; |
1656 | ax = &t->ax; | 1642 | case CADET_TUNNEL_KEY_AX_RECV: |
1643 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1644 | /* We are responding, so only require reply | ||
1645 | if WE have a channel waiting. */ | ||
1646 | if (NULL != t->unverified_ax) | ||
1647 | { | ||
1648 | /* Send AX_AUTH so we might get this one verified */ | ||
1649 | ax = t->unverified_ax; | ||
1650 | } | ||
1651 | else | ||
1652 | { | ||
1653 | /* How can this be? */ | ||
1654 | GNUNET_break (0); | ||
1655 | ax = &t->ax; | ||
1656 | } | ||
1657 | send_kx_auth (t, | ||
1658 | NULL, | ||
1659 | ax, | ||
1660 | (0 == GCT_count_channels (t)) | ||
1661 | ? GNUNET_NO | ||
1662 | : GNUNET_YES); | ||
1663 | break; | ||
1664 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1665 | /* We are responding, so only require reply | ||
1666 | if WE have a channel waiting. */ | ||
1667 | if (NULL != t->unverified_ax) | ||
1668 | { | ||
1669 | /* Send AX_AUTH so we might get this one verified */ | ||
1670 | ax = t->unverified_ax; | ||
1671 | } | ||
1672 | else | ||
1673 | { | ||
1674 | /* How can this be? */ | ||
1675 | GNUNET_break (0); | ||
1676 | ax = &t->ax; | ||
1677 | } | ||
1678 | send_kx_auth (t, | ||
1679 | NULL, | ||
1680 | ax, | ||
1681 | (0 == GCT_count_channels (t)) | ||
1682 | ? GNUNET_NO | ||
1683 | : GNUNET_YES); | ||
1684 | break; | ||
1685 | case CADET_TUNNEL_KEY_OK: | ||
1686 | /* Must have been the *other* peer asking us to | ||
1687 | respond with a KX_AUTH. */ | ||
1688 | if (NULL != t->unverified_ax) | ||
1689 | { | ||
1690 | /* Sending AX_AUTH in response to AX so we might get this one verified */ | ||
1691 | ax = t->unverified_ax; | ||
1692 | } | ||
1693 | else | ||
1694 | { | ||
1695 | /* Sending AX_AUTH in response to AX_AUTH */ | ||
1696 | ax = &t->ax; | ||
1697 | } | ||
1698 | send_kx_auth (t, | ||
1699 | NULL, | ||
1700 | ax, | ||
1701 | GNUNET_NO); | ||
1702 | break; | ||
1657 | } | 1703 | } |
1658 | send_kx_auth (t, | ||
1659 | NULL, | ||
1660 | ax, | ||
1661 | GNUNET_NO); | ||
1662 | break; | ||
1663 | } | ||
1664 | } | 1704 | } |
1665 | 1705 | ||
1666 | 1706 | ||
@@ -1677,76 +1717,117 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1677 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 1717 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
1678 | { | 1718 | { |
1679 | struct CadetTunnel *t = ct->t; | 1719 | struct CadetTunnel *t = ct->t; |
1680 | struct CadetTunnelAxolotl *ax; | ||
1681 | int ret; | 1720 | int ret; |
1682 | 1721 | ||
1683 | if (0 == | 1722 | GNUNET_STATISTICS_update (stats, |
1684 | memcmp (&t->ax.DHRr, | 1723 | "# KX received", |
1685 | &msg->ratchet_key, | 1724 | 1, |
1686 | sizeof (msg->ratchet_key))) | 1725 | GNUNET_NO); |
1726 | if (GNUNET_YES == | ||
1727 | alice_or_betty (GCP_get_id (t->destination))) | ||
1687 | { | 1728 | { |
1688 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1729 | /* Betty/Bob is not allowed to send KX! */ |
1689 | "Got duplicate KX. Firing back KX_AUTH.\n"); | 1730 | GNUNET_break_op (0); |
1690 | send_kx_auth (t, | ||
1691 | ct, | ||
1692 | &t->ax, | ||
1693 | GNUNET_NO); | ||
1694 | return; | 1731 | return; |
1695 | } | 1732 | } |
1733 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1734 | "Received KX message from %s with ephemeral %s from %s on connection %s\n", | ||
1735 | GCT_2s (t), | ||
1736 | GNUNET_e2s (&msg->ephemeral_key), | ||
1737 | GNUNET_i2s (GCP_get_id (t->destination)), | ||
1738 | GCC_2s (ct->cc)); | ||
1739 | #if 1 | ||
1740 | if ( (0 == | ||
1741 | memcmp (&t->ax.DHRr, | ||
1742 | &msg->ratchet_key, | ||
1743 | sizeof (msg->ratchet_key))) && | ||
1744 | (0 == | ||
1745 | memcmp (&t->ax.last_ephemeral, | ||
1746 | &msg->ephemeral_key, | ||
1747 | sizeof (msg->ephemeral_key))) ) | ||
1696 | 1748 | ||
1749 | { | ||
1750 | GNUNET_STATISTICS_update (stats, | ||
1751 | "# Duplicate KX received", | ||
1752 | 1, | ||
1753 | GNUNET_NO); | ||
1754 | send_kx_auth (t, | ||
1755 | ct, | ||
1756 | &t->ax, | ||
1757 | GNUNET_NO); | ||
1758 | return; | ||
1759 | } | ||
1760 | #endif | ||
1697 | /* We only keep ONE unverified KX around, so if there is an existing one, | 1761 | /* We only keep ONE unverified KX around, so if there is an existing one, |
1698 | clean it up. */ | 1762 | clean it up. */ |
1699 | if (NULL != t->unverified_ax) | 1763 | if (NULL != t->unverified_ax) |
1700 | { | 1764 | { |
1701 | if (0 == | 1765 | if ( (0 == |
1702 | memcmp (&t->unverified_ax->DHRr, | 1766 | memcmp (&t->unverified_ax->DHRr, |
1703 | &msg->ratchet_key, | 1767 | &msg->ratchet_key, |
1704 | sizeof (msg->ratchet_key))) | 1768 | sizeof (msg->ratchet_key))) && |
1769 | (0 == | ||
1770 | memcmp (&t->unverified_ax->last_ephemeral, | ||
1771 | &msg->ephemeral_key, | ||
1772 | sizeof (msg->ephemeral_key))) ) | ||
1705 | { | 1773 | { |
1706 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1774 | GNUNET_STATISTICS_update (stats, |
1707 | "Got duplicate unverified KX on %s. Fire back KX_AUTH again.\n", | 1775 | "# Duplicate unverified KX received", |
1708 | GCT_2s (t)); | 1776 | 1, |
1777 | GNUNET_NO); | ||
1778 | #if 1 | ||
1709 | send_kx_auth (t, | 1779 | send_kx_auth (t, |
1710 | ct, | 1780 | ct, |
1711 | t->unverified_ax, | 1781 | t->unverified_ax, |
1712 | GNUNET_NO); | 1782 | GNUNET_NO); |
1713 | return; | 1783 | return; |
1784 | #endif | ||
1714 | } | 1785 | } |
1715 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1786 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1716 | "Dropping old unverified KX state. Got a fresh KX for %s.\n", | 1787 | "Dropping old unverified KX state.\n"); |
1717 | GCT_2s (t)); | 1788 | GNUNET_STATISTICS_update (stats, |
1789 | "# Unverified KX dropped for fresh KX", | ||
1790 | 1, | ||
1791 | GNUNET_NO); | ||
1792 | GNUNET_break (NULL == t->unverified_ax->skipped_head); | ||
1718 | memset (t->unverified_ax, | 1793 | memset (t->unverified_ax, |
1719 | 0, | 1794 | 0, |
1720 | sizeof (struct CadetTunnelAxolotl)); | 1795 | sizeof (struct CadetTunnelAxolotl)); |
1721 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1722 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1723 | } | 1796 | } |
1724 | else | 1797 | else |
1725 | { | 1798 | { |
1726 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1799 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1727 | "Creating fresh unverified KX for %s.\n", | 1800 | "Creating fresh unverified KX for %s\n", |
1728 | GCT_2s (t)); | 1801 | GCT_2s (t)); |
1802 | GNUNET_STATISTICS_update (stats, | ||
1803 | "# Fresh KX setup", | ||
1804 | 1, | ||
1805 | GNUNET_NO); | ||
1729 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); | 1806 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); |
1730 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1731 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1732 | } | 1807 | } |
1733 | /* Set as the 'current' RK/DHRr the one we are currently using, | 1808 | /* Set as the 'current' RK/DHRr the one we are currently using, |
1734 | so that the duplicate-detection logic of | 1809 | so that the duplicate-detection logic of |
1735 | #update_ax_by_kx can work. */ | 1810 | #update_ax_by_kx can work. */ |
1736 | t->unverified_ax->RK = t->ax.RK; | 1811 | t->unverified_ax->RK = t->ax.RK; |
1737 | t->unverified_ax->DHRr = t->ax.DHRr; | 1812 | t->unverified_ax->DHRr = t->ax.DHRr; |
1813 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1814 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1738 | t->unverified_attempts = 0; | 1815 | t->unverified_attempts = 0; |
1739 | ax = t->unverified_ax; | ||
1740 | 1816 | ||
1741 | /* Update 'ax' by the new key material */ | 1817 | /* Update 'ax' by the new key material */ |
1742 | ret = update_ax_by_kx (ax, | 1818 | ret = update_ax_by_kx (t->unverified_ax, |
1743 | GCP_get_id (t->destination), | 1819 | GCP_get_id (t->destination), |
1744 | &msg->ephemeral_key, | 1820 | &msg->ephemeral_key, |
1745 | &msg->ratchet_key); | 1821 | &msg->ratchet_key); |
1746 | GNUNET_break (GNUNET_SYSERR != ret); | 1822 | GNUNET_break (GNUNET_SYSERR != ret); |
1747 | if (GNUNET_OK != ret) | 1823 | if (GNUNET_OK != ret) |
1824 | { | ||
1825 | GNUNET_STATISTICS_update (stats, | ||
1826 | "# Useless KX", | ||
1827 | 1, | ||
1828 | GNUNET_NO); | ||
1748 | return; /* duplicate KX, nothing to do */ | 1829 | return; /* duplicate KX, nothing to do */ |
1749 | 1830 | } | |
1750 | /* move ahead in our state machine */ | 1831 | /* move ahead in our state machine */ |
1751 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | 1832 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) |
1752 | GCT_change_estate (t, | 1833 | GCT_change_estate (t, |
@@ -1767,6 +1848,75 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1767 | } | 1848 | } |
1768 | 1849 | ||
1769 | 1850 | ||
1851 | #if DEBUG_KX | ||
1852 | static void | ||
1853 | check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1854 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2) | ||
1855 | { | ||
1856 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1857 | struct GNUNET_CRYPTO_EcdhePublicKey p2; | ||
1858 | struct GNUNET_HashCode hc1; | ||
1859 | struct GNUNET_HashCode hc2; | ||
1860 | |||
1861 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1862 | &p1); | ||
1863 | GNUNET_CRYPTO_ecdhe_key_get_public (e2, | ||
1864 | &p2); | ||
1865 | GNUNET_assert (GNUNET_OK == | ||
1866 | GNUNET_CRYPTO_ecc_ecdh (e1, | ||
1867 | &p2, | ||
1868 | &hc1)); | ||
1869 | GNUNET_assert (GNUNET_OK == | ||
1870 | GNUNET_CRYPTO_ecc_ecdh (e2, | ||
1871 | &p1, | ||
1872 | &hc2)); | ||
1873 | GNUNET_break (0 == memcmp (&hc1, | ||
1874 | &hc2, | ||
1875 | sizeof (hc1))); | ||
1876 | } | ||
1877 | |||
1878 | |||
1879 | static void | ||
1880 | check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1881 | const struct GNUNET_CRYPTO_EddsaPrivateKey *e2) | ||
1882 | { | ||
1883 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1884 | struct GNUNET_CRYPTO_EddsaPublicKey p2; | ||
1885 | struct GNUNET_HashCode hc1; | ||
1886 | struct GNUNET_HashCode hc2; | ||
1887 | |||
1888 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1889 | &p1); | ||
1890 | GNUNET_CRYPTO_eddsa_key_get_public (e2, | ||
1891 | &p2); | ||
1892 | GNUNET_assert (GNUNET_OK == | ||
1893 | GNUNET_CRYPTO_ecdh_eddsa (e1, | ||
1894 | &p2, | ||
1895 | &hc1)); | ||
1896 | GNUNET_assert (GNUNET_OK == | ||
1897 | GNUNET_CRYPTO_eddsa_ecdh (e2, | ||
1898 | &p1, | ||
1899 | &hc2)); | ||
1900 | GNUNET_break (0 == memcmp (&hc1, | ||
1901 | &hc2, | ||
1902 | sizeof (hc1))); | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | static void | ||
1907 | test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1908 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2, | ||
1909 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d1, | ||
1910 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d2) | ||
1911 | { | ||
1912 | check_ee (e1, e2); | ||
1913 | check_ed (e1, d2); | ||
1914 | check_ed (e2, d1); | ||
1915 | } | ||
1916 | |||
1917 | #endif | ||
1918 | |||
1919 | |||
1770 | /** | 1920 | /** |
1771 | * Handle KX_AUTH message. | 1921 | * Handle KX_AUTH message. |
1772 | * | 1922 | * |
@@ -1782,6 +1932,10 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, | |||
1782 | struct GNUNET_HashCode kx_auth; | 1932 | struct GNUNET_HashCode kx_auth; |
1783 | int ret; | 1933 | int ret; |
1784 | 1934 | ||
1935 | GNUNET_STATISTICS_update (stats, | ||
1936 | "# KX_AUTH received", | ||
1937 | 1, | ||
1938 | GNUNET_NO); | ||
1785 | if ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | 1939 | if ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || |
1786 | (CADET_TUNNEL_KEY_AX_RECV == t->estate) ) | 1940 | (CADET_TUNNEL_KEY_AX_RECV == t->estate) ) |
1787 | { | 1941 | { |
@@ -1792,9 +1946,9 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, | |||
1792 | return; | 1946 | return; |
1793 | } | 1947 | } |
1794 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1948 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1795 | "Handling KX_AUTH message for %s\n", | 1949 | "Handling KX_AUTH message from %s with ephemeral %s\n", |
1796 | GCT_2s (t)); | 1950 | GCT_2s (t), |
1797 | 1951 | GNUNET_e2s (&msg->kx.ephemeral_key)); | |
1798 | /* We do everything in ax_tmp until we've checked the authentication | 1952 | /* We do everything in ax_tmp until we've checked the authentication |
1799 | so we don't clobber anything we care about by accident. */ | 1953 | so we don't clobber anything we care about by accident. */ |
1800 | ax_tmp = t->ax; | 1954 | ax_tmp = t->ax; |
@@ -1828,9 +1982,39 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, | |||
1828 | "# KX_AUTH not using our last KX received (auth failure)", | 1982 | "# KX_AUTH not using our last KX received (auth failure)", |
1829 | 1, | 1983 | 1, |
1830 | GNUNET_NO); | 1984 | GNUNET_NO); |
1831 | send_kx (t, | 1985 | LOG (GNUNET_ERROR_TYPE_WARNING, |
1832 | ct, | 1986 | "KX AUTH missmatch!\n"); |
1833 | &t->ax); | 1987 | #if DEBUG_KX |
1988 | { | ||
1989 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
1990 | |||
1991 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0, | ||
1992 | &ephemeral_key); | ||
1993 | if (0 != memcmp (&ephemeral_key, | ||
1994 | &msg->r_ephemeral_key_XXX, | ||
1995 | sizeof (ephemeral_key))) | ||
1996 | { | ||
1997 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1998 | "My ephemeral is %s!\n", | ||
1999 | GNUNET_e2s (&ephemeral_key)); | ||
2000 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2001 | "Response is for ephemeral %s!\n", | ||
2002 | GNUNET_e2s (&msg->r_ephemeral_key_XXX)); | ||
2003 | } | ||
2004 | else | ||
2005 | { | ||
2006 | test_crypto_bug (&ax_tmp.kx_0, | ||
2007 | &msg->kx.ephemeral_key_XXX, | ||
2008 | my_private_key, | ||
2009 | &msg->kx.private_key_XXX); | ||
2010 | } | ||
2011 | } | ||
2012 | #endif | ||
2013 | if (NULL == t->kx_task) | ||
2014 | t->kx_task | ||
2015 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2016 | &retry_kx, | ||
2017 | t); | ||
1834 | return; | 2018 | return; |
1835 | } | 2019 | } |
1836 | /* Yep, we're good. */ | 2020 | /* Yep, we're good. */ |
@@ -1862,6 +2046,13 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, | |||
1862 | Nothing to do here. */ | 2046 | Nothing to do here. */ |
1863 | break; | 2047 | break; |
1864 | } | 2048 | } |
2049 | if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags))) | ||
2050 | { | ||
2051 | send_kx_auth (t, | ||
2052 | NULL, | ||
2053 | &t->ax, | ||
2054 | GNUNET_NO); | ||
2055 | } | ||
1865 | } | 2056 | } |
1866 | 2057 | ||
1867 | 2058 | ||
@@ -2236,8 +2427,8 @@ connection_ready_cb (void *cls, | |||
2236 | { | 2427 | { |
2237 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 2428 | case CADET_TUNNEL_KEY_UNINITIALIZED: |
2238 | /* Do not begin KX if WE have no channels waiting! */ | 2429 | /* Do not begin KX if WE have no channels waiting! */ |
2239 | if (0 == GCT_count_channels (t)) | 2430 | if (0 != GNUNET_TIME_absolute_get_remaining (t->next_kx_attempt).rel_value_us) |
2240 | return; | 2431 | return; /* wait for timeout before retrying */ |
2241 | /* We are uninitialized, just transmit immediately, | 2432 | /* We are uninitialized, just transmit immediately, |
2242 | without undue delay. */ | 2433 | without undue delay. */ |
2243 | if (NULL != t->kx_task) | 2434 | if (NULL != t->kx_task) |
@@ -2248,6 +2439,15 @@ connection_ready_cb (void *cls, | |||
2248 | send_kx (t, | 2439 | send_kx (t, |
2249 | ct, | 2440 | ct, |
2250 | &t->ax); | 2441 | &t->ax); |
2442 | if ( (0 == | ||
2443 | GCT_count_channels (t)) && | ||
2444 | (NULL == t->destroy_task) ) | ||
2445 | { | ||
2446 | t->destroy_task | ||
2447 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | ||
2448 | &destroy_tunnel, | ||
2449 | t); | ||
2450 | } | ||
2251 | break; | 2451 | break; |
2252 | case CADET_TUNNEL_KEY_AX_RECV: | 2452 | case CADET_TUNNEL_KEY_AX_RECV: |
2253 | case CADET_TUNNEL_KEY_AX_SENT: | 2453 | case CADET_TUNNEL_KEY_AX_SENT: |
@@ -2263,6 +2463,8 @@ connection_ready_cb (void *cls, | |||
2263 | case CADET_TUNNEL_KEY_OK: | 2463 | case CADET_TUNNEL_KEY_OK: |
2264 | if (GNUNET_YES == t->kx_auth_requested) | 2464 | if (GNUNET_YES == t->kx_auth_requested) |
2265 | { | 2465 | { |
2466 | if (0 != GNUNET_TIME_absolute_get_remaining (t->next_kx_attempt).rel_value_us) | ||
2467 | return; /* wait for timeout */ | ||
2266 | if (NULL != t->kx_task) | 2468 | if (NULL != t->kx_task) |
2267 | { | 2469 | { |
2268 | GNUNET_SCHEDULER_cancel (t->kx_task); | 2470 | GNUNET_SCHEDULER_cancel (t->kx_task); |
@@ -2370,15 +2572,21 @@ evaluate_connection (void *cls, | |||
2370 | { | 2572 | { |
2371 | struct EvaluationSummary *es = cls; | 2573 | struct EvaluationSummary *es = cls; |
2372 | struct CadetConnection *cc = ct->cc; | 2574 | struct CadetConnection *cc = ct->cc; |
2373 | struct CadetPeerPath *ps = GCC_get_path (cc); | 2575 | unsigned int ct_length; |
2576 | struct CadetPeerPath *ps; | ||
2374 | const struct CadetConnectionMetrics *metrics; | 2577 | const struct CadetConnectionMetrics *metrics; |
2375 | GNUNET_CONTAINER_HeapCostType ct_desirability; | 2578 | GNUNET_CONTAINER_HeapCostType ct_desirability; |
2376 | struct GNUNET_TIME_Relative uptime; | 2579 | struct GNUNET_TIME_Relative uptime; |
2377 | struct GNUNET_TIME_Relative last_use; | 2580 | struct GNUNET_TIME_Relative last_use; |
2378 | uint32_t ct_length; | ||
2379 | double score; | 2581 | double score; |
2380 | double success_rate; | 2582 | double success_rate; |
2381 | 2583 | ||
2584 | ps = GCC_get_path (cc, | ||
2585 | &ct_length); | ||
2586 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2587 | "Evaluating path %s of existing %s\n", | ||
2588 | GCPP_2s (ps), | ||
2589 | GCC_2s (cc)); | ||
2382 | if (ps == es->path) | 2590 | if (ps == es->path) |
2383 | { | 2591 | { |
2384 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2592 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -2387,8 +2595,39 @@ evaluate_connection (void *cls, | |||
2387 | es->duplicate = GNUNET_YES; | 2595 | es->duplicate = GNUNET_YES; |
2388 | return; | 2596 | return; |
2389 | } | 2597 | } |
2598 | if (NULL != es->path) | ||
2599 | { | ||
2600 | int duplicate = GNUNET_YES; | ||
2601 | |||
2602 | for (unsigned int i=0;i<ct_length;i++) | ||
2603 | { | ||
2604 | GNUNET_assert (GCPP_get_length (es->path) > i); | ||
2605 | if (GCPP_get_peer_at_offset (es->path, | ||
2606 | i) != | ||
2607 | GCPP_get_peer_at_offset (ps, | ||
2608 | i)) | ||
2609 | { | ||
2610 | duplicate = GNUNET_NO; | ||
2611 | break; | ||
2612 | } | ||
2613 | } | ||
2614 | if (GNUNET_YES == duplicate) | ||
2615 | { | ||
2616 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2617 | "Ignoring overlapping path %s.\n", | ||
2618 | GCPP_2s (es->path)); | ||
2619 | es->duplicate = GNUNET_YES; | ||
2620 | return; | ||
2621 | } | ||
2622 | else | ||
2623 | { | ||
2624 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2625 | "Known path %s differs from proposed path\n", | ||
2626 | GCPP_2s (ps)); | ||
2627 | } | ||
2628 | } | ||
2629 | |||
2390 | ct_desirability = GCPP_get_desirability (ps); | 2630 | ct_desirability = GCPP_get_desirability (ps); |
2391 | ct_length = GCPP_get_length (ps); | ||
2392 | metrics = GCC_get_metrics (cc); | 2631 | metrics = GCC_get_metrics (cc); |
2393 | uptime = GNUNET_TIME_absolute_get_duration (metrics->age); | 2632 | uptime = GNUNET_TIME_absolute_get_duration (metrics->age); |
2394 | last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use); | 2633 | last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use); |
@@ -2437,6 +2676,8 @@ consider_path_cb (void *cls, | |||
2437 | struct CadetTConnection *ct; | 2676 | struct CadetTConnection *ct; |
2438 | 2677 | ||
2439 | GNUNET_assert (off < GCPP_get_length (path)); | 2678 | GNUNET_assert (off < GCPP_get_length (path)); |
2679 | GNUNET_assert (GCPP_get_peer_at_offset (path, | ||
2680 | off) == t->destination); | ||
2440 | es.min_length = UINT_MAX; | 2681 | es.min_length = UINT_MAX; |
2441 | es.max_length = 0; | 2682 | es.max_length = 0; |
2442 | es.max_desire = 0; | 2683 | es.max_desire = 0; |
@@ -2446,6 +2687,13 @@ consider_path_cb (void *cls, | |||
2446 | es.worst = NULL; | 2687 | es.worst = NULL; |
2447 | 2688 | ||
2448 | /* Compute evaluation summary over existing connections. */ | 2689 | /* Compute evaluation summary over existing connections. */ |
2690 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2691 | "Evaluating proposed path %s for target %s\n", | ||
2692 | GCPP_2s (path), | ||
2693 | GCT_2s (t)); | ||
2694 | /* FIXME: suspect this does not ACTUALLY iterate | ||
2695 | over all existing paths, otherwise dup detection | ||
2696 | should work!!! */ | ||
2449 | GCT_iterate_connections (t, | 2697 | GCT_iterate_connections (t, |
2450 | &evaluate_connection, | 2698 | &evaluate_connection, |
2451 | &es); | 2699 | &es); |
@@ -2590,9 +2838,10 @@ GCT_consider_path (struct CadetTunnel *t, | |||
2590 | unsigned int off) | 2838 | unsigned int off) |
2591 | { | 2839 | { |
2592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2840 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2593 | "Considering %s for %s\n", | 2841 | "Considering %s for %s (offset %u)\n", |
2594 | GCPP_2s (p), | 2842 | GCPP_2s (p), |
2595 | GCT_2s (t)); | 2843 | GCT_2s (t), |
2844 | off); | ||
2596 | (void) consider_path_cb (t, | 2845 | (void) consider_path_cb (t, |
2597 | p, | 2846 | p, |
2598 | off); | 2847 | off); |