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_CRYPTO_EcdsaPublicKey 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_CRYPTO_ecdsa_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_CRYPTO_EcdsaPrivateKey *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;
1003  struct GNUNET_CRYPTO_EcdsaPrivateKey *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,
1088  handle);
1089 }
1090 
1091 
1099 void
1101  const char *url,
1102  void *cls)
1103 {
1104  struct RequestHandle *handle = cls;
1105  struct EgoEntry *ego_entry;
1106  char *keystring;
1107 
1108  keystring = NULL;
1109 
1110  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1111  {
1112  handle->response_code = MHD_HTTP_NOT_FOUND;
1115  return;
1116  }
1117  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1118  ego_entry = get_egoentry (handle, keystring, NULL);
1119 
1120  if (NULL == ego_entry)
1121  {
1122  handle->response_code = MHD_HTTP_NOT_FOUND;
1125  return;
1126  }
1127 
1128  handle->response_code = MHD_HTTP_NO_CONTENT;
1129  handle->op = GNUNET_IDENTITY_delete (identity_handle,
1130  ego_entry->identifier,
1131  &do_finished,
1132  handle);
1133 }
1134 
1135 
1143 void
1145  const char *url,
1146  void *cls)
1147 {
1148  struct RequestHandle *handle = cls;
1149  struct EgoEntry *ego_entry;
1150  char *name;
1151 
1152  name = NULL;
1153 
1154  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1155  {
1156  handle->response_code = MHD_HTTP_NOT_FOUND;
1159  return;
1160  }
1161  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1162  ego_entry = get_egoentry (handle, NULL, name);
1163 
1164  if (NULL == ego_entry)
1165  {
1166  handle->response_code = MHD_HTTP_NOT_FOUND;
1169  return;
1170  }
1171 
1172  handle->response_code = MHD_HTTP_NO_CONTENT;
1173  handle->op = GNUNET_IDENTITY_delete (identity_handle,
1174  ego_entry->identifier,
1175  &do_finished,
1176  handle);
1177 }
1178 
1179 
1187 static void
1189  const char *url,
1190  void *cls)
1191 {
1192  struct MHD_Response *resp;
1193  struct RequestHandle *handle = cls;
1194 
1195  // For now, independent of path return all options
1196  resp = GNUNET_REST_create_response (NULL);
1197  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
1198  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1200  return;
1201 }
1202 
1203 
1204 static void
1205 list_ego (void *cls,
1206  struct GNUNET_IDENTITY_Ego *ego,
1207  void **ctx,
1208  const char *identifier)
1209 {
1210  struct EgoEntry *ego_entry;
1211  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1212 
1213  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1214  {
1216  return;
1217  }
1218  if (ID_REST_STATE_INIT == state)
1219  {
1220  ego_entry = GNUNET_new (struct EgoEntry);
1223  ego_entry->ego = ego;
1224  ego_entry->identifier = GNUNET_strdup (identifier);
1226  ego_tail,
1227  ego_entry);
1228  }
1229  /* Ego renamed or added */
1230  if (identifier != NULL)
1231  {
1232  for (ego_entry = ego_head; NULL != ego_entry;
1233  ego_entry = ego_entry->next)
1234  {
1235  if (ego_entry->ego == ego)
1236  {
1237  /* Rename */
1238  GNUNET_free (ego_entry->identifier);
1239  ego_entry->identifier = GNUNET_strdup (identifier);
1240  break;
1241  }
1242  }
1243  if (NULL == ego_entry)
1244  {
1245  /* Add */
1246  ego_entry = GNUNET_new (struct EgoEntry);
1249  ego_entry->ego = ego;
1250  ego_entry->identifier = GNUNET_strdup (identifier);
1252  ego_tail,
1253  ego_entry);
1254  }
1255  }
1256  else
1257  {
1258  /* Delete */
1259  for (ego_entry = ego_head; NULL != ego_entry;
1260  ego_entry = ego_entry->next)
1261  {
1262  if (ego_entry->ego == ego)
1263  break;
1264  }
1265  if (NULL == ego_entry)
1266  return; /* Not found */
1267 
1268  GNUNET_CONTAINER_DLL_remove (ego_head,
1269  ego_tail,
1270  ego_entry);
1271  GNUNET_free (ego_entry->identifier);
1272  GNUNET_free (ego_entry->keystring);
1273  GNUNET_free (ego_entry);
1274  return;
1275  }
1276 
1277 }
1278 
1279 
1291 static enum GNUNET_GenericReturnValue
1294  void *proc_cls)
1295 {
1296  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1298  static const struct GNUNET_REST_RequestHandler handlers[] =
1299  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1300  &ego_get_pubkey },
1301  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1302  { MHD_HTTP_METHOD_GET,
1304  &ego_get_subsystem },
1305  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1306  { MHD_HTTP_METHOD_PUT,
1308  &ego_edit_pubkey },
1309  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1310  { MHD_HTTP_METHOD_PUT,
1312  &ego_edit_subsystem },
1313  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1314  { MHD_HTTP_METHOD_DELETE,
1316  &ego_delete_pubkey },
1317  { MHD_HTTP_METHOD_DELETE,
1319  &ego_delete_name },
1320  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1322 
1323 
1324  handle->response_code = 0;
1326  handle->proc_cls = proc_cls;
1327  handle->proc = proc;
1328  handle->rest_handle = rest_handle;
1329  handle->data = rest_handle->data;
1330  handle->data_size = rest_handle->data_size;
1331 
1332  handle->url = GNUNET_strdup (rest_handle->url);
1333  if (handle->url[strlen (handle->url) - 1] == '/')
1334  handle->url[strlen (handle->url) - 1] = '\0';
1335  handle->timeout_task =
1336  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1337  GNUNET_CONTAINER_DLL_insert (requests_head,
1338  requests_tail,
1339  handle);
1340  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1341  if (GNUNET_NO ==
1342  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1343  {
1344  cleanup_handle (handle);
1345  return GNUNET_NO;
1346  }
1347 
1348  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1349  return GNUNET_YES;
1350 }
1351 
1352 
1359 void *
1361 {
1362  static struct Plugin plugin;
1363  struct GNUNET_REST_Plugin *api;
1364 
1365  cfg = cls;
1366  if (NULL != plugin.cfg)
1367  return NULL; /* can only initialize once! */
1368  memset (&plugin, 0, sizeof(struct Plugin));
1369  plugin.cfg = cfg;
1370  api = GNUNET_new (struct GNUNET_REST_Plugin);
1371  api->cls = &plugin;
1375  "%s, %s, %s, %s, %s",
1376  MHD_HTTP_METHOD_GET,
1377  MHD_HTTP_METHOD_POST,
1378  MHD_HTTP_METHOD_PUT,
1379  MHD_HTTP_METHOD_DELETE,
1380  MHD_HTTP_METHOD_OPTIONS);
1382  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1383 
1384  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1385  return api;
1386 }
1387 
1388 
1395 void *
1397 {
1398  struct GNUNET_REST_Plugin *api = cls;
1399  struct Plugin *plugin = api->cls;
1400  struct EgoEntry *ego_entry;
1401  struct EgoEntry *ego_tmp;
1402 
1403  plugin->cfg = NULL;
1404  while (NULL != requests_head)
1405  cleanup_handle (requests_head);
1406  if (NULL != identity_handle)
1407  GNUNET_IDENTITY_disconnect (identity_handle);
1408 
1409  for (ego_entry = ego_head; NULL != ego_entry;)
1410  {
1411  ego_tmp = ego_entry;
1412  ego_entry = ego_entry->next;
1413  GNUNET_free (ego_tmp->identifier);
1414  GNUNET_free (ego_tmp->keystring);
1415  GNUNET_free (ego_tmp);
1416  }
1417 
1419  GNUNET_free (api);
1420  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1421  return NULL;
1422 }
1423 
1424 
1425 /* end of plugin_rest_identity.c */
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:566
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void ego_edit_name(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity PUT request with name.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
char * name
Plugin name.
#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM
Parameter subsystem.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
static 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.
#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_CRYPTO_EcdsaPrivateKey pk
Private key from command line option, or NULL.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete(struct GNUNET_IDENTITY_Handle *h, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls)
Delete an existing identity.
Definition: identity_api.c:826
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.
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.
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:677
const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:595
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create(struct GNUNET_IDENTITY_Handle *h, const char *name, const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls)
Create a new identity with the given name.
Definition: identity_api.c:724
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
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct returned by the initialization function of the plugin
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_get(struct GNUNET_IDENTITY_Handle *h, const char *service_name, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Obtain the identity that is currently preferred/default for a service.
Definition: identity_api.c:632
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.
Private ECC key encoded for transmission.
#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)...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void ego_delete_pubkey(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity DELETE request with public key.
void * proc_cls
The closure of the result processor.
#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN
Error message Unknown Error.
Handle for an operation with the identity service.
Definition: identity_api.c:39
#define GNUNET_REST_HANDLER_END
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
The request handle.
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
The ego list.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
Handle for an ego.
Definition: identity.h:245
#define GNUNET_REST_ERROR_DATA_INVALID
Error message Data invalid.
char * name
Name to look up.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
char * emsg
Error response message.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
const char * url
The url as string.
Handle for the service.
Definition: identity_api.c:95
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
char * name
Plugin name.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
#define GNUNET_REST_IDENTITY_MISSING_NAME
Error message Missing identity name.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:884
static void 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.
char * GNUNET_CRYPTO_ecdsa_private_key_to_string(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
Convert a private key to a string.
Definition: crypto_ecc.c:331
char * GNUNET_CRYPTO_ecdsa_public_key_to_string(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:232
const char * data
The POST data.
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.
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.
#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
Handle for a plugin.
Definition: block.c:37
const char * data
The data from the REST request.
#define GNUNET_REST_IDENTITY_PARAM_PRIVKEY
Parameter private key.
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
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
#define GNUNET_REST_API_NS_IDENTITY
Identity Namespace.
static void do_error(void *cls)
Task run on errors.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename(struct GNUNET_IDENTITY_Handle *h, const char *old_name, const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls)
Renames an existing identity.
Definition: identity_api.c:773
struct EgoEntry * prev
DLL.
void ego_create(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle identity POST request.
void * libgnunet_plugin_rest_identity_done(void *cls)
Exit point from the plugin.
struct EgoEntry * ego_entry
IDENTITY Operation.
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.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:608
struct EgoEntry * next
DLL.
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:971
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.