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 static struct EgoEntry *ego_head;
133 
137 static struct EgoEntry *ego_tail;
138 
142 static int state;
143 
148 
152 struct Plugin
153 {
154  const struct GNUNET_CONFIGURATION_Handle *cfg;
155 };
156 
160 struct EgoEntry
161 {
165  struct EgoEntry *next;
166 
170  struct EgoEntry *prev;
171 
175  char *identifier;
176 
180  char *keystring;
181 
186 };
187 
191 struct RequestHandle
192 {
196  struct RequestHandle *next;
197 
201  struct RequestHandle *prev;
202 
206  const char *data;
207 
211  char *name;
212 
216  size_t data_size;
217 
222 
226  struct GNUNET_REST_RequestHandle *rest_handle;
227 
232 
237 
242 
246  void *proc_cls;
247 
251  char *url;
252 
256  char *emsg;
257 
261  int response_code;
262 };
263 
268 
273 
278 static void
279 cleanup_handle (void *cls)
280 {
281  struct RequestHandle *handle = cls;
282 
283  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
284  if (NULL != handle->timeout_task)
285  {
287  handle->timeout_task = NULL;
288  }
289 
290  if (NULL != handle->url)
291  GNUNET_free (handle->url);
292  if (NULL != handle->emsg)
293  GNUNET_free (handle->emsg);
294  if (NULL != handle->name)
295  GNUNET_free (handle->name);
296  GNUNET_CONTAINER_DLL_remove (requests_head,
297  requests_tail,
298  handle);
299  GNUNET_free (handle);
300 }
301 
302 
308 static void
309 do_error (void *cls)
310 {
311  struct RequestHandle *handle = cls;
312  struct MHD_Response *resp;
313  json_t *json_error = json_object ();
314  char *response;
315 
316  if (NULL == handle->emsg)
318 
319  json_object_set_new (json_error, "error", json_string (handle->emsg));
320 
321  if (0 == handle->response_code)
322  handle->response_code = MHD_HTTP_OK;
323  response = json_dumps (json_error, 0);
324  resp = GNUNET_REST_create_response (response);
325  MHD_add_response_header (resp, "Content-Type", "application/json");
326  handle->proc (handle->proc_cls, resp, handle->response_code);
327  json_decref (json_error);
328  GNUNET_free (response);
330 }
331 
332 
342 struct EgoEntry *
343 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
344 {
345  struct EgoEntry *ego_entry;
346 
347  if (NULL != pubkey)
348  {
349  for (ego_entry = ego_head; NULL != ego_entry;
350  ego_entry = ego_entry->next)
351  {
352  if (0 != strcasecmp (pubkey, ego_entry->keystring))
353  continue;
354  return ego_entry;
355  }
356  }
357  if (NULL != name)
358  {
359  for (ego_entry = ego_head; NULL != ego_entry;
360  ego_entry = ego_entry->next)
361  {
362  if (0 != strcasecmp (name, ego_entry->identifier))
363  continue;
364  return ego_entry;
365  }
366  }
367  return NULL;
368 }
369 
370 
379 static void
381  struct GNUNET_IDENTITY_Ego *ego,
382  void **ctx,
383  const char *name)
384 {
385  struct RequestHandle *handle = cls;
386  struct MHD_Response *resp;
387  struct GNUNET_IDENTITY_PublicKey public_key;
388  json_t *json_root;
389  char *result_str;
390  char *public_key_string;
391 
392  if (NULL == ego)
393  {
394  handle->response_code = MHD_HTTP_NOT_FOUND;
397  return;
398  }
399 
400  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
401  public_key_string = GNUNET_IDENTITY_public_key_to_string (&public_key);
402 
403  // create json with subsystem identity
404  json_root = json_object ();
405  json_object_set_new (json_root,
407  json_string (public_key_string));
408  json_object_set_new (json_root,
410  json_string (name));
411 
412  result_str = json_dumps (json_root, 0);
413  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
414  resp = GNUNET_REST_create_response (result_str);
415  MHD_add_response_header (resp, "Content-Type", "application/json");
416  json_decref (json_root);
417  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
418  GNUNET_free (result_str);
419  GNUNET_free (public_key_string);
421 }
422 
423 
431 void
433  const char *url,
434  void *cls)
435 {
436  struct RequestHandle *handle = cls;
437  char *subsystem;
438 
439  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
440  {
441  handle->emsg = GNUNET_strdup ("Missing subsystem name");
443  return;
444  }
445  subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
446  // requested default identity of subsystem
447  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
448 
449  handle->op = GNUNET_IDENTITY_get (identity_handle,
450  subsystem,
452  handle);
453 
454  if (NULL == handle->op)
455  {
456  handle->response_code = MHD_HTTP_NOT_FOUND;
459  return;
460  }
461 }
462 
463 
471 void
473  const char *url,
474  void *cls)
475 {
476  struct RequestHandle *handle = cls;
477  struct EgoEntry *ego_entry;
478  struct MHD_Response *resp;
479  struct GNUNET_HashCode key;
480  json_t *json_root;
481  json_t *json_ego;
482  char *result_str;
483  char *privkey_str;
484 
485  json_root = json_array ();
486  // Return ego/egos
487  for (ego_entry = ego_head; NULL != ego_entry;
488  ego_entry = ego_entry->next)
489  {
490  json_ego = json_object ();
491  json_object_set_new (json_ego,
493  json_string (ego_entry->keystring));
494  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
495  if (GNUNET_YES ==
497  handle->rest_handle->url_param_map, &key))
498  {
501  json_object_set_new (json_ego,
503  json_string (privkey_str));
504  GNUNET_free (privkey_str);
505  }
506 
507  json_object_set_new (json_ego,
509  json_string (ego_entry->identifier));
510  json_array_append (json_root, json_ego);
511  json_decref (json_ego);
512  }
513 
514  result_str = json_dumps (json_root, 0);
515  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
516  resp = GNUNET_REST_create_response (result_str);
517  MHD_add_response_header (resp, "Content-Type", "application/json");
518  json_decref (json_root);
519  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
520  GNUNET_free (result_str);
522 }
523 
524 
531 void
532 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
533 {
534  struct MHD_Response *resp;
535  struct GNUNET_HashCode key;
536  json_t *json_ego;
537  char *result_str;
538  char *privkey_str;
539 
540  json_ego = json_object ();
541  json_object_set_new (json_ego,
543  json_string (ego_entry->keystring));
544  json_object_set_new (json_ego,
546  json_string (ego_entry->identifier));
547  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
548  if (GNUNET_YES ==
550  handle->rest_handle->url_param_map, &key))
551  {
554  json_object_set_new (json_ego,
556  json_string (privkey_str));
557  GNUNET_free (privkey_str);
558  }
559 
560  result_str = json_dumps (json_ego, 0);
561  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
562  resp = GNUNET_REST_create_response (result_str);
563  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
564  MHD_add_response_header (resp, "Content-Type", "application/json");
565  json_decref (json_ego);
566  GNUNET_free (result_str);
568 }
569 
570 
578 void
580  const char *url,
581  void *cls)
582 {
583  struct RequestHandle *handle = cls;
584  struct EgoEntry *ego_entry;
585  char *keystring;
586 
587  keystring = NULL;
588 
589  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
590  {
591  handle->response_code = MHD_HTTP_NOT_FOUND;
594  return;
595  }
596  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
597  ego_entry = get_egoentry (handle, keystring, NULL);
598 
599  if (NULL == ego_entry)
600  {
601  handle->response_code = MHD_HTTP_NOT_FOUND;
604  return;
605  }
606 
607  ego_get_response (handle, ego_entry);
608 }
609 
610 
618 void
620  const char *url,
621  void *cls)
622 {
623  struct RequestHandle *handle = cls;
624  struct EgoEntry *ego_entry;
625  char *egoname;
626 
627  egoname = NULL;
628 
629  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
630  {
631  handle->response_code = MHD_HTTP_NOT_FOUND;
634  return;
635  }
636  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
637  ego_entry = get_egoentry (handle, NULL, egoname);
638 
639  if (NULL == ego_entry)
640  {
641  handle->response_code = MHD_HTTP_NOT_FOUND;
644  return;
645  }
646 
647  ego_get_response (handle, ego_entry);
648 }
649 
650 
657 static void
658 do_finished (void *cls, const char *emsg)
659 {
660  struct RequestHandle *handle = cls;
661  struct MHD_Response *resp;
662 
663  handle->op = NULL;
664  if (NULL != emsg)
665  {
666  handle->emsg = GNUNET_strdup (emsg);
668  return;
669  }
670  if (0 == handle->response_code)
671  {
672  handle->response_code = MHD_HTTP_NO_CONTENT;
673  }
674  resp = GNUNET_REST_create_response (NULL);
675  handle->proc (handle->proc_cls, resp, handle->response_code);
677 }
678 
679 
687 static void
689  const struct GNUNET_IDENTITY_PrivateKey *pk,
690  const char *emsg)
691 {
692  struct RequestHandle *handle = cls;
693 
694  (void) pk;
695  do_finished (handle, emsg);
696 }
697 
698 
705 void
707 {
708  struct EgoEntry *ego_entry_tmp;
709  struct MHD_Response *resp;
710  json_t *data_js;
711  json_error_t err;
712  char *newname;
713  char term_data[handle->data_size + 1];
714  int json_state;
715 
716  // if no data
717  if (0 >= handle->data_size)
718  {
721  return;
722  }
723  // if not json
724  term_data[handle->data_size] = '\0';
725  GNUNET_memcpy (term_data, handle->data, handle->data_size);
726  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
727 
728  if (NULL == data_js)
729  {
732  return;
733  }
734 
735  newname = NULL;
736  // NEW NAME
737  json_state = 0;
738  json_state = json_unpack (data_js,
739  "{s:s!}",
741  &newname);
742  // Change name with pubkey or name identifier
743  if (0 != json_state)
744  {
747  json_decref (data_js);
748  return;
749  }
750 
751  if (NULL == newname)
752  {
755  json_decref (data_js);
756  return;
757  }
758 
759  if (0 >= strlen (newname))
760  {
763  json_decref (data_js);
764  return;
765  }
766 
767  ego_entry_tmp = get_egoentry (handle, NULL, newname);
768  if (NULL != ego_entry_tmp)
769  {
770  // Ego with same name not allowed (even if its the ego we change)
771  resp = GNUNET_REST_create_response (NULL);
772  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
774  json_decref (data_js);
775  return;
776  }
777  handle->op = GNUNET_IDENTITY_rename (identity_handle,
778  ego_entry->identifier,
779  newname,
780  &do_finished,
781  handle);
782  if (NULL == handle->op)
783  {
784  handle->emsg = GNUNET_strdup ("Rename failed");
786  json_decref (data_js);
787  return;
788  }
789  json_decref (data_js);
790  return;
791 }
792 
793 
801 void
803  const char *url,
804  void *cls)
805 {
806  struct RequestHandle *handle = cls;
807  struct EgoEntry *ego_entry;
808  char *keystring;
809 
810  keystring = NULL;
811 
812  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
813  {
814  handle->response_code = MHD_HTTP_NOT_FOUND;
817  return;
818  }
819  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
820  ego_entry = get_egoentry (handle, keystring, NULL);
821 
822  if (NULL == ego_entry)
823  {
824  handle->response_code = MHD_HTTP_NOT_FOUND;
827  return;
828  }
829 
830  ego_edit (handle, ego_entry);
831 }
832 
833 
841 void
843  const char *url,
844  void *cls)
845 {
846  struct RequestHandle *handle = cls;
847  struct EgoEntry *ego_entry;
848  char *name;
849 
850  name = NULL;
851 
852  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
853  {
854  handle->response_code = MHD_HTTP_NOT_FOUND;
857  return;
858  }
859  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
860  ego_entry = get_egoentry (handle, NULL, name);
861 
862  if (NULL == ego_entry)
863  {
864  handle->response_code = MHD_HTTP_NOT_FOUND;
867  return;
868  }
869 
870  ego_edit (handle, ego_entry);
871 }
872 
873 
881 void
883  const char *url,
884  void *cls)
885 {
886  struct RequestHandle *handle = cls;
887  struct EgoEntry *ego_entry;
888  json_t *data_js;
889  json_error_t err;
890  char *newsubsys;
891  char *name;
892  char term_data[handle->data_size + 1];
893  int json_state;
894 
895  name = NULL;
896 
897  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
898  {
899  handle->response_code = MHD_HTTP_NOT_FOUND;
902  return;
903  }
904  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
905  ego_entry = get_egoentry (handle, NULL, name);
906 
907  if (NULL == ego_entry)
908  {
909  handle->response_code = MHD_HTTP_NOT_FOUND;
912  return;
913  }
914 
915  // if no data
916  if (0 >= handle->data_size)
917  {
920  return;
921  }
922  // if not json
923  term_data[handle->data_size] = '\0';
924  GNUNET_memcpy (term_data, handle->data, handle->data_size);
925  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
926 
927  if (NULL == data_js)
928  {
931  return;
932  }
933 
934  newsubsys = NULL;
935  // SUBSYSTEM
936  json_state = 0;
937  json_state = json_unpack (data_js,
938  "{s:s!}",
940  &newsubsys);
941  // Change subsystem with pubkey or name identifier
942  if (0 != json_state)
943  {
946  json_decref (data_js);
947  return;
948  }
949 
950  if (NULL == newsubsys)
951  {
954  json_decref (data_js);
955  return;
956  }
957 
958  if (0 >= strlen (newsubsys))
959  {
962  json_decref (data_js);
963  return;
964  }
965 
966  handle->response_code = MHD_HTTP_NO_CONTENT;
967  handle->op = GNUNET_IDENTITY_set (identity_handle,
968  newsubsys,
969  ego_entry->ego,
970  &do_finished,
971  handle);
972  if (NULL == handle->op)
973  {
974  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
976  return;
977  }
978  json_decref (data_js);
979  return;
980 }
981 
982 
990 void
992  const char *url,
993  void *cls)
994 {
995  struct RequestHandle *handle = cls;
996  struct EgoEntry *ego_entry;
997  struct MHD_Response *resp;
998  json_t *data_js;
999  json_error_t err;
1000  char *egoname;
1001  char *privkey;
1002  struct GNUNET_IDENTITY_PrivateKey pk;
1003  struct GNUNET_IDENTITY_PrivateKey *pk_ptr;
1004  int json_unpack_state;
1005  char term_data[handle->data_size + 1];
1006 
1007  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
1008  {
1010  return;
1011  }
1012 
1013  if (0 >= handle->data_size)
1014  {
1017  return;
1018  }
1019  term_data[handle->data_size] = '\0';
1020  GNUNET_memcpy (term_data, handle->data, handle->data_size);
1021  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
1022  if (NULL == data_js)
1023  {
1026  json_decref (data_js);
1027  return;
1028  }
1029  json_unpack_state = 0;
1030  privkey = NULL;
1031  json_unpack_state =
1032  json_unpack (data_js, "{s:s, s?:s!}",
1035  if (0 != json_unpack_state)
1036  {
1039  json_decref (data_js);
1040  return;
1041  }
1042 
1043  if (NULL == egoname)
1044  {
1047  json_decref (data_js);
1048  return;
1049  }
1050  if (0 >= strlen (egoname))
1051  {
1052  json_decref (data_js);
1055  return;
1056  }
1057  GNUNET_STRINGS_utf8_tolower (egoname, egoname);
1058  for (ego_entry = ego_head; NULL != ego_entry;
1059  ego_entry = ego_entry->next)
1060  {
1061  if (0 == strcasecmp (egoname, ego_entry->identifier))
1062  {
1063  resp = GNUNET_REST_create_response (NULL);
1064  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1066  json_decref (data_js);
1067  return;
1068  }
1069  }
1070  handle->name = GNUNET_strdup (egoname);
1071  if (NULL != privkey)
1072  {
1074  strlen (privkey),
1075  &pk,
1076  sizeof(struct
1078  pk_ptr = &pk;
1079  }
1080  else
1081  pk_ptr = NULL;
1082  json_decref (data_js);
1083  handle->response_code = MHD_HTTP_CREATED;
1084  handle->op = GNUNET_IDENTITY_create (identity_handle,
1085  handle->name,
1086  pk_ptr,
1089  handle);
1090 }
1091 
1092 
1100 void
1102  const char *url,
1103  void *cls)
1104 {
1105  struct RequestHandle *handle = cls;
1106  struct EgoEntry *ego_entry;
1107  char *keystring;
1108 
1109  keystring = NULL;
1110 
1111  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1112  {
1113  handle->response_code = MHD_HTTP_NOT_FOUND;
1116  return;
1117  }
1118  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1119  ego_entry = get_egoentry (handle, keystring, NULL);
1120 
1121  if (NULL == ego_entry)
1122  {
1123  handle->response_code = MHD_HTTP_NOT_FOUND;
1126  return;
1127  }
1128 
1129  handle->response_code = MHD_HTTP_NO_CONTENT;
1130  handle->op = GNUNET_IDENTITY_delete (identity_handle,
1131  ego_entry->identifier,
1132  &do_finished,
1133  handle);
1134 }
1135 
1136 
1144 void
1146  const char *url,
1147  void *cls)
1148 {
1149  struct RequestHandle *handle = cls;
1150  struct EgoEntry *ego_entry;
1151  char *name;
1152 
1153  name = NULL;
1154 
1155  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1156  {
1157  handle->response_code = MHD_HTTP_NOT_FOUND;
1160  return;
1161  }
1162  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1163  ego_entry = get_egoentry (handle, NULL, name);
1164 
1165  if (NULL == ego_entry)
1166  {
1167  handle->response_code = MHD_HTTP_NOT_FOUND;
1170  return;
1171  }
1172 
1173  handle->response_code = MHD_HTTP_NO_CONTENT;
1174  handle->op = GNUNET_IDENTITY_delete (identity_handle,
1175  ego_entry->identifier,
1176  &do_finished,
1177  handle);
1178 }
1179 
1180 
1188 static void
1190  const char *url,
1191  void *cls)
1192 {
1193  struct MHD_Response *resp;
1194  struct RequestHandle *handle = cls;
1195 
1196  // For now, independent of path return all options
1197  resp = GNUNET_REST_create_response (NULL);
1198  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1199  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1201  return;
1202 }
1203 
1204 
1205 static void
1206 list_ego (void *cls,
1207  struct GNUNET_IDENTITY_Ego *ego,
1208  void **ctx,
1209  const char *identifier)
1210 {
1211  struct EgoEntry *ego_entry;
1212  struct GNUNET_IDENTITY_PublicKey pk;
1213 
1214  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1215  {
1217  return;
1218  }
1219  if (ID_REST_STATE_INIT == state)
1220  {
1221  ego_entry = GNUNET_new (struct EgoEntry);
1224  ego_entry->ego = ego;
1225  ego_entry->identifier = GNUNET_strdup (identifier);
1227  ego_tail,
1228  ego_entry);
1229  }
1230  /* Ego renamed or added */
1231  if (identifier != NULL)
1232  {
1233  for (ego_entry = ego_head; NULL != ego_entry;
1234  ego_entry = ego_entry->next)
1235  {
1236  if (ego_entry->ego == ego)
1237  {
1238  /* Rename */
1239  GNUNET_free (ego_entry->identifier);
1240  ego_entry->identifier = GNUNET_strdup (identifier);
1241  break;
1242  }
1243  }
1244  if (NULL == ego_entry)
1245  {
1246  /* Add */
1247  ego_entry = GNUNET_new (struct EgoEntry);
1250  ego_entry->ego = ego;
1251  ego_entry->identifier = GNUNET_strdup (identifier);
1253  ego_tail,
1254  ego_entry);
1255  }
1256  }
1257  else
1258  {
1259  /* Delete */
1260  for (ego_entry = ego_head; NULL != ego_entry;
1261  ego_entry = ego_entry->next)
1262  {
1263  if (ego_entry->ego == ego)
1264  break;
1265  }
1266  if (NULL == ego_entry)
1267  return; /* Not found */
1268 
1269  GNUNET_CONTAINER_DLL_remove (ego_head,
1270  ego_tail,
1271  ego_entry);
1272  GNUNET_free (ego_entry->identifier);
1273  GNUNET_free (ego_entry->keystring);
1274  GNUNET_free (ego_entry);
1275  return;
1276  }
1277 
1278 }
1279 
1280 
1292 static enum GNUNET_GenericReturnValue
1295  void *proc_cls)
1296 {
1297  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1299  static const struct GNUNET_REST_RequestHandler handlers[] =
1300  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1301  &ego_get_pubkey },
1302  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1303  { MHD_HTTP_METHOD_GET,
1305  &ego_get_subsystem },
1306  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1307  { MHD_HTTP_METHOD_PUT,
1309  &ego_edit_pubkey },
1310  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1311  { MHD_HTTP_METHOD_PUT,
1313  &ego_edit_subsystem },
1314  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1315  { MHD_HTTP_METHOD_DELETE,
1317  &ego_delete_pubkey },
1318  { MHD_HTTP_METHOD_DELETE,
1320  &ego_delete_name },
1321  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1323 
1324 
1325  handle->response_code = 0;
1327  handle->proc_cls = proc_cls;
1328  handle->proc = proc;
1329  handle->rest_handle = rest_handle;
1330  handle->data = rest_handle->data;
1331  handle->data_size = rest_handle->data_size;
1332 
1333  handle->url = GNUNET_strdup (rest_handle->url);
1334  if (handle->url[strlen (handle->url) - 1] == '/')
1335  handle->url[strlen (handle->url) - 1] = '\0';
1336  handle->timeout_task =
1337  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1338  GNUNET_CONTAINER_DLL_insert (requests_head,
1339  requests_tail,
1340  handle);
1341  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1342  if (GNUNET_NO ==
1343  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1344  {
1345  cleanup_handle (handle);
1346  return GNUNET_NO;
1347  }
1348 
1349  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1350  return GNUNET_YES;
1351 }
1352 
1353 
1360 void *
1362 {
1363  static struct Plugin plugin;
1364  struct GNUNET_REST_Plugin *api;
1365 
1366  cfg = cls;
1367  if (NULL != plugin.cfg)
1368  return NULL; /* can only initialize once! */
1369  memset (&plugin, 0, sizeof(struct Plugin));
1370  plugin.cfg = cfg;
1371  api = GNUNET_new (struct GNUNET_REST_Plugin);
1372  api->cls = &plugin;
1376  "%s, %s, %s, %s, %s",
1377  MHD_HTTP_METHOD_GET,
1378  MHD_HTTP_METHOD_POST,
1379  MHD_HTTP_METHOD_PUT,
1380  MHD_HTTP_METHOD_DELETE,
1381  MHD_HTTP_METHOD_OPTIONS);
1383  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1384 
1385  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1386  return api;
1387 }
1388 
1389 
1396 void *
1398 {
1399  struct GNUNET_REST_Plugin *api = cls;
1400  struct Plugin *plugin = api->cls;
1401  struct EgoEntry *ego_entry;
1402  struct EgoEntry *ego_tmp;
1403 
1404  plugin->cfg = NULL;
1405  while (NULL != requests_head)
1406  cleanup_handle (requests_head);
1407  if (NULL != identity_handle)
1408  GNUNET_IDENTITY_disconnect (identity_handle);
1409 
1410  for (ego_entry = ego_head; NULL != ego_entry;)
1411  {
1412  ego_tmp = ego_entry;
1413  ego_entry = ego_entry->next;
1414  GNUNET_free (ego_tmp->identifier);
1415  GNUNET_free (ego_tmp->keystring);
1416  GNUNET_free (ego_tmp);
1417  }
1418 
1420  GNUNET_free (api);
1421  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1422  return NULL;
1423 }
1424 
1425 
1426 /* 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:610
#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 char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#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:863
static struct EgoEntry * ego_head
Ego list.
#define GNUNET_REST_API_NS_IDENTITY_NAME
Identity Namespace with public key specifier.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
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.
static struct EgoEntry * ego_tail
Ego list.
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:720
static enum GNUNET_GenericReturnValue rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
size_t data_size
the length of the REST data
A private key for an identity as per LSD0001.
#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:675
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
static void do_finished(void *cls, const char *emsg)
Processing finished.
static struct RequestHandle * requests_head
DLL.
static struct RequestHandle * requests_tail
DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_REST_API_NS_IDENTITY_PUBKEY
Identity Namespace with public key specifier.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
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 GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:652
#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.
char * GNUNET_IDENTITY_private_key_to_string(const struct GNUNET_IDENTITY_PrivateKey *key)
Creates a (Base32) string representation of the private key.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
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:36
#define GNUNET_REST_ERROR_DATA_INVALID
Error message Data invalid.
char * name
Name to look up.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create(struct GNUNET_IDENTITY_Handle *h, const char *name, const struct GNUNET_IDENTITY_PrivateKey *privkey, enum GNUNET_IDENTITY_KeyType ktype, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls)
Create a new ego with the given name.
Definition: identity_api.c:757
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_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
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:921
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
#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.
static char * plugin
Solver plugin name as string.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
const char * data
The POST data.
struct RequestHandle * next
DLL.
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.
static void do_finished_create(void *cls, const struct GNUNET_IDENTITY_PrivateKey *pk, const char *emsg)
Processing finished, when creating an ego.
void ego_get_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request with a name.
struct RequestHandle * prev
DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
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.
An identity key as per LSD0001.
#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 GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
Handle for a plugin.
Definition: block.c:37
const char * data
The data from the REST request.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
#define GNUNET_REST_IDENTITY_PARAM_PRIVKEY
Parameter private key.
static int state
The processing state.
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
#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:810
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.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
#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.
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:972
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_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:568
#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.