2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @author Martin Schanzenbach
22 * @file src/identity/gnunet-service-identity-provider.c
23 * @brief Identity Token Service
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_identity_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_statistics_service.h"
34 #include "gnunet_gns_service.h"
36 #include "gnunet_signatures.h"
37 #include "identity_provider.h"
38 #include "identity_token.h"
46 * Normal operation state
48 #define STATE_POST_INIT 1
51 * Minimum interval between updates
53 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
56 * Service state (to detect initial update pass)
61 * Head of ego entry DLL
63 static struct EgoEntry *ego_head;
66 * Tail of ego entry DLL
68 static struct EgoEntry *ego_tail;
73 static struct GNUNET_IDENTITY_Handle *identity_handle;
78 static struct GNUNET_NAMESTORE_Handle *ns_handle;
83 static struct GNUNET_GNS_Handle *gns_handle;
88 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
93 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
98 static struct GNUNET_SCHEDULER_Task * timeout_task;
104 static struct GNUNET_SCHEDULER_Task * update_task;
107 * Timeout for next update pass
109 static struct GNUNET_TIME_Relative min_rel_exp;
113 * Currently processed token
115 static struct IdentityToken *token;
118 * Label for currently processed token
123 * Scopes for processed token
128 * Expiration for processed token
130 static uint64_t rd_exp;
133 * ECDHE Privkey for processed token metadata
135 static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey;
138 * Handle to the statistics service.
140 static struct GNUNET_STATISTICS_Handle *stats;
143 * Notification context, simplifies client broadcasts.
145 static struct GNUNET_SERVER_NotificationContext *nc;
147 struct ExchangeHandle
153 struct GNUNET_SERVER_Client *client;
158 struct TokenTicket *ticket;
163 struct IdentityToken *token;
168 struct GNUNET_GNS_LookupRequest *lookup_request;
173 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
187 struct GNUNET_SERVER_Client *client;
192 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
197 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
202 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
207 struct GNUNET_TIME_Absolute expiration;
222 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
227 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
232 struct IdentityToken *token;
237 struct TokenTicket *ticket;
242 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
246 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
254 struct EgoEntry *next;
259 struct EgoEntry *prev;
264 struct GNUNET_IDENTITY_Ego *ego;
267 * Attribute map. Contains the attributes as json_t
269 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
272 * Attributes are old and should be updated if GNUNET_YES
274 int attributes_dirty;
280 static const struct GNUNET_CONFIGURATION_Handle *cfg;
284 * Continuation for token store call
287 * @param success error code
288 * @param emsg error message
291 store_token_cont (void *cls,
296 if (GNUNET_SYSERR == success)
298 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299 "Failed to update token: %s\n",
303 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
308 * This function updates the old token with new attributes,
309 * removes deleted attributes and expiration times.
311 * @param cls the ego entry
312 * @param tc task context
315 handle_token_update (void *cls,
316 const struct GNUNET_SCHEDULER_TaskContext *tc)
318 char *token_metadata;
322 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
323 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
324 struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey;
325 struct EgoEntry *ego_entry = cls;
326 struct GNUNET_GNSRECORD_Data token_record[2];
327 struct GNUNET_HashCode key_hash;
328 struct GNUNET_TIME_Relative token_rel_exp;
329 struct GNUNET_TIME_Relative token_ttl;
330 struct GNUNET_TIME_Absolute token_exp;
331 struct GNUNET_TIME_Absolute token_nbf;
332 struct GNUNET_TIME_Absolute new_exp;
333 struct GNUNET_TIME_Absolute new_iat;
334 struct GNUNET_TIME_Absolute new_nbf;
335 struct IdentityToken *new_token;
336 json_t *payload_json;
339 json_t *token_nbf_json;
340 json_t *token_exp_json;
341 size_t token_metadata_len;
343 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
344 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
347 //Note: We need the token expiration time here. Not the record expiration
349 //There are two types of tokens: Token that expire on GNS level with
350 //an absolute expiration time. Those are basically tokens that will
351 //be automatically revoked on (record)expiration.
352 //Tokens stored with relative expiration times will expire on the token level (token expiration)
353 //but this service will reissue new tokens that can be retrieved from GNS
356 payload_json = token->payload;
358 token_exp_json = json_object_get (payload_json, "exp");
359 token_nbf_json = json_object_get (payload_json, "nbf");
360 token_exp.abs_value_us = json_integer_value(token_exp_json);
361 token_nbf.abs_value_us = json_integer_value(token_nbf_json);
362 token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
364 token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
365 if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
367 //This token is not yet expired! Save and skip
368 if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
370 min_rel_exp = token_ttl;
372 json_decref (payload_json);
377 GNUNET_free (scopes);
379 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
383 "Token is expired. Create a new one\n");
384 new_token = token_create (&pub_key,
386 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
387 new_nbf = GNUNET_TIME_absolute_get ();
390 json_object_foreach(payload_json, key, value) {
391 if (0 == strcmp (key, "exp"))
393 token_add_json (new_token, key, json_integer (new_exp.abs_value_us));
395 else if (0 == strcmp (key, "nbf"))
397 token_add_json (new_token, key, json_integer (new_nbf.abs_value_us));
399 else if (0 == strcmp (key, "iat"))
401 token_add_json (new_token, key, json_integer (new_iat.abs_value_us));
403 else if ((0 == strcmp (key, "iss"))
404 || (0 == strcmp (key, "aud")))
408 else if ((0 == strcmp (key, "sub"))
409 || (0 == strcmp (key, "rnl")))
411 token_add_json (new_token, key, value);
414 GNUNET_CRYPTO_hash (key,
417 //Check if attr still exists. omit of not
418 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
421 cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
423 token_add_json (new_token, key, cur_value);
428 // reassemble and set
429 GNUNET_assert (token_serialize (new_token,
434 json_decref (payload_json);
436 token_record[0].data = enc_token_str;
437 token_record[0].data_size = strlen (enc_token_str) + 1;
438 token_record[0].expiration_time = rd_exp; //Old expiration time
439 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
440 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
443 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
444 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
445 + strlen (scopes) + 1; //With 0-Terminator
446 token_metadata = GNUNET_malloc (token_metadata_len);
447 write_ptr = token_metadata;
448 memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
449 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
450 memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
451 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
452 memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
454 token_record[1].data = token_metadata;
455 token_record[1].data_size = token_metadata_len;
456 token_record[1].expiration_time = rd_exp;
457 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
458 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
460 ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token);
468 token_destroy (new_token);
469 token_destroy (token);
470 GNUNET_free (new_ecdhe_privkey);
471 GNUNET_free (enc_token_str);
475 GNUNET_free (scopes);
480 update_identities(void *cls,
481 const struct GNUNET_SCHEDULER_TaskContext *tc);
489 * @param value the json_t attribute value
493 clear_ego_attrs (void *cls,
494 const struct GNUNET_HashCode *key,
497 json_t *attr_value = value;
499 json_decref (attr_value);
507 * Update all ID_TOKEN records for an identity and store them
509 * @param cls the identity entry
510 * @param zone the identity
511 * @param lbl the name of the record
512 * @param rd_count number of records
513 * @param rd record data
517 token_collect (void *cls,
518 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
520 unsigned int rd_count,
521 const struct GNUNET_GNSRECORD_Data *rd)
523 struct EgoEntry *ego_entry = cls;
524 const struct GNUNET_GNSRECORD_Data *token_record;
525 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
526 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
532 ">>> Updating Ego finished\n");
533 //Clear attribute map for ego
534 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
537 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
538 update_task = GNUNET_SCHEDULER_add_now (&update_identities,
543 //There should be only a single record for a token under a label
546 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
550 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
552 token_metadata_record = &rd[0];
553 token_record = &rd[1];
555 token_record = &rd[0];
556 token_metadata_record = &rd[1];
558 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
560 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
563 if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN)
565 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
569 //Get metadata and decrypt token
570 ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
571 aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&ecdhe_privkey+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey);
572 scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
574 token_parse2 (token_record->data,
579 //token = GNUNET_GNSRECORD_value_to_string (rd->record_type,
582 label = GNUNET_strdup (lbl);
583 rd_exp = token_record->expiration_time;
585 GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry);
591 * Collect all ID_ATTR records for an identity and store them
593 * @param cls the identity entry
594 * @param zone the identity
595 * @param lbl the name of the record
596 * @param rd_count number of records
597 * @param rd record data
601 attribute_collect (void *cls,
602 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
604 unsigned int rd_count,
605 const struct GNUNET_GNSRECORD_Data *rd)
607 struct EgoEntry *ego_entry = cls;
609 struct GNUNET_HashCode key;
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617 ">>> Updating Attributes finished\n");
618 ego_entry->attributes_dirty = GNUNET_NO;
619 update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_entry);
625 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
628 GNUNET_CRYPTO_hash (lbl,
633 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
635 attr = GNUNET_GNSRECORD_value_to_string (rd->record_type,
638 attr_value = json_string (attr);
639 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
642 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
646 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
650 attr_value = json_array();
651 for (i = 0; i < rd_count; i++)
653 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
655 attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
658 json_array_append_new (attr_value, json_string (attr));
663 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
666 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
667 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
673 * Update identity information for ego. If attribute map is
674 * dirty, first update the attributes.
676 * @param cls the ego to update
677 * param tc task context
681 update_identities(void *cls,
682 const struct GNUNET_SCHEDULER_TaskContext *tc)
684 struct EgoEntry *next_ego = cls;
685 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
687 if (NULL == next_ego)
689 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
690 min_rel_exp = MIN_WAIT_TIME;
691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
692 ">>> Finished. Rescheduling in %d\n",
693 min_rel_exp.rel_value_us);
695 //finished -> TODO reschedule
696 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
699 min_rel_exp.rel_value_us = 0;
702 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
703 if (GNUNET_YES == next_ego->attributes_dirty)
705 //Starting over. We must update the Attributes for they might have changed.
706 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
714 //Ego will be dirty next time
715 next_ego->attributes_dirty = GNUNET_YES;
716 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
726 * Function called initially to start update task
731 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
732 //Initially iterate all itenties and refresh all tokens
733 update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head);
737 * Initial ego collection function.
742 * @param identifier ego name
746 struct GNUNET_IDENTITY_Ego *ego,
748 const char *identifier)
750 struct EgoEntry *new_entry;
751 if ((NULL == ego) && (STATE_INIT == state))
753 state = STATE_POST_INIT;
757 if (STATE_INIT == state) {
758 new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
759 new_entry->ego = ego;
760 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
762 new_entry->attributes_dirty = GNUNET_YES;
763 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
773 struct EgoEntry *ego_entry;
774 struct EgoEntry *ego_tmp;
776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
780 GNUNET_SERVER_notification_context_destroy (nc);
785 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
789 if (NULL != timeout_task)
790 GNUNET_SCHEDULER_cancel (timeout_task);
791 if (NULL != update_task)
792 GNUNET_SCHEDULER_cancel (update_task);
793 if (NULL != identity_handle)
794 GNUNET_IDENTITY_disconnect (identity_handle);
795 if (NULL != gns_handle)
796 GNUNET_GNS_disconnect (gns_handle);
798 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
800 GNUNET_NAMESTORE_cancel (ns_qe);
801 if (NULL != ns_handle)
802 GNUNET_NAMESTORE_disconnect (ns_handle);
808 for (ego_entry = ego_head;
812 if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
814 GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
819 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
820 ego_entry = ego_entry->next;
821 GNUNET_free (ego_tmp);
829 * @param tc task context
832 do_shutdown (void *cls,
833 const struct GNUNET_SCHEDULER_TaskContext *tc)
835 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
836 "Shutting down...\n");
841 static struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage*
842 create_exchange_result_message (const char* token,
845 struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage *erm;
846 uint16_t token_len = strlen (token) + 1;
847 erm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage)
849 erm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
850 erm->header.size = htons (sizeof (struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage)
852 memcpy (&erm[1], token, token_len);
857 static struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage*
858 create_issue_result_message (const char* ticket)
860 struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
862 irm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen(ticket) + 1);
863 irm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
864 irm->header.size = htons (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage) + strlen (ticket) + 1);
865 memcpy (&irm[1], ticket, strlen (ticket) + 1);
870 store_token_issue_cont (void *cls,
874 struct IssueHandle *handle = cls;
875 struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm;
876 char* token_ticket_str;
877 handle->ns_qe = NULL;
878 if (GNUNET_SYSERR == success)
883 if (GNUNET_OK != ticket_serialize (handle->ticket,
887 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
888 ticket_destroy (handle->ticket);
889 GNUNET_free (handle);
890 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
893 irm = create_issue_result_message (token_ticket_str);
894 GNUNET_SERVER_notification_context_unicast (nc,
898 GNUNET_SERVER_client_set_user_context (handle->client, NULL);
899 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
900 GNUNET_free (handle->scopes);
901 token_destroy (handle->token);
902 ticket_destroy (handle->ticket);
903 GNUNET_free (handle);
905 GNUNET_free (token_ticket_str);
909 * Build a GNUid token for identity
910 * @param handle the handle
911 * @param ego_entry the ego to build the token for
912 * @param name name of the ego
913 * @param token_aud token audience
914 * @param token the resulting gnuid token
915 * @return identifier string of token (label)
918 sign_and_return_token (void *cls,
919 const struct GNUNET_SCHEDULER_TaskContext *tc)
921 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
922 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
923 struct IssueHandle *handle = cls;
924 struct GNUNET_GNSRECORD_Data token_record[2];
925 struct GNUNET_TIME_Relative etime_rel;
929 char *token_metadata;
934 size_t token_metadata_len;
938 GNUNET_asprintf (&nonce_str, "%d", handle->nonce);
939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
942 rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
944 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
947 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
950 handle->ticket = ticket_create (nonce_str,
957 GNUNET_STRINGS_fancy_time_to_relative ("1d", //TODO
960 ticket_destroy (handle->ticket);
961 GNUNET_free (handle);
962 GNUNET_SCHEDULER_add_now (&do_shutdown, handle);
965 time = GNUNET_TIME_absolute_get().abs_value_us;
966 exp_time = time + etime_rel.rel_value_us;
968 token_add_json (handle->token, "nbf", json_integer (time));
969 token_add_json (handle->token, "iat", json_integer (time));
970 token_add_json (handle->token, "exp", json_integer (exp_time));
971 token_add_attr (handle->token, "nonce", nonce_str);
974 //Token in a serialized encrypted format
975 GNUNET_assert (token_serialize (handle->token,
980 //Token record E,E_K (Token)
981 token_record[0].data = enc_token_str;
982 token_record[0].data_size = strlen (enc_token_str) + 1;
983 token_record[0].expiration_time = exp_time;
984 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN;
985 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
988 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
989 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
990 + strlen (handle->scopes) + 1; //With 0-Terminator
991 token_metadata = GNUNET_malloc (token_metadata_len);
992 write_ptr = token_metadata;
993 memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
994 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
995 memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
996 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
997 memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator;
999 GNUNET_free (ecdhe_privkey);
1001 token_record[1].data = token_metadata;
1002 token_record[1].data_size = token_metadata_len;
1003 token_record[1].expiration_time = exp_time;
1004 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
1005 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1008 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1013 &store_token_issue_cont,
1015 GNUNET_free (lbl_str);
1016 GNUNET_free (nonce_str);
1017 GNUNET_free (enc_token_str);
1018 GNUNET_free (token_metadata);
1022 * Collect attributes for token
1025 attr_collect (void *cls,
1026 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1028 unsigned int rd_count,
1029 const struct GNUNET_GNSRECORD_Data *rd)
1034 struct IssueHandle *handle = cls;
1035 struct GNUNET_HashCode key;
1039 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
1040 handle->ns_it = NULL;
1041 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1045 GNUNET_CRYPTO_hash (label,
1049 if (0 == rd_count ||
1050 ( (NULL != handle->attr_map) &&
1051 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
1056 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
1064 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1066 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
1069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1070 token_add_json (handle->token,
1072 json_string (data));
1075 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1080 attr_arr = json_array();
1081 for (; i < rd_count; i++)
1083 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1085 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1089 json_array_append_new (attr_arr, json_string (data));
1094 if (0 < json_array_size (attr_arr))
1096 token_add_json (handle->token, label, attr_arr);
1098 json_decref (attr_arr);
1099 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1103 process_lookup_result (void *cls, uint32_t rd_count,
1104 const struct GNUNET_GNSRECORD_Data *rd)
1106 struct ExchangeHandle *handle = cls;
1107 struct GNUNET_IDENTITY_PROVIDER_ExchangeResultMessage *erm;
1111 handle->lookup_request = NULL;
1114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1115 "Number of tokens %d != 2.",
1117 GNUNET_free (handle->label);
1118 GNUNET_free (handle);
1119 GNUNET_SCHEDULER_add_now (&do_shutdown, handle);
1124 GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN,
1129 GNUNET_assert (GNUNET_OK == token_parse (record_str,
1130 &handle->aud_privkey,
1134 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
1135 &handle->aud_privkey,
1138 erm = create_exchange_result_message (token_str,
1140 GNUNET_SERVER_notification_context_unicast (nc,
1144 GNUNET_SERVER_client_set_user_context (handle->client, NULL);
1145 ticket_destroy (handle->ticket);
1146 token_destroy (handle->token);
1147 GNUNET_free (record_str);
1148 GNUNET_free (token_str);
1149 GNUNET_free (handle);
1156 * Handler for exchange message
1159 * @param client who sent the message
1160 * @param message the message
1163 handle_exchange_message (void *cls,
1164 struct GNUNET_SERVER_Client *client,
1165 const struct GNUNET_MessageHeader *message)
1167 const struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *em;
1168 struct ExchangeHandle *xchange_handle;
1173 size = ntohs (message->size);
1174 if (size <= sizeof (struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage))
1177 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1180 em = (const struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *) message;
1181 ticket = (const char *) &em[1];
1182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1183 "Received EXCHANGE of `%s' from client\n",
1185 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
1186 xchange_handle->aud_privkey = em->aud_privkey;
1188 if (GNUNET_SYSERR == ticket_parse (ticket,
1189 &xchange_handle->aud_privkey,
1190 &xchange_handle->ticket))
1192 GNUNET_free (xchange_handle);
1193 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n",
1197 xchange_handle->ticket->payload->label);
1198 GNUNET_asprintf (&lookup_query,
1200 xchange_handle->ticket->payload->label);
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202 GNUNET_SERVER_notification_context_add (nc, client);
1203 GNUNET_SERVER_client_set_user_context (client, xchange_handle);
1204 xchange_handle->client = client;
1205 xchange_handle->lookup_request = GNUNET_GNS_lookup (gns_handle,
1207 &xchange_handle->ticket->payload->identity_key,
1208 GNUNET_GNSRECORD_TYPE_ID_TOKEN,
1209 GNUNET_GNS_LO_LOCAL_MASTER,
1211 &process_lookup_result,
1213 GNUNET_free (lookup_query);
1219 * Handler for issue message
1222 * @param client who sent the message
1223 * @param message the message
1226 handle_issue_message (void *cls,
1227 struct GNUNET_SERVER_Client *client,
1228 const struct GNUNET_MessageHeader *message)
1230 const struct GNUNET_IDENTITY_PROVIDER_IssueMessage *im;
1235 struct GNUNET_HashCode key;
1236 struct IssueHandle *issue_handle;
1238 size = ntohs (message->size);
1239 if (size <= sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueMessage))
1242 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1245 im = (const struct GNUNET_IDENTITY_PROVIDER_IssueMessage *) message;
1246 scopes = (const char *) &im[1];
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Received ISSUE of `%s' from client\n",
1250 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1251 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1253 scopes_tmp = GNUNET_strdup (scopes);
1254 scope = strtok(scopes_tmp, ",");
1255 for (; NULL != scope; scope = strtok (NULL, ","))
1257 GNUNET_CRYPTO_hash (scope,
1260 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1263 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1265 GNUNET_free (scopes_tmp);
1267 issue_handle->aud_key = im->aud_key;
1268 issue_handle->iss_key = im->iss_key;
1269 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1270 issue_handle->nonce = im->nonce;
1271 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1272 GNUNET_SERVER_notification_context_add (nc, client);
1273 GNUNET_SERVER_client_set_user_context (client, issue_handle);
1274 issue_handle->client = client;
1275 issue_handle->scopes = GNUNET_strdup (scopes);
1276 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1277 &issue_handle->iss_pkey);
1278 issue_handle->token = token_create (&issue_handle->iss_pkey,
1281 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1290 * Main function that will be run
1292 * @param cls closure
1293 * @param args remaining command-line arguments
1294 * @param cfgfile name of the configuration file used (for saving, can be NULL)
1295 * @param c configuration
1299 struct GNUNET_SERVER_Handle *server,
1300 const struct GNUNET_CONFIGURATION_Handle *c)
1302 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1303 {&handle_issue_message, NULL,
1304 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 0},
1305 {&handle_exchange_message, NULL,
1306 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 0},
1312 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1313 GNUNET_SERVER_add_handlers (server, handlers);
1314 nc = GNUNET_SERVER_notification_context_create (server, 1);
1316 //Connect to identity and namestore services
1317 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1318 if (NULL == ns_handle)
1320 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1323 gns_handle = GNUNET_GNS_connect (cfg);
1324 if (NULL == gns_handle)
1326 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1329 identity_handle = GNUNET_IDENTITY_connect (cfg,
1333 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1334 &do_shutdown, NULL);
1342 * @param argc number of arguments from the cli
1343 * @param argv command line arguments
1344 * @return 0 ok, 1 on error
1348 main (int argc, char *const *argv)
1350 return (GNUNET_OK ==
1351 GNUNET_SERVICE_run (argc, argv, "identity-provider",
1352 GNUNET_SERVICE_OPTION_NONE,
1353 &run, NULL)) ? 0 : 1;
1356 /* end of gnunet-rest-server.c */