GNUnet  0.17.6
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 "identity.h"
32 #include "gnunet_crypto_lib.h"
33 #include "microhttpd.h"
34 #include <jansson.h>
35 
39 #define GNUNET_REST_API_NS_IDENTITY "/identity"
40 
44 #define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
45 
49 #define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
50 
54 #define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
55 
59 #define GNUNET_REST_API_NS_SIGN "/sign"
60 
64 #define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
65 
69 #define GNUNET_REST_IDENTITY_PARAM_PRIVKEY "privkey"
70 
74 #define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
75 
79 #define GNUNET_REST_IDENTITY_PARAM_NAME "name"
80 
84 #define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
85 
89 #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
90 
94 #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
95 
99 #define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
100 
104 #define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
105 
109 #define GNUNET_REST_ERROR_NO_DATA "No data"
110 
114 #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
115 
119 #define ID_REST_STATE_INIT 0
120 
124 #define ID_REST_STATE_POST_INIT 1
125 
130 
134 static char *allow_methods;
135 
139 static struct EgoEntry *ego_head;
140 
144 static struct EgoEntry *ego_tail;
145 
149 static int state;
150 
155 
159 struct Plugin
160 {
161  const struct GNUNET_CONFIGURATION_Handle *cfg;
162 };
163 
167 struct EgoEntry
168 {
172  struct EgoEntry *next;
173 
177  struct EgoEntry *prev;
178 
182  char *identifier;
183 
187  char *keystring;
188 
193 };
194 
198 struct RequestHandle
199 {
203  struct RequestHandle *next;
204 
208  struct RequestHandle *prev;
209 
213  const char *data;
214 
218  char *name;
219 
223  size_t data_size;
224 
229 
234 
239 
244 
249 
253  void *proc_cls;
254 
258  char *url;
259 
263  char *emsg;
264 
268  int response_code;
269 };
270 
275 
280 
285 static void
286 cleanup_handle (void *cls)
287 {
288  struct RequestHandle *handle = cls;
289 
290  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
291  if (NULL != handle->timeout_task)
292  {
293  GNUNET_SCHEDULER_cancel (handle->timeout_task);
294  handle->timeout_task = NULL;
295  }
296 
297  if (NULL != handle->url)
298  GNUNET_free (handle->url);
299  if (NULL != handle->emsg)
300  GNUNET_free (handle->emsg);
301  if (NULL != handle->name)
302  GNUNET_free (handle->name);
305  handle);
307 }
308 
309 
315 static void
316 do_error (void *cls)
317 {
318  struct RequestHandle *handle = cls;
319  struct MHD_Response *resp;
320  json_t *json_error = json_object ();
321  char *response;
322 
323  if (NULL == handle->emsg)
325 
326  json_object_set_new (json_error, "error", json_string (handle->emsg));
327 
328  if (0 == handle->response_code)
329  handle->response_code = MHD_HTTP_OK;
330  response = json_dumps (json_error, 0);
332  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
333  "Content-Type",
334  "application/json"));
335  handle->proc (handle->proc_cls, resp, handle->response_code);
336  json_decref (json_error);
339 }
340 
341 
351 struct EgoEntry *
352 get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
353 {
354  struct EgoEntry *ego_entry;
355 
356  if (NULL != pubkey)
357  {
358  for (ego_entry = ego_head; NULL != ego_entry;
359  ego_entry = ego_entry->next)
360  {
361  if (0 != strcasecmp (pubkey, ego_entry->keystring))
362  continue;
363  return ego_entry;
364  }
365  }
366  if (NULL != name)
367  {
368  for (ego_entry = ego_head; NULL != ego_entry;
369  ego_entry = ego_entry->next)
370  {
371  if (0 != strcasecmp (name, ego_entry->identifier))
372  continue;
373  return ego_entry;
374  }
375  }
376  return NULL;
377 }
378 
379 
388 static void
390  struct GNUNET_IDENTITY_Ego *ego,
391  void **ctx,
392  const char *name)
393 {
394  struct RequestHandle *handle = cls;
395  struct MHD_Response *resp;
396  struct GNUNET_IDENTITY_PublicKey public_key;
397  json_t *json_root;
398  char *result_str;
399  char *public_key_string;
400 
401  if (NULL == ego)
402  {
403  handle->response_code = MHD_HTTP_NOT_FOUND;
406  return;
407  }
408 
409  GNUNET_IDENTITY_ego_get_public_key (ego, &public_key);
410  public_key_string = GNUNET_IDENTITY_public_key_to_string (&public_key);
411 
412  // create json with subsystem identity
413  json_root = json_object ();
414  json_object_set_new (json_root,
416  json_string (public_key_string));
417  json_object_set_new (json_root,
419  json_string (name));
420 
421  result_str = json_dumps (json_root, 0);
422  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
423  resp = GNUNET_REST_create_response (result_str);
424  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
425  "Content-Type",
426  "application/json"));
427  json_decref (json_root);
428  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
429  GNUNET_free (result_str);
430  GNUNET_free (public_key_string);
432 }
433 
434 
442 void
444  const char *url,
445  void *cls)
446 {
447  struct RequestHandle *handle = cls;
448  char *subsystem;
449 
450  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
451  {
452  handle->emsg = GNUNET_strdup ("Missing subsystem name");
454  return;
455  }
457  // requested default identity of subsystem
458  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
459 
461  subsystem,
463  handle);
464 
465  if (NULL == handle->op)
466  {
467  handle->response_code = MHD_HTTP_NOT_FOUND;
470  return;
471  }
472 }
473 
474 
482 void
484  const char *url,
485  void *cls)
486 {
487  struct RequestHandle *handle = cls;
488  struct EgoEntry *ego_entry;
489  struct MHD_Response *resp;
490  struct GNUNET_HashCode key;
491  json_t *json_root;
492  json_t *json_ego;
493  char *result_str;
494  char *privkey_str;
495 
496  json_root = json_array ();
497  // Return ego/egos
498  for (ego_entry = ego_head; NULL != ego_entry;
499  ego_entry = ego_entry->next)
500  {
501  json_ego = json_object ();
502  json_object_set_new (json_ego,
504  json_string (ego_entry->keystring));
505  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
506  if (GNUNET_YES ==
508  handle->rest_handle->url_param_map, &key))
509  {
512  json_object_set_new (json_ego,
514  json_string (privkey_str));
515  GNUNET_free (privkey_str);
516  }
517 
518  json_object_set_new (json_ego,
520  json_string (ego_entry->identifier));
521  json_array_append (json_root, json_ego);
522  json_decref (json_ego);
523  }
524 
525  result_str = json_dumps (json_root, 0);
526  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
527  resp = GNUNET_REST_create_response (result_str);
528  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
529  "Content-Type",
530  "application/json"));
531  json_decref (json_root);
532  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
533  GNUNET_free (result_str);
535 }
536 
537 
544 void
545 ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
546 {
547  struct MHD_Response *resp;
548  struct GNUNET_HashCode key;
549  json_t *json_ego;
550  char *result_str;
551  char *privkey_str;
552 
553  json_ego = json_object ();
554  json_object_set_new (json_ego,
556  json_string (ego_entry->keystring));
557  json_object_set_new (json_ego,
559  json_string (ego_entry->identifier));
560  GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
561  if (GNUNET_YES ==
563  handle->rest_handle->url_param_map, &key))
564  {
567  json_object_set_new (json_ego,
569  json_string (privkey_str));
570  GNUNET_free (privkey_str);
571  }
572 
573  result_str = json_dumps (json_ego, 0);
574  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
575  resp = GNUNET_REST_create_response (result_str);
576  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
577  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
578  "Content-Type",
579  "application/json"));
580  json_decref (json_ego);
581  GNUNET_free (result_str);
583 }
584 
585 
593 void
595  const char *url,
596  void *cls)
597 {
598  struct RequestHandle *handle = cls;
599  struct EgoEntry *ego_entry;
600  char *keystring;
601 
602  keystring = NULL;
603 
604  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
605  {
606  handle->response_code = MHD_HTTP_NOT_FOUND;
609  return;
610  }
612  ego_entry = get_egoentry (handle, keystring, NULL);
613 
614  if (NULL == ego_entry)
615  {
616  handle->response_code = MHD_HTTP_NOT_FOUND;
619  return;
620  }
621 
622  ego_get_response (handle, ego_entry);
623 }
624 
625 
633 void
635  const char *url,
636  void *cls)
637 {
638  struct RequestHandle *handle = cls;
639  struct EgoEntry *ego_entry;
640  char *egoname;
641 
642  egoname = NULL;
643 
644  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
645  {
646  handle->response_code = MHD_HTTP_NOT_FOUND;
649  return;
650  }
651  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
652  ego_entry = get_egoentry (handle, NULL, egoname);
653 
654  if (NULL == ego_entry)
655  {
656  handle->response_code = MHD_HTTP_NOT_FOUND;
659  return;
660  }
661 
662  ego_get_response (handle, ego_entry);
663 }
664 
665 
672 static void
673 do_finished (void *cls, const char *emsg)
674 {
675  struct RequestHandle *handle = cls;
676  struct MHD_Response *resp;
677 
678  handle->op = NULL;
679  if (NULL != emsg)
680  {
681  handle->emsg = GNUNET_strdup (emsg);
683  return;
684  }
685  if (0 == handle->response_code)
686  {
687  handle->response_code = MHD_HTTP_NO_CONTENT;
688  }
689  resp = GNUNET_REST_create_response (NULL);
690  handle->proc (handle->proc_cls, resp, handle->response_code);
692 }
693 
694 
702 static void
704  const struct GNUNET_IDENTITY_PrivateKey *pk,
705  const char *emsg)
706 {
707  struct RequestHandle *handle = cls;
708 
709  (void) pk;
711 }
712 
713 
720 void
722 {
723  struct EgoEntry *ego_entry_tmp;
724  struct MHD_Response *resp;
725  json_t *data_js;
726  json_error_t err;
727  char *newname;
728  char term_data[handle->data_size + 1];
729  int json_state;
730 
731  // if no data
732  if (0 >= handle->data_size)
733  {
736  return;
737  }
738  // if not json
739  term_data[handle->data_size] = '\0';
740  GNUNET_memcpy (term_data, handle->data, handle->data_size);
741  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
742 
743  if (NULL == data_js)
744  {
747  return;
748  }
749 
750  newname = NULL;
751  // NEW NAME
752  json_state = 0;
753  json_state = json_unpack (data_js,
754  "{s:s!}",
756  &newname);
757  // Change name with pubkey or name identifier
758  if (0 != json_state)
759  {
762  json_decref (data_js);
763  return;
764  }
765 
766  if (NULL == newname)
767  {
770  json_decref (data_js);
771  return;
772  }
773 
774  if (0 >= strlen (newname))
775  {
778  json_decref (data_js);
779  return;
780  }
781 
782  ego_entry_tmp = get_egoentry (handle, NULL, newname);
783  if (NULL != ego_entry_tmp)
784  {
785  // Ego with same name not allowed (even if its the ego we change)
786  resp = GNUNET_REST_create_response (NULL);
787  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
789  json_decref (data_js);
790  return;
791  }
793  ego_entry->identifier,
794  newname,
795  &do_finished,
796  handle);
797  if (NULL == handle->op)
798  {
799  handle->emsg = GNUNET_strdup ("Rename failed");
801  json_decref (data_js);
802  return;
803  }
804  json_decref (data_js);
805  return;
806 }
807 
808 
816 void
818  const char *url,
819  void *cls)
820 {
821  struct RequestHandle *handle = cls;
822  struct EgoEntry *ego_entry;
823  char *keystring;
824 
825  keystring = NULL;
826 
827  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
828  {
829  handle->response_code = MHD_HTTP_NOT_FOUND;
832  return;
833  }
835  ego_entry = get_egoentry (handle, keystring, NULL);
836 
837  if (NULL == ego_entry)
838  {
839  handle->response_code = MHD_HTTP_NOT_FOUND;
842  return;
843  }
844 
845  ego_edit (handle, ego_entry);
846 }
847 
848 
856 void
858  const char *url,
859  void *cls)
860 {
861  struct RequestHandle *handle = cls;
862  struct EgoEntry *ego_entry;
863  char *name;
864 
865  name = NULL;
866 
867  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
868  {
869  handle->response_code = MHD_HTTP_NOT_FOUND;
872  return;
873  }
874  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
875  ego_entry = get_egoentry (handle, NULL, name);
876 
877  if (NULL == ego_entry)
878  {
879  handle->response_code = MHD_HTTP_NOT_FOUND;
882  return;
883  }
884 
885  ego_edit (handle, ego_entry);
886 }
887 
888 
896 void
898  const char *url,
899  void *cls)
900 {
901  struct RequestHandle *handle = cls;
902  struct EgoEntry *ego_entry;
903  json_t *data_js;
904  json_error_t err;
905  char *newsubsys;
906  char *name;
907  char term_data[handle->data_size + 1];
908  int json_state;
909 
910  name = NULL;
911 
912  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
913  {
914  handle->response_code = MHD_HTTP_NOT_FOUND;
917  return;
918  }
919  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
920  ego_entry = get_egoentry (handle, NULL, name);
921 
922  if (NULL == ego_entry)
923  {
924  handle->response_code = MHD_HTTP_NOT_FOUND;
927  return;
928  }
929 
930  // if no data
931  if (0 >= handle->data_size)
932  {
935  return;
936  }
937  // if not json
938  term_data[handle->data_size] = '\0';
939  GNUNET_memcpy (term_data, handle->data, handle->data_size);
940  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
941 
942  if (NULL == data_js)
943  {
946  return;
947  }
948 
949  newsubsys = NULL;
950  // SUBSYSTEM
951  json_state = 0;
952  json_state = json_unpack (data_js,
953  "{s:s!}",
955  &newsubsys);
956  // Change subsystem with pubkey or name identifier
957  if (0 != json_state)
958  {
961  json_decref (data_js);
962  return;
963  }
964 
965  if (NULL == newsubsys)
966  {
969  json_decref (data_js);
970  return;
971  }
972 
973  if (0 >= strlen (newsubsys))
974  {
977  json_decref (data_js);
978  return;
979  }
980 
981  handle->response_code = MHD_HTTP_NO_CONTENT;
983  newsubsys,
984  ego_entry->ego,
985  &do_finished,
986  handle);
987  if (NULL == handle->op)
988  {
989  handle->emsg = GNUNET_strdup ("Setting subsystem failed");
991  return;
992  }
993  json_decref (data_js);
994  return;
995 }
996 
997 
1005 void
1007  const char *url,
1008  void *cls)
1009 {
1010  struct RequestHandle *handle = cls;
1011  struct EgoEntry *ego_entry;
1012  struct MHD_Response *resp;
1013  json_t *data_js;
1014  json_error_t err;
1015  char *egoname;
1016  char *privkey;
1018  struct GNUNET_IDENTITY_PrivateKey *pk_ptr;
1019  int json_unpack_state;
1020  char term_data[handle->data_size + 1];
1021 
1022  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
1023  {
1025  return;
1026  }
1027 
1028  if (0 >= handle->data_size)
1029  {
1032  return;
1033  }
1034  term_data[handle->data_size] = '\0';
1035  GNUNET_memcpy (term_data, handle->data, handle->data_size);
1036  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
1037  if (NULL == data_js)
1038  {
1041  json_decref (data_js);
1042  return;
1043  }
1044  json_unpack_state = 0;
1045  privkey = NULL;
1046  json_unpack_state =
1047  json_unpack (data_js, "{s:s, s?:s!}",
1050  if (0 != json_unpack_state)
1051  {
1054  json_decref (data_js);
1055  return;
1056  }
1057 
1058  if (NULL == egoname)
1059  {
1062  json_decref (data_js);
1063  return;
1064  }
1065  if (0 >= strlen (egoname))
1066  {
1067  json_decref (data_js);
1070  return;
1071  }
1073  for (ego_entry = ego_head; NULL != ego_entry;
1074  ego_entry = ego_entry->next)
1075  {
1076  if (0 == strcasecmp (egoname, ego_entry->identifier))
1077  {
1078  resp = GNUNET_REST_create_response (NULL);
1079  handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
1081  json_decref (data_js);
1082  return;
1083  }
1084  }
1085  handle->name = GNUNET_strdup (egoname);
1086  if (NULL != privkey)
1087  {
1089  strlen (privkey),
1090  &pk,
1091  sizeof(struct
1093  pk_ptr = &pk;
1094  }
1095  else
1096  pk_ptr = NULL;
1097  json_decref (data_js);
1098  handle->response_code = MHD_HTTP_CREATED;
1100  handle->name,
1101  pk_ptr,
1104  handle);
1105 }
1106 
1107 
1115 void
1117  const char *url,
1118  void *cls)
1119 {
1120  struct RequestHandle *handle = cls;
1121  struct EgoEntry *ego_entry;
1122  char *keystring;
1123 
1124  keystring = NULL;
1125 
1126  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
1127  {
1128  handle->response_code = MHD_HTTP_NOT_FOUND;
1131  return;
1132  }
1133  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
1134  ego_entry = get_egoentry (handle, keystring, NULL);
1135 
1136  if (NULL == ego_entry)
1137  {
1138  handle->response_code = MHD_HTTP_NOT_FOUND;
1141  return;
1142  }
1143 
1144  handle->response_code = MHD_HTTP_NO_CONTENT;
1146  ego_entry->identifier,
1147  &do_finished,
1148  handle);
1149 }
1150 
1151 
1159 void
1161  const char *url,
1162  void *cls)
1163 {
1164  struct RequestHandle *handle = cls;
1165  struct EgoEntry *ego_entry;
1166  char *name;
1167 
1168  name = NULL;
1169 
1170  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
1171  {
1172  handle->response_code = MHD_HTTP_NOT_FOUND;
1175  return;
1176  }
1177  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME) + 1];
1178  ego_entry = get_egoentry (handle, NULL, name);
1179 
1180  if (NULL == ego_entry)
1181  {
1182  handle->response_code = MHD_HTTP_NOT_FOUND;
1185  return;
1186  }
1187 
1188  handle->response_code = MHD_HTTP_NO_CONTENT;
1190  ego_entry->identifier,
1191  &do_finished,
1192  handle);
1193 }
1194 
1196 {
1197  void *data;
1199 };
1200 
1201 void
1202 ego_sign_data_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
1203 {
1204  struct RequestHandle *handle = ((struct ego_sign_data_cls *) cls)->handle;
1205  unsigned char *data
1206  = (unsigned char *) ((struct ego_sign_data_cls *) cls)->data; // data is url decoded
1207  struct MHD_Response *resp;
1208  struct GNUNET_CRYPTO_EddsaSignature sig;
1209  char *sig_str;
1210  char *result;
1211 
1212  if (ego == NULL)
1213  {
1214  handle->response_code = MHD_HTTP_BAD_REQUEST;
1215  handle->emsg = GNUNET_strdup ("Ego not found");
1217  return;
1218  }
1219 
1220  if (ntohl (ego->pk.type) != GNUNET_IDENTITY_TYPE_EDDSA)
1221  {
1222  handle->response_code = MHD_HTTP_BAD_REQUEST;
1223  handle->emsg = GNUNET_strdup ("Ego has to use an EdDSA key");
1225  return;
1226  }
1227 
1229  (void *) data,
1230  strlen ( (char*) data),
1231  &sig))
1232  {
1233  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1234  handle->emsg = GNUNET_strdup ("Signature creation failed");
1236  return;
1237  }
1238 
1240  sizeof (struct GNUNET_CRYPTO_EddsaSignature),
1241  &sig_str);
1242 
1244  "{\"signature\": \"%s\"}",
1245  sig_str);
1246 
1248  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1249 
1250  free (data);
1251  free (sig_str);
1252  free (result);
1253  free (cls);
1255 }
1256 
1263 void
1265  const char *url,
1266  void *cls)
1267 {
1268  // TODO: replace with precompiler #define
1269  const char *username_key = "user";
1270  const char *data_key = "data";
1271 
1272  struct RequestHandle *handle = cls;
1273  struct GNUNET_HashCode cache_key_username;
1274  struct GNUNET_HashCode cache_key_data;
1275  char *username;
1276  char *data;
1277 
1278  struct ego_sign_data_cls *cls2;
1279 
1280  GNUNET_CRYPTO_hash (username_key, strlen (username_key), &cache_key_username);
1281  GNUNET_CRYPTO_hash (data_key, strlen (data_key), &cache_key_data);
1282 
1284  handle->rest_handle->url_param_map,
1285  &cache_key_username)) ||
1287  handle->rest_handle->url_param_map,
1288  &cache_key_data)))
1289  {
1290  handle->response_code = MHD_HTTP_BAD_REQUEST;
1291  handle->emsg = GNUNET_strdup ("URL parameter missing");
1293  return;
1294  }
1295 
1296  username = (char *) GNUNET_CONTAINER_multihashmap_get (
1297  handle->rest_handle->url_param_map,
1298  &cache_key_username);
1299 
1301  handle->rest_handle->url_param_map,
1302  &cache_key_data);
1303 
1304  cls2 = malloc (sizeof(struct ego_sign_data_cls));
1305  cls2->data = (void *) GNUNET_strdup (data);
1306  cls2->handle = handle;
1307 
1309  username,
1311  cls2);
1312 }
1313 
1321 static void
1323  const char *url,
1324  void *cls)
1325 {
1326  struct MHD_Response *resp;
1327  struct RequestHandle *handle = cls;
1328 
1329  // For now, independent of path return all options
1330  resp = GNUNET_REST_create_response (NULL);
1331  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1332  "Access-Control-Allow-Methods",
1333  allow_methods));
1334  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1336  return;
1337 }
1338 
1339 
1340 static void
1341 list_ego (void *cls,
1342  struct GNUNET_IDENTITY_Ego *ego,
1343  void **ctx,
1344  const char *identifier)
1345 {
1346  struct EgoEntry *ego_entry;
1348 
1349  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1350  {
1352  return;
1353  }
1354  if (NULL == ego)
1355  {
1357  "Called with NULL ego\n");
1358  return;
1359  }
1360  if (ID_REST_STATE_INIT == state)
1361  {
1362  ego_entry = GNUNET_new (struct EgoEntry);
1365  ego_entry->ego = ego;
1366  ego_entry->identifier = GNUNET_strdup (identifier);
1368  ego_tail,
1369  ego_entry);
1370  }
1371  /* Ego renamed or added */
1372  if (identifier != NULL)
1373  {
1374  for (ego_entry = ego_head; NULL != ego_entry;
1375  ego_entry = ego_entry->next)
1376  {
1377  if (ego_entry->ego == ego)
1378  {
1379  /* Rename */
1380  GNUNET_free (ego_entry->identifier);
1381  ego_entry->identifier = GNUNET_strdup (identifier);
1382  break;
1383  }
1384  }
1385  if (NULL == ego_entry)
1386  {
1387  /* Add */
1388  ego_entry = GNUNET_new (struct EgoEntry);
1391  ego_entry->ego = ego;
1392  ego_entry->identifier = GNUNET_strdup (identifier);
1394  ego_tail,
1395  ego_entry);
1396  }
1397  }
1398  else
1399  {
1400  /* Delete */
1401  for (ego_entry = ego_head; NULL != ego_entry;
1402  ego_entry = ego_entry->next)
1403  {
1404  if (ego_entry->ego == ego)
1405  break;
1406  }
1407  if (NULL == ego_entry)
1408  return; /* Not found */
1409 
1411  ego_tail,
1412  ego_entry);
1413  GNUNET_free (ego_entry->identifier);
1414  GNUNET_free (ego_entry->keystring);
1415  GNUNET_free (ego_entry);
1416  return;
1417  }
1418 
1419 }
1420 
1421 
1433 static enum GNUNET_GenericReturnValue
1434 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1436  void *proc_cls)
1437 {
1438  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1440  static const struct GNUNET_REST_RequestHandler handlers[] =
1441  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1442  &ego_get_pubkey },
1443  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1444  { MHD_HTTP_METHOD_GET,
1446  &ego_get_subsystem },
1447  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1448  { MHD_HTTP_METHOD_PUT,
1450  &ego_edit_pubkey },
1451  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1452  { MHD_HTTP_METHOD_PUT,
1454  &ego_edit_subsystem },
1455  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1456  { MHD_HTTP_METHOD_DELETE,
1458  &ego_delete_pubkey },
1459  { MHD_HTTP_METHOD_DELETE,
1461  &ego_delete_name },
1462  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1463  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_SIGN, &ego_sign_data},
1465 
1466 
1467  handle->response_code = 0;
1469  handle->proc_cls = proc_cls;
1470  handle->proc = proc;
1471  handle->rest_handle = rest_handle;
1472  handle->data = rest_handle->data;
1473  handle->data_size = rest_handle->data_size;
1474 
1475  handle->url = GNUNET_strdup (rest_handle->url);
1476  if (handle->url[strlen (handle->url) - 1] == '/')
1477  handle->url[strlen (handle->url) - 1] = '\0';
1478  handle->timeout_task =
1481  requests_tail,
1482  handle);
1483  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1484  if (GNUNET_NO ==
1485  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1486  {
1488  return GNUNET_NO;
1489  }
1490 
1491  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1492  return GNUNET_YES;
1493 }
1494 
1495 
1502 void *
1504 {
1505  static struct Plugin plugin;
1506  struct GNUNET_REST_Plugin *api;
1507 
1508  cfg = cls;
1509  if (NULL != plugin.cfg)
1510  return NULL; /* can only initialize once! */
1511  memset (&plugin, 0, sizeof(struct Plugin));
1512  plugin.cfg = cfg;
1513  api = GNUNET_new (struct GNUNET_REST_Plugin);
1514  api->cls = &plugin;
1518  "%s, %s, %s, %s, %s",
1519  MHD_HTTP_METHOD_GET,
1520  MHD_HTTP_METHOD_POST,
1521  MHD_HTTP_METHOD_PUT,
1522  MHD_HTTP_METHOD_DELETE,
1523  MHD_HTTP_METHOD_OPTIONS);
1526 
1527  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1528  return api;
1529 }
1530 
1531 
1538 void *
1540 {
1541  struct GNUNET_REST_Plugin *api = cls;
1542  struct Plugin *plugin = api->cls;
1543  struct EgoEntry *ego_entry;
1544  struct EgoEntry *ego_tmp;
1545 
1546  plugin->cfg = NULL;
1547  while (NULL != requests_head)
1549  if (NULL != identity_handle)
1551 
1552  for (ego_entry = ego_head; NULL != ego_entry;)
1553  {
1554  ego_tmp = ego_entry;
1555  ego_entry = ego_entry->next;
1556  GNUNET_free (ego_tmp->identifier);
1557  GNUNET_free (ego_tmp->keystring);
1558  GNUNET_free (ego_tmp);
1559  }
1560 
1562  GNUNET_free (api);
1563  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
1564  return NULL;
1565 }
1566 
1567 
1568 /* 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 char * egoname
Ego Attribut String.
Definition: gnunet-did.c:96
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
uint32_t data
The data value.
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 int result
Global testing status.
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.
cryptographic primitives for GNUnet
Identity service; implements identity management for GNUnet.
API for helper library to parse/create REST.
GNUnet service REST plugin header.
#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
enum GNUNET_GenericReturnValue 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_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
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_EgoLookup * GNUNET_IDENTITY_ego_lookup(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_IDENTITY_EgoCallback cb, void *cb_cls)
Lookup an ego by name.
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.
@ GNUNET_IDENTITY_TYPE_EDDSA
EDDSA identity.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_raw(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, void *data, size_t size, struct GNUNET_CRYPTO_EddsaSignature *sig)
Definition: crypto_ecc.c:598
#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:96
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
#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:1281
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
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:1254
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:789
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1657
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:450
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Common type definitions for the identity service and API.
#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.
void ego_sign_data(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
#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.
#define GNUNET_REST_API_NS_SIGN
Identity Namespace with sign specifier.
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.
void ego_sign_data_cb(void *cls, struct GNUNET_IDENTITY_Ego *ego)
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.
an ECC signature using EdDSA.
A 512-bit hashcode.
Handle for an ego.
Definition: identity.h:37
struct GNUNET_IDENTITY_PrivateKey pk
The identity key pair.
Definition: identity.h:51
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.
uint32_t type
Type of public key.
struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_key
AN EdDSA identtiy key.
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).
struct RequestHandle * handle