Ejemplo n.º 1
0
/**
 * Callback invoked from identity service with ego information.
 * An @a ego of NULL means the ego was not found.
 *
 * @param cls closure with the configuration
 * @param ego an ego known to identity service, or NULL
 */
static void
identity_cb (void *cls,
	     const struct GNUNET_IDENTITY_Ego *ego)
{
  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;

  el = NULL;
  if (NULL == ego)
  {
    if (NULL != ego_name)
    {
      fprintf (stderr,
               _("Ego `%s' not known to identity service\n"),
               ego_name);
    }
    GNUNET_SCHEDULER_shutdown ();
    ret = -1;
    return;
  }
  zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
  GNUNET_free_non_null (ego_name);
  ego_name = NULL;
  GNUNET_CLIENT_service_test ("namestore", cfg,
			      GNUNET_TIME_UNIT_SECONDS,
			      &testservice_task,
			      (void *) cfg);
}
Ejemplo n.º 2
0
/**
 * Method called to inform about the egos of this peer.
 *
 * When used with #GNUNET_IDENTITY_connect, this function is
 * initially called for all egos and then again whenever a
 * ego's name changes or if it is deleted.  At the end of
 * the initial pass over all egos, the function is once called
 * with 'NULL' for @a ego. That does NOT mean that the callback won't
 * be invoked in the future or that there was an error.
 *
 * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get,
 * this function is only called ONCE, and 'NULL' being passed in
 * @a ego does indicate an error (i.e. name is taken or no default
 * value is known).  If @a ego is non-NULL and if '*ctx'
 * is set in those callbacks, the value WILL be passed to a subsequent
 * call to the identity callback of #GNUNET_IDENTITY_connect (if
 * that one was not NULL).
 *
 * When an identity is renamed, this function is called with the
 * (known) @a ego but the NEW @a name.
 *
 * When an identity is deleted, this function is called with the
 * (known) ego and "NULL" for the @a name.  In this case,
 * the @a ego is henceforth invalid (and the @a ctx should also be
 * cleaned up).
 *
 * @param cls closure
 * @param ego ego handle
 * @param ctx context for application to store data for this ego
 *                 (during the lifetime of this process, initially NULL)
 * @param name name assigned by the user for this ego,
 *                   NULL if the user just deleted the ego and it
 *                   must thus no longer be used
 */
static void
identity_cb (void *cls,
             struct GNUNET_IDENTITY_Ego *ego,
             void **ctx,
             const char *name)
{
    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key;
    struct GNUNET_GNSRECORD_Data rd;
    char *rd_string;
    char *peername;

    if (NULL == name)
        return;
    if (NULL == ego)
    {
        if (NULL == qe)
        {
            fprintf (stderr,
                     "Failed to find master-zone ego\n");
            GNUNET_SCHEDULER_shutdown ();
            return;
        }
        GNUNET_IDENTITY_disconnect (identity);
        identity = NULL;
        return;
    }
    GNUNET_assert (NULL != name);
    if (0 != strcmp (name,
                     "master-zone"))
    {
        fprintf (stderr,
                 "Unexpected name %s\n",
                 name);
        return;
    }
    zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
    rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
    peername = GNUNET_strdup (GNUNET_i2s_full (&id));
    GNUNET_asprintf (&rd_string,
                     "6 %s %s",
                     peername,
                     "www");
    GNUNET_free (peername);
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_GNSRECORD_string_to_value (GNUNET_GNSRECORD_TYPE_VPN,
                           rd_string,
                           (void**) &rd.data,
                           &rd.data_size));
    rd.record_type = GNUNET_GNSRECORD_TYPE_VPN;

    qe = GNUNET_NAMESTORE_records_store (namestore,
                                         zone_key,
                                         "www",
                                         1, &rd,
                                         &commence_testing,
                                         NULL);
    GNUNET_free ((void**)rd.data);
    GNUNET_free (rd_string);
}
Ejemplo n.º 3
0
static void
identity_cb (void *cls,
             struct GNUNET_IDENTITY_Ego *ego,
             void **ctx,
             const char *name)
{
  struct GNUNET_GNSRECORD_Data rd;
  struct GNUNET_CRYPTO_EcdsaPublicKey pub;

  if (NULL == name)
    return;
  if (NULL == ego)
    return;
  if (0 == strcmp (name, "phone-ego"))
  {
    GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
    GNUNET_asprintf (&gns_name,
                     "phone.%s",
                     GNUNET_GNSRECORD_pkey_to_zkey (&pub));
    phone = GNUNET_CONVERSATION_phone_create (cfg,
                                              ego,
                                              &phone_event_handler,
                                              NULL);
    GNUNET_assert (NULL != phone);
    memset (&rd, 0, sizeof (rd));
    GNUNET_CONVERSATION_phone_get_record (phone,
                                          &rd);
    GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE);
    rd.expiration_time = UINT64_MAX;
    qe = GNUNET_NAMESTORE_records_store (ns,
                                         GNUNET_IDENTITY_ego_get_private_key (ego),
                                         "phone" /* GNS label */,
                                         1,
                                         &rd,
                                         &namestore_put_cont,
                                         NULL);
    return;
  }
  if (0 == strcmp (name, "caller-ego"))
  {
    GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
    GNUNET_asprintf (&gns_caller_id,
                     "%s",
                     GNUNET_GNSRECORD_pkey_to_zkey (&pub));
    call = GNUNET_CONVERSATION_call_start (cfg,
                                           ego,
                                           ego,
                                           gns_name,
                                           &call_speaker,
                                           &call_mic,
                                           &call_event_handler,
                                           NULL);
    return;
  }
}
/**
 *
 * Update identity information for ego. If attribute map is
 * dirty, first update the attributes.
 *
 * @param cls the ego to update
 * param tc task context
 *
 */
static void
update_identities(void *cls,
                  const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct EgoEntry *next_ego = cls;
  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
  if (NULL == next_ego)
  {
    if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
      min_rel_exp = MIN_WAIT_TIME;
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                ">>> Finished. Rescheduling in %d\n",
                min_rel_exp.rel_value_us);
    ns_it = NULL;
    //finished -> TODO reschedule
    update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
                                                &update_identities,
                                                ego_head);
    min_rel_exp.rel_value_us = 0;
    return;
  }
  priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
  if (GNUNET_YES == next_ego->attributes_dirty)
  {
    //Starting over. We must update the Attributes for they might have changed.
    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
                                                   priv_key,
                                                   &attribute_collect,
                                                   next_ego);

  }
  else
  {
    //Ego will be dirty next time
    next_ego->attributes_dirty = GNUNET_YES;
    ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
                                                   priv_key,
                                                   &token_collect,
                                                   next_ego);
  }
}
/**
 * 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;
}