X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fidentity%2Fidentity_api.c;h=d5035ba4980ce5458b76f26dab6fffaf18840c93;hb=65e91346db9fe4ca1b1ff6516872454c468eb7f2;hp=757cec76d1b8785050b624c5527c373b9bd7f495;hpb=a7349d7a85cc142fa2416671da346d368819775d;p=oweals%2Fgnunet.git diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c index 757cec76d..d5035ba49 100644 --- a/src/identity/identity_api.c +++ b/src/identity/identity_api.c @@ -48,9 +48,9 @@ struct GNUNET_IDENTITY_Ego struct GNUNET_CRYPTO_EccPrivateKey *pk; /** - * Current identifier (name) associated with this ego. + * Current name associated with this ego. */ - char *identifier; + char *name; /** * Client context associated with this ego. @@ -175,6 +175,24 @@ struct GNUNET_IDENTITY_Handle }; +/** + * Obtain the ego representing 'anonymous' users. + */ +const struct GNUNET_IDENTITY_Ego * +GNUNET_IDENTITY_ego_get_anonymous () +{ + static struct GNUNET_IDENTITY_Ego anon; + struct GNUNET_CRYPTO_EccPublicKey pub; + + if (NULL != anon.pk) + return &anon; + anon.pk = (struct GNUNET_CRYPTO_EccPrivateKey *) GNUNET_CRYPTO_ecc_key_get_anonymous (); + GNUNET_CRYPTO_ecc_key_get_public (anon.pk, + &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &anon.id); + return &anon; +} + /** * Try again to connect to network size estimation service. @@ -234,17 +252,20 @@ message_handler (void *cls, const struct GNUNET_IDENTITY_ResultCodeMessage *rcm; const struct GNUNET_IDENTITY_UpdateMessage *um; const struct GNUNET_IDENTITY_SetDefaultMessage *sdm; - struct GNUNET_CRYPTO_EccPrivateKey *priv; - struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub; + struct GNUNET_CRYPTO_EccPublicKey pub; struct GNUNET_HashCode id; const char *str; uint16_t size; + uint16_t name_len; if (NULL == msg) { reschedule_connect (h); return; } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received message of type %d from identity service\n", + ntohs (msg->type)); size = ntohs (msg->size); switch (ntohs (msg->type)) { @@ -274,7 +295,8 @@ message_handler (void *cls, if (NULL != op->cont) op->cont (op->cls, str); - GNUNET_break (NULL == op->cb); + else if (NULL != op->cb) + op->cb (op->cls, NULL, NULL, NULL); GNUNET_free (op); break; case GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE: @@ -285,29 +307,31 @@ message_handler (void *cls, return; } um = (const struct GNUNET_IDENTITY_UpdateMessage *) msg; + name_len = ntohs (um->name_len); + str = (const char *) &um[1]; - if ( (size > sizeof (struct GNUNET_IDENTITY_UpdateMessage)) && - ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_UpdateMessage) - 1]) ) + if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) || + ( (0 != name_len) && + ('\0' != str[name_len - 1])) ) { GNUNET_break (0); reschedule_connect (h); return; } - if (size == sizeof (struct GNUNET_IDENTITY_UpdateMessage)) - str = NULL; - - // FIXME: um->pk does NOT work! - priv = GNUNET_CRYPTO_ecc_decode_key (NULL, 0, GNUNET_YES); // FIXME... - if (NULL == priv) + if (GNUNET_YES == ntohs (um->end_of_list)) { - GNUNET_break (0); - reschedule_connect (h); - return; + /* end of initial list of data */ + if (NULL != h->cb) + h->cb (h->cb_cls, NULL, NULL, NULL); + break; } - GNUNET_CRYPTO_ecc_key_get_public (priv, + GNUNET_CRYPTO_ecc_key_get_public (&um->private_key, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); - + if (0 == name_len) + str = NULL; + else + str = (const char *) &um[1]; ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); if (NULL == ego) @@ -317,13 +341,13 @@ message_handler (void *cls, { /* deletion of unknown ego? not allowed */ GNUNET_break (0); - GNUNET_CRYPTO_ecc_key_free (priv); reschedule_connect (h); return; } ego = GNUNET_new (struct GNUNET_IDENTITY_Ego); - ego->pk = priv; - ego->identifier = GNUNET_strdup (str); + ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); + *ego->pk = um->private_key; + ego->name = GNUNET_strdup (str); ego->id = id; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (h->egos, @@ -331,15 +355,12 @@ message_handler (void *cls, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } - else - { - GNUNET_CRYPTO_ecc_key_free (priv); - } /* inform application about change */ - h->cb (h->cb_cls, - ego, - &ego->ctx, - str); + if (NULL != h->cb) + h->cb (h->cb_cls, + ego, + &ego->ctx, + str); if (NULL == str) { /* ego was deleted */ @@ -347,15 +368,15 @@ message_handler (void *cls, GNUNET_CONTAINER_multihashmap_remove (h->egos, &ego->id, ego)); - GNUNET_CRYPTO_ecc_key_free (ego->pk); - GNUNET_free (ego->identifier); + GNUNET_free (ego->pk); + GNUNET_free (ego->name); GNUNET_free (ego); } else { /* ego changed name */ - GNUNET_free (ego->identifier); - ego->identifier = GNUNET_strdup (str); + GNUNET_free (ego->name); + ego->name = GNUNET_strdup (str); } break; case GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT: @@ -366,27 +387,21 @@ message_handler (void *cls, return; } sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) msg; + GNUNET_break (0 == ntohs (sdm->reserved)); + name_len = ntohs (sdm->name_len); str = (const char *) &sdm[1]; - if ( (size > sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) && - ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) - 1]) ) + if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) || + ( (0 != name_len) && + ('\0' != str[name_len - 1]) ) ) { GNUNET_break (0); reschedule_connect (h); return; } - if (size == sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) - str = NULL; - // FIXME: sdr->pk does NOT work! - priv = GNUNET_CRYPTO_ecc_decode_key (NULL, 0, GNUNET_YES); // FIXME... - if (NULL == priv) - { - GNUNET_break (0); - reschedule_connect (h); - return; - } - GNUNET_CRYPTO_ecc_key_get_public (priv, + /* Note: we know which service this should be for, so we're not + really using 'str' henceforth */ + GNUNET_CRYPTO_ecc_key_get_public (&sdm->private_key, &pub); - GNUNET_CRYPTO_ecc_key_free (priv); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); @@ -400,12 +415,12 @@ message_handler (void *cls, GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); + GNUNET_free (ego->name); if (NULL != op->cb) op->cb (op->cls, ego, &ego->ctx, - ego->identifier); - GNUNET_break (NULL == op->cont); + ego->name); GNUNET_free (op); break; default: @@ -453,6 +468,9 @@ send_next_message (void *cls, reschedule_connect (h); return 0; } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sending message of type %d to identity service\n", + ntohs (op->msg->type)); memcpy (buf, op->msg, ret); if ( (NULL == op->cont) && (NULL == op->cb) ) @@ -487,13 +505,14 @@ transmit_next (struct GNUNET_IDENTITY_Handle *h) GNUNET_assert (NULL == h->th); if (NULL == op) return; + if (NULL == h->client) + return; h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (op->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_next_message, h); - } @@ -550,6 +569,7 @@ GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, h->cfg = cfg; h->cb = cb; h->cb_cls = cb_cls; + h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES); h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h); return h; @@ -563,12 +583,27 @@ GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_IDENTITY_ego_get_key (struct GNUNET_IDENTITY_Ego *ego) +GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego) { return ego->pk; } +/** + * Get the identifier (public key) of an ego. + * + * @param ego identity handle with the private key + * @param pk set to ego's public key + */ +void +GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, + struct GNUNET_CRYPTO_EccPublicKey *pk) +{ + GNUNET_CRYPTO_ecc_key_get_public (ego->pk, + pk); +} + + /** * Obtain the identity that is currently preferred/default * for a service. @@ -585,7 +620,36 @@ GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, GNUNET_IDENTITY_Callback cb, void *cb_cls) { - return NULL; + struct GNUNET_IDENTITY_Operation *op; + struct GNUNET_IDENTITY_GetDefaultMessage *gdm; + size_t slen; + + slen = strlen (service_name) + 1; + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_GetDefaultMessage)) + { + GNUNET_break (0); + return NULL; + } + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) + + slen); + op->h = id; + op->cb = cb; + op->cls = cb_cls; + gdm = (struct GNUNET_IDENTITY_GetDefaultMessage *) &op[1]; + gdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT); + gdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) + + slen); + gdm->name_len = htons (slen); + gdm->reserved = htons (0); + memcpy (&gdm[1], service_name, slen); + op->msg = &gdm->header; + GNUNET_CONTAINER_DLL_insert_tail (id->op_head, + id->op_tail, + op); + if (NULL == id->th) + transmit_next (id); + return op; } @@ -606,26 +670,91 @@ GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, GNUNET_IDENTITY_Continuation cont, void *cont_cls) { - return NULL; + struct GNUNET_IDENTITY_Operation *op; + struct GNUNET_IDENTITY_SetDefaultMessage *sdm; + size_t slen; + + slen = strlen (service_name) + 1; + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) + { + GNUNET_break (0); + return NULL; + } + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + + slen); + op->h = id; + op->cont = cont; + op->cls = cont_cls; + sdm = (struct GNUNET_IDENTITY_SetDefaultMessage *) &op[1]; + sdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT); + sdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + + slen); + sdm->name_len = htons (slen); + sdm->reserved = htons (0); + sdm->private_key = *ego->pk; + memcpy (&sdm[1], service_name, slen); + op->msg = &sdm->header; + GNUNET_CONTAINER_DLL_insert_tail (id->op_head, + id->op_tail, + op); + if (NULL == id->th) + transmit_next (id); + return op; } /** - * Create a new identity with the given identifier. + * Create a new identity with the given name. * * @param id identity service to use - * @param identifier desired identifier - * @param cb function to call with the result (will only be called once) - * @param cb_cls closure for cb + * @param name desired name + * @param cont function to call with the result (will only be called once) + * @param cont_cls closure for cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, - const char *identifier, - GNUNET_IDENTITY_Callback cb, - void *cb_cls) + const char *name, + GNUNET_IDENTITY_Continuation cont, + void *cont_cls) { - return NULL; + struct GNUNET_IDENTITY_Operation *op; + struct GNUNET_IDENTITY_CreateRequestMessage *crm; + struct GNUNET_CRYPTO_EccPrivateKey *pk; + size_t slen; + + slen = strlen (name) + 1; + pk = GNUNET_CRYPTO_ecc_key_create (); + + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_CreateRequestMessage)) + { + GNUNET_break (0); + GNUNET_free (pk); + return NULL; + } + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + + slen); + op->h = id; + op->cont = cont; + op->cls = cont_cls; + crm = (struct GNUNET_IDENTITY_CreateRequestMessage *) &op[1]; + crm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_CREATE); + crm->header.size = htons (sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + + slen); + crm->name_len = htons (slen); + crm->reserved = htons (0); + crm->private_key = *pk; + memcpy (&crm[1], name, slen); + op->msg = &crm->header; + GNUNET_CONTAINER_DLL_insert_tail (id->op_head, + id->op_tail, + op); + if (NULL == id->th) + transmit_next (id); + GNUNET_free (pk); + return op; } @@ -633,20 +762,56 @@ GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, * Renames an existing identity. * * @param id identity service to use - * @param old_identifier old identifier - * @param new_identifier desired new identifier + * @param old_name old name + * @param new_name desired new name * @param cb function to call with the result (will only be called once) * @param cb_cls closure for cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, - const char *old_identifier, - const char *new_identifier, + const char *old_name, + const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { - return NULL; + struct GNUNET_IDENTITY_Operation *op; + struct GNUNET_IDENTITY_RenameMessage *grm; + size_t slen_old; + size_t slen_new; + char *dst; + + slen_old = strlen (old_name) + 1; + slen_new = strlen (new_name) + 1; + if ( (slen_old >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || + (slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || + (slen_old + slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_RenameMessage)) ) + { + GNUNET_break (0); + return NULL; + } + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_IDENTITY_RenameMessage) + + slen_old + slen_new); + op->h = id; + op->cont = cb; + op->cls = cb_cls; + grm = (struct GNUNET_IDENTITY_RenameMessage *) &op[1]; + grm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_RENAME); + grm->header.size = htons (sizeof (struct GNUNET_IDENTITY_RenameMessage) + + slen_old + slen_new); + grm->old_name_len = htons (slen_old); + grm->new_name_len = htons (slen_new); + dst = (char *) &grm[1]; + memcpy (dst, old_name, slen_old); + memcpy (&dst[slen_old], new_name, slen_new); + op->msg = &grm->header; + GNUNET_CONTAINER_DLL_insert_tail (id->op_head, + id->op_tail, + op); + if (NULL == id->th) + transmit_next (id); + return op; } @@ -654,18 +819,47 @@ GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, * Delete an existing identity. * * @param id identity service to use - * @param identifier identifier of the identity to delete + * @param name name of the identity to delete * @param cb function to call with the result (will only be called once) * @param cb_cls closure for cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, - const char *identifier, + const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { - return NULL; + struct GNUNET_IDENTITY_Operation *op; + struct GNUNET_IDENTITY_DeleteMessage *gdm; + size_t slen; + + slen = strlen (name) + 1; + if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_DeleteMessage)) + { + GNUNET_break (0); + return NULL; + } + op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + + sizeof (struct GNUNET_IDENTITY_DeleteMessage) + + slen); + op->h = id; + op->cont = cb; + op->cls = cb_cls; + gdm = (struct GNUNET_IDENTITY_DeleteMessage *) &op[1]; + gdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_DELETE); + gdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_DeleteMessage) + + slen); + gdm->name_len = htons (slen); + gdm->reserved = htons (0); + memcpy (&gdm[1], name, slen); + op->msg = &gdm->header; + GNUNET_CONTAINER_DLL_insert_tail (id->op_head, + id->op_tail, + op); + if (NULL == id->th) + transmit_next (id); + return op; } @@ -678,7 +872,7 @@ GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, * @param op operation to cancel */ void -GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) +GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op) { struct GNUNET_IDENTITY_Handle *h = op->h; @@ -710,6 +904,33 @@ GNUNET_IDENITY_cancel (struct GNUNET_IDENTITY_Operation *op) } +/** + * Free ego from hash map. + * + * @param cls identity service handle + * @param key unused + * @param value ego to free + * @return GNUNET_OK (continue to iterate) + */ +static int +free_ego (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_IDENTITY_Handle *h = cls; + struct GNUNET_IDENTITY_Ego *ego = value; + + h->cb (h->cb_cls, + ego, + &ego->ctx, + NULL); + GNUNET_free (ego->pk); + GNUNET_free (ego->name); + GNUNET_free (ego); + return GNUNET_OK; +} + + /** * Disconnect from identity service * @@ -719,6 +940,7 @@ void GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h) { GNUNET_assert (NULL != h); + GNUNET_assert (h->op_head == h->op_tail); if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->reconnect_task); @@ -729,6 +951,14 @@ GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h) GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } + if (NULL != h->egos) + { + GNUNET_CONTAINER_multihashmap_iterate (h->egos, + &free_ego, + h); + GNUNET_CONTAINER_multihashmap_destroy (h->egos); + h->egos = NULL; + } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client);