static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { zi = NULL; res = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records); GNUNET_SCHEDULER_add_now (&end, NULL); return; } if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { failed = check_zone_1 (label, rd_count, rd); if (GNUNET_YES == failed) GNUNET_break (0); } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { failed = check_zone_2 (label, rd_count, rd); if (GNUNET_YES == failed) GNUNET_break (0); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } if (failed == GNUNET_NO) { returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); res = 1; GNUNET_SCHEDULER_add_now (&end, NULL); } }
/** * Continuation for token store call * * @param cls NULL * @param success error code * @param emsg error message */ static void store_token_cont (void *cls, int32_t success, const char *emsg) { ns_qe = NULL; if (GNUNET_SYSERR == success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to update token: %s\n", emsg); return; } GNUNET_NAMESTORE_zone_iterator_next (ns_it); }
/** * * Update all ID_TOKEN records for an identity and store them * * @param cls the identity entry * @param zone the identity * @param lbl the name of the record * @param rd_count number of records * @param rd record data * */ static void token_collect (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *lbl, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct EgoEntry *ego_entry = cls; if (NULL == lbl) { //Done GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Ego finished\n"); //Clear attribute map for ego GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, &clear_ego_attrs, ego_entry); GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next); return; } //There should be only a single record for a token under a label if ((1 != rd_count) || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN) || (0 == (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags))) { GNUNET_NAMESTORE_zone_iterator_next (ns_it); return; } token = GNUNET_GNSRECORD_value_to_string (rd->record_type, rd->data, rd->data_size); label = GNUNET_strdup (lbl); GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry); }
/** * Method called periodicattluy that triggers * iteration over root zone * * @param cls closure * @param tc task context */ static void update_zone_dht_next(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; GNUNET_NAMESTORE_zone_iterator_next(namestore_iter); }
static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { GNUNET_break (2 == returned_records); if (2 == returned_records) { res = 0; /* Last iteraterator callback, we are done */ zi = NULL; } else res = 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records ); GNUNET_SCHEDULER_add_now (&end, NULL); return; } GNUNET_assert (NULL != zone); if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_1)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (label, s_name_2)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received data for not requested zone\n"); failed = GNUNET_YES; GNUNET_break (0); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } if (failed == GNUNET_NO) { returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } }
/** * Process a record that was stored in the namestore. * * @param cls closure * @param zone_key private key of the zone * @param rname name that is being mapped (at most 255 characters long) * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void display_record (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *rname, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { const char *typestring; char *s; unsigned int i; const char *ets; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Relative rt; if (NULL == rname) { list_it = NULL; test_finished (); return; } if ( (NULL != name) && (0 != strcmp (name, rname)) ) { GNUNET_NAMESTORE_zone_iterator_next (list_it); return; } FPRINTF (stdout, "%s:\n", rname); for (i=0;i<rd_len;i++) { if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && (0 != strcmp (rname, "+")) ) continue; typestring = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type); s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, rd[i].data, rd[i].data_size); if (NULL == s) { FPRINTF (stdout, _("\tCorrupt or unsupported record of type %u\n"), (unsigned int) rd[i].record_type); continue; } if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { rt.rel_value_us = rd[i].expiration_time; ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES); } else { at.abs_value_us = rd[i].expiration_time; ets = GNUNET_STRINGS_absolute_time_to_string (at); } FPRINTF (stdout, "\t%s: %s (%s)\t%s\t%s\n", typestring, s, ets, (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE" : "PUBLIC", (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW" : ""); GNUNET_free (s); } FPRINTF (stdout, "%s", "\n"); GNUNET_NAMESTORE_zone_iterator_next (list_it); }
static void zone_proc (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, struct GNUNET_TIME_Absolute expire, const char *name, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { int failed = GNUNET_NO; if ((zone_key == NULL) && (name == NULL)) { GNUNET_break (3 == returned_records); if (3 == returned_records) res = 0; else res = 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n",returned_records ); GNUNET_SCHEDULER_add_now (&end, NULL); } else { /* verify signature returned from name store */ if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(zone_key, expire, name, rd_count, rd, signature)) { failed = GNUNET_YES; GNUNET_break (0); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s \n", name); if (0 == strcmp (name, s_name_1)) { /* name_1 */ if (rd_count == 1) { if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_1)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name_1, 1, s_rd_1, signature)) { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (name, s_name_2)) { /* name_2 */ if (rd_count == 1) { if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_2)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey, expire, s_name_2, 1, s_rd_2, signature)) { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (name, s_name_3)) { /* name_3 */ if (rd_count == 1) { if (GNUNET_YES != GNUNET_NAMESTORE_records_cmp(rd, s_rd_3)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature(&pubkey2, expire, s_name_3, 1, s_rd_3, signature)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s'\n", name); res = 1; GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } if (failed == GNUNET_NO) { returned_records ++; if (1 == returned_records) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping zone iteration after %u received record \n",returned_records ); GNUNET_NAMESTORE_zone_iteration_stop (zi); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3), &end , NULL); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } } }
/** * Process a record that was stored in the namestore, adding * the information to the HTML. * * @param cls closure with the `struct ZoneinfoRequest *` * @param zone_key private key of the zone; NULL on disconnect * @param name label of the records; NULL on disconnect * @param rd_len number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ static void iterate_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { struct ZoneinfoRequest *zr = cls; struct MHD_Response *response; char* full_page; size_t bytes_free; char* pkey; char* new_buf; if (NULL == name) { zr->list_it = NULL; /* return static form */ GNUNET_asprintf (&full_page, ZONEINFO_PAGE, zr->zoneinfo, zr->zoneinfo); response = MHD_create_response_from_buffer (strlen (full_page), (void *) full_page, MHD_RESPMEM_MUST_FREE); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, MIME_HTML); MHD_queue_response (zr->connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (zr->zoneinfo); GNUNET_free (zr); run_httpd_now (); return; } if (1 != rd_len) { GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); return; } if (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type) { GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); return; } bytes_free = zr->buf_len - zr->write_offset; pkey = GNUNET_GNSRECORD_value_to_string (rd->record_type, rd->data, rd->data_size); if (NULL == pkey) { GNUNET_break (0); GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); return; } if (bytes_free < (strlen (name) + strlen (pkey) + 40)) { new_buf = GNUNET_malloc (zr->buf_len * 2); memcpy (new_buf, zr->zoneinfo, zr->write_offset); GNUNET_free (zr->zoneinfo); zr->zoneinfo = new_buf; zr->buf_len *= 2; } sprintf (zr->zoneinfo + zr->write_offset, "<tr><td>%s</td><td>%s</td></tr>", name, pkey); zr->write_offset = strlen (zr->zoneinfo); GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); GNUNET_free (pkey); }
/** * * Collect all ID_ATTR records for an identity and store them * * @param cls the identity entry * @param zone the identity * @param lbl the name of the record * @param rd_count number of records * @param rd record data * */ static void attribute_collect (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *lbl, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct EgoEntry *ego_entry = cls; json_t *attr_value; struct GNUNET_HashCode key; char* attr; int i; if (NULL == lbl) { //Done GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Attributes finished\n"); ego_entry->attributes_dirty = GNUNET_NO; GNUNET_SCHEDULER_add_now (&update_identities, ego_entry); return; } if (0 == rd_count) { GNUNET_NAMESTORE_zone_iterator_next (ns_it); return; } GNUNET_CRYPTO_hash (lbl, strlen (lbl), &key); if (1 == rd_count) { if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) { attr = GNUNET_GNSRECORD_value_to_string (rd->record_type, rd->data, rd->data_size); attr_value = json_string (attr); GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, &key, attr_value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); GNUNET_free (attr); } GNUNET_NAMESTORE_zone_iterator_next (ns_it); return; } attr_value = json_array(); for (i = 0; i < rd_count; i++) { if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) { attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, rd[i].data, rd[i].data_size); json_array_append_new (attr_value, json_string (attr)); GNUNET_free (attr); } } GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map, &key, attr_value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); GNUNET_NAMESTORE_zone_iterator_next (ns_it); return; }
/** * This function updates the old token with new attributes, * removes deleted attributes and expiration times. * * @param cls the ego entry * @param tc task context */ static void handle_token_update (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char *token_header; char *token_payload; char *token_payload_json; char *new_token; char *new_payload_str; char *new_payload_base64; char *sig_str; char *key; char *padding; const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; struct EgoEntry *ego_entry = cls; struct GNUNET_GNSRECORD_Data token_record; struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; struct GNUNET_CRYPTO_EcdsaSignature sig; struct GNUNET_HashCode key_hash; struct GNUNET_TIME_Relative token_rel_exp; struct GNUNET_TIME_Relative token_ttl; struct GNUNET_TIME_Absolute token_exp; struct GNUNET_TIME_Absolute token_nbf; struct GNUNET_TIME_Absolute new_exp; struct GNUNET_TIME_Absolute new_iat; struct GNUNET_TIME_Absolute new_nbf; json_t *payload_json; json_t *value; json_t *cur_value; json_t *new_payload_json; json_t *token_nbf_json; json_t *token_exp_json; json_error_t json_err; priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); //Note: We need the token expiration time here. Not the record expiration //time. //There are two types of tokens: Token that expire on GNS level with //an absolute expiration time. Those are basically tokens that will //be automatically revoked on (record)expiration. //Tokens stored with relative expiration times will expire on the token level (token expiration) //but this service will reissue new tokens that can be retrieved from GNS //automatically. token_header = strtok (token, "."); token_payload = strtok (NULL, "."); GNUNET_STRINGS_base64_decode (token_payload, strlen (token_payload), &token_payload_json); payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err); GNUNET_free (token_payload_json); token_exp_json = json_object_get (payload_json, "exp"); token_nbf_json = json_object_get (payload_json, "nbf"); token_exp.abs_value_us = json_integer_value(token_exp_json); token_nbf.abs_value_us = json_integer_value(token_nbf_json); token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp); token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp); if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us) { //This token is not yet expired! Save and skip if (min_rel_exp.rel_value_us > token_ttl.rel_value_us) { min_rel_exp = token_ttl; } json_decref (payload_json); GNUNET_free (token); token = NULL; GNUNET_free (label); label = NULL; GNUNET_NAMESTORE_zone_iterator_next (ns_it); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Token is expired. Create a new one\n"); new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); new_nbf = GNUNET_TIME_absolute_get (); new_iat = new_nbf; new_payload_json = json_object(); json_object_foreach(payload_json, key, value) { if (0 == strcmp (key, "exp")) { json_object_set_new (new_payload_json, key, json_integer (new_exp.abs_value_us)); } else if (0 == strcmp (key, "nbf")) { json_object_set_new (new_payload_json, key, json_integer (new_nbf.abs_value_us)); } else if (0 == strcmp (key, "iat")) { json_object_set_new (new_payload_json, key, json_integer (new_iat.abs_value_us)); } else if ((0 == strcmp (key, "iss")) || (0 == strcmp (key, "aud")) || (0 == strcmp (key, "sub")) || (0 == strcmp (key, "rnl"))) { json_object_set (new_payload_json, key, value); } else { GNUNET_CRYPTO_hash (key, strlen (key), &key_hash); //Check if attr still exists. omit of not if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map, &key_hash)) { cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map, &key_hash); json_object_set (new_payload_json, key, cur_value); } } } // reassemble and set new_payload_str = json_dumps (new_payload_json, JSON_COMPACT); json_decref (payload_json); json_decref (new_payload_json); GNUNET_STRINGS_base64_encode (new_payload_str, strlen (new_payload_str), &new_payload_base64); //Remove padding padding = strtok(new_payload_base64, "="); while (NULL != padding) padding = strtok(NULL, "="); GNUNET_asprintf (&new_token, "%s,%s", token_header, new_payload_base64); purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + strlen (new_token)); purpose->size = htonl (strlen (new_token) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN); memcpy (&purpose[1], new_token, strlen (new_token)); if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, purpose, &sig)) GNUNET_break(0); GNUNET_free (new_token); sig_str = GNUNET_STRINGS_data_to_string_alloc (&sig, sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); GNUNET_asprintf (&new_token, "%s.%s.%s", token_header, new_payload_base64, sig_str); GNUNET_free (sig_str); GNUNET_free (new_payload_str); GNUNET_free (new_payload_base64); GNUNET_free (purpose); token_record.data = new_token; token_record.data_size = strlen (new_token); token_record.expiration_time = new_exp.abs_value_us; token_record.record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; token_record.flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, priv_key, label, 1, &token_record, &store_token_cont, ego_entry); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token); GNUNET_free (new_token); GNUNET_free (token); token = NULL; GNUNET_free (label); label = NULL; }