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_ALL "/identity/all"
43 
47 #define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
48 
52 #define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
53 
57 #define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
58 
62 #define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
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  handle->proc (handle->proc_cls, resp, handle->response_code);
318  json_decref (json_error);
319  GNUNET_free (response);
321 }
322 
323 
333 struct EgoEntry *
334 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
335 {
336  struct EgoEntry *ego_entry;
337 
338  if (NULL != pubkey)
339  {
340  for (ego_entry = handle->ego_head; NULL != ego_entry;
341  ego_entry = ego_entry->next)
342  {
343  if (0 != strcasecmp (pubkey, ego_entry->keystring))
344  continue;
345  return ego_entry;
346  }
347  }
348  if (NULL != name)
349  {
350  for (ego_entry = handle->ego_head; NULL != ego_entry;
351  ego_entry = ego_entry->next)
352  {
353  if (0 != strcasecmp (name, ego_entry->identifier))
354  continue;
355  return ego_entry;
356  }
357  }
358  return NULL;
359 }
360 
361 
370 static void
372  struct GNUNET_IDENTITY_Ego *ego,
373  void **ctx,
374  const char *name)
375 {
376  struct RequestHandle *handle = cls;
377  struct MHD_Response *resp;
378  struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
379  json_t *json_root;
380  char *result_str;
381  char *public_key_string;
382 
383  if (NULL == ego)
384  {
385  handle->response_code = MHD_HTTP_NOT_FOUND;
388  return;
389  }
390 
391  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
392  public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (&public_key);
393 
394  // create json with subsystem identity
395  json_root = json_object ();
396  json_object_set_new (json_root,
398  json_string (public_key_string));
399  json_object_set_new (json_root,
401  json_string (name));
402 
403  result_str = json_dumps (json_root, 0);
404  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
405  resp = GNUNET_REST_create_response (result_str);
406 
407  json_decref (json_root);
408  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
409  GNUNET_free (result_str);
410  GNUNET_free (public_key_string);
412 }
413 
414 
422 void
424  const char *url,
425  void *cls)
426 {
427  struct RequestHandle *handle = cls;
428  char *subsystem;
429 
430  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
431  {
432  handle->emsg = GNUNET_strdup ("Missing subsystem name");
434  return;
435  }
436  subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
437  // requested default identity of subsystem
438  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
439 
440  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
441  subsystem,
443  handle);
444 
445  if (NULL == handle->op)
446  {
447  handle->response_code = MHD_HTTP_NOT_FOUND;
450  return;
451  }
452 }
453 
454 
462 void
464  const char *url,
465  void *cls)
466 {
467  struct RequestHandle *handle = cls;
468  struct EgoEntry *ego_entry;
469  struct MHD_Response *resp;
470  json_t *json_root;
471  json_t *json_ego;
472  char *result_str;
473 
474  json_root = json_array ();
475  // Return ego/egos
476  for (ego_entry = handle->ego_head; NULL != ego_entry;
477  ego_entry = ego_entry->next)
478  {
479  json_ego = json_object ();
480  json_object_set_new (json_ego,
482  json_string (ego_entry->keystring));
483  json_object_set_new (json_ego,
485  json_string (ego_entry->identifier));
486  json_array_append (json_root, json_ego);
487  json_decref (json_ego);
488  }
489 
490  result_str = json_dumps (json_root, 0);
491  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
492  resp = GNUNET_REST_create_response (result_str);
493 
494  json_decref (json_root);
495  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
496  GNUNET_free (result_str);
498 }
499 
500 
507 void
508 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
509 {
510  struct MHD_Response *resp;
511  json_t *json_ego;
512  char *result_str;
513 
514  json_ego = json_object ();
515  json_object_set_new (json_ego,
517  json_string (ego_entry->keystring));
518  json_object_set_new (json_ego,
520  json_string (ego_entry->identifier));
521 
522  result_str = json_dumps (json_ego, 0);
523  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
524  resp = GNUNET_REST_create_response (result_str);
525  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
526 
527  json_decref (json_ego);
528  GNUNET_free (result_str);
530 }
531 
532 
540 void
542  const char *url,
543  void *cls)
544 {
545  struct RequestHandle *handle = cls;
546  struct EgoEntry *ego_entry;
547  char *keystring;
548 
549  keystring = NULL;
550 
551  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
552  {
553  handle->response_code = MHD_HTTP_NOT_FOUND;
556  return;
557  }
558  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
559  ego_entry = get_egoentry (handle, keystring, NULL);
560 
561  if (NULL == ego_entry)
562  {
563  handle->response_code = MHD_HTTP_NOT_FOUND;
566  return;
567  }
568 
569  ego_get_response (handle, ego_entry);
570 }
571 
572 
580 void
582  const char *url,
583  void *cls)
584 {
585  struct RequestHandle *handle = cls;
586  struct EgoEntry *ego_entry;
587  char *egoname;
588 
589  egoname = NULL;
590 
591  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
592  {
593  handle->response_code = MHD_HTTP_NOT_FOUND;
596  return;
597  }
598  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
599  ego_entry = get_egoentry (handle, NULL, egoname);
600 
601  if (NULL == ego_entry)
602  {
603  handle->response_code = MHD_HTTP_NOT_FOUND;
606  return;
607  }
608 
609  ego_get_response (handle, ego_entry);
610 }
611 
612 
619 static void
620 do_finished (void *cls, const char *emsg)
621 {
622  struct RequestHandle *handle = cls;
623  struct MHD_Response *resp;
624 
625  handle->op = NULL;
626  if (NULL != emsg)
627  {
628  handle->emsg = GNUNET_strdup (emsg);
630  return;
631  }
632  if (0 == handle->response_code)
633  {
634  handle->response_code = MHD_HTTP_NO_CONTENT;
635  }
636  resp = GNUNET_REST_create_response (NULL);
637  handle->proc (handle->proc_cls, resp, handle->response_code);
639 }
640 
641 
649 static void
651  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
652  const char *emsg)
653 {
654  struct RequestHandle *handle = cls;
655 
656  (void) pk;
657  do_finished (handle, emsg);
658 }
659 
660 
667 void
669 {
670  struct EgoEntry *ego_entry_tmp;
671  struct MHD_Response *resp;
672  json_t *data_js;
673  json_error_t err;
674  char *newname;
675  char term_data[handle->data_size + 1];
676  int json_state;
677 
678  // if no data
679  if (0 >= handle->data_size)
680  {
683  return;
684  }
685  // if not json
686  term_data[handle->data_size] = '\0';
687  GNUNET_memcpy (term_data, handle->data, handle->data_size);
688  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
689 
690  if (NULL == data_js)
691  {
694  return;
695  }
696 
697  newname = NULL;
698  // NEW NAME
699  json_state = 0;
700  json_state = json_unpack (data_js,
701  "{s:s!}",
703  &newname);
704  // Change name with pubkey or name identifier
705  if (0 != json_state)
706  {
709  json_decref (data_js);
710  return;
711  }
712 
713  if (NULL == newname)
714  {
717  json_decref (data_js);
718  return;
719  }
720 
721  if (0 >= strlen (newname))
722  {
725  json_decref (data_js);
726  return;
727  }
728 
729  ego_entry_tmp = get_egoentry (handle, NULL, newname);
730  if (NULL != ego_entry_tmp)
731  {
732  // Ego with same name not allowed (even if its the ego we change)
733  resp = GNUNET_REST_create_response (NULL);
734  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
736  json_decref (data_js);
737  return;
738  }
739  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
740  ego_entry->identifier,
741  newname,
742  &do_finished,
743  handle);
744  if (NULL == handle->op)
745  {
746  handle->emsg = GNUNET_strdup ("Rename failed");
748  json_decref (data_js);
749  return;
750  }
751  json_decref (data_js);
752  return;
753 }
754 
755 
763 void
765  const char *url,
766  void *cls)
767 {
768  struct RequestHandle *handle = cls;
769  struct EgoEntry *ego_entry;
770  char *keystring;
771 
772  keystring = NULL;
773 
774  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
775  {
776  handle->response_code = MHD_HTTP_NOT_FOUND;
779  return;
780  }
781  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
782  ego_entry = get_egoentry (handle, keystring, NULL);
783 
784  if (NULL == ego_entry)
785  {
786  handle->response_code = MHD_HTTP_NOT_FOUND;
789  return;
790  }
791 
792  ego_edit (handle, ego_entry);
793 }
794 
795 
803 void
805  const char *url,
806  void *cls)
807 {
808  struct RequestHandle *handle = cls;
809  struct EgoEntry *ego_entry;
810  char *name;
811 
812  name = NULL;
813 
814  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
815  {
816  handle->response_code = MHD_HTTP_NOT_FOUND;
819  return;
820  }
821  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
822  ego_entry = get_egoentry (handle, NULL, name);
823 
824  if (NULL == ego_entry)
825  {
826  handle->response_code = MHD_HTTP_NOT_FOUND;
829  return;
830  }
831 
832  ego_edit (handle, ego_entry);
833 }
834 
835 
843 void
845  const char *url,
846  void *cls)
847 {
848  struct RequestHandle *handle = cls;
849  struct EgoEntry *ego_entry;
850  json_t *data_js;
851  json_error_t err;
852  char *newsubsys;
853  char *name;
854  char term_data[handle->data_size + 1];
855  int json_state;
856 
857  name = NULL;
858 
859  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
860  {
861  handle->response_code = MHD_HTTP_NOT_FOUND;
864  return;
865  }
866  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
867  ego_entry = get_egoentry (handle, NULL, name);
868 
869  if (NULL == ego_entry)
870  {
871  handle->response_code = MHD_HTTP_NOT_FOUND;
874  return;
875  }
876 
877  // if no data
878  if (0 >= handle->data_size)
879  {
882  return;
883  }
884  // if not json
885  term_data[handle->data_size] = '\0';
886  GNUNET_memcpy (term_data, handle->data, handle->data_size);
887  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
888 
889  if (NULL == data_js)
890  {
893  return;
894  }
895 
896  newsubsys = NULL;
897  // SUBSYSTEM
898  json_state = 0;
899  json_state = json_unpack (data_js,
900  "{s:s!}",
902  &newsubsys);
903  // Change subsystem with pubkey or name identifier
904  if (0 != json_state)
905  {
908  json_decref (data_js);
909  return;
910  }
911 
912  if (NULL == newsubsys)
913  {
916  json_decref (data_js);
917  return;
918  }
919 
920  if (0 >= strlen (newsubsys))
921  {
924  json_decref (data_js);
925  return;
926  }
927 
928  handle->response_code = MHD_HTTP_NO_CONTENT;
929  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
930  newsubsys,
931  ego_entry->ego,
932  &do_finished,
933  handle);
934  if (NULL == handle->op)
935  {
936  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
938  return;
939  }
940  json_decref (data_js);
941  return;
942 }
943 
944 
952 void
954  const char *url,
955  void *cls)
956 {
957  struct RequestHandle *handle = cls;
958  struct EgoEntry *ego_entry;
959  struct MHD_Response *resp;
960  json_t *data_js;
961  json_error_t err;
962  char *egoname;
963  int json_unpack_state;
964  char term_data[handle->data_size + 1];
965 
966  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
967  {
969  return;
970  }
971 
972  if (0 >= handle->data_size)
973  {
976  return;
977  }
978  term_data[handle->data_size] = '\0';
979  GNUNET_memcpy (term_data, handle->data, handle->data_size);
980  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
981  if (NULL == data_js)
982  {
985  json_decref (data_js);
986  return;
987  }
988  json_unpack_state = 0;
989  json_unpack_state =
990  json_unpack (data_js, "{s:s!}", GNUNET_REST_IDENTITY_PARAM_NAME, &egoname);
991  if (0 != json_unpack_state)
992  {
995  json_decref (data_js);
996  return;
997  }
998 
999  if (NULL == egoname)
1000  {
1003  json_decref (data_js);
1004  return;
1005  }
1006  if (0 >= strlen (egoname))
1007  {
1008  json_decref (data_js);
1011  return;
1012  }
1013  GNUNET_STRINGS_utf8_tolower (egoname, egoname);
1014  for (ego_entry = handle->ego_head; NULL != ego_entry;
1015  ego_entry = ego_entry->next)
1016  {
1017  if (0 == strcasecmp (egoname, ego_entry->identifier))
1018  {
1019  resp = GNUNET_REST_create_response (NULL);
1020  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1022  json_decref (data_js);
1023  return;
1024  }
1025  }
1026  handle->name = GNUNET_strdup (egoname);
1027  json_decref (data_js);
1028  handle->response_code = MHD_HTTP_CREATED;
1029  handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
1030  handle->name,
1032  handle);
1033 }
1034 
1035 
1043 void
1045  const char *url,
1046  void *cls)
1047 {
1048  struct RequestHandle *handle = cls;
1049  struct EgoEntry *ego_entry;
1050  char *keystring;
1051 
1052  keystring = NULL;
1053 
1054  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1055  {
1056  handle->response_code = MHD_HTTP_NOT_FOUND;
1059  return;
1060  }
1061  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1062  ego_entry = get_egoentry (handle, keystring, NULL);
1063 
1064  if (NULL == ego_entry)
1065  {
1066  handle->response_code = MHD_HTTP_NOT_FOUND;
1069  return;
1070  }
1071 
1072  handle->response_code = MHD_HTTP_NO_CONTENT;
1073  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1074  ego_entry->identifier,
1075  &do_finished,
1076  handle);
1077 }
1078 
1079 
1087 void
1089  const char *url,
1090  void *cls)
1091 {
1092  struct RequestHandle *handle = cls;
1093  struct EgoEntry *ego_entry;
1094  char *name;
1095 
1096  name = NULL;
1097 
1098  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1099  {
1100  handle->response_code = MHD_HTTP_NOT_FOUND;
1103  return;
1104  }
1105  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1106  ego_entry = get_egoentry (handle, NULL, name);
1107 
1108  if (NULL == ego_entry)
1109  {
1110  handle->response_code = MHD_HTTP_NOT_FOUND;
1113  return;
1114  }
1115 
1116  handle->response_code = MHD_HTTP_NO_CONTENT;
1117  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
1118  ego_entry->identifier,
1119  &do_finished,
1120  handle);
1121 }
1122 
1123 
1131 static void
1133  const char *url,
1134  void *cls)
1135 {
1136  struct MHD_Response *resp;
1137  struct RequestHandle *handle = cls;
1138 
1139  // For now, independent of path return all options
1140  resp = GNUNET_REST_create_response (NULL);
1141  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1142  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1144  return;
1145 }
1146 
1147 
1153 static void
1155 {
1157  static const struct GNUNET_REST_RequestHandler handlers[] =
1158  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ALL, &ego_get_all },
1159  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1160  &ego_get_pubkey },
1161  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1162  { MHD_HTTP_METHOD_GET,
1164  &ego_get_subsystem },
1165  { MHD_HTTP_METHOD_PUT,
1167  &ego_edit_pubkey },
1168  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1169  { MHD_HTTP_METHOD_PUT,
1171  &ego_edit_subsystem },
1172  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1173  { MHD_HTTP_METHOD_DELETE,
1175  &ego_delete_pubkey },
1176  { MHD_HTTP_METHOD_DELETE,
1178  &ego_delete_name },
1179  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1181 
1182  if (GNUNET_NO ==
1183  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1184  {
1185  handle->response_code = err.error_code;
1187  }
1188 }
1189 
1190 
1224 static void
1225 init_egos (void *cls,
1226  struct GNUNET_IDENTITY_Ego *ego,
1227  void **ctx,
1228  const char *identifier)
1229 {
1230  struct RequestHandle *handle = cls;
1231  struct EgoEntry *ego_entry;
1232  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1233 
1234  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1235  {
1236  handle->state = ID_REST_STATE_POST_INIT;
1237  init_cont (handle);
1238  return;
1239  }
1240  if (ID_REST_STATE_INIT == handle->state)
1241  {
1242  ego_entry = GNUNET_new (struct EgoEntry);
1245  ego_entry->ego = ego;
1246  ego_entry->identifier = GNUNET_strdup (identifier);
1248  handle->ego_tail,
1249  ego_entry);
1250  return;
1251  }
1252  // Check if ego exists
1253  for (ego_entry = handle->ego_head; NULL != ego_entry;)
1254  {
1255  struct EgoEntry *tmp = ego_entry;
1256  ego_entry = ego_entry->next;
1257  if (ego != tmp->ego)
1258  continue;
1259  // Deleted
1260  if (NULL == identifier)
1261  {
1263  handle->ego_tail,
1264  tmp);
1265  GNUNET_free (tmp->keystring);
1266  GNUNET_free (tmp->identifier);
1267  GNUNET_free (tmp);
1268  }
1269  else
1270  {
1271  // Renamed
1272  GNUNET_free (tmp->identifier);
1273  tmp->identifier = GNUNET_strdup (identifier);
1274  }
1275  return;
1276  }
1277  // New ego
1278  ego_entry = GNUNET_new (struct EgoEntry);
1281  ego_entry->ego = ego;
1282  GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
1284  handle->ego_tail,
1285  ego_entry);
1286 
1287 }
1288 
1289 
1301 static void
1304  void *proc_cls)
1305 {
1306  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1307 
1308  handle->response_code = 0;
1310  handle->proc_cls = proc_cls;
1311  handle->proc = proc;
1312  handle->rest_handle = rest_handle;
1313  handle->data = rest_handle->data;
1314  handle->data_size = rest_handle->data_size;
1315 
1316  handle->url = GNUNET_strdup (rest_handle->url);
1317  if (handle->url[strlen (handle->url) - 1] == '/')
1318  handle->url[strlen (handle->url) - 1] = '\0';
1319  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1320 
1321  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
1322 
1323  handle->timeout_task =
1324  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1325 
1326  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1327 }
1328 
1329 
1336 void *
1338 {
1339  static struct Plugin plugin;
1340  struct GNUNET_REST_Plugin *api;
1341 
1342  cfg = cls;
1343  if (NULL != plugin.cfg)
1344  return NULL; /* can only initialize once! */
1345  memset (&plugin, 0, sizeof(struct Plugin));
1346  plugin.cfg = cfg;
1347  api = GNUNET_new (struct GNUNET_REST_Plugin);
1348  api->cls = &plugin;
1352  "%s, %s, %s, %s, %s",
1353  MHD_HTTP_METHOD_GET,
1354  MHD_HTTP_METHOD_POST,
1355  MHD_HTTP_METHOD_PUT,
1356  MHD_HTTP_METHOD_DELETE,
1357  MHD_HTTP_METHOD_OPTIONS);
1358 
1359  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1360  return api;
1361 }
1362 
1363 
1370 void *
1372 {
1373  struct GNUNET_REST_Plugin *api = cls;
1374  struct Plugin *plugin = api->cls;
1375 
1376  plugin->cfg = NULL;
1377 
1379  GNUNET_free (api);
1380  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1381  return NULL;
1382 }
1383 
1384 
1385 /* 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_API_NS_IDENTITY_ALL
Identity Namespace with public key specifier.
#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:78
#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:181
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:1253
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:1280
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:332
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:85
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:553
#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:966
char * url
The url.