GNUnet  0.10.x
plugin_rest_reclaim.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012-2015 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
27 #include "platform.h"
28 #include "microhttpd.h"
29 #include <inttypes.h>
30 #include <jansson.h>
31 #include "gnunet_gns_service.h"
32 #include "gnunet_gnsrecord_lib.h"
35 #include "gnunet_reclaim_service.h"
36 #include "gnunet_rest_lib.h"
37 #include "gnunet_rest_plugin.h"
38 #include "gnunet_signatures.h"
39 #include "json_reclaim.h"
40 
44 #define GNUNET_REST_API_NS_RECLAIM "/reclaim"
45 
49 #define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
50 
54 #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
55 
59 #define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
60 
64 #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
65 
69 #define ID_REST_STATE_INIT 0
70 
74 #define ID_REST_STATE_POST_INIT 1
75 
80 
84 static char *allow_methods;
85 
89 struct Plugin {
90  const struct GNUNET_CONFIGURATION_Handle *cfg;
91 };
92 
96 struct EgoEntry {
100  struct EgoEntry *next;
101 
105  struct EgoEntry *prev;
106 
110  char *identifier;
111 
115  char *keystring;
116 
120  struct GNUNET_IDENTITY_Ego *ego;
121 };
122 
123 
124 struct RequestHandle {
128  struct EgoEntry *ego_head;
129 
133  struct EgoEntry *ego_tail;
134 
138  struct EgoEntry *ego_entry;
139 
143  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
144 
148  int state;
149 
154 
158  struct GNUNET_REST_RequestHandle *rest_handle;
159 
164 
169 
173  struct GNUNET_RECLAIM_Handle *idp;
174 
178  struct GNUNET_RECLAIM_Operation *idp_op;
179 
183  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
184 
188  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
189 
193  struct GNUNET_RECLAIM_Ticket ticket;
194 
198  struct GNUNET_TIME_Relative timeout;
199 
204 
209 
213  void *proc_cls;
214 
218  char *url;
219 
223  char *emsg;
224 
228  int response_code;
229 
233  json_t *resp_object;
234 };
235 
240 static void
242 {
243  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
244  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
245  struct EgoEntry *ego_entry;
246  struct EgoEntry *ego_tmp;
247 
248  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
249  if (NULL != handle->resp_object)
250  json_decref(handle->resp_object);
251  if (NULL != handle->timeout_task)
253  if (NULL != handle->identity_handle)
255  if (NULL != handle->attr_it)
257  if (NULL != handle->ticket_it)
259  if (NULL != handle->idp)
261  if (NULL != handle->url)
262  GNUNET_free(handle->url);
263  if (NULL != handle->emsg)
264  GNUNET_free(handle->emsg);
265  if (NULL != handle->attr_list)
266  {
267  for (claim_entry = handle->attr_list->list_head; NULL != claim_entry;)
268  {
269  claim_tmp = claim_entry;
270  claim_entry = claim_entry->next;
271  GNUNET_free(claim_tmp->claim);
272  GNUNET_free(claim_tmp);
273  }
274  GNUNET_free(handle->attr_list);
275  }
276  for (ego_entry = handle->ego_head; NULL != ego_entry;)
277  {
278  ego_tmp = ego_entry;
279  ego_entry = ego_entry->next;
280  GNUNET_free(ego_tmp->identifier);
281  GNUNET_free(ego_tmp->keystring);
282  GNUNET_free(ego_tmp);
283  }
284  GNUNET_free(handle);
285 }
286 
287 static void
289 {
290  cleanup_handle(cls);
291 }
292 
293 
299 static void
300 do_error(void *cls)
301 {
302  struct RequestHandle *handle = cls;
303  struct MHD_Response *resp;
304  char *json_error;
305 
306  GNUNET_asprintf(&json_error, "{ \"error\" : \"%s\" }", handle->emsg);
307  if (0 == handle->response_code)
308  {
309  handle->response_code = MHD_HTTP_BAD_REQUEST;
310  }
311  resp = GNUNET_REST_create_response(json_error);
312  MHD_add_response_header(resp, "Content-Type", "application/json");
313  handle->proc(handle->proc_cls, resp, handle->response_code);
315  GNUNET_free(json_error);
316 }
317 
318 
324 static void
325 do_timeout(void *cls)
326 {
327  struct RequestHandle *handle = cls;
328 
329  handle->timeout_task = NULL;
330  do_error(handle);
331 }
332 
333 
334 static void
336 {
337  struct RequestHandle *handle = cls;
338 
339  do_error(handle);
340 }
341 
342 static void
343 finished_cont(void *cls, int32_t success, const char *emsg)
344 {
345  struct RequestHandle *handle = cls;
346  struct MHD_Response *resp;
347 
348  resp = GNUNET_REST_create_response(emsg);
349  if (GNUNET_OK != success)
350  {
352  return;
353  }
354  handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
356 }
357 
358 
364 static void
365 return_response(void *cls)
366 {
367  char *result_str;
368  struct RequestHandle *handle = cls;
369  struct MHD_Response *resp;
370 
371  result_str = json_dumps(handle->resp_object, 0);
372  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
373  resp = GNUNET_REST_create_response(result_str);
374  handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
375  GNUNET_free(result_str);
376  cleanup_handle(handle);
377 }
378 
379 static void
381 {
382  struct RequestHandle *handle = cls;
383 
384  // Done
385  handle->attr_it = NULL;
386  handle->ticket_it = NULL;
388 }
389 
390 
395 static void
396 ticket_collect(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
397 {
398  json_t *json_resource;
399  struct RequestHandle *handle = cls;
400  json_t *value;
401  char *tmp;
402 
403  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
404  tmp = GNUNET_STRINGS_data_to_string_alloc(&ticket->rnd, sizeof(uint64_t));
405  json_resource = json_object();
406  GNUNET_free(tmp);
407  json_array_append(handle->resp_object, json_resource);
408 
409  tmp =
411  sizeof(struct
413  value = json_string(tmp);
414  json_object_set_new(json_resource, "issuer", value);
415  GNUNET_free(tmp);
416  tmp =
418  sizeof(struct
420  value = json_string(tmp);
421  json_object_set_new(json_resource, "audience", value);
422  GNUNET_free(tmp);
423  tmp = GNUNET_STRINGS_data_to_string_alloc(&ticket->rnd, sizeof(uint64_t));
424  value = json_string(tmp);
425  json_object_set_new(json_resource, "rnd", value);
426  GNUNET_free(tmp);
428 }
429 
430 
438 static void
440  const char *url,
441  void *cls)
442 {
443  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
444  struct RequestHandle *handle = cls;
445  struct EgoEntry *ego_entry;
446  char *identity;
447 
449  "Getting tickets for %s.\n",
450  handle->url);
451  if (strlen(GNUNET_REST_API_NS_IDENTITY_TICKETS) >= strlen(handle->url))
452  {
453  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
455  return;
456  }
457  identity = handle->url + strlen(GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
458 
459  for (ego_entry = handle->ego_head; NULL != ego_entry;
460  ego_entry = ego_entry->next)
461  if (0 == strcmp(identity, ego_entry->identifier))
462  break;
463  handle->resp_object = json_array();
464 
465  if (NULL == ego_entry)
466  {
467  // Done
468  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
470  return;
471  }
472  priv_key = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
473  handle->idp = GNUNET_RECLAIM_connect(cfg);
474  handle->ticket_it =
476  priv_key,
478  handle,
480  handle,
482  handle);
483 }
484 
485 
486 static void
488  const char *url,
489  void *cls)
490 {
491  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
492  const char *identity;
493  struct RequestHandle *handle = cls;
494  struct EgoEntry *ego_entry;
495  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
496  struct GNUNET_TIME_Relative exp;
497  char term_data[handle->rest_handle->data_size + 1];
498  json_t *data_json;
499  json_error_t err;
500  struct GNUNET_JSON_Specification attrspec[] =
502 
504  "Adding an attribute for %s.\n",
505  handle->url);
506  if (strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen(handle->url))
507  {
508  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
510  return;
511  }
512  identity = handle->url + strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
513 
514  for (ego_entry = handle->ego_head; NULL != ego_entry;
515  ego_entry = ego_entry->next)
516  if (0 == strcmp(identity, ego_entry->identifier))
517  break;
518 
519  if (NULL == ego_entry)
520  {
521  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
522  return;
523  }
524  identity_priv = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
525 
526  if (0 >= handle->rest_handle->data_size)
527  {
529  return;
530  }
531 
532  term_data[handle->rest_handle->data_size] = '\0';
533  GNUNET_memcpy(term_data,
534  handle->rest_handle->data,
535  handle->rest_handle->data_size);
536  data_json = json_loads(term_data, JSON_DECODE_ANY, &err);
538  GNUNET_JSON_parse(data_json, attrspec, NULL, NULL));
539  json_decref(data_json);
540  if (NULL == attribute)
541  {
543  "Unable to parse attribute from %s\n",
544  term_data);
546  return;
547  }
551  if (0 == attribute->id)
552  attribute->id =
554  handle->idp = GNUNET_RECLAIM_connect(cfg);
556  handle->idp_op = GNUNET_RECLAIM_attribute_store(handle->idp,
557  identity_priv,
558  attribute,
559  &exp,
560  &finished_cont,
561  handle);
562  GNUNET_JSON_parse_free(attrspec);
563 }
564 
565 
570 static void
573  const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
574 {
575  struct RequestHandle *handle = cls;
576  json_t *attr_obj;
577  const char *type;
578  char *tmp_value;
579  char *id_str;
580 
581  if ((NULL == attr->name) || (NULL == attr->data))
582  {
584  return;
585  }
586 
587  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
588 
590  attr->data,
591  attr->data_size);
592 
593  attr_obj = json_object();
594  json_object_set_new(attr_obj, "value", json_string(tmp_value));
595  json_object_set_new(attr_obj, "name", json_string(attr->name));
597  json_object_set_new(attr_obj, "type", json_string(type));
598  id_str = GNUNET_STRINGS_data_to_string_alloc(&attr->id, sizeof(uint64_t));
599  json_object_set_new(attr_obj, "id", json_string(id_str));
600  json_array_append(handle->resp_object, attr_obj);
601  json_decref(attr_obj);
602  GNUNET_free(tmp_value);
604 }
605 
606 
614 static void
616  const char *url,
617  void *cls)
618 {
619  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
620  struct RequestHandle *handle = cls;
621  struct EgoEntry *ego_entry;
622  char *identity;
623 
625  "Getting attributes for %s.\n",
626  handle->url);
627  if (strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen(handle->url))
628  {
629  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
631  return;
632  }
633  identity = handle->url + strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
634 
635  for (ego_entry = handle->ego_head; NULL != ego_entry;
636  ego_entry = ego_entry->next)
637  if (0 == strcmp(identity, ego_entry->identifier))
638  break;
639  handle->resp_object = json_array();
640 
641 
642  if (NULL == ego_entry)
643  {
644  // Done
645  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
647  return;
648  }
649  priv_key = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
650  handle->idp = GNUNET_RECLAIM_connect(cfg);
652  priv_key,
654  handle,
655  &attr_collect,
656  handle,
658  handle);
659 }
660 
661 
662 static void
663 delete_finished_cb(void *cls, int32_t success, const char *emsg)
664 {
665  struct RequestHandle *handle = cls;
666  struct MHD_Response *resp;
667 
668  resp = GNUNET_REST_create_response(emsg);
669  if (GNUNET_OK != success)
670  {
672  return;
673  }
674  handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
676 }
677 
678 
686 static void
688  const char *url,
689  void *cls)
690 {
691  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
692  struct RequestHandle *handle = cls;
693  struct GNUNET_RECLAIM_ATTRIBUTE_Claim attr;
694  struct EgoEntry *ego_entry;
695  char *identity_id_str;
696  char *identity;
697  char *id;
698 
699  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Deleting attributes.\n");
700  if (strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >= strlen(handle->url))
701  {
702  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
704  return;
705  }
706  identity_id_str =
707  strdup(handle->url + strlen(GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1);
708  identity = strtok(identity_id_str, "/");
709  id = strtok(NULL, "/");
710  if ((NULL == identity) || (NULL == id))
711  {
712  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
713  GNUNET_free(identity_id_str);
715  return;
716  }
717 
718  for (ego_entry = handle->ego_head; NULL != ego_entry;
719  ego_entry = ego_entry->next)
720  if (0 == strcmp(identity, ego_entry->identifier))
721  break;
722  handle->resp_object = json_array();
723  if (NULL == ego_entry)
724  {
725  // Done
726  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
727  GNUNET_free(identity_id_str);
729  return;
730  }
731  priv_key = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
732  handle->idp = GNUNET_RECLAIM_connect(cfg);
733  memset(&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim));
734  GNUNET_STRINGS_string_to_data(id, strlen(id), &attr.id, sizeof(uint64_t));
735  attr.name = "";
736  handle->idp_op = GNUNET_RECLAIM_attribute_delete(handle->idp,
737  priv_key,
738  &attr,
740  handle);
741  GNUNET_free(identity_id_str);
742 }
743 
744 
745 static void
747  const char *url,
748  void *cls)
749 {
750  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
751  struct RequestHandle *handle = cls;
752  struct EgoEntry *ego_entry;
753  struct GNUNET_RECLAIM_Ticket *ticket = NULL;
754  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
755  char term_data[handle->rest_handle->data_size + 1];
756  json_t *data_json;
757  json_error_t err;
758  struct GNUNET_JSON_Specification tktspec[] =
760 
761  if (0 >= handle->rest_handle->data_size)
762  {
764  return;
765  }
766 
767  term_data[handle->rest_handle->data_size] = '\0';
768  GNUNET_memcpy(term_data,
769  handle->rest_handle->data,
770  handle->rest_handle->data_size);
771  data_json = json_loads(term_data, JSON_DECODE_ANY, &err);
772  if ((NULL == data_json) ||
773  (GNUNET_OK != GNUNET_JSON_parse(data_json, tktspec, NULL, NULL)))
774  {
775  handle->emsg = GNUNET_strdup("Not a ticket!\n");
777  GNUNET_JSON_parse_free(tktspec);
778  if (NULL != data_json)
779  json_decref(data_json);
780  return;
781  }
782  json_decref(data_json);
783  if (NULL == ticket)
784  {
786  "Unable to parse ticket from %s\n",
787  term_data);
789  return;
790  }
791 
792  for (ego_entry = handle->ego_head; NULL != ego_entry;
793  ego_entry = ego_entry->next)
794  {
795  GNUNET_IDENTITY_ego_get_public_key(ego_entry->ego, &tmp_pk);
796  if (0 == memcmp(&ticket->identity,
797  &tmp_pk,
798  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
799  break;
800  }
801  if (NULL == ego_entry)
802  {
803  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
804  GNUNET_JSON_parse_free(tktspec);
805  return;
806  }
807  identity_priv = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
808 
809  handle->idp = GNUNET_RECLAIM_connect(cfg);
810  handle->idp_op = GNUNET_RECLAIM_ticket_revoke(handle->idp,
811  identity_priv,
812  ticket,
813  &finished_cont,
814  handle);
815  GNUNET_JSON_parse_free(tktspec);
816 }
817 
818 static void
821  const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
822 {
823  struct RequestHandle *handle = cls;
824  char *val_str;
825  json_t *value;
826 
827  if (NULL == identity)
828  {
830  return;
831  }
832 
833  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
835  attr->data,
836  attr->data_size);
837  if (NULL == val_str)
838  {
840  "Failed to parse value for: %s\n",
841  attr->name);
842  return;
843  }
844  value = json_string(val_str);
845  json_object_set_new(handle->resp_object, attr->name, value);
846  json_decref(value);
847  GNUNET_free(val_str);
848 }
849 
850 static void
852  const char *url,
853  void *cls)
854 {
855  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
856  struct RequestHandle *handle = cls;
857  struct EgoEntry *ego_entry;
859  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
860  char term_data[handle->rest_handle->data_size + 1];
861  json_t *data_json;
862  json_error_t err;
863  struct GNUNET_JSON_Specification tktspec[] =
865 
866  if (0 >= handle->rest_handle->data_size)
867  {
869  return;
870  }
871 
872  term_data[handle->rest_handle->data_size] = '\0';
873  GNUNET_memcpy(term_data,
874  handle->rest_handle->data,
875  handle->rest_handle->data_size);
876  data_json = json_loads(term_data, JSON_DECODE_ANY, &err);
877  if (NULL == data_json)
878  {
880  "Unable to parse JSON Object from %s\n",
881  term_data);
883  return;
884  }
885  if (GNUNET_OK != GNUNET_JSON_parse(data_json, tktspec, NULL, NULL))
886  {
887  handle->emsg = GNUNET_strdup("Not a ticket!\n");
889  GNUNET_JSON_parse_free(tktspec);
890  json_decref(data_json);
891  return;
892  }
893  for (ego_entry = handle->ego_head; NULL != ego_entry;
894  ego_entry = ego_entry->next)
895  {
896  GNUNET_IDENTITY_ego_get_public_key(ego_entry->ego, &tmp_pk);
897  if (0 == memcmp(&ticket->audience,
898  &tmp_pk,
899  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
900  break;
901  }
902  if (NULL == ego_entry)
903  {
904  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Identity unknown\n");
905  GNUNET_JSON_parse_free(tktspec);
906  return;
907  }
908  identity_priv = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
909  handle->resp_object = json_object();
910  handle->idp = GNUNET_RECLAIM_connect(cfg);
911  handle->idp_op = GNUNET_RECLAIM_ticket_consume(handle->idp,
912  identity_priv,
913  ticket,
914  &consume_cont,
915  handle);
916  GNUNET_JSON_parse_free(tktspec);
917 }
918 
919 
927 static void
929  const char *url,
930  void *cls)
931 {
932  struct MHD_Response *resp;
933  struct RequestHandle *handle = cls;
934 
935  // For now, independent of path return all options
936  resp = GNUNET_REST_create_response(NULL);
937  MHD_add_response_header(resp, "Access-Control-Allow-Methods", allow_methods);
938  handle->proc(handle->proc_cls, resp, MHD_HTTP_OK);
939  cleanup_handle(handle);
940  return;
941 }
942 
948 static void
950 {
952  static const struct GNUNET_REST_RequestHandler handlers[] =
953  { { MHD_HTTP_METHOD_GET,
956  { MHD_HTTP_METHOD_POST,
959  { MHD_HTTP_METHOD_DELETE,
962  { MHD_HTTP_METHOD_GET,
965  { MHD_HTTP_METHOD_POST,
968  { MHD_HTTP_METHOD_POST,
971  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
973 
974  if (GNUNET_NO ==
975  GNUNET_REST_handle_request(handle->rest_handle, handlers, &err, handle))
976  {
977  handle->response_code = err.error_code;
979  }
980 }
981 
1015 static void
1016 list_ego(void *cls,
1017  struct GNUNET_IDENTITY_Ego *ego,
1018  void **ctx,
1019  const char *identifier)
1020 {
1021  struct RequestHandle *handle = cls;
1022  struct EgoEntry *ego_entry;
1023  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1024 
1025  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1026  {
1027  handle->state = ID_REST_STATE_POST_INIT;
1028  init_cont(handle);
1029  return;
1030  }
1031  if (ID_REST_STATE_INIT == handle->state)
1032  {
1033  ego_entry = GNUNET_new(struct EgoEntry);
1036  ego_entry->ego = ego;
1037  ego_entry->identifier = GNUNET_strdup(identifier);
1039  handle->ego_tail,
1040  ego_entry);
1041  }
1042 }
1043 
1044 static void
1047  void *proc_cls)
1048 {
1049  struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
1050 
1051  handle->response_code = 0;
1053  handle->proc_cls = proc_cls;
1054  handle->proc = proc;
1055  handle->state = ID_REST_STATE_INIT;
1056  handle->rest_handle = rest_handle;
1057 
1058  handle->url = GNUNET_strdup(rest_handle->url);
1059  if (handle->url[strlen(handle->url) - 1] == '/')
1060  handle->url[strlen(handle->url) - 1] = '\0';
1061  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1062  handle->identity_handle = GNUNET_IDENTITY_connect(cfg, &list_ego, handle);
1063  handle->timeout_task =
1064  GNUNET_SCHEDULER_add_delayed(handle->timeout, &do_timeout, handle);
1065  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1066 }
1067 
1074 void *
1076 {
1077  static struct Plugin plugin;
1078  struct GNUNET_REST_Plugin *api;
1079 
1080  cfg = cls;
1081  if (NULL != plugin.cfg)
1082  return NULL; /* can only initialize once! */
1083  memset(&plugin, 0, sizeof(struct Plugin));
1084  plugin.cfg = cfg;
1085  api = GNUNET_new(struct GNUNET_REST_Plugin);
1086  api->cls = &plugin;
1090  "%s, %s, %s, %s, %s",
1091  MHD_HTTP_METHOD_GET,
1092  MHD_HTTP_METHOD_POST,
1093  MHD_HTTP_METHOD_PUT,
1094  MHD_HTTP_METHOD_DELETE,
1095  MHD_HTTP_METHOD_OPTIONS);
1096 
1098  _("Identity Provider REST API initialized\n"));
1099  return api;
1100 }
1101 
1102 
1109 void *
1111 {
1112  struct GNUNET_REST_Plugin *api = cls;
1113  struct Plugin *plugin = api->cls;
1114 
1115  plugin->cfg = NULL;
1116 
1118  GNUNET_free(api);
1120  "Identity Provider REST plugin is finished\n");
1121  return NULL;
1122 }
1123 
1124 /* end of plugin_rest_reclaim.c */
static void list_attribute_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
List attributes for identity request.
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:525
void * cls
Closure for parser and cleaner.
const char * name
The name of the attribute.
struct GNUNET_RECLAIM_ATTRIBUTE_Claim * claim
The attribute claim.
char * GNUNET_RECLAIM_ATTRIBUTE_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;claim&#39; of an attribute to a string.
#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES
Attribute namespace.
Handle to the service.
Definition: reclaim_api.c:232
The authorization ticket.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
static void attr_collect(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
Collect all attributes for an ego.
static void consume_ticket_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
static void cleanup_handle_delayed(void *cls)
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_AttributeResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all attributes for a local identity.
Definition: reclaim_api.c:948
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct EgoEntry * ego_tail
Ego list.
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
If listing is enabled, prints information about the egos.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_attribute_store(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, const struct GNUNET_TIME_Relative *exp_interval, GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls)
Store an attribute.
Definition: reclaim_api.c:844
struct GNUNET_RECLAIM_TicketIterator * GNUNET_RECLAIM_ticket_iteration_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_TicketCallback proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
Lists all tickets that have been issued to remote identites (relying parties)
Definition: reclaim_api.c:1139
size_t data_size
Number of bytes in data.
void * cls
The closure of the plugin.
size_t data_size
The POST data size.
static void collect_error_cb(void *cls)
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Random on unsigned 64-bit values.
struct GNUNET_RECLAIM_AttributeIterator * attr_it
Attribute iterator.
static void add_attribute_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
GNUNET_REST_ResultProcessor proc
The plugin result processor.
static struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * attr_list
Attribute list.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_JSON_parse_free(struct GNUNET_JSON_Specification *spec)
Frees all elements allocated during a GNUNET_JSON_parse() operation.
Definition: json.c:100
#define GNUNET_REST_API_NS_IDENTITY_CONSUME
Revoke namespace.
static void finished_cont(void *cls, int32_t success, const char *emsg)
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:553
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:814
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct returned by the initialization function of the plugin
void GNUNET_RECLAIM_ticket_iteration_next(struct GNUNET_RECLAIM_TicketIterator *it)
Calls the ticket processor specified in GNUNET_RECLAIM_ticket_iteration_start for the next record...
Definition: reclaim_api.c:1183
static void init_cont(struct RequestHandle *handle)
Handle rest request.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
Entry in parser specification for GNUNET_JSON_parse().
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1203
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Private ECC key encoded for transmission.
void GNUNET_RECLAIM_get_attributes_next(struct GNUNET_RECLAIM_AttributeIterator *it)
Calls the record processor specified in GNUNET_RECLAIM_get_attributes_start for the next record...
Definition: reclaim_api.c:994
Handle for an operation with the service.
Definition: reclaim_api.c:41
void(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void * proc_cls
The closure of the result processor.
static void collect_finished_cb(void *cls)
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static void consume_cont(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
Handle for an operation with the identity service.
Definition: identity_api.c:39
#define GNUNET_REST_HANDLER_END
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:46
The request handle.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
const void * data
Binary value stored as attribute value.
The ego list.
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
#define ID_REST_STATE_INIT
State while collecting all egos.
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
static void rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
Handle for an ego.
Definition: identity.h:237
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_revoke(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_ContinuationWithStatus cb, void *cb_cls)
Revoked an issued ticket.
Definition: reclaim_api.c:1234
Handle for a attribute iterator operation.
Definition: reclaim_api.c:165
static char * allow_methods
HTTP methods allows for this plugin.
enum State state
current state of profiling
json_t * resp_object
Response object.
const char * GNUNET_RECLAIM_ATTRIBUTE_number_to_typename(uint32_t type)
Convert a type number to the corresponding type string.
static char * value
Value of the record to add/remove.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_attribute_delete(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls)
Delete an attribute.
Definition: reclaim_api.c:891
char * emsg
Error response message.
int GNUNET_JSON_parse(const json_t *root, struct GNUNET_JSON_Specification *spec, const char **error_json_name, unsigned int *error_line)
Navigate and parse data in a JSON tree.
Definition: json.c:45
const char * url
The url as string.
Handle for the service.
Definition: identity_api.c:94
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
char * name
Plugin name.
struct GNUNET_TIME_Relative timeout
Timeout.
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
static struct GNUNET_IDENTITY_Handle * identity_handle
Identity handle.
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void list_tickets_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
List tickets for identity request.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:835
#define ID_REST_STATE_POST_INIT
Done collecting egos.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
int GNUNET_REST_handle_request(struct GNUNET_REST_RequestHandle *conn, const struct GNUNET_REST_RequestHandler *handlers, struct GNUNET_REST_RequestHandlerError *err, void *cls)
Definition: rest.c:75
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
int response_code
HTTP response code.
#define GNUNET_REST_API_NS_RECLAIM
REST root namespace.
int state
The processing state.
static void ticket_collect(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
Collect all attributes for an ego.
static void delete_attribute_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
List attributes for identity request.
char * GNUNET_CRYPTO_ecdsa_public_key_to_string(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:334
static void return_response(void *cls)
Return attributes for identity.
const char * data
The POST data.
struct GNUNET_CRYPTO_EcdsaPublicKey identity
The ticket issuer (= the user)
char * keystring
Public key string.
struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
void * libgnunet_plugin_rest_reclaim_done(void *cls)
Exit point from the plugin.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * attr_list
Attribute claim list.
#define GNUNET_REST_API_NS_IDENTITY_REVOKE
Revoke namespace.
uint64_t rnd
The ticket random (NBO)
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static void delete_finished_cb(void *cls, int32_t success, const char *emsg)
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:119
static struct Ego * ego_head
Head of DLL of all egos.
void GNUNET_IDENTITY_ego_get_public_key(const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:566
static void do_error(void *cls)
Task run on error, sends error message.
char * identifier
Ego Identifier.
struct GNUNET_JSON_Specification GNUNET_RECLAIM_JSON_spec_claim(struct GNUNET_RECLAIM_ATTRIBUTE_Claim **attr)
JSON Specification for Reclaim claims.
Definition: json_reclaim.c:131
static void revoke_ticket_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
configuration data
Definition: configuration.c:83
struct EgoEntry * ego_head
Ego list.
Handle for a plugin.
Definition: block.c:37
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1015
struct GNUNET_CRYPTO_EcdsaPublicKey audience
The ticket audience (= relying party)
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
static void do_timeout(void *cls)
Task run on timeout, sends error message.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:56
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
A list of GNUNET_RECLAIM_ATTRIBUTE_Claim structures.
Handle for a ticket iterator operation.
Definition: reclaim_api.c:103
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
void * libgnunet_plugin_rest_reclaim_init(void *cls)
Entry point for the plugin.
struct GNUNET_RECLAIM_Operation * idp_op
Idp Operation.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1095
struct EgoEntry * prev
DLL.
struct GNUNET_JSON_Specification GNUNET_JSON_spec_end(void)
End of a parser specification.
Definition: json_helper.c:35
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:921
static struct Ego * ego_tail
Tail of DLL of all egos.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:774
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * next
DLL.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_head
List head.
struct EgoEntry * next
DLL.
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:953
struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
#define GNUNET_REST_API_NS_IDENTITY_TICKETS
Ticket namespace.
struct GNUNET_JSON_Specification GNUNET_RECLAIM_JSON_spec_ticket(struct GNUNET_RECLAIM_Ticket **ticket)
JSON Specification for Reclaim tickets.
Definition: json_reclaim.c:247
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
High-quality operations are desired.
char * url
The url.