aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-02-05 00:50:38 +0100
committerMartin Schanzenbach <schanzen@gnunet.org>2022-02-05 15:38:39 +0100
commitee865f851ca4b173da8d00e87a0ad446efc8037e (patch)
tree92a627afa5799d78df0fd5b09a711ca3b89a8b6b /src/namestore
parent65f9e37ce036acdfab29b25b9b6f69de1b126962 (diff)
downloadgnunet-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.c97
-rw-r--r--src/namestore/namestore.h6
-rw-r--r--src/namestore/namestore_api.c50
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 */
1463static void
1464lookup_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 */
987struct GNUNET_NAMESTORE_QueueEntry * 972struct GNUNET_NAMESTORE_QueueEntry *
988GNUNET_NAMESTORE_records_store ( 973GNUNET_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 */
1073struct GNUNET_NAMESTORE_QueueEntry *
1074GNUNET_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.