Beispiel #1
0
/**
 * Listen to the pipe, decode messages and send to core.
 */
static void *
listenAndDistribute (void *unused)
{
  char *line;
  unsigned int linesize;
  SMTPMessage *mp;
  FILE *fdes;
  char *retl;
  char *out;
  unsigned int size;
  GNUNET_TransportPacket *coreMP;
  int fd;
  unsigned int pos;

  linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2) / MAX_CHAR_PER_LINE;      /* maximum size of a line supported */
  line = GNUNET_malloc (linesize + 2);  /* 2 bytes for off-by-one errors, just to be safe... */

#define READLINE(l,limit) \
  do { retl = fgets(l, (limit), fdes);				\
    if ( (retl == NULL) || (smtp_shutdown == GNUNET_YES)) {\
      goto END; \
    }\
    if (core_api->load_monitor != NULL) \
     GNUNET_network_monitor_notify_transmission(core_api->load_monitor, GNUNET_ND_DOWNLOAD, strlen(retl)); \
  } while (0)


  while (smtp_shutdown == GNUNET_NO)
  {
    fd = OPEN (pipename, O_RDONLY | O_ASYNC);
    if (fd == -1)
    {
      if (smtp_shutdown == GNUNET_NO)
        GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
      continue;
    }
    fdes = fdopen (fd, "r");
    while (smtp_shutdown == GNUNET_NO)
    {
      /* skip until end of header */
      do
      {
        READLINE (line, linesize);
      }
      while ((line[0] != '\r') && (line[0] != '\n'));   /* expect newline */
      READLINE (line, linesize);        /* read base64 encoded message; decode, process */
      pos = 0;
      while (1)
      {
        pos = strlen (line) - 1;        /* ignore new line */
        READLINE (&line[pos], linesize - pos);  /* read base64 encoded message; decode, process */
        if ((line[pos] == '\r') || (line[pos] == '\n'))
          break;                /* empty line => end of message! */
      }
      size = GNUNET_STRINGS_base64_decode (line, pos, &out);
      if (size < sizeof (SMTPMessage))
      {
        GNUNET_GE_BREAK (ectx, 0);
        GNUNET_free (out);
        goto END;
      }

      mp = (SMTPMessage *) &out[size - sizeof (SMTPMessage)];
      if (ntohs (mp->header.size) != size)
      {
        GNUNET_GE_LOG (ectx,
                       GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
                       _("Received malformed message via %s. Ignored.\n"),
                       "SMTP");
#if DEBUG_SMTP
        GNUNET_GE_LOG (ectx,
                       GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                       "Size returned by base64=%d, in the msg=%d.\n", size,
                       ntohl (mp->size));
#endif
        GNUNET_free (out);
        goto END;
      }
      if (stats != NULL)
        stats->change (stat_bytesReceived, size);
      coreMP = GNUNET_new (GNUNET_TransportPacket);
      coreMP->msg = out;
      coreMP->size = size - sizeof (SMTPMessage);
      coreMP->tsession = NULL;
      coreMP->sender = mp->sender;
#if DEBUG_SMTP
      GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                     "SMTP message passed to the core.\n");
#endif

      core_api->receive (coreMP);
    }
END:
#if DEBUG_SMTP
    GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
                   "SMTP message processed.\n");
#endif
    if (fdes != NULL)
      fclose (fdes);
  }
  GNUNET_free (line);
  return NULL;
}
Beispiel #2
0
/**
 * Initialize the database connections and associated
 * data structures (create tables and indices
 * as needed as well).
 *
 * @param plugin the plugin context (state for this module)
 * @return GNUNET_OK on success
 */
static int
database_setup (struct Plugin *plugin)
{
  char *afsdir;
  char *key;
  char *sub_system;
  const char *peer_id;
  char *peer;
  char *value;
  char *expiry;
  struct GNUNET_DISK_FileHandle *fh;
  struct GNUNET_PEERSTORE_Record *entry;
  struct GNUNET_HashCode hkey;
  size_t size;
  char *buffer;
  char *line;

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "peerstore-flat",
                                               "FILENAME", &afsdir))
  {
    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "peerstore-flat",
                               "FILENAME");
    return GNUNET_SYSERR;
  }
  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
  {
    if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
    {
      GNUNET_break (0);
      GNUNET_free (afsdir);
      return GNUNET_SYSERR;
    }
  }
  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
  plugin->fn = afsdir;

  fh = GNUNET_DISK_file_open (afsdir,
                              GNUNET_DISK_OPEN_CREATE |
                              GNUNET_DISK_OPEN_READWRITE,
                              GNUNET_DISK_PERM_USER_WRITE |
                              GNUNET_DISK_PERM_USER_READ);
  if (NULL == fh)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to initialize file: %s.\n"),
                afsdir);
    return GNUNET_SYSERR;
  }

  /* Load data from file into hashmap */
  plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
                                                     GNUNET_NO);

  if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
                                              &size,
                                              GNUNET_YES,
                                              GNUNET_YES))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to get filesize: %s.\n"),
                afsdir);
    return GNUNET_SYSERR;
  }

  buffer = GNUNET_malloc (size + 1);

  if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh,
                                              buffer,
                                              size))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to read file: %s.\n"),
                afsdir);
    GNUNET_DISK_file_close (fh);
    GNUNET_free (buffer);
    return GNUNET_SYSERR;
  }
  
  buffer[size] = '\0';
  GNUNET_DISK_file_close (fh);
  if (0 < size) {
    line = strtok (buffer, "\n");
    while (line != NULL) {
      sub_system = strtok (line, ",");
      if (NULL == sub_system)
        break;
      peer = strtok (NULL, ",");
      if (NULL == peer)
        break;
      key = strtok (NULL, ",");
      if (NULL == key)
        break;
      value = strtok (NULL, ",");
      if (NULL == value)
        break;
      expiry = strtok (NULL, ",");
      if (NULL == expiry)
        break;
      entry = GNUNET_new (struct GNUNET_PEERSTORE_Record);
      entry->sub_system = GNUNET_strdup (sub_system);
      entry->key = GNUNET_strdup (key);
      GNUNET_STRINGS_base64_decode (peer,
                                    strlen (peer),
                                    (char**)&entry->peer);
      entry->value_size = GNUNET_STRINGS_base64_decode (value,
                                                        strlen (value),
                                                        (char**)&entry->value);
      if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_time_to_absolute (expiry,
                                             entry->expiry))
      {
        GNUNET_free (entry->sub_system);
        GNUNET_free (entry->key);
        GNUNET_free (entry->peer);
        GNUNET_free (entry);
        break;
      }
      peer_id = GNUNET_i2s (entry->peer);
      GNUNET_CRYPTO_hash (peer_id,
                          strlen (peer_id),
                          &hkey);

      GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (plugin->hm,
                                         &hkey,
                                         entry,
                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));

    }
  }
/**
 * 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;
}
Beispiel #4
0
/**
 * Initialize the database connections and associated
 * data structures (create tables and indices
 * as needed as well).
 *
 * @param plugin the plugin context (state for this module)
 * @return #GNUNET_OK on success
 */
static int
database_setup (struct Plugin *plugin)
{
  char *afsdir;
  char* block_buffer;
  char* buffer;
  char* line;
  char* query;
  char* block;
  size_t size;
  struct FlatFileEntry *entry;
  struct GNUNET_DISK_FileHandle *fh;

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namecache-flat",
                                               "FILENAME", &afsdir))
  {
    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                               "namecache-flat", "FILENAME");
    return GNUNET_SYSERR;
  }
  if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
  {
    if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
    {
      GNUNET_break (0);
      GNUNET_free (afsdir);
      return GNUNET_SYSERR;
    }
  }
  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
  plugin->fn = afsdir;

  /* Load data from file into hashmap */
  plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
                                                     GNUNET_NO);
  fh = GNUNET_DISK_file_open (afsdir,
                              GNUNET_DISK_OPEN_CREATE |
                              GNUNET_DISK_OPEN_READWRITE,
                              GNUNET_DISK_PERM_USER_WRITE |
                              GNUNET_DISK_PERM_USER_READ);
  if (NULL == fh)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to initialize file: %s.\n"),
                afsdir);
    return GNUNET_SYSERR;
  }

  if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
                                              &size,
                                              GNUNET_YES,
                                              GNUNET_YES))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to get filesize: %s.\n"),
                afsdir);
    return GNUNET_SYSERR;
  }

  if (0 == size)
    return GNUNET_OK;

  buffer = GNUNET_malloc (size);

  if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh,
                                              buffer,
                                              size))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to read file: %s.\n"),
                afsdir);
    return GNUNET_SYSERR;
  }

  GNUNET_DISK_file_close (fh);
  if (0 < size) {
    line = strtok (buffer, "\n");
    while (line != NULL) {
      query = strtok (line, ",");
      if (NULL == query)
        break;
      block = strtok (NULL, ",");
      if (NULL == block)
        break;
      line = strtok (NULL, "\n");
      entry = GNUNET_malloc (sizeof (struct FlatFileEntry));
      GNUNET_CRYPTO_hash_from_string (query,
                                      &entry->query);
      GNUNET_STRINGS_base64_decode (block,
                                    strlen (block),
                                    &block_buffer);
      entry->block = (struct GNUNET_GNSRECORD_Block *) block_buffer;
      if (GNUNET_OK != 
          GNUNET_CONTAINER_multihashmap_put (plugin->hm,
                                             &entry->query,
                                             entry,
                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
      {
        GNUNET_free (entry);
        GNUNET_break (0);
      }
    }
  }
  GNUNET_free (buffer);
  return GNUNET_OK;
}