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 
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  {
286  GNUNET_SCHEDULER_cancel (handle->timeout_task);
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);
298  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);
325  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
326  "Content-Type",
327  "application/json"));
328  handle->proc (handle->proc_cls, resp, handle->response_code);
329  json_decref (json_error);
332 }
333 
334 
344 struct EgoEntry *
345 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
346 {
347  struct EgoEntry *ego_entry;
348 
349  if (NULL != pubkey)
350  {
351  for (ego_entry = ego_head; NULL != ego_entry;
352  ego_entry = ego_entry->next)
353  {
354  if (0 != strcasecmp (pubkey, ego_entry->keystring))
355  continue;
356  return ego_entry;
357  }
358  }
359  if (NULL != name)
360  {
361  for (ego_entry = ego_head; NULL != ego_entry;
362  ego_entry = ego_entry->next)
363  {
364  if (0 != strcasecmp (name, ego_entry->identifier))
365  continue;
366  return ego_entry;
367  }
368  }
369  return NULL;
370 }
371 
372 
381 static void
383  struct GNUNET_IDENTITY_Ego *ego,
384  void **ctx,
385  const char *name)
386 {
387  struct RequestHandle *handle = cls;
388  struct MHD_Response *resp;
389  struct GNUNET_IDENTITY_PublicKey public_key;
390  json_t *json_root;
391  char *result_str;
392  char *public_key_string;
393 
394  if (NULL == ego)
395  {
396  handle->response_code = MHD_HTTP_NOT_FOUND;
399  return;
400  }
401 
402  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
403  public_key_string = GNUNET_IDENTITY_public_key_to_string (&public_key);
404 
405  // create json with subsystem identity
406  json_root = json_object ();
407  json_object_set_new (json_root,
409  json_string (public_key_string));
410  json_object_set_new (json_root,
412  json_string (name));
413 
414  result_str = json_dumps (json_root, 0);
415  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
416  resp = GNUNET_REST_create_response (result_str);
417  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
418  "Content-Type",
419  "application/json"));
420  json_decref (json_root);
421  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
422  GNUNET_free (result_str);
423  GNUNET_free (public_key_string);
425 }
426 
427 
435 void
437  const char *url,
438  void *cls)
439 {
440  struct RequestHandle *handle = cls;
441  char *subsystem;
442 
443  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
444  {
445  handle->emsg = GNUNET_strdup ("Missing subsystem name");
447  return;
448  }
450  // requested default identity of subsystem
451  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
452 
454  subsystem,
456  handle);
457 
458  if (NULL == handle->op)
459  {
460  handle->response_code = MHD_HTTP_NOT_FOUND;
463  return;
464  }
465 }
466 
467 
475 void
477  const char *url,
478  void *cls)
479 {
480  struct RequestHandle *handle = cls;
481  struct EgoEntry *ego_entry;
482  struct MHD_Response *resp;
483  struct GNUNET_HashCode key;
484  json_t *json_root;
485  json_t *json_ego;
486  char *result_str;
487  char *privkey_str;
488 
489  json_root = json_array ();
490  // Return ego/egos
491  for (ego_entry = ego_head; NULL != ego_entry;
492  ego_entry = ego_entry->next)
493  {
494  json_ego = json_object ();
495  json_object_set_new (json_ego,
497  json_string (ego_entry->keystring));
498  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
499  if (GNUNET_YES ==
501  handle->rest_handle->url_param_map, &key))
502  {
505  json_object_set_new (json_ego,
507  json_string (privkey_str));
508  GNUNET_free (privkey_str);
509  }
510 
511  json_object_set_new (json_ego,
513  json_string (ego_entry->identifier));
514  json_array_append (json_root, json_ego);
515  json_decref (json_ego);
516  }
517 
518  result_str = json_dumps (json_root, 0);
519  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
520  resp = GNUNET_REST_create_response (result_str);
521  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
522  "Content-Type",
523  "application/json"));
524  json_decref (json_root);
525  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
526  GNUNET_free (result_str);
528 }
529 
530 
537 void
538 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
539 {
540  struct MHD_Response *resp;
541  struct GNUNET_HashCode key;
542  json_t *json_ego;
543  char *result_str;
544  char *privkey_str;
545 
546  json_ego = json_object ();
547  json_object_set_new (json_ego,
549  json_string (ego_entry->keystring));
550  json_object_set_new (json_ego,
552  json_string (ego_entry->identifier));
553  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
554  if (GNUNET_YES ==
556  handle->rest_handle->url_param_map, &key))
557  {
560  json_object_set_new (json_ego,
562  json_string (privkey_str));
563  GNUNET_free (privkey_str);
564  }
565 
566  result_str = json_dumps (json_ego, 0);
567  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
568  resp = GNUNET_REST_create_response (result_str);
569  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
570  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
571  "Content-Type",
572  "application/json"));
573  json_decref (json_ego);
574  GNUNET_free (result_str);
576 }
577 
578 
586 void
588  const char *url,
589  void *cls)
590 {
591  struct RequestHandle *handle = cls;
592  struct EgoEntry *ego_entry;
593  char *keystring;
594 
595  keystring = NULL;
596 
597  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
598  {
599  handle->response_code = MHD_HTTP_NOT_FOUND;
602  return;
603  }
605  ego_entry = get_egoentry (handle, keystring, NULL);
606 
607  if (NULL == ego_entry)
608  {
609  handle->response_code = MHD_HTTP_NOT_FOUND;
612  return;
613  }
614 
615  ego_get_response (handle, ego_entry);
616 }
617 
618 
626 void
628  const char *url,
629  void *cls)
630 {
631  struct RequestHandle *handle = cls;
632  struct EgoEntry *ego_entry;
633  char *egoname;
634 
635  egoname = NULL;
636 
637  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
638  {
639  handle->response_code = MHD_HTTP_NOT_FOUND;
642  return;
643  }
644  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
645  ego_entry = get_egoentry (handle, NULL, egoname);
646 
647  if (NULL == ego_entry)
648  {
649  handle->response_code = MHD_HTTP_NOT_FOUND;
652  return;
653  }
654 
655  ego_get_response (handle, ego_entry);
656 }
657 
658 
665 static void
666 do_finished (void *cls, const char *emsg)
667 {
668  struct RequestHandle *handle = cls;
669  struct MHD_Response *resp;
670 
671  handle->op = NULL;
672  if (NULL != emsg)
673  {
674  handle->emsg = GNUNET_strdup (emsg);
676  return;
677  }
678  if (0 == handle->response_code)
679  {
680  handle->response_code = MHD_HTTP_NO_CONTENT;
681  }
682  resp = GNUNET_REST_create_response (NULL);
683  handle->proc (handle->proc_cls, resp, handle->response_code);
685 }
686 
687 
695 static void
697  const struct GNUNET_IDENTITY_PrivateKey *pk,
698  const char *emsg)
699 {
700  struct RequestHandle *handle = cls;
701 
702  (void) pk;
704 }
705 
706 
713 void
715 {
716  struct EgoEntry *ego_entry_tmp;
717  struct MHD_Response *resp;
718  json_t *data_js;
719  json_error_t err;
720  char *newname;
721  char term_data[handle->data_size + 1];
722  int json_state;
723 
724  // if no data
725  if (0 >= handle->data_size)
726  {
729  return;
730  }
731  // if not json
732  term_data[handle->data_size] = '\0';
733  GNUNET_memcpy (term_data, handle->data, handle->data_size);
734  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
735 
736  if (NULL == data_js)
737  {
740  return;
741  }
742 
743  newname = NULL;
744  // NEW NAME
745  json_state = 0;
746  json_state = json_unpack (data_js,
747  "{s:s!}",
749  &newname);
750  // Change name with pubkey or name identifier
751  if (0 != json_state)
752  {
755  json_decref (data_js);
756  return;
757  }
758 
759  if (NULL == newname)
760  {
763  json_decref (data_js);
764  return;
765  }
766 
767  if (0 >= strlen (newname))
768  {
771  json_decref (data_js);
772  return;
773  }
774 
775  ego_entry_tmp = get_egoentry (handle, NULL, newname);
776  if (NULL != ego_entry_tmp)
777  {
778  // Ego with same name not allowed (even if its the ego we change)
779  resp = GNUNET_REST_create_response (NULL);
780  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
782  json_decref (data_js);
783  return;
784  }
786  ego_entry->identifier,
787  newname,
788  &do_finished,
789  handle);
790  if (NULL == handle->op)
791  {
792  handle->emsg = GNUNET_strdup ("Rename failed");
794  json_decref (data_js);
795  return;
796  }
797  json_decref (data_js);
798  return;
799 }
800 
801 
809 void
811  const char *url,
812  void *cls)
813 {
814  struct RequestHandle *handle = cls;
815  struct EgoEntry *ego_entry;
816  char *keystring;
817 
818  keystring = NULL;
819 
820  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
821  {
822  handle->response_code = MHD_HTTP_NOT_FOUND;
825  return;
826  }
828  ego_entry = get_egoentry (handle, keystring, NULL);
829 
830  if (NULL == ego_entry)
831  {
832  handle->response_code = MHD_HTTP_NOT_FOUND;
835  return;
836  }
837 
838  ego_edit (handle, ego_entry);
839 }
840 
841 
849 void
851  const char *url,
852  void *cls)
853 {
854  struct RequestHandle *handle = cls;
855  struct EgoEntry *ego_entry;
856  char *name;
857 
858  name = NULL;
859 
860  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
861  {
862  handle->response_code = MHD_HTTP_NOT_FOUND;
865  return;
866  }
867  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
868  ego_entry = get_egoentry (handle, NULL, name);
869 
870  if (NULL == ego_entry)
871  {
872  handle->response_code = MHD_HTTP_NOT_FOUND;
875  return;
876  }
877 
878  ego_edit (handle, ego_entry);
879 }
880 
881 
889 void
891  const char *url,
892  void *cls)
893 {
894  struct RequestHandle *handle = cls;
895  struct EgoEntry *ego_entry;
896  json_t *data_js;
897  json_error_t err;
898  char *newsubsys;
899  char *name;
900  char term_data[handle->data_size + 1];
901  int json_state;
902 
903  name = NULL;
904 
905  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
906  {
907  handle->response_code = MHD_HTTP_NOT_FOUND;
910  return;
911  }
912  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
913  ego_entry = get_egoentry (handle, NULL, name);
914 
915  if (NULL == ego_entry)
916  {
917  handle->response_code = MHD_HTTP_NOT_FOUND;
920  return;
921  }
922 
923  // if no data
924  if (0 >= handle->data_size)
925  {
928  return;
929  }
930  // if not json
931  term_data[handle->data_size] = '\0';
932  GNUNET_memcpy (term_data, handle->data, handle->data_size);
933  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
934 
935  if (NULL == data_js)
936  {
939  return;
940  }
941 
942  newsubsys = NULL;
943  // SUBSYSTEM
944  json_state = 0;
945  json_state = json_unpack (data_js,
946  "{s:s!}",
948  &newsubsys);
949  // Change subsystem with pubkey or name identifier
950  if (0 != json_state)
951  {
954  json_decref (data_js);
955  return;
956  }
957 
958  if (NULL == newsubsys)
959  {
962  json_decref (data_js);
963  return;
964  }
965 
966  if (0 >= strlen (newsubsys))
967  {
970  json_decref (data_js);
971  return;
972  }
973 
974  handle->response_code = MHD_HTTP_NO_CONTENT;
976  newsubsys,
977  ego_entry->ego,
978  &do_finished,
979  handle);
980  if (NULL == handle->op)
981  {
982  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
984  return;
985  }
986  json_decref (data_js);
987  return;
988 }
989 
990 
998 void
1000  const char *url,
1001  void *cls)
1002 {
1003  struct RequestHandle *handle = cls;
1004  struct EgoEntry *ego_entry;
1005  struct MHD_Response *resp;
1006  json_t *data_js;
1007  json_error_t err;
1008  char *egoname;
1009  char *privkey;
1011  struct GNUNET_IDENTITY_PrivateKey *pk_ptr;
1012  int json_unpack_state;
1013  char term_data[handle->data_size + 1];
1014 
1015  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
1016  {
1018  return;
1019  }
1020 
1021  if (0 >= handle->data_size)
1022  {
1025  return;
1026  }
1027  term_data[handle->data_size] = '\0';
1028  GNUNET_memcpy (term_data, handle->data, handle->data_size);
1029  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
1030  if (NULL == data_js)
1031  {
1034  json_decref (data_js);
1035  return;
1036  }
1037  json_unpack_state = 0;
1038  privkey = NULL;
1039  json_unpack_state =
1040  json_unpack (data_js, "{s:s, s?:s!}",
1043  if (0 != json_unpack_state)
1044  {
1047  json_decref (data_js);
1048  return;
1049  }
1050 
1051  if (NULL == egoname)
1052  {
1055  json_decref (data_js);
1056  return;
1057  }
1058  if (0 >= strlen (egoname))
1059  {
1060  json_decref (data_js);
1063  return;
1064  }
1065  GNUNET_STRINGS_utf8_tolower (egoname, egoname);
1066  for (ego_entry = ego_head; NULL != ego_entry;
1067  ego_entry = ego_entry->next)
1068  {
1069  if (0 == strcasecmp (egoname, ego_entry->identifier))
1070  {
1071  resp = GNUNET_REST_create_response (NULL);
1072  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1074  json_decref (data_js);
1075  return;
1076  }
1077  }
1078  handle->name = GNUNET_strdup (egoname);
1079  if (NULL != privkey)
1080  {
1082  strlen (privkey),
1083  &pk,
1084  sizeof(struct
1086  pk_ptr = &pk;
1087  }
1088  else
1089  pk_ptr = NULL;
1090  json_decref (data_js);
1091  handle->response_code = MHD_HTTP_CREATED;
1093  handle->name,
1094  pk_ptr,
1097  handle);
1098 }
1099 
1100 
1108 void
1110  const char *url,
1111  void *cls)
1112 {
1113  struct RequestHandle *handle = cls;
1114  struct EgoEntry *ego_entry;
1115  char *keystring;
1116 
1117  keystring = NULL;
1118 
1119  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1120  {
1121  handle->response_code = MHD_HTTP_NOT_FOUND;
1124  return;
1125  }
1126  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1127  ego_entry = get_egoentry (handle, keystring, NULL);
1128 
1129  if (NULL == ego_entry)
1130  {
1131  handle->response_code = MHD_HTTP_NOT_FOUND;
1134  return;
1135  }
1136 
1137  handle->response_code = MHD_HTTP_NO_CONTENT;
1139  ego_entry->identifier,
1140  &do_finished,
1141  handle);
1142 }
1143 
1144 
1152 void
1154  const char *url,
1155  void *cls)
1156 {
1157  struct RequestHandle *handle = cls;
1158  struct EgoEntry *ego_entry;
1159  char *name;
1160 
1161  name = NULL;
1162 
1163  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1164  {
1165  handle->response_code = MHD_HTTP_NOT_FOUND;
1168  return;
1169  }
1170  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1171  ego_entry = get_egoentry (handle, NULL, name);
1172 
1173  if (NULL == ego_entry)
1174  {
1175  handle->response_code = MHD_HTTP_NOT_FOUND;
1178  return;
1179  }
1180 
1181  handle->response_code = MHD_HTTP_NO_CONTENT;
1183  ego_entry->identifier,
1184  &do_finished,
1185  handle);
1186 }
1187 
1188 
1196 static void
1198  const char *url,
1199  void *cls)
1200 {
1201  struct MHD_Response *resp;
1202  struct RequestHandle *handle = cls;
1203 
1204  // For now, independent of path return all options
1205  resp = GNUNET_REST_create_response (NULL);
1206  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1207  "Access-Control-Allow-Methods",
1208  allow_methods));
1209  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1211  return;
1212 }
1213 
1214 
1215 static void
1216 list_ego (void *cls,
1217  struct GNUNET_IDENTITY_Ego *ego,
1218  void **ctx,
1219  const char *identifier)
1220 {
1221  struct EgoEntry *ego_entry;
1223 
1224  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1225  {
1227  return;
1228  }
1229  if (NULL == ego)
1230  {
1232  "Called with NULL ego\n");
1233  return;
1234  }
1235  if (ID_REST_STATE_INIT == state)
1236  {
1237  ego_entry = GNUNET_new (struct EgoEntry);
1240  ego_entry->ego = ego;
1241  ego_entry->identifier = GNUNET_strdup (identifier);
1243  ego_tail,
1244  ego_entry);
1245  }
1246  /* Ego renamed or added */
1247  if (identifier != NULL)
1248  {
1249  for (ego_entry = ego_head; NULL != ego_entry;
1250  ego_entry = ego_entry->next)
1251  {
1252  if (ego_entry->ego == ego)
1253  {
1254  /* Rename */
1255  GNUNET_free (ego_entry->identifier);
1256  ego_entry->identifier = GNUNET_strdup (identifier);
1257  break;
1258  }
1259  }
1260  if (NULL == ego_entry)
1261  {
1262  /* Add */
1263  ego_entry = GNUNET_new (struct EgoEntry);
1266  ego_entry->ego = ego;
1267  ego_entry->identifier = GNUNET_strdup (identifier);
1269  ego_tail,
1270  ego_entry);
1271  }
1272  }
1273  else
1274  {
1275  /* Delete */
1276  for (ego_entry = ego_head; NULL != ego_entry;
1277  ego_entry = ego_entry->next)
1278  {
1279  if (ego_entry->ego == ego)
1280  break;
1281  }
1282  if (NULL == ego_entry)
1283  return; /* Not found */
1284 
1286  ego_tail,
1287  ego_entry);
1288  GNUNET_free (ego_entry->identifier);
1289  GNUNET_free (ego_entry->keystring);
1290  GNUNET_free (ego_entry);
1291  return;
1292  }
1293 
1294 }
1295 
1296 
1308 static enum GNUNET_GenericReturnValue
1309 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1311  void *proc_cls)
1312 {
1313  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1315  static const struct GNUNET_REST_RequestHandler handlers[] =
1316  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1317  &ego_get_pubkey },
1318  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1319  { MHD_HTTP_METHOD_GET,
1321  &ego_get_subsystem },
1322  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1323  { MHD_HTTP_METHOD_PUT,
1325  &ego_edit_pubkey },
1326  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1327  { MHD_HTTP_METHOD_PUT,
1329  &ego_edit_subsystem },
1330  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1331  { MHD_HTTP_METHOD_DELETE,
1333  &ego_delete_pubkey },
1334  { MHD_HTTP_METHOD_DELETE,
1336  &ego_delete_name },
1337  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1339 
1340 
1341  handle->response_code = 0;
1343  handle->proc_cls = proc_cls;
1344  handle->proc = proc;
1345  handle->rest_handle = rest_handle;
1346  handle->data = rest_handle->data;
1347  handle->data_size = rest_handle->data_size;
1348 
1349  handle->url = GNUNET_strdup (rest_handle->url);
1350  if (handle->url[strlen (handle->url) - 1] == '/')
1351  handle->url[strlen (handle->url) - 1] = '\0';
1352  handle->timeout_task =
1355  requests_tail,
1356  handle);
1357  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1358  if (GNUNET_NO ==
1359  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1360  {
1362  return GNUNET_NO;
1363  }
1364 
1365  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1366  return GNUNET_YES;
1367 }
1368 
1369 
1376 void *
1378 {
1379  static struct Plugin plugin;
1380  struct GNUNET_REST_Plugin *api;
1381 
1382  cfg = cls;
1383  if (NULL != plugin.cfg)
1384  return NULL; /* can only initialize once! */
1385  memset (&plugin, 0, sizeof(struct Plugin));
1386  plugin.cfg = cfg;
1387  api = GNUNET_new (struct GNUNET_REST_Plugin);
1388  api->cls = &plugin;
1392  "%s, %s, %s, %s, %s",
1393  MHD_HTTP_METHOD_GET,
1394  MHD_HTTP_METHOD_POST,
1395  MHD_HTTP_METHOD_PUT,
1396  MHD_HTTP_METHOD_DELETE,
1397  MHD_HTTP_METHOD_OPTIONS);
1400 
1401  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1402  return api;
1403 }
1404 
1405 
1412 void *
1414 {
1415  struct GNUNET_REST_Plugin *api = cls;
1416  struct Plugin *plugin = api->cls;
1417  struct EgoEntry *ego_entry;
1418  struct EgoEntry *ego_tmp;
1419 
1420  plugin->cfg = NULL;
1421  while (NULL != requests_head)
1423  if (NULL != identity_handle)
1425 
1426  for (ego_entry = ego_head; NULL != ego_entry;)
1427  {
1428  ego_tmp = ego_entry;
1429  ego_entry = ego_entry->next;
1430  GNUNET_free (ego_tmp->identifier);
1431  GNUNET_free (ego_tmp->keystring);
1432  GNUNET_free (ego_tmp);
1433  }
1434 
1436  GNUNET_free (api);
1437  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1438  return NULL;
1439 }
1440 
1441 
1442 /* end of plugin_rest_identity.c */
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
struct Plugin * plugin
The process handle to the testbed service.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
static char * subsystem
Set to subsystem that we're going to get stats for (or NULL for all).
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:92
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
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).
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
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
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_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
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
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
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
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
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
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
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
@ GNUNET_IDENTITY_TYPE_ECDSA
The identity type.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
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(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
#define GNUNET_REST_HANDLER_END
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
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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
enum GNUNET_GenericReturnValue 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:775
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:444
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM
Identity Subsystem Namespace.
static struct EgoEntry * ego_tail
Ego list.
#define GNUNET_REST_IDENTITY_MISSING_NAME
Error message Missing identity name.
#define GNUNET_REST_IDENTITY_PARAM_NAME
Parameter name.
void ego_get_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request with a public key.
#define GNUNET_REST_API_NS_IDENTITY
Identity Namespace.
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_delete_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity DELETE request with public key.
#define GNUNET_REST_IDENTITY_PARAM_PRIVKEY
Parameter private key.
void * libgnunet_plugin_rest_identity_done(void *cls)
Exit point from the plugin.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
static void do_finished(void *cls, const char *emsg)
Processing finished.
#define GNUNET_REST_ERROR_NO_DATA
Error message No data.
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_INIT
State while collecting all egos.
void * libgnunet_plugin_rest_identity_init(void *cls)
Entry point for the plugin.
static struct RequestHandle * requests_head
DLL.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
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.
static int state
The processing state.
static struct EgoEntry * ego_head
Ego list.
#define GNUNET_REST_API_NS_IDENTITY_NAME
Identity Namespace with public key specifier.
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,...
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
static char * allow_methods
HTTP methods allows for this plugin.
void ego_edit(struct RequestHandle *handle, struct EgoEntry *ego_entry)
Processing edit ego with EgoEntry ego_entry.
void ego_edit_subsystem(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity subsystem PUT request with name.
void ego_delete_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity DELETE request with name.
static void ego_get_for_subsystem(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Callback for GET Request with subsystem.
static struct RequestHandle * requests_tail
DLL.
#define GNUNET_REST_IDENTITY_PARAM_NEWNAME
Parameter new name.
void ego_get_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request with a name.
#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM
Parameter subsystem.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
#define GNUNET_REST_IDENTITY_MISSING_PUBKEY
Error message Missing identity name.
void ego_get_response(struct RequestHandle *handle, struct EgoEntry *ego_entry)
Responds with the ego_entry identity.
void ego_get_subsystem(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity GET request for subsystem.
#define GNUNET_REST_ERROR_DATA_INVALID
Error message Data invalid.
void ego_edit_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity PUT request with public key.
static void do_finished_create(void *cls, const struct GNUNET_IDENTITY_PrivateKey *pk, const char *emsg)
Processing finished, when creating an ego.
#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN
Error message Unknown Error.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
#define GNUNET_REST_API_NS_IDENTITY_PUBKEY
Identity Namespace with public key specifier.
#define GNUNET_REST_IDENTITY_PARAM_PUBKEY
Parameter public key.
void ego_create(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity POST request.
#define GNUNET_REST_IDENTITY_NOT_FOUND
Error message No identity found.
static void do_error(void *cls)
Task run on errors.
static void cleanup_handle(void *cls)
Cleanup lookup handle.
The ego list.
char * identifier
Ego Identifier.
struct EgoEntry * prev
DLL.
char * keystring
Public key string.
struct EgoEntry * next
DLL.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
void * cls
Closure for all of the callbacks.
A 512-bit hashcode.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:96
Handle for an operation with the identity service.
Definition: identity_api.c:40
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
struct returned by the initialization function of the plugin
char * name
Plugin name.
void * cls
The closure of the plugin.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
const char * data
The POST data.
const char * url
The url as string.
size_t data_size
The POST data size.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
Entry in list of pending tasks.
Definition: scheduler.c:135
Time for relative time used by GNUnet, in microseconds.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
The request handle.
char * emsg
Error response message.
struct GNUNET_IDENTITY_Operation * op
IDENTITY Operation.
struct RequestHandle * prev
DLL.
size_t data_size
the length of the REST data
int response_code
Response code.
struct EgoEntry * ego_entry
IDENTITY Operation.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
void * proc_cls
The closure of the result processor.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
struct RequestHandle * next
DLL.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
char * name
Name to look up.
char * url
The url.
const char * data
The data from the REST request.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).