diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-02-05 00:50:38 +0100 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-02-05 15:38:39 +0100 |
commit | ee865f851ca4b173da8d00e87a0ad446efc8037e (patch) | |
tree | 92a627afa5799d78df0fd5b09a711ca3b89a8b6b /src/namestore | |
parent | 65f9e37ce036acdfab29b25b9b6f69de1b126962 (diff) | |
download | gnunet-ee865f851ca4b173da8d00e87a0ad446efc8037e.tar.gz gnunet-ee865f851ca4b173da8d00e87a0ad446efc8037e.zip |
GNS: Implement Tombstone logic
GNS: Namestore zonemaster record store processing
ZONEMASTER: Do not publish records if tombstone expires in the future
NAMESTORE: Purge old tombstones.
Diffstat (limited to 'src/namestore')
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 97 | ||||
-rw-r--r-- | src/namestore/namestore.h | 6 | ||||
-rw-r--r-- | src/namestore/namestore_api.c | 50 |
3 files changed, 119 insertions, 34 deletions
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index 3842621ae..cebdf38c5 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -951,12 +951,12 @@ refresh_block (struct NamestoreClient *nc, | |||
951 | exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); | 951 | exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); |
952 | if (cache_keys) | 952 | if (cache_keys) |
953 | GNUNET_assert (GNUNET_OK == | 953 | GNUNET_assert (GNUNET_OK == |
954 | GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, | 954 | GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, |
955 | res, res_count, &block)); | 955 | res, res_count, &block)); |
956 | else | 956 | else |
957 | GNUNET_assert (GNUNET_OK == | 957 | GNUNET_assert (GNUNET_OK == |
958 | GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, | 958 | GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, |
959 | res, res_count, &block)); | 959 | res, res_count, &block)); |
960 | GNUNET_assert (NULL != block); | 960 | GNUNET_assert (NULL != block); |
961 | GNUNET_IDENTITY_key_get_public (zone_key, &pkey); | 961 | GNUNET_IDENTITY_key_get_public (zone_key, &pkey); |
962 | GNUNET_log ( | 962 | GNUNET_log ( |
@@ -974,7 +974,7 @@ refresh_block (struct NamestoreClient *nc, | |||
974 | cop->nc = nc; | 974 | cop->nc = nc; |
975 | cop->zi = zi; | 975 | cop->zi = zi; |
976 | if (NULL != zi) | 976 | if (NULL != zi) |
977 | zi->cache_ops++; | 977 | zi->cache_ops ++; |
978 | cop->rid = rid; | 978 | cop->rid = rid; |
979 | GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); | 979 | GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); |
980 | cop->qe = GNUNET_NAMECACHE_block_cache (namecache, | 980 | cop->qe = GNUNET_NAMECACHE_block_cache (namecache, |
@@ -1341,7 +1341,6 @@ check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1341 | return GNUNET_OK; | 1341 | return GNUNET_OK; |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | |||
1345 | /** | 1344 | /** |
1346 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | 1345 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message |
1347 | * | 1346 | * |
@@ -1452,6 +1451,39 @@ check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1452 | 1451 | ||
1453 | 1452 | ||
1454 | /** | 1453 | /** |
1454 | * Check if set contains a tombstone, store if necessary | ||
1455 | * | ||
1456 | * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found) | ||
1457 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
1458 | * @param private_key the private key of the zone (unused) | ||
1459 | * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT | ||
1460 | * @param rd_count number of records in @a rd | ||
1461 | * @param rd records stored under @a label in the zone | ||
1462 | */ | ||
1463 | static void | ||
1464 | lookup_tombstone_it (void *cls, | ||
1465 | uint64_t seq, | ||
1466 | const struct GNUNET_IDENTITY_PrivateKey *private_key, | ||
1467 | const char *label, | ||
1468 | unsigned int rd_count, | ||
1469 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1470 | { | ||
1471 | struct GNUNET_GNSRECORD_TombstoneRecord *ts = cls; | ||
1472 | |||
1473 | (void) private_key; | ||
1474 | GNUNET_assert (0 != seq); | ||
1475 | for (unsigned int c = 0; c < rd_count; c++) | ||
1476 | { | ||
1477 | if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[c].record_type) | ||
1478 | { | ||
1479 | memcpy (ts, rd[c].data, rd[c].data_size); | ||
1480 | return; | ||
1481 | } | ||
1482 | } | ||
1483 | } | ||
1484 | |||
1485 | |||
1486 | /** | ||
1455 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | 1487 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message |
1456 | * | 1488 | * |
1457 | * @param cls client sending the message | 1489 | * @param cls client sending the message |
@@ -1470,14 +1502,15 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1470 | unsigned int rd_count; | 1502 | unsigned int rd_count; |
1471 | int res; | 1503 | int res; |
1472 | struct StoreActivity *sa; | 1504 | struct StoreActivity *sa; |
1505 | struct GNUNET_GNSRECORD_TombstoneRecord tombstone; | ||
1473 | 1506 | ||
1474 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1507 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1475 | "Received NAMESTORE_RECORD_STORE message\n"); | 1508 | "Received NAMESTORE_RECORD_STORE message\n"); |
1509 | tombstone.time_of_death.abs_value_us__ = 0; | ||
1476 | rid = ntohl (rp_msg->gns_header.r_id); | 1510 | rid = ntohl (rp_msg->gns_header.r_id); |
1477 | name_len = ntohs (rp_msg->name_len); | 1511 | name_len = ntohs (rp_msg->name_len); |
1478 | rd_count = ntohs (rp_msg->rd_count); | 1512 | rd_count = ntohs (rp_msg->rd_count); |
1479 | rd_ser_len = ntohs (rp_msg->rd_len); | 1513 | rd_ser_len = ntohs (rp_msg->rd_len); |
1480 | GNUNET_break (0 == ntohs (rp_msg->reserved)); | ||
1481 | name_tmp = (const char *) &rp_msg[1]; | 1514 | name_tmp = (const char *) &rp_msg[1]; |
1482 | rd_ser = &name_tmp[name_len]; | 1515 | rd_ser = &name_tmp[name_len]; |
1483 | { | 1516 | { |
@@ -1513,8 +1546,8 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1513 | (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls, | 1546 | (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls, |
1514 | &rp_msg->private_key, | 1547 | &rp_msg->private_key, |
1515 | conv_name, | 1548 | conv_name, |
1516 | NULL, | 1549 | &lookup_tombstone_it, |
1517 | 0))) | 1550 | &tombstone))) |
1518 | { | 1551 | { |
1519 | /* This name does not exist, so cannot be removed */ | 1552 | /* This name does not exist, so cannot be removed */ |
1520 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1553 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1525,16 +1558,34 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1525 | else | 1558 | else |
1526 | { | 1559 | { |
1527 | /* remove "NICK" records, unless this is for the | 1560 | /* remove "NICK" records, unless this is for the |
1528 | #GNUNET_GNS_EMPTY_LABEL_AT label */ | 1561 | #GNUNET_GNS_EMPTY_LABEL_AT label |
1529 | struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; | 1562 | Also, add or update tombstone record if this is a zonemaster request. |
1563 | Also, add existing tombstone record to set if this is not a zonemaster | ||
1564 | request if one existed in the old set. | ||
1565 | This is why we (may) need one additional record */ | ||
1566 | struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count) + 1]; | ||
1530 | unsigned int rd_clean_off; | 1567 | unsigned int rd_clean_off; |
1531 | int have_nick; | 1568 | int have_nick; |
1569 | int have_tombstone; | ||
1532 | 1570 | ||
1533 | rd_clean_off = 0; | 1571 | rd_clean_off = 0; |
1534 | have_nick = GNUNET_NO; | 1572 | have_nick = GNUNET_NO; |
1573 | have_tombstone = GNUNET_NO; | ||
1535 | for (unsigned int i = 0; i < rd_count; i++) | 1574 | for (unsigned int i = 0; i < rd_count; i++) |
1536 | { | 1575 | { |
1537 | rd_clean[rd_clean_off] = rd[i]; | 1576 | rd_clean[rd_clean_off] = rd[i]; |
1577 | if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type)) | ||
1578 | rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_CRITICAL; | ||
1579 | /* Do not allow to set tombstone records unless zonemaster */ | ||
1580 | if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type) | ||
1581 | { | ||
1582 | if (1 == ntohs (rp_msg->is_zonemaster)) | ||
1583 | { | ||
1584 | have_tombstone = GNUNET_YES; | ||
1585 | rd_clean_off++; | ||
1586 | } | ||
1587 | continue; | ||
1588 | } | ||
1538 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || | 1589 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || |
1539 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) | 1590 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) |
1540 | rd_clean_off++; | 1591 | rd_clean_off++; |
@@ -1545,8 +1596,24 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1545 | cache_nick (&rp_msg->private_key, &rd[i]); | 1596 | cache_nick (&rp_msg->private_key, &rd[i]); |
1546 | have_nick = GNUNET_YES; | 1597 | have_nick = GNUNET_YES; |
1547 | } | 1598 | } |
1548 | if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type)) | 1599 | } |
1549 | rd_clean[i].flags |= GNUNET_GNSRECORD_RF_CRITICAL; | 1600 | /* At this point we are either zonemaster and have set a new tombstone |
1601 | * (have_tombstone) or we are not zonemaster and we may want to | ||
1602 | * add the old tombstone (if there was any and if it is not already | ||
1603 | * old). | ||
1604 | */ | ||
1605 | if ((GNUNET_NO == have_tombstone) && | ||
1606 | GNUNET_TIME_absolute_cmp (GNUNET_TIME_absolute_get (), (<), | ||
1607 | GNUNET_TIME_absolute_ntoh ( | ||
1608 | tombstone.time_of_death))) | ||
1609 | { | ||
1610 | rd_clean[rd_clean_off].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE; | ||
1611 | rd_clean[rd_clean_off].expiration_time = | ||
1612 | GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
1613 | rd_clean[rd_clean_off].data = &tombstone; | ||
1614 | rd_clean[rd_clean_off].data_size = sizeof (tombstone); | ||
1615 | rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
1616 | rd_clean_off++; | ||
1550 | } | 1617 | } |
1551 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | 1618 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && |
1552 | (GNUNET_NO == have_nick)) | 1619 | (GNUNET_NO == have_nick)) |
@@ -1561,9 +1628,9 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1561 | rd_clean); | 1628 | rd_clean); |
1562 | } | 1629 | } |
1563 | 1630 | ||
1564 | if (GNUNET_OK != res) | 1631 | if ((GNUNET_OK != res) || (1 == ntohs (rp_msg->is_zonemaster))) |
1565 | { | 1632 | { |
1566 | /* store not successful, not need to tell monitors */ | 1633 | /* store not successful or zonemaster, not need to tell monitors */ |
1567 | send_store_response (nc, res, rid); | 1634 | send_store_response (nc, res, rid); |
1568 | GNUNET_SERVICE_client_continue (nc->client); | 1635 | GNUNET_SERVICE_client_continue (nc->client); |
1569 | GNUNET_free (conv_name); | 1636 | GNUNET_free (conv_name); |
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index fd9a8ed47..bcc8f5d4e 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h | |||
@@ -83,9 +83,11 @@ struct RecordStoreMessage | |||
83 | uint16_t rd_count GNUNET_PACKED; | 83 | uint16_t rd_count GNUNET_PACKED; |
84 | 84 | ||
85 | /** | 85 | /** |
86 | * always zero (for alignment) | 86 | * This is a zonemaster request. |
87 | * It means more authoritative tombstone processing | ||
88 | * and not notification of monitors. | ||
87 | */ | 89 | */ |
88 | uint16_t reserved GNUNET_PACKED; | 90 | uint16_t is_zonemaster GNUNET_PACKED; |
89 | 91 | ||
90 | /** | 92 | /** |
91 | * The private key of the authority. | 93 | * The private key of the authority. |
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index b24db9b26..935357d36 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -969,28 +969,14 @@ warn_delay (void *cls) | |||
969 | GNUNET_NAMESTORE_cancel (qe); | 969 | GNUNET_NAMESTORE_cancel (qe); |
970 | } | 970 | } |
971 | 971 | ||
972 | |||
973 | /** | ||
974 | * Store an item in the namestore. If the item is already present, | ||
975 | * it is replaced with the new record. Use an empty array to | ||
976 | * remove all records under the given name. | ||
977 | * | ||
978 | * @param h handle to the namestore | ||
979 | * @param pkey private key of the zone | ||
980 | * @param label name that is being mapped (at most 255 characters long) | ||
981 | * @param rd_count number of records in the @a rd array | ||
982 | * @param rd array of records with data to store | ||
983 | * @param cont continuation to call when done | ||
984 | * @param cont_cls closure for @a cont | ||
985 | * @return handle to abort the request | ||
986 | */ | ||
987 | struct GNUNET_NAMESTORE_QueueEntry * | 972 | struct GNUNET_NAMESTORE_QueueEntry * |
988 | GNUNET_NAMESTORE_records_store ( | 973 | GNUNET_NAMESTORE_records_store_ ( |
989 | struct GNUNET_NAMESTORE_Handle *h, | 974 | struct GNUNET_NAMESTORE_Handle *h, |
990 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | 975 | const struct GNUNET_IDENTITY_PrivateKey *pkey, |
991 | const char *label, | 976 | const char *label, |
992 | unsigned int rd_count, | 977 | unsigned int rd_count, |
993 | const struct GNUNET_GNSRECORD_Data *rd, | 978 | const struct GNUNET_GNSRECORD_Data *rd, |
979 | int is_zonemaster, | ||
994 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | 980 | GNUNET_NAMESTORE_ContinuationWithStatus cont, |
995 | void *cont_cls) | 981 | void *cont_cls) |
996 | { | 982 | { |
@@ -1037,7 +1023,7 @@ GNUNET_NAMESTORE_records_store ( | |||
1037 | msg->name_len = htons (name_len); | 1023 | msg->name_len = htons (name_len); |
1038 | msg->rd_count = htons (rd_count); | 1024 | msg->rd_count = htons (rd_count); |
1039 | msg->rd_len = htons (rd_ser_len); | 1025 | msg->rd_len = htons (rd_ser_len); |
1040 | msg->reserved = htons (0); | 1026 | msg->is_zonemaster = (GNUNET_YES == is_zonemaster) ? ntohs(1) : ntohs(0); |
1041 | msg->private_key = *pkey; | 1027 | msg->private_key = *pkey; |
1042 | 1028 | ||
1043 | name_tmp = (char *) &msg[1]; | 1029 | name_tmp = (char *) &msg[1]; |
@@ -1070,6 +1056,36 @@ GNUNET_NAMESTORE_records_store ( | |||
1070 | return qe; | 1056 | return qe; |
1071 | } | 1057 | } |
1072 | 1058 | ||
1059 | /** | ||
1060 | * Store an item in the namestore. If the item is already present, | ||
1061 | * it is replaced with the new record. Use an empty array to | ||
1062 | * remove all records under the given name. | ||
1063 | * | ||
1064 | * @param h handle to the namestore | ||
1065 | * @param pkey private key of the zone | ||
1066 | * @param label name that is being mapped (at most 255 characters long) | ||
1067 | * @param rd_count number of records in the @a rd array | ||
1068 | * @param rd array of records with data to store | ||
1069 | * @param cont continuation to call when done | ||
1070 | * @param cont_cls closure for @a cont | ||
1071 | * @return handle to abort the request | ||
1072 | */ | ||
1073 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1074 | GNUNET_NAMESTORE_records_store ( | ||
1075 | struct GNUNET_NAMESTORE_Handle *h, | ||
1076 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1077 | const char *label, | ||
1078 | unsigned int rd_count, | ||
1079 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1080 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1081 | void *cont_cls) | ||
1082 | { | ||
1083 | return GNUNET_NAMESTORE_records_store_ (h, pkey, label, rd_count, rd, | ||
1084 | GNUNET_NO, cont, cont_cls); | ||
1085 | } | ||
1086 | |||
1087 | |||
1088 | |||
1073 | 1089 | ||
1074 | /** | 1090 | /** |
1075 | * Lookup an item in the namestore. | 1091 | * Lookup an item in the namestore. |