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_PRIVKEY "privkey"
63 
67 #define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
68 
72 #define GNUNET_REST_IDENTITY_PARAM_NAME "name"
73 
77 #define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
78 
82 #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
83 
87 #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
88 
92 #define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
93 
97 #define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
98 
102 #define GNUNET_REST_ERROR_NO_DATA "No data"
103 
107 #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
108 
112 #define ID_REST_STATE_INIT 0
113 
117 #define ID_REST_STATE_POST_INIT 1
118 
123 
127 static char *allow_methods;
128 
132 struct Plugin
133 {
134  const struct GNUNET_CONFIGURATION_Handle *cfg;
135 };
136 
140 struct EgoEntry
141 {
145  struct EgoEntry *next;
146 
150  struct EgoEntry *prev;
151 
155  char *identifier;
156 
160  char *keystring;
161 
166 };
167 
171 struct RequestHandle
172 {
176  const char *data;
177 
181  char *name;
182 
186  size_t data_size;
187 
188 
193 
198 
202  int state;
203 
208 
213 
217  struct GNUNET_REST_RequestHandle *rest_handle;
218 
223 
228 
233 
237  void *proc_cls;
238 
242  char *url;
243 
247  char *emsg;
248 
252  int response_code;
253 };
254 
259 static void
260 cleanup_handle (void *cls)
261 {
262  struct RequestHandle *handle = cls;
263  struct EgoEntry *ego_entry;
264  struct EgoEntry *ego_tmp;
265 
266  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
267  if (NULL != handle->timeout_task)
268  {
270  handle->timeout_task = NULL;
271  }
272 
273  if (NULL != handle->url)
274  GNUNET_free (handle->url);
275  if (NULL != handle->emsg)
276  GNUNET_free (handle->emsg);
277  if (NULL != handle->name)
278  GNUNET_free (handle->name);
279  if (NULL != handle->identity_handle)
281 
282  for (ego_entry = handle->ego_head; NULL != ego_entry;)
283  {
284  ego_tmp = ego_entry;
285  ego_entry = ego_entry->next;
286  GNUNET_free (ego_tmp->identifier);
287  GNUNET_free (ego_tmp->keystring);
288  GNUNET_free (ego_tmp);
289  }
290 
291  GNUNET_free (handle);
292 }
293 
294 
300 static void
301 do_error (void *cls)
302 {
303  struct RequestHandle *handle = cls;
304  struct MHD_Response *resp;
305  json_t *json_error = json_object ();
306  char *response;
307 
308  if (NULL == handle->emsg)
310 
311  json_object_set_new (json_error, "error", json_string (handle->emsg));
312 
313  if (0 == handle->response_code)
314  handle->response_code = MHD_HTTP_OK;
315  response = json_dumps (json_error, 0);
316  resp = GNUNET_REST_create_response (response);
317  MHD_add_response_header (resp, "Content-Type", "application/json");
318  handle->proc (handle->proc_cls, resp, handle->response_code);
319  json_decref (json_error);
320  GNUNET_free (response);
322 }
323 
324 
334 struct EgoEntry *
335 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
336 {
337  struct EgoEntry *ego_entry;
338 
339  if (NULL != pubkey)
340  {
341  for (ego_entry = handle->ego_head; NULL != ego_entry;
342  ego_entry = ego_entry->next)
343  {
344  if (0 != strcasecmp (pubkey, ego_entry->keystring))
345  continue;
346  return ego_entry;
347  }
348  }
349  if (NULL != name)
350  {
351  for (ego_entry = handle->ego_head; NULL != ego_entry;
352  ego_entry = ego_entry->next)
353  {
354  if (0 != strcasecmp (name, ego_entry->identifier))
355  continue;
356  return ego_entry;
357  }
358  }
359  return NULL;
360 }
361 
362 
371 static void
373  struct GNUNET_IDENTITY_Ego *ego,
374  void **ctx,
375  const char *name)
376 {
377  struct RequestHandle *handle = cls;
378  struct MHD_Response *resp;
379  struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
380  json_t *json_root;
381  char *result_str;
382  char *public_key_string;
383 
384  if (NULL == ego)
385  {
386  handle->response_code = MHD_HTTP_NOT_FOUND;
389  return;
390  }
391 
392  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
393  public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (&public_key);
394 
395  // create json with subsystem identity
396  json_root = json_object ();
397  json_object_set_new (json_root,
399  json_string (public_key_string));
400  json_object_set_new (json_root,
402  json_string (name));
403 
404  result_str = json_dumps (json_root, 0);
405  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
406  resp = GNUNET_REST_create_response (result_str);
407  MHD_add_response_header (resp, "Content-Type", "application/json");
408  json_decref (json_root);
409  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
410  GNUNET_free (result_str);
411  GNUNET_free (public_key_string);
413 }
414 
415 
423 void
425  const char *url,
426  void *cls)
427 {
428  struct RequestHandle *handle = cls;
429  char *subsystem;
430 
431  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
432  {
433  handle->emsg = GNUNET_strdup ("Missing subsystem name");
435  return;
436  }
437  subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
438  // requested default identity of subsystem
439  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
440 
441  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
442  subsystem,
444  handle);
445 
446  if (NULL == handle->op)
447  {
448  handle->response_code = MHD_HTTP_NOT_FOUND;
451  return;
452  }
453 }
454 
455 
463 void
465  const char *url,
466  void *cls)
467 {
468  struct RequestHandle *handle = cls;
469  struct EgoEntry *ego_entry;
470  struct MHD_Response *resp;
471  struct GNUNET_HashCode key;
472  json_t *json_root;
473  json_t *json_ego;
474  char *result_str;
475  char *privkey_str;
476 
477  json_root = json_array ();
478  // Return ego/egos
479  for (ego_entry = handle->ego_head; NULL != ego_entry;
480  ego_entry = ego_entry->next)
481  {
482  json_ego = json_object ();
483  json_object_set_new (json_ego,
485  json_string (ego_entry->keystring));
486  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
487  if (GNUNET_YES ==
489  handle->rest_handle->url_param_map, &key))
490  {
493  json_object_set_new (json_ego,
495  json_string (privkey_str));
496  GNUNET_free (privkey_str);
497  }
498 
499  json_object_set_new (json_ego,
501  json_string (ego_entry->identifier));
502  json_array_append (json_root, json_ego);
503  json_decref (json_ego);
504  }
505 
506  result_str = json_dumps (json_root, 0);
507  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
508  resp = GNUNET_REST_create_response (result_str);
509  MHD_add_response_header (resp, "Content-Type", "application/json");
510  json_decref (json_root);
511  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
512  GNUNET_free (result_str);
514 }
515 
516 
523 void
524 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
525 {
526  struct MHD_Response *resp;
527  struct GNUNET_HashCode key;
528  json_t *json_ego;
529  char *result_str;
530  char *privkey_str;
531 
532  json_ego = json_object ();
533  json_object_set_new (json_ego,
535  json_string (ego_entry->keystring));
536  json_object_set_new (json_ego,
538  json_string (ego_entry->identifier));
539  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
540  if (GNUNET_YES ==
542  handle->rest_handle->url_param_map, &key))
543  {
546  json_object_set_new (json_ego,
548  json_string (privkey_str));
549  GNUNET_free (privkey_str);
550  }
551 
552  result_str = json_dumps (json_ego, 0);
553  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
554  resp = GNUNET_REST_create_response (result_str);
555  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
556  MHD_add_response_header (resp, "Content-Type", "application/json");
557  json_decref (json_ego);
558  GNUNET_free (result_str);
560 }
561 
562 
570 void
572  const char *url,
573  void *cls)
574 {
575  struct RequestHandle *handle = cls;
576  struct EgoEntry *ego_entry;
577  char *keystring;
578 
579  keystring = NULL;
580 
581  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
582  {
583  handle->response_code = MHD_HTTP_NOT_FOUND;
586  return;
587  }
588  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
589  ego_entry = get_egoentry (handle, keystring, NULL);
590 
591  if (NULL == ego_entry)
592  {
593  handle->response_code = MHD_HTTP_NOT_FOUND;
596  return;
597  }
598 
599  ego_get_response (handle, ego_entry);
600 }
601 
602 
610 void
612  const char *url,
613  void *cls)
614 {
615  struct RequestHandle *handle = cls;
616  struct EgoEntry *ego_entry;
617  char *egoname;
618 
619  egoname = NULL;
620 
621  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
622  {
623  handle->response_code = MHD_HTTP_NOT_FOUND;
626  return;
627  }
628  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
629  ego_entry = get_egoentry (handle, NULL, egoname);
630 
631  if (NULL == ego_entry)
632  {
633  handle->response_code = MHD_HTTP_NOT_FOUND;
636  return;
637  }
638 
639  ego_get_response (handle, ego_entry);
640 }
641 
642 
649 static void
650 do_finished (void *cls, const char *emsg)
651 {
652  struct RequestHandle *handle = cls;
653  struct MHD_Response *resp;
654 
655  handle->op = NULL;
656  if (NULL != emsg)
657  {
658  handle->emsg = GNUNET_strdup (emsg);
660  return;
661  }
662  if (0 == handle->response_code)
663  {
664  handle->response_code = MHD_HTTP_NO_CONTENT;
665  }
666  resp = GNUNET_REST_create_response (NULL);
667  handle->proc (handle->proc_cls, resp, handle->response_code);
669 }
670 
671 
679 static void
681  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
682  const char *emsg)
683 {
684  struct RequestHandle *handle = cls;
685 
686  (void) pk;
687  do_finished (handle, emsg);
688 }
689 
690 
697 void
699 {
700  struct EgoEntry *ego_entry_tmp;
701  struct MHD_Response *resp;
702  json_t *data_js;
703  json_error_t err;
704  char *newname;
705  char term_data[handle->data_size + 1];
706  int json_state;
707 
708  // if no data
709  if (0 >= handle->data_size)
710  {
713  return;
714  }
715  // if not json
716  term_data[handle->data_size] = '\0';
717  GNUNET_memcpy (term_data, handle->data, handle->data_size);
718  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
719 
720  if (NULL == data_js)
721  {
724  return;
725  }
726 
727  newname = NULL;
728  // NEW NAME
729  json_state = 0;
730  json_state = json_unpack (data_js,
731  "{s:s!}",
733  &newname);
734  // Change name with pubkey or name identifier
735  if (0 != json_state)
736  {
739  json_decref (data_js);
740  return;
741  }
742 
743  if (NULL == newname)
744  {
747  json_decref (data_js);
748  return;
749  }
750 
751  if (0 >= strlen (newname))
752  {
755  json_decref (data_js);
756  return;
757  }
758 
759  ego_entry_tmp = get_egoentry (handle, NULL, newname);
760  if (NULL != ego_entry_tmp)
761  {
762  // Ego with same name not allowed (even if its the ego we change)
763  resp = GNUNET_REST_create_response (NULL);
764  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
766  json_decref (data_js);
767  return;
768  }
769  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
770  ego_entry->identifier,
771  newname,
772  &do_finished,
773  handle);
774  if (NULL == handle->op)
775  {
776  handle->emsg = GNUNET_strdup ("Rename failed");
778  json_decref (data_js);
779  return;
780  }
781  json_decref (data_js);
782  return;
783 }
784 
785 
793 void
795  const char *url,
796  void *cls)
797 {
798  struct RequestHandle *handle = cls;
799  struct EgoEntry *ego_entry;
800  char *keystring;
801 
802  keystring = NULL;
803 
804  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
805  {
806  handle->response_code = MHD_HTTP_NOT_FOUND;
809  return;
810  }
811  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
812  ego_entry = get_egoentry (handle, keystring, NULL);
813 
814  if (NULL == ego_entry)
815  {
816  handle->response_code = MHD_HTTP_NOT_FOUND;
819  return;
820  }
821 
822  ego_edit (handle, ego_entry);
823 }
824 
825 
833 void
835  const char *url,
836  void *cls)
837 {
838  struct RequestHandle *handle = cls;
839  struct EgoEntry *ego_entry;
840  char *name;
841 
842  name = NULL;
843 
844  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
845  {
846  handle->response_code = MHD_HTTP_NOT_FOUND;
849  return;
850  }
851  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
852  ego_entry = get_egoentry (handle, NULL, name);
853 
854  if (NULL == ego_entry)
855  {
856  handle->response_code = MHD_HTTP_NOT_FOUND;
859  return;
860  }
861 
862  ego_edit (handle, ego_entry);
863 }
864 
865 
873 void
875  const char *url,
876  void *cls)
877 {
878  struct RequestHandle *handle = cls;
879  struct EgoEntry *ego_entry;
880  json_t *data_js;
881  json_error_t err;
882  char *newsubsys;
883  char *name;
884  char term_data[handle->data_size + 1];
885  int json_state;
886 
887  name = NULL;
888 
889  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
890  {
891  handle->response_code = MHD_HTTP_NOT_FOUND;
894  return;
895  }
896  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
897  ego_entry = get_egoentry (handle, NULL, name);
898 
899  if (NULL == ego_entry)
900  {
901  handle->response_code = MHD_HTTP_NOT_FOUND;
904  return;
905  }
906 
907  // if no data
908  if (0 >= handle->data_size)
909  {
912  return;
913  }
914  // if not json
915  term_data[handle->data_size] = '\0';
916  GNUNET_memcpy (term_data, handle->data, handle->data_size);
917  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
918 
919  if (NULL == data_js)
920  {
923  return;
924  }
925 
926  newsubsys = NULL;
927  // SUBSYSTEM
928  json_state = 0;
929  json_state = json_unpack (data_js,
930  "{s:s!}",
932  &newsubsys);
933  // Change subsystem with pubkey or name identifier
934  if (0 != json_state)
935  {
938  json_decref (data_js);
939  return;
940  }
941 
942  if (NULL == newsubsys)
943  {
946  json_decref (data_js);
947  return;
948  }
949 
950  if (0 >= strlen (newsubsys))
951  {
954  json_decref (data_js);
955  return;
956  }
957 
958  handle->response_code = MHD_HTTP_NO_CONTENT;
959  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
960  newsubsys,
961  ego_entry->ego,
962  &do_finished,
963  handle);
964  if (NULL == handle->op)
965  {
966  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
968  return;
969  }
970  json_decref (data_js);
971  return;
972 }
973 
974 
982 void
984  const char *url,
985  void *cls)
986 {
987  struct RequestHandle *handle = cls;
988  struct EgoEntry *ego_entry;
989  struct MHD_Response *resp;
990  json_t *data_js;
991  json_error_t err;
992  char *egoname;
993  char *privkey;
995  struct GNUNET_CRYPTO_EcdsaPrivateKey *pk_ptr;
996  int json_unpack_state;
997  char term_data[handle->data_size + 1];
998 
999  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
1000  {
1002  return;
1003  }
1004 
1005  if (0 >= handle->data_size)
1006  {
1009  return;
1010  }
1011  term_data[handle->data_size] = '\0';
1012  GNUNET_memcpy (term_data, handle->data, handle->data_size);
1013  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
1014  if (NULL == data_js)
1015  {
1018  json_decref (data_js);
1019  return;
1020  }
1021  json_unpack_state = 0;
1022  privkey = NULL;
1023  json_unpack_state =
1024  json_unpack (data_js, "{s:s, s?:s!}",
1027  if (0 != json_unpack_state)
1028  {
1031  json_decref (data_js);
1032  return;
1033  }
1034 
1035  if (NULL == egoname)
1036  {
1039  json_decref (data_js);
1040  return;
1041  }
1042  if (0 >= strlen (egoname))
1043  {
1044  json_decref (data_js);
1047  return;
1048  }
1049  GNUNET_STRINGS_utf8_tolower (egoname, egoname);
1050  for (ego_entry = handle->ego_head; NULL != ego_entry;
1051  ego_entry = ego_entry->next)
1052  {
1053  if (0 == strcasecmp (egoname, ego_entry->identifier))
1054  {
1055  resp = GNUNET_REST_create_response (NULL);
1056  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1058  json_decref (data_js);
1059  return;
1060  }
1061  }
1062  handle->name = GNUNET_strdup (egoname);
1063  if (NULL != privkey)
1064  {
1066  strlen (privkey),
1067  &pk,
1068  sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
1069  pk_ptr = &pk;
1070  }
1071  else
1072  pk_ptr = NULL;
1073  json_decref (data_js);
1074  handle->response_code = MHD_HTTP_CREATED;
1075  handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
1076  handle->name,
1077  pk_ptr,
1079  handle);
1080 }
1081 
1082 
1090 void
1092  const char *url,
1093  void *cls)
1094 {
1095  struct RequestHandle *handle = cls;
1096  struct EgoEntry *ego_entry;
1097  char *keystring;
1098 
1099  keystring = NULL;
1100 
1101  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1102  {
1103  handle->response_code = MHD_HTTP_NOT_FOUND;
1106  return;
1107  }
1108  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1109  ego_entry = get_egoentry (handle, keystring, NULL);
1110 
1111  if (NULL == ego_entry)
1112  {
1113  handle->response_code = MHD_HTTP_NOT_FOUND;
1116  return;
1117  }
1118 
1119  handle->response_code = MHD_HTTP_NO_CONTENT;
1120  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1121  ego_entry->identifier,
1122  &do_finished,
1123  handle);
1124 }
1125 
1126 
1134 void
1136  const char *url,
1137  void *cls)
1138 {
1139  struct RequestHandle *handle = cls;
1140  struct EgoEntry *ego_entry;
1141  char *name;
1142 
1143  name = NULL;
1144 
1145  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1146  {
1147  handle->response_code = MHD_HTTP_NOT_FOUND;
1150  return;
1151  }
1152  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1153  ego_entry = get_egoentry (handle, NULL, name);
1154 
1155  if (NULL == ego_entry)
1156  {
1157  handle->response_code = MHD_HTTP_NOT_FOUND;
1160  return;
1161  }
1162 
1163  handle->response_code = MHD_HTTP_NO_CONTENT;
1164  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1165  ego_entry->identifier,
1166  &do_finished,
1167  handle);
1168 }
1169 
1170 
1178 static void
1180  const char *url,
1181  void *cls)
1182 {
1183  struct MHD_Response *resp;
1184  struct RequestHandle *handle = cls;
1185 
1186  // For now, independent of path return all options
1187  resp = GNUNET_REST_create_response (NULL);
1188  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1189  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1191  return;
1192 }
1193 
1194 
1200 static void
1202 {
1204  static const struct GNUNET_REST_RequestHandler handlers[] =
1205  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1206  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1207  &ego_get_pubkey },
1208  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1209  { MHD_HTTP_METHOD_GET,
1211  &ego_get_subsystem },
1212  { MHD_HTTP_METHOD_PUT,
1214  &ego_edit_pubkey },
1215  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1216  { MHD_HTTP_METHOD_PUT,
1218  &ego_edit_subsystem },
1219  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1220  { MHD_HTTP_METHOD_DELETE,
1222  &ego_delete_pubkey },
1223  { MHD_HTTP_METHOD_DELETE,
1225  &ego_delete_name },
1226  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1228 
1229  if (GNUNET_NO ==
1230  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1231  {
1232  handle->response_code = err.error_code;
1234  }
1235 }
1236 
1237 
1271 static void
1272 init_egos (void *cls,
1273  struct GNUNET_IDENTITY_Ego *ego,
1274  void **ctx,
1275  const char *identifier)
1276 {
1277  struct RequestHandle *handle = cls;
1278  struct EgoEntry *ego_entry;
1279  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1280 
1281  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1282  {
1283  handle->state = ID_REST_STATE_POST_INIT;
1284  init_cont (handle);
1285  return;
1286  }
1287  if (ID_REST_STATE_INIT == handle->state)
1288  {
1289  ego_entry = GNUNET_new (struct EgoEntry);
1292  ego_entry->ego = ego;
1293  ego_entry->identifier = GNUNET_strdup (identifier);
1295  handle->ego_tail,
1296  ego_entry);
1297  return;
1298  }
1299  // Check if ego exists
1300  for (ego_entry = handle->ego_head; NULL != ego_entry;)
1301  {
1302  struct EgoEntry *tmp = ego_entry;
1303  ego_entry = ego_entry->next;
1304  if (ego != tmp->ego)
1305  continue;
1306  // Deleted
1307  if (NULL == identifier)
1308  {
1310  handle->ego_tail,
1311  tmp);
1312  GNUNET_free (tmp->keystring);
1313  GNUNET_free (tmp->identifier);
1314  GNUNET_free (tmp);
1315  }
1316  else
1317  {
1318  // Renamed
1319  GNUNET_free (tmp->identifier);
1320  tmp->identifier = GNUNET_strdup (identifier);
1321  }
1322  return;
1323  }
1324  // New ego
1325  ego_entry = GNUNET_new (struct EgoEntry);
1328  ego_entry->ego = ego;
1329  GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1331  handle->ego_tail,
1332  ego_entry);
1333 
1334 }
1335 
1336 
1348 static void
1351  void *proc_cls)
1352 {
1353  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1354 
1355  handle->response_code = 0;
1357  handle->proc_cls = proc_cls;
1358  handle->proc = proc;
1359  handle->rest_handle = rest_handle;
1360  handle->data = rest_handle->data;
1361  handle->data_size = rest_handle->data_size;
1362 
1363  handle->url = GNUNET_strdup (rest_handle->url);
1364  if (handle->url[strlen (handle->url) - 1] == '/')
1365  handle->url[strlen (handle->url) - 1] = '\0';
1366  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1367 
1368  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
1369 
1370  handle->timeout_task =
1371  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1372 
1373  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1374 }
1375 
1376 
1383 void *
1385 {
1386  static struct Plugin plugin;
1387  struct GNUNET_REST_Plugin *api;
1388 
1389  cfg = cls;
1390  if (NULL != plugin.cfg)
1391  return NULL; /* can only initialize once! */
1392  memset (&plugin, 0, sizeof(struct Plugin));
1393  plugin.cfg = cfg;
1394  api = GNUNET_new (struct GNUNET_REST_Plugin);
1395  api->cls = &plugin;
1399  "%s, %s, %s, %s, %s",
1400  MHD_HTTP_METHOD_GET,
1401  MHD_HTTP_METHOD_POST,
1402  MHD_HTTP_METHOD_PUT,
1403  MHD_HTTP_METHOD_DELETE,
1404  MHD_HTTP_METHOD_OPTIONS);
1405 
1406  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1407  return api;
1408 }
1409 
1410 
1417 void *
1419 {
1420  struct GNUNET_REST_Plugin *api = cls;
1421  struct Plugin *plugin = api->cls;
1422 
1423  plugin->cfg = NULL;
1424 
1426  GNUNET_free (api);
1427  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1428  return NULL;
1429 }
1430 
1431 
1432 /* 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:566
#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 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_CRYPTO_EcdsaPrivateKey pk
Private key from command line option, or NULL.
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:826
#define GNUNET_REST_API_NS_IDENTITY_NAME
Identity Namespace with public key specifier.
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:677
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:595
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create(struct GNUNET_IDENTITY_Handle *h, const char *name, const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls)
Create a new identity with the given name.
Definition: identity_api.c:724
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:632
static void init_cont(struct RequestHandle *handle)
Handle rest request.
static void do_finished(void *cls, const char *emsg)
Processing finished.
#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.
int GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL)...
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:184
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:1269
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.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
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:1296
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:884
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
void ego_edit(struct RequestHandle *handle, struct EgoEntry *ego_entry)
Processing edit ego with EgoEntry ego_entry.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
A 512-bit hashcode.
int response_code
Response code.
int state
The processing state.
static char * plugin
Solver plugin name as string.
char * GNUNET_CRYPTO_ecdsa_private_key_to_string(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
Convert a private key to a string.
Definition: crypto_ecc.c:331
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:232
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
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.
#define GNUNET_REST_IDENTITY_PARAM_PRIVKEY
Parameter private key.
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:773
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.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:608
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:970
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:972
char * url
The url.