GNUnet  0.11.x
plugin_rest_identity.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 "gnunet_rest_plugin.h"
30 #include "gnunet_rest_lib.h"
31 #include "microhttpd.h"
32 #include <jansson.h>
33 
37 #define GNUNET_REST_API_NS_IDENTITY "/identity"
38 
42 #define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
43 
47 #define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
48 
52 #define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
53 
57 #define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
58 
62 #define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
63 
67 #define GNUNET_REST_IDENTITY_PARAM_NAME "name"
68 
72 #define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
73 
77 #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
78 
82 #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
83 
87 #define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
88 
92 #define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
93 
97 #define GNUNET_REST_ERROR_NO_DATA "No data"
98 
102 #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
103 
107 #define ID_REST_STATE_INIT 0
108 
112 #define ID_REST_STATE_POST_INIT 1
113 
118 
122 static char *allow_methods;
123 
127 struct Plugin
128 {
129  const struct GNUNET_CONFIGURATION_Handle *cfg;
130 };
131 
135 struct EgoEntry
136 {
140  struct EgoEntry *next;
141 
145  struct EgoEntry *prev;
146 
150  char *identifier;
151 
155  char *keystring;
156 
161 };
162 
166 struct RequestHandle
167 {
171  const char *data;
172 
176  char *name;
177 
181  size_t data_size;
182 
183 
188 
193 
197  int state;
198 
203 
208 
212  struct GNUNET_REST_RequestHandle *rest_handle;
213 
218 
223 
228 
232  void *proc_cls;
233 
237  char *url;
238 
242  char *emsg;
243 
247  int response_code;
248 };
249 
254 static void
255 cleanup_handle (void *cls)
256 {
257  struct RequestHandle *handle = cls;
258  struct EgoEntry *ego_entry;
259  struct EgoEntry *ego_tmp;
260 
261  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
262  if (NULL != handle->timeout_task)
263  {
265  handle->timeout_task = NULL;
266  }
267 
268  if (NULL != handle->url)
269  GNUNET_free (handle->url);
270  if (NULL != handle->emsg)
271  GNUNET_free (handle->emsg);
272  if (NULL != handle->name)
273  GNUNET_free (handle->name);
274  if (NULL != handle->identity_handle)
276 
277  for (ego_entry = handle->ego_head; NULL != ego_entry;)
278  {
279  ego_tmp = ego_entry;
280  ego_entry = ego_entry->next;
281  GNUNET_free (ego_tmp->identifier);
282  GNUNET_free (ego_tmp->keystring);
283  GNUNET_free (ego_tmp);
284  }
285 
286  GNUNET_free (handle);
287 }
288 
289 
295 static void
296 do_error (void *cls)
297 {
298  struct RequestHandle *handle = cls;
299  struct MHD_Response *resp;
300  json_t *json_error = json_object ();
301  char *response;
302 
303  if (NULL == handle->emsg)
305 
306  json_object_set_new (json_error, "error", json_string (handle->emsg));
307 
308  if (0 == handle->response_code)
309  handle->response_code = MHD_HTTP_OK;
310  response = json_dumps (json_error, 0);
311  resp = GNUNET_REST_create_response (response);
312  handle->proc (handle->proc_cls, resp, handle->response_code);
313  json_decref (json_error);
314  GNUNET_free (response);
316 }
317 
318 
328 struct EgoEntry *
329 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
330 {
331  struct EgoEntry *ego_entry;
332 
333  if (NULL != pubkey)
334  {
335  for (ego_entry = handle->ego_head; NULL != ego_entry;
336  ego_entry = ego_entry->next)
337  {
338  if (0 != strcasecmp (pubkey, ego_entry->keystring))
339  continue;
340  return ego_entry;
341  }
342  }
343  if (NULL != name)
344  {
345  for (ego_entry = handle->ego_head; NULL != ego_entry;
346  ego_entry = ego_entry->next)
347  {
348  if (0 != strcasecmp (name, ego_entry->identifier))
349  continue;
350  return ego_entry;
351  }
352  }
353  return NULL;
354 }
355 
356 
365 static void
367  struct GNUNET_IDENTITY_Ego *ego,
368  void **ctx,
369  const char *name)
370 {
371  struct RequestHandle *handle = cls;
372  struct MHD_Response *resp;
373  struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
374  json_t *json_root;
375  char *result_str;
376  char *public_key_string;
377 
378  if (NULL == ego)
379  {
380  handle->response_code = MHD_HTTP_NOT_FOUND;
383  return;
384  }
385 
386  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
387  public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (&public_key);
388 
389  // create json with subsystem identity
390  json_root = json_object ();
391  json_object_set_new (json_root,
393  json_string (public_key_string));
394  json_object_set_new (json_root,
396  json_string (name));
397 
398  result_str = json_dumps (json_root, 0);
399  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
400  resp = GNUNET_REST_create_response (result_str);
401 
402  json_decref (json_root);
403  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
404  GNUNET_free (result_str);
405  GNUNET_free (public_key_string);
407 }
408 
409 
417 void
419  const char *url,
420  void *cls)
421 {
422  struct RequestHandle *handle = cls;
423  char *subsystem;
424 
425  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
426  {
427  handle->emsg = GNUNET_strdup ("Missing subsystem name");
429  return;
430  }
431  subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
432  // requested default identity of subsystem
433  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
434 
435  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
436  subsystem,
438  handle);
439 
440  if (NULL == handle->op)
441  {
442  handle->response_code = MHD_HTTP_NOT_FOUND;
445  return;
446  }
447 }
448 
449 
457 void
459  const char *url,
460  void *cls)
461 {
462  struct RequestHandle *handle = cls;
463  struct EgoEntry *ego_entry;
464  struct MHD_Response *resp;
465  json_t *json_root;
466  json_t *json_ego;
467  char *result_str;
468 
469  json_root = json_array ();
470  // Return ego/egos
471  for (ego_entry = handle->ego_head; NULL != ego_entry;
472  ego_entry = ego_entry->next)
473  {
474  json_ego = json_object ();
475  json_object_set_new (json_ego,
477  json_string (ego_entry->keystring));
478  json_object_set_new (json_ego,
480  json_string (ego_entry->identifier));
481  json_array_append (json_root, json_ego);
482  json_decref (json_ego);
483  }
484 
485  result_str = json_dumps (json_root, 0);
486  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
487  resp = GNUNET_REST_create_response (result_str);
488 
489  json_decref (json_root);
490  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
491  GNUNET_free (result_str);
493 }
494 
495 
502 void
503 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
504 {
505  struct MHD_Response *resp;
506  json_t *json_ego;
507  char *result_str;
508 
509  json_ego = json_object ();
510  json_object_set_new (json_ego,
512  json_string (ego_entry->keystring));
513  json_object_set_new (json_ego,
515  json_string (ego_entry->identifier));
516 
517  result_str = json_dumps (json_ego, 0);
518  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
519  resp = GNUNET_REST_create_response (result_str);
520  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
521 
522  json_decref (json_ego);
523  GNUNET_free (result_str);
525 }
526 
527 
535 void
537  const char *url,
538  void *cls)
539 {
540  struct RequestHandle *handle = cls;
541  struct EgoEntry *ego_entry;
542  char *keystring;
543 
544  keystring = NULL;
545 
546  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
547  {
548  handle->response_code = MHD_HTTP_NOT_FOUND;
551  return;
552  }
553  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
554  ego_entry = get_egoentry (handle, keystring, NULL);
555 
556  if (NULL == ego_entry)
557  {
558  handle->response_code = MHD_HTTP_NOT_FOUND;
561  return;
562  }
563 
564  ego_get_response (handle, ego_entry);
565 }
566 
567 
575 void
577  const char *url,
578  void *cls)
579 {
580  struct RequestHandle *handle = cls;
581  struct EgoEntry *ego_entry;
582  char *egoname;
583 
584  egoname = NULL;
585 
586  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
587  {
588  handle->response_code = MHD_HTTP_NOT_FOUND;
591  return;
592  }
593  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
594  ego_entry = get_egoentry (handle, NULL, egoname);
595 
596  if (NULL == ego_entry)
597  {
598  handle->response_code = MHD_HTTP_NOT_FOUND;
601  return;
602  }
603 
604  ego_get_response (handle, ego_entry);
605 }
606 
607 
614 static void
615 do_finished (void *cls, const char *emsg)
616 {
617  struct RequestHandle *handle = cls;
618  struct MHD_Response *resp;
619 
620  handle->op = NULL;
621  if (NULL != emsg)
622  {
623  handle->emsg = GNUNET_strdup (emsg);
625  return;
626  }
627  if (0 == handle->response_code)
628  {
629  handle->response_code = MHD_HTTP_NO_CONTENT;
630  }
631  resp = GNUNET_REST_create_response (NULL);
632  handle->proc (handle->proc_cls, resp, handle->response_code);
634 }
635 
636 
644 static void
646  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
647  const char *emsg)
648 {
649  struct RequestHandle *handle = cls;
650 
651  (void) pk;
652  do_finished (handle, emsg);
653 }
654 
655 
662 void
664 {
665  struct EgoEntry *ego_entry_tmp;
666  struct MHD_Response *resp;
667  json_t *data_js;
668  json_error_t err;
669  char *newname;
670  char term_data[handle->data_size + 1];
671  int json_state;
672 
673  // if no data
674  if (0 >= handle->data_size)
675  {
678  return;
679  }
680  // if not json
681  term_data[handle->data_size] = '\0';
682  GNUNET_memcpy (term_data, handle->data, handle->data_size);
683  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
684 
685  if (NULL == data_js)
686  {
689  return;
690  }
691 
692  newname = NULL;
693  // NEW NAME
694  json_state = 0;
695  json_state = json_unpack (data_js,
696  "{s:s!}",
698  &newname);
699  // Change name with pubkey or name identifier
700  if (0 != json_state)
701  {
704  json_decref (data_js);
705  return;
706  }
707 
708  if (NULL == newname)
709  {
712  json_decref (data_js);
713  return;
714  }
715 
716  if (0 >= strlen (newname))
717  {
720  json_decref (data_js);
721  return;
722  }
723 
724  ego_entry_tmp = get_egoentry (handle, NULL, newname);
725  if (NULL != ego_entry_tmp)
726  {
727  // Ego with same name not allowed (even if its the ego we change)
728  resp = GNUNET_REST_create_response (NULL);
729  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
731  json_decref (data_js);
732  return;
733  }
734  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
735  ego_entry->identifier,
736  newname,
737  &do_finished,
738  handle);
739  if (NULL == handle->op)
740  {
741  handle->emsg = GNUNET_strdup ("Rename failed");
743  json_decref (data_js);
744  return;
745  }
746  json_decref (data_js);
747  return;
748 }
749 
750 
758 void
760  const char *url,
761  void *cls)
762 {
763  struct RequestHandle *handle = cls;
764  struct EgoEntry *ego_entry;
765  char *keystring;
766 
767  keystring = NULL;
768 
769  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
770  {
771  handle->response_code = MHD_HTTP_NOT_FOUND;
774  return;
775  }
776  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
777  ego_entry = get_egoentry (handle, keystring, NULL);
778 
779  if (NULL == ego_entry)
780  {
781  handle->response_code = MHD_HTTP_NOT_FOUND;
784  return;
785  }
786 
787  ego_edit (handle, ego_entry);
788 }
789 
790 
798 void
800  const char *url,
801  void *cls)
802 {
803  struct RequestHandle *handle = cls;
804  struct EgoEntry *ego_entry;
805  char *name;
806 
807  name = NULL;
808 
809  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
810  {
811  handle->response_code = MHD_HTTP_NOT_FOUND;
814  return;
815  }
816  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
817  ego_entry = get_egoentry (handle, NULL, name);
818 
819  if (NULL == ego_entry)
820  {
821  handle->response_code = MHD_HTTP_NOT_FOUND;
824  return;
825  }
826 
827  ego_edit (handle, ego_entry);
828 }
829 
830 
838 void
840  const char *url,
841  void *cls)
842 {
843  struct RequestHandle *handle = cls;
844  struct EgoEntry *ego_entry;
845  json_t *data_js;
846  json_error_t err;
847  char *newsubsys;
848  char *name;
849  char term_data[handle->data_size + 1];
850  int json_state;
851 
852  name = NULL;
853 
854  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
855  {
856  handle->response_code = MHD_HTTP_NOT_FOUND;
859  return;
860  }
861  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
862  ego_entry = get_egoentry (handle, NULL, name);
863 
864  if (NULL == ego_entry)
865  {
866  handle->response_code = MHD_HTTP_NOT_FOUND;
869  return;
870  }
871 
872  // if no data
873  if (0 >= handle->data_size)
874  {
877  return;
878  }
879  // if not json
880  term_data[handle->data_size] = '\0';
881  GNUNET_memcpy (term_data, handle->data, handle->data_size);
882  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
883 
884  if (NULL == data_js)
885  {
888  return;
889  }
890 
891  newsubsys = NULL;
892  // SUBSYSTEM
893  json_state = 0;
894  json_state = json_unpack (data_js,
895  "{s:s!}",
897  &newsubsys);
898  // Change subsystem with pubkey or name identifier
899  if (0 != json_state)
900  {
903  json_decref (data_js);
904  return;
905  }
906 
907  if (NULL == newsubsys)
908  {
911  json_decref (data_js);
912  return;
913  }
914 
915  if (0 >= strlen (newsubsys))
916  {
919  json_decref (data_js);
920  return;
921  }
922 
923  handle->response_code = MHD_HTTP_NO_CONTENT;
924  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
925  newsubsys,
926  ego_entry->ego,
927  &do_finished,
928  handle);
929  if (NULL == handle->op)
930  {
931  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
933  return;
934  }
935  json_decref (data_js);
936  return;
937 }
938 
939 
947 void
949  const char *url,
950  void *cls)
951 {
952  struct RequestHandle *handle = cls;
953  struct EgoEntry *ego_entry;
954  struct MHD_Response *resp;
955  json_t *data_js;
956  json_error_t err;
957  char *egoname;
958  int json_unpack_state;
959  char term_data[handle->data_size + 1];
960 
961  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
962  {
964  return;
965  }
966 
967  if (0 >= handle->data_size)
968  {
971  return;
972  }
973  term_data[handle->data_size] = '\0';
974  GNUNET_memcpy (term_data, handle->data, handle->data_size);
975  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
976  if (NULL == data_js)
977  {
980  json_decref (data_js);
981  return;
982  }
983  json_unpack_state = 0;
984  json_unpack_state =
985  json_unpack (data_js, "{s:s!}", GNUNET_REST_IDENTITY_PARAM_NAME, &egoname);
986  if (0 != json_unpack_state)
987  {
990  json_decref (data_js);
991  return;
992  }
993 
994  if (NULL == egoname)
995  {
998  json_decref (data_js);
999  return;
1000  }
1001  if (0 >= strlen (egoname))
1002  {
1003  json_decref (data_js);
1006  return;
1007  }
1008  GNUNET_STRINGS_utf8_tolower (egoname, egoname);
1009  for (ego_entry = handle->ego_head; NULL != ego_entry;
1010  ego_entry = ego_entry->next)
1011  {
1012  if (0 == strcasecmp (egoname, ego_entry->identifier))
1013  {
1014  resp = GNUNET_REST_create_response (NULL);
1015  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1017  json_decref (data_js);
1018  return;
1019  }
1020  }
1021  handle->name = GNUNET_strdup (egoname);
1022  json_decref (data_js);
1023  handle->response_code = MHD_HTTP_CREATED;
1024  handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
1025  handle->name,
1027  handle);
1028 }
1029 
1030 
1038 void
1040  const char *url,
1041  void *cls)
1042 {
1043  struct RequestHandle *handle = cls;
1044  struct EgoEntry *ego_entry;
1045  char *keystring;
1046 
1047  keystring = NULL;
1048 
1049  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1050  {
1051  handle->response_code = MHD_HTTP_NOT_FOUND;
1054  return;
1055  }
1056  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1057  ego_entry = get_egoentry (handle, keystring, NULL);
1058 
1059  if (NULL == ego_entry)
1060  {
1061  handle->response_code = MHD_HTTP_NOT_FOUND;
1064  return;
1065  }
1066 
1067  handle->response_code = MHD_HTTP_NO_CONTENT;
1068  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1069  ego_entry->identifier,
1070  &do_finished,
1071  handle);
1072 }
1073 
1074 
1082 void
1084  const char *url,
1085  void *cls)
1086 {
1087  struct RequestHandle *handle = cls;
1088  struct EgoEntry *ego_entry;
1089  char *name;
1090 
1091  name = NULL;
1092 
1093  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1094  {
1095  handle->response_code = MHD_HTTP_NOT_FOUND;
1098  return;
1099  }
1100  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1101  ego_entry = get_egoentry (handle, NULL, name);
1102 
1103  if (NULL == ego_entry)
1104  {
1105  handle->response_code = MHD_HTTP_NOT_FOUND;
1108  return;
1109  }
1110 
1111  handle->response_code = MHD_HTTP_NO_CONTENT;
1112  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1113  ego_entry->identifier,
1114  &do_finished,
1115  handle);
1116 }
1117 
1118 
1126 static void
1128  const char *url,
1129  void *cls)
1130 {
1131  struct MHD_Response *resp;
1132  struct RequestHandle *handle = cls;
1133 
1134  // For now, independent of path return all options
1135  resp = GNUNET_REST_create_response (NULL);
1136  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1137  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1139  return;
1140 }
1141 
1142 
1148 static void
1150 {
1152  static const struct GNUNET_REST_RequestHandler handlers[] =
1153  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1154  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1155  &ego_get_pubkey },
1156  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1157  { MHD_HTTP_METHOD_GET,
1159  &ego_get_subsystem },
1160  { MHD_HTTP_METHOD_PUT,
1162  &ego_edit_pubkey },
1163  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1164  { MHD_HTTP_METHOD_PUT,
1166  &ego_edit_subsystem },
1167  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1168  { MHD_HTTP_METHOD_DELETE,
1170  &ego_delete_pubkey },
1171  { MHD_HTTP_METHOD_DELETE,
1173  &ego_delete_name },
1174  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1176 
1177  if (GNUNET_NO ==
1178  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1179  {
1180  handle->response_code = err.error_code;
1182  }
1183 }
1184 
1185 
1219 static void
1220 init_egos (void *cls,
1221  struct GNUNET_IDENTITY_Ego *ego,
1222  void **ctx,
1223  const char *identifier)
1224 {
1225  struct RequestHandle *handle = cls;
1226  struct EgoEntry *ego_entry;
1227  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1228 
1229  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1230  {
1231  handle->state = ID_REST_STATE_POST_INIT;
1232  init_cont (handle);
1233  return;
1234  }
1235  if (ID_REST_STATE_INIT == handle->state)
1236  {
1237  ego_entry = GNUNET_new (struct EgoEntry);
1240  ego_entry->ego = ego;
1241  ego_entry->identifier = GNUNET_strdup (identifier);
1243  handle->ego_tail,
1244  ego_entry);
1245  return;
1246  }
1247  // Check if ego exists
1248  for (ego_entry = handle->ego_head; NULL != ego_entry;)
1249  {
1250  struct EgoEntry *tmp = ego_entry;
1251  ego_entry = ego_entry->next;
1252  if (ego != tmp->ego)
1253  continue;
1254  // Deleted
1255  if (NULL == identifier)
1256  {
1258  handle->ego_tail,
1259  tmp);
1260  GNUNET_free (tmp->keystring);
1261  GNUNET_free (tmp->identifier);
1262  GNUNET_free (tmp);
1263  }
1264  else
1265  {
1266  // Renamed
1267  GNUNET_free (tmp->identifier);
1268  tmp->identifier = GNUNET_strdup (identifier);
1269  }
1270  return;
1271  }
1272  // New ego
1273  ego_entry = GNUNET_new (struct EgoEntry);
1276  ego_entry->ego = ego;
1277  GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1279  handle->ego_tail,
1280  ego_entry);
1281 
1282 }
1283 
1284 
1296 static void
1299  void *proc_cls)
1300 {
1301  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1302 
1303  handle->response_code = 0;
1305  handle->proc_cls = proc_cls;
1306  handle->proc = proc;
1307  handle->rest_handle = rest_handle;
1308  handle->data = rest_handle->data;
1309  handle->data_size = rest_handle->data_size;
1310 
1311  handle->url = GNUNET_strdup (rest_handle->url);
1312  if (handle->url[strlen (handle->url) - 1] == '/')
1313  handle->url[strlen (handle->url) - 1] = '\0';
1314  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1315 
1316  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
1317 
1318  handle->timeout_task =
1319  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1320 
1321  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1322 }
1323 
1324 
1331 void *
1333 {
1334  static struct Plugin plugin;
1335  struct GNUNET_REST_Plugin *api;
1336 
1337  cfg = cls;
1338  if (NULL != plugin.cfg)
1339  return NULL; /* can only initialize once! */
1340  memset (&plugin, 0, sizeof(struct Plugin));
1341  plugin.cfg = cfg;
1342  api = GNUNET_new (struct GNUNET_REST_Plugin);
1343  api->cls = &plugin;
1347  "%s, %s, %s, %s, %s",
1348  MHD_HTTP_METHOD_GET,
1349  MHD_HTTP_METHOD_POST,
1350  MHD_HTTP_METHOD_PUT,
1351  MHD_HTTP_METHOD_DELETE,
1352  MHD_HTTP_METHOD_OPTIONS);
1353 
1354  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1355  return api;
1356 }
1357 
1358 
1365 void *
1367 {
1368  struct GNUNET_REST_Plugin *api = cls;
1369  struct Plugin *plugin = api->cls;
1370 
1371  plugin->cfg = NULL;
1372 
1374  GNUNET_free (api);
1375  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1376  return NULL;
1377 }
1378 
1379 
1380 /* end of plugin_rest_identity.c */
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:527
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void ego_edit_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity PUT request with name.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
char * name
Plugin name.
#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM
Parameter subsystem.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
static void init_egos(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
If listing is enabled, prints information about the egos.
static struct GNUNET_CRYPTO_EddsaPrivateKey * pk
Private key of this peer.
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey
Public key of the zone to look in.
struct EgoEntry * ego_tail
Ego list.
#define GNUNET_REST_ERROR_NO_DATA
Error message No data.
void * libgnunet_plugin_rest_identity_init(void *cls)
Entry point for the plugin.
void * cls
The closure of the plugin.
size_t data_size
The POST data size.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete(struct GNUNET_IDENTITY_Handle *h, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls)
Delete an existing identity.
Definition: identity_api.c:777
#define GNUNET_REST_API_NS_IDENTITY_NAME
Identity Namespace with public key specifier.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create(struct GNUNET_IDENTITY_Handle *h, const char *name, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls)
Create a new identity with the given name.
Definition: identity_api.c:677
GNUNET_REST_ResultProcessor proc
The plugin result processor.
static void do_finished_create(void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk, const char *emsg)
Processing finished, when creating an ego.
struct EgoEntry * get_egoentry(struct RequestHandle *handle, char *pubkey, char *name)
Get EgoEntry from list with either a public key or a name If public key and name are not NULL...
void ego_delete_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity DELETE request with name.
void ego_get_subsystem(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request for subsystem.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_set(struct GNUNET_IDENTITY_Handle *h, const char *service_name, struct GNUNET_IDENTITY_Ego *ego, GNUNET_IDENTITY_Continuation cont, void *cont_cls)
Set the preferred/default identity for a service.
Definition: identity_api.c:631
size_t data_size
the length of the REST data
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct returned by the initialization function of the plugin
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_get(struct GNUNET_IDENTITY_Handle *h, const char *service_name, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Obtain the identity that is currently preferred/default for a service.
Definition: identity_api.c:586
static void init_cont(struct RequestHandle *handle)
Handle rest request.
static void do_finished(void *cls, const char *emsg)
Processing finished.
#define GNUNET_NO
Definition: gnunet_common.h:86
#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.
#define GNUNET_REST_API_NS_IDENTITY_PUBKEY
Identity Namespace with public key specifier.
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 ego_delete_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity DELETE request with public key.
void * proc_cls
The closure of the result processor.
#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN
Error message Unknown Error.
Handle for an operation with the identity service.
Definition: identity_api.c:39
#define GNUNET_REST_HANDLER_END
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
The request handle.
#define _(String)
GNU gettext support macro.
Definition: platform.h:180
The ego list.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
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:1271
Handle for an ego.
Definition: identity.h:245
#define GNUNET_REST_ERROR_DATA_INVALID
Error message Data invalid.
char * name
Name to look up.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
char * emsg
Error response message.
const char * url
The url as string.
Handle for the service.
Definition: identity_api.c:95
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:1298
char * name
Plugin name.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
#define GNUNET_REST_IDENTITY_MISSING_NAME
Error message Missing identity name.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:837
static void rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM
Identity Subsystem Namespace.
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:77
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
void ego_edit(struct RequestHandle *handle, struct EgoEntry *ego_entry)
Processing edit ego with EgoEntry ego_entry.
int response_code
Response code.
int state
The processing state.
static char * plugin
Solver plugin name as string.
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:223
const char * data
The POST data.
char * keystring
Public key string.
void ego_get_response(struct RequestHandle *handle, struct EgoEntry *ego_entry)
Responds with the ego_entry identity.
void ego_get_all(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request - responds with all identities.
void ego_get_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request with a name.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:124
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:568
static void cleanup_handle(void *cls)
Cleanup lookup handle.
static char * allow_methods
HTTP methods allows for this plugin.
#define GNUNET_REST_IDENTITY_PARAM_PUBKEY
Parameter public key.
char * identifier
Ego Identifier.
static void ego_get_for_subsystem(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Callback for GET Request with subsystem.
#define GNUNET_REST_IDENTITY_PARAM_NEWNAME
Parameter new name.
#define GNUNET_REST_IDENTITY_MISSING_PUBKEY
Error message Missing identity name.
void ego_edit_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity PUT request with public key.
configuration data
Definition: configuration.c:84
struct EgoEntry * ego_head
Ego list.
Handle for a plugin.
Definition: block.c:37
const char * data
The data from the REST request.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
#define GNUNET_REST_API_NS_IDENTITY
Identity Namespace.
static void do_error(void *cls)
Task run on errors.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename(struct GNUNET_IDENTITY_Handle *h, const char *old_name, const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls)
Renames an existing identity.
Definition: identity_api.c:724
struct EgoEntry * prev
DLL.
void ego_create(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity POST request.
void * libgnunet_plugin_rest_identity_done(void *cls)
Exit point from the plugin.
struct EgoEntry * ego_entry
IDENTITY Operation.
#define GNUNET_REST_IDENTITY_PARAM_NAME
Parameter name.
void ego_edit_subsystem(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity subsystem PUT request with name.
struct EgoEntry * next
DLL.
void ego_get_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request with a public key.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
struct GNUNET_IDENTITY_Operation * op
IDENTITY Operation.
#define GNUNET_free(ptr)
Wrapper around free.
#define ID_REST_STATE_INIT
State while collecting all egos.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:567
#define GNUNET_REST_IDENTITY_NOT_FOUND
Error message No identity found.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:974
char * url
The url.