/** * Store values in hashmap in file and free data * * @param plugin the plugin context */ static int store_and_free_entries (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_DISK_FileHandle *fh = cls; struct FlatFileEntry *entry = value; char *line; char *block_b64; struct GNUNET_CRYPTO_HashAsciiEncoded query; size_t block_size; block_size = ntohl (entry->block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature); GNUNET_STRINGS_base64_encode ((char*)entry->block, block_size, &block_b64); GNUNET_CRYPTO_hash_to_enc (&entry->query, &query); GNUNET_asprintf (&line, "%s,%s\n", (char*)&query, block_b64); GNUNET_free (block_b64); GNUNET_DISK_file_write (fh, line, strlen (line)); GNUNET_free (entry->block); GNUNET_free (entry); return GNUNET_YES; }
/** * Send a message to the specified remote node. * * @param tsession the GNUNET_MessageHello identifying the remote node * @param msg what to send * @param size the size of the message * @param important is this message important enough to override typical limits? * @return GNUNET_SYSERR on error, GNUNET_OK on success */ static int api_send (GNUNET_TSession * tsession, const void *msg, const unsigned int size, int important) { const GNUNET_MessageHello *hello; const EmailAddress *haddr; char *m; char *filter; char *fvalue; SMTPMessage *mp; struct GetMessageClosure gm_cls; smtp_session_t session; smtp_message_t message; smtp_recipient_t recipient; #define EBUF_LEN 128 char ebuf[EBUF_LEN]; GNUNET_CronTime now; if (smtp_shutdown == GNUNET_YES) return GNUNET_SYSERR; if ((size == 0) || (size > smtpAPI.mtu)) { GNUNET_GE_BREAK (ectx, 0); return GNUNET_SYSERR; } now = GNUNET_get_time (); if ((important != GNUNET_YES) && ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS) return GNUNET_NO; /* rate too high */ last_transmission = now; hello = (const GNUNET_MessageHello *) tsession->internal; if (hello == NULL) return GNUNET_SYSERR; GNUNET_mutex_lock (lock); session = smtp_create_session (); if (session == NULL) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"), "smtp_create_session", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); GNUNET_mutex_unlock (lock); return GNUNET_SYSERR; } if (0 == smtp_set_server (session, smtp_server_name)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"), "smtp_set_server", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); return GNUNET_SYSERR; } haddr = (const EmailAddress *) &hello[1]; message = smtp_add_message (session); if (message == NULL) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_add_message", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); return GNUNET_SYSERR; } smtp_set_header (message, "To", NULL, haddr->senderAddress); smtp_set_header (message, "From", NULL, email); filter = GNUNET_strdup (haddr->filter); fvalue = strstr (filter, ": "); GNUNET_GE_ASSERT (NULL, NULL != fvalue); fvalue[0] = '\0'; fvalue += 2; if (0 == smtp_set_header (message, filter, fvalue)) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_set_header", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); GNUNET_free (filter); return GNUNET_SYSERR; } GNUNET_free (filter); m = GNUNET_malloc (size + sizeof (SMTPMessage)); GNUNET_memcpy (m, msg, size); mp = (SMTPMessage *) &m[size]; mp->header.size = htons (size + sizeof (SMTPMessage)); mp->header.type = htons (0); mp->sender = *core_api->my_identity; gm_cls.ebody = NULL; gm_cls.pos = 0; gm_cls.esize = GNUNET_STRINGS_base64_encode (m, size + sizeof (SMTPMessage), &gm_cls.ebody); GNUNET_free (m); if (0 == smtp_size_set_estimate (message, gm_cls.esize)) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); } if (0 == smtp_set_messagecb (message, &get_message, &gm_cls)) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); GNUNET_free (gm_cls.ebody); return GNUNET_SYSERR; } recipient = smtp_add_recipient (message, haddr->senderAddress); if (recipient == NULL) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); return GNUNET_SYSERR; } if (0 == smtp_start_session (session)) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"), "smtp_start_session", smtp_strerror (smtp_errno (), ebuf, EBUF_LEN)); smtp_destroy_session (session); GNUNET_mutex_unlock (lock); GNUNET_free (gm_cls.ebody); return GNUNET_SYSERR; } if (stats != NULL) stats->change (stat_bytesSent, size); if (core_api->load_monitor != NULL) GNUNET_network_monitor_notify_transmission (core_api->load_monitor, GNUNET_ND_UPLOAD, gm_cls.esize); smtp_message_reset_status (message); /* this is needed to plug a 28-byte/message memory leak in libesmtp */ smtp_destroy_session (session); GNUNET_mutex_unlock (lock); GNUNET_free (gm_cls.ebody); return GNUNET_OK; }
/** * 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; }