aboutsummaryrefslogtreecommitdiff
path: root/src/identity
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity')
-rw-r--r--src/identity/.gitignore4
-rw-r--r--src/identity/Makefile.am97
-rw-r--r--src/identity/gnunet-identity.c534
-rw-r--r--src/identity/gnunet-service-identity.c1253
-rw-r--r--src/identity/identity.conf.in17
-rw-r--r--src/identity/identity.h281
-rw-r--r--src/identity/identity_api.c1267
-rw-r--r--src/identity/identity_api_lookup.c229
-rw-r--r--src/identity/identity_api_suffix_lookup.c229
-rw-r--r--src/identity/plugin_rest_identity.c1442
-rw-r--r--src/identity/test_identity.c306
-rw-r--r--src/identity/test_identity.conf8
-rw-r--r--src/identity/test_identity_defaults.c299
-rwxr-xr-xsrc/identity/test_plugin_rest_identity.sh157
14 files changed, 0 insertions, 6123 deletions
diff --git a/src/identity/.gitignore b/src/identity/.gitignore
deleted file mode 100644
index 634a0bdd6..000000000
--- a/src/identity/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
1gnunet-service-identity
2gnunet-identity
3test_identity
4test_identity_defaults
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
deleted file mode 100644
index 59ace6c41..000000000
--- a/src/identity/Makefile.am
+++ /dev/null
@@ -1,97 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6if USE_COVERAGE
7 AM_CFLAGS = --coverage -O0
8 XLIB = -lgcov
9endif
10
11plugin_LTLIBRARIES = libgnunet_plugin_rest_identity.la
12
13pkgcfgdir= $(pkgdatadir)/config.d/
14
15libexecdir= $(pkglibdir)/libexec/
16
17pkgcfg_DATA = \
18 identity.conf
19
20lib_LTLIBRARIES = \
21 libgnunetidentity.la
22
23
24libgnunet_plugin_rest_identity_la_SOURCES = \
25 plugin_rest_identity.c
26libgnunet_plugin_rest_identity_la_LIBADD = \
27 libgnunetidentity.la \
28 $(top_builddir)/src/rest/libgnunetrest.la \
29 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
30 $(LTLIBINTL) -ljansson $(MHD_LIBS)
31libgnunet_plugin_rest_identity_la_LDFLAGS = \
32 $(GN_PLUGIN_LDFLAGS)
33libgnunet_plugin_rest_identity_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
34
35
36libgnunetidentity_la_SOURCES = \
37 identity_api.c \
38 identity_api_lookup.c \
39 identity_api_suffix_lookup.c \
40 identity.h
41libgnunetidentity_la_LIBADD = \
42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(GN_LIBINTL) $(XLIB)
44libgnunetidentity_la_LDFLAGS = \
45 $(GN_LIB_LDFLAGS) \
46 -version-info 1:0:0
47
48bin_PROGRAMS = \
49 gnunet-identity
50
51libexec_PROGRAMS = \
52 gnunet-service-identity
53
54gnunet_service_identity_SOURCES = \
55 gnunet-service-identity.c
56gnunet_service_identity_LDADD = \
57 $(top_builddir)/src/statistics/libgnunetstatistics.la \
58 $(top_builddir)/src/util/libgnunetutil.la \
59 $(GN_LIBINTL)
60
61
62gnunet_identity_SOURCES = \
63 gnunet-identity.c
64gnunet_identity_LDADD = \
65 libgnunetidentity.la \
66 $(top_builddir)/src/statistics/libgnunetstatistics.la \
67 $(top_builddir)/src/util/libgnunetutil.la \
68 $(GN_LIBINTL)
69
70check_PROGRAMS = \
71 test_identity \
72 test_identity_defaults
73
74if ENABLE_TEST_RUN
75AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
76TESTS = $(check_PROGRAMS)
77endif
78
79
80test_identity_SOURCES = \
81 test_identity.c
82test_identity_LDADD = \
83 libgnunetidentity.la \
84 $(top_builddir)/src/testing/libgnunettesting.la \
85 $(top_builddir)/src/util/libgnunetutil.la
86
87test_identity_defaults_SOURCES = \
88 test_identity_defaults.c
89test_identity_defaults_LDADD = \
90 libgnunetidentity.la \
91 $(top_builddir)/src/testing/libgnunettesting.la \
92 $(top_builddir)/src/util/libgnunetutil.la
93
94EXTRA_DIST = \
95 test_identity.conf
96
97
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
deleted file mode 100644
index d8dc936d3..000000000
--- a/src/identity/gnunet-identity.c
+++ /dev/null
@@ -1,534 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018, 2019 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 */
20/**
21 * @file identity/gnunet-identity.c
22 * @brief IDENTITY management command line tool
23 * @author Christian Grothoff
24 *
25 * Todo:
26 * - add options to get default egos
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31
32
33/**
34 * Return value from main on timeout.
35 */
36#define TIMEOUT_STATUS_CODE 40
37
38/**
39 * Handle to IDENTITY service.
40 */
41static struct GNUNET_IDENTITY_Handle *sh;
42
43/**
44 * Was "list" specified?
45 */
46static int list;
47
48/**
49 * Was "monitor" specified?
50 */
51static int monitor;
52
53/**
54 * Was "private" specified?
55 */
56static int private_keys;
57
58/**
59 * Was "verbose" specified?
60 */
61static unsigned int verbose;
62
63/**
64 * Was "quiet" specified?
65 */
66static int quiet;
67
68/**
69 * Was "eddsa" specified?
70 */
71static int type_eddsa;
72
73/**
74 * -C option
75 */
76static char *create_ego;
77
78/**
79 * -D option
80 */
81static char *delete_ego;
82
83/**
84 * -P option
85 */
86static char *privkey_ego;
87
88/**
89 * -s option.
90 */
91static char *set_ego;
92
93/**
94 * -S option.
95 */
96static char *set_subsystem;
97
98/**
99 * Operation handle for set operation.
100 */
101static struct GNUNET_IDENTITY_Operation *set_op;
102
103/**
104 * Handle for create operation.
105 */
106static struct GNUNET_IDENTITY_Operation *create_op;
107
108/**
109 * Handle for delete operation.
110 */
111static struct GNUNET_IDENTITY_Operation *delete_op;
112
113/**
114 * Private key from command line option, or NULL.
115 */
116struct GNUNET_IDENTITY_PrivateKey pk;
117
118/**
119 * Value to return from #main().
120 */
121static int global_ret;
122
123
124/**
125 * Task run on shutdown.
126 *
127 * @param cls NULL
128 */
129static void
130shutdown_task (void *cls)
131{
132 if (NULL != set_op)
133 {
134 GNUNET_IDENTITY_cancel (set_op);
135 set_op = NULL;
136 }
137 if (NULL != create_op)
138 {
139 GNUNET_IDENTITY_cancel (create_op);
140 create_op = NULL;
141 }
142 if (NULL != delete_op)
143 {
144 GNUNET_IDENTITY_cancel (delete_op);
145 delete_op = NULL;
146 }
147 if (NULL != set_ego)
148 {
149 GNUNET_free (set_ego);
150 set_ego = NULL;
151 }
152 GNUNET_IDENTITY_disconnect (sh);
153 sh = NULL;
154}
155
156
157/**
158 * Test if we are finished yet.
159 */
160static void
161test_finished (void)
162{
163 if ( (NULL == create_op) &&
164 (NULL == delete_op) &&
165 (NULL == set_op) &&
166 (NULL == set_subsystem) &&
167 (! list) &&
168 (! monitor))
169 {
170 if (TIMEOUT_STATUS_CODE == global_ret)
171 global_ret = 0;
172 GNUNET_SCHEDULER_shutdown ();
173 }
174}
175
176
177/**
178 * Deletion operation finished.
179 *
180 * @param cls pointer to operation handle
181 * @param emsg NULL on success, otherwise an error message
182 */
183static void
184delete_finished (void *cls,
185 const char *emsg)
186{
187 struct GNUNET_IDENTITY_Operation **op = cls;
188
189 *op = NULL;
190 if (NULL != emsg)
191 fprintf (stderr, "%s\n", gettext (emsg));
192 test_finished ();
193}
194
195
196/**
197 * Creation operation finished.
198 *
199 * @param cls pointer to operation handle
200 * @param pk private key of the ego, or NULL on error
201 * @param emsg error message, NULL on success
202 */
203static void
204create_finished (void *cls,
205 const struct GNUNET_IDENTITY_PrivateKey *pk,
206 const char *emsg)
207{
208 struct GNUNET_IDENTITY_Operation **op = cls;
209
210 *op = NULL;
211 if (NULL == pk)
212 {
213 fprintf (stderr,
214 _ ("Failed to create ego: %s\n"),
215 emsg);
216 global_ret = 1;
217 }
218 else if (verbose)
219 {
220 struct GNUNET_IDENTITY_PublicKey pub;
221 char *pubs;
222
223 GNUNET_IDENTITY_key_get_public (pk, &pub);
224 pubs = GNUNET_IDENTITY_public_key_to_string (&pub);
225 if (private_keys)
226 {
227 char *privs;
228
229 privs = GNUNET_IDENTITY_private_key_to_string (pk);
230 fprintf (stdout, "%s - %s\n", pubs, privs);
231 GNUNET_free (privs);
232 }
233 else
234 {
235 fprintf (stdout, "%s\n", pubs);
236 }
237 GNUNET_free (pubs);
238 }
239 test_finished ();
240}
241
242
243/**
244 * Function called by #GNUNET_IDENTITY_set up on completion.
245 *
246 * @param cls NULL
247 * @param emsg error message (NULL on success)
248 */
249static void
250set_done (void *cls, const char *emsg)
251{
252 set_op = NULL;
253 if (NULL != emsg)
254 {
255 fprintf (stderr, _ ("Failed to set default ego: %s\n"), emsg);
256 global_ret = 1;
257 }
258 test_finished ();
259}
260
261
262/**
263 * If listing is enabled, prints information about the egos.
264 *
265 * This function is initially called for all egos and then again
266 * whenever a ego's identifier changes or if it is deleted. At the
267 * end of the initial pass over all egos, the function is once called
268 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
269 * be invoked in the future or that there was an error.
270 *
271 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
272 * function is only called ONCE, and 'NULL' being passed in 'ego' does
273 * indicate an error (for example because name is taken or no default value is
274 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
275 * value WILL be passed to a subsequent call to the identity callback of
276 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
277 *
278 * When an identity is renamed, this function is called with the
279 * (known) ego but the NEW identifier.
280 *
281 * When an identity is deleted, this function is called with the
282 * (known) ego and "NULL" for the 'identifier'. In this case,
283 * the 'ego' is henceforth invalid (and the 'ctx' should also be
284 * cleaned up).
285 *
286 * @param cls closure
287 * @param ego ego handle
288 * @param ctx context for application to store data for this ego
289 * (during the lifetime of this process, initially NULL)
290 * @param identifier identifier assigned by the user for this ego,
291 * NULL if the user just deleted the ego and it
292 * must thus no longer be used
293 */
294static void
295print_ego (void *cls,
296 struct GNUNET_IDENTITY_Ego *ego,
297 void **ctx,
298 const char *identifier)
299{
300 struct GNUNET_IDENTITY_PublicKey pk;
301 char *s;
302 char *privs;
303
304 if ( (NULL != set_ego) &&
305 (NULL != set_subsystem) &&
306 (NULL != ego) &&
307 (NULL != identifier) &&
308 (0 == strcmp (identifier, set_ego)))
309 {
310 set_op = GNUNET_IDENTITY_set (sh,
311 set_subsystem,
312 ego,
313 &set_done,
314 NULL);
315 GNUNET_free (set_subsystem);
316 set_subsystem = NULL;
317 GNUNET_free (set_ego);
318 set_ego = NULL;
319 }
320 if ( (NULL == ego) &&
321 (NULL != set_ego) &&
322 (NULL != set_subsystem) )
323 {
324 fprintf (stderr,
325 "Could not set ego to `%s' for subsystem `%s', ego not known\n",
326 set_ego,
327 set_subsystem);
328 GNUNET_free (set_subsystem);
329 set_subsystem = NULL;
330 GNUNET_free (set_ego);
331 set_ego = NULL;
332 }
333 if ((NULL == ego) && (! monitor))
334 {
335 list = 0;
336 test_finished ();
337 return;
338 }
339 if (! (list | monitor))
340 return;
341 if ( (NULL == ego) ||
342 (NULL == identifier) )
343 return;
344 if ( (NULL != set_ego) &&
345 (0 != strcmp (identifier,
346 set_ego)) )
347 return;
348 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
349 s = GNUNET_IDENTITY_public_key_to_string (&pk);
350 privs = GNUNET_IDENTITY_private_key_to_string (
351 GNUNET_IDENTITY_ego_get_private_key (ego));
352 if ((monitor) || (NULL != identifier))
353 {
354 if (quiet)
355 {
356 if (private_keys)
357 fprintf (stdout, "%s - %s\n", s, privs);
358 else
359 fprintf (stdout, "%s\n", s);
360 }
361 else
362 {
363 if (private_keys)
364 fprintf (stdout, "%s - %s - %s - %s\n",
365 identifier, s, privs,
366 (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
367 "ECDSA" : "EdDSA");
368 else
369 fprintf (stdout, "%s - %s - %s\n",
370 identifier, s,
371 (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
372 "ECDSA" : "EdDSA");
373
374 }
375 }
376 GNUNET_free (privs);
377 GNUNET_free (s);
378}
379
380
381/**
382 * Main function that will be run by the scheduler.
383 *
384 * @param cls closure
385 * @param args remaining command-line arguments
386 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
387 * @param cfg configuration
388 */
389static void
390run (void *cls,
391 char *const *args,
392 const char *cfgfile,
393 const struct GNUNET_CONFIGURATION_Handle *cfg)
394{
395 if ((NULL != set_subsystem) && (NULL == set_ego))
396 {
397 fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
398 return;
399 }
400 sh = GNUNET_IDENTITY_connect (cfg,
401 (monitor | list) ||
402 (NULL != set_ego) ||
403 (NULL != set_subsystem)
404 ? &print_ego
405 : NULL,
406 NULL);
407 if (NULL != delete_ego)
408 delete_op =
409 GNUNET_IDENTITY_delete (sh,
410 delete_ego,
411 &delete_finished,
412 &delete_op);
413 if (NULL != create_ego)
414 {
415 if (NULL != privkey_ego)
416 {
417 GNUNET_STRINGS_string_to_data (privkey_ego,
418 strlen (privkey_ego),
419 &pk,
420 sizeof(struct
421 GNUNET_IDENTITY_PrivateKey));
422 create_op =
423 GNUNET_IDENTITY_create (sh,
424 create_ego,
425 &pk,
426 0, // Ignored
427 &create_finished,
428 &create_op);
429 }
430 else
431 create_op =
432 GNUNET_IDENTITY_create (sh,
433 create_ego,
434 NULL,
435 (type_eddsa) ?
436 GNUNET_IDENTITY_TYPE_EDDSA :
437 GNUNET_IDENTITY_TYPE_ECDSA,
438 &create_finished,
439 &create_op);
440 }
441 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
442 NULL);
443 test_finished ();
444}
445
446
447/**
448 * The main function.
449 *
450 * @param argc number of arguments from the command line
451 * @param argv command line arguments
452 * @return 0 ok, 1 on error
453 */
454int
455main (int argc, char *const *argv)
456{
457 struct GNUNET_GETOPT_CommandLineOption options[] = {
458 GNUNET_GETOPT_option_string ('C',
459 "create",
460 "NAME",
461 gettext_noop ("create ego NAME"),
462 &create_ego),
463 GNUNET_GETOPT_option_string ('D',
464 "delete",
465 "NAME",
466 gettext_noop ("delete ego NAME "),
467 &delete_ego),
468 GNUNET_GETOPT_option_string ('P',
469 "privkey",
470 "PRIVATE_KEY",
471 gettext_noop (
472 "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
473 &privkey_ego),
474 GNUNET_GETOPT_option_flag ('X',
475 "eddsa",
476 gettext_noop (
477 "generate an EdDSA identity. (use together with -C) EXPERIMENTAL"),
478 &type_eddsa),
479 GNUNET_GETOPT_option_flag ('d',
480 "display",
481 gettext_noop ("display all egos"),
482 &list),
483 GNUNET_GETOPT_option_flag ('q',
484 "quiet",
485 gettext_noop ("reduce output"),
486 &quiet),
487 GNUNET_GETOPT_option_string (
488 'e',
489 "ego",
490 "NAME",
491 gettext_noop (
492 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"),
493 &set_ego),
494 GNUNET_GETOPT_option_flag ('m',
495 "monitor",
496 gettext_noop ("run in monitor mode egos"),
497 &monitor),
498 GNUNET_GETOPT_option_flag ('p',
499 "private-keys",
500 gettext_noop ("display private keys as well"),
501 &private_keys),
502 GNUNET_GETOPT_option_string (
503 's',
504 "set",
505 "SUBSYSTEM",
506 gettext_noop (
507 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
508 &set_subsystem),
509 GNUNET_GETOPT_option_verbose (&verbose),
510 GNUNET_GETOPT_OPTION_END
511 };
512 int res;
513
514 if (GNUNET_OK !=
515 GNUNET_STRINGS_get_utf8_args (argc, argv,
516 &argc, &argv))
517 return 4;
518 global_ret = TIMEOUT_STATUS_CODE; /* timeout */
519 res = GNUNET_PROGRAM_run (argc,
520 argv,
521 "gnunet-identity",
522 gettext_noop ("Maintain egos"),
523 options,
524 &run,
525 NULL);
526 GNUNET_free_nz ((void *) argv);
527
528 if (GNUNET_OK != res)
529 return 3;
530 return global_ret;
531}
532
533
534/* end of gnunet-identity.c */
diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c
deleted file mode 100644
index 2bb4b0897..000000000
--- a/src/identity/gnunet-service-identity.c
+++ /dev/null
@@ -1,1253 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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 */
20
21/**
22 * @file identity/gnunet-service-identity.c
23 * @brief identity management service
24 * @author Christian Grothoff
25 *
26 * The purpose of this service is to manage private keys that
27 * represent the various egos/pseudonyms/identities of a GNUnet user.
28 *
29 * Todo:
30 * - auto-initialze default egos; maybe trigger default
31 * initializations (such as gnunet-gns-import.sh?)
32 */
33#include "platform.h"
34#include "gnunet_util_lib.h"
35#include "gnunet_constants.h"
36#include "gnunet_protocols.h"
37#include "gnunet_statistics_service.h"
38#include "gnunet_identity_service.h"
39#include "identity.h"
40
41
42/**
43 * Information we keep about each ego.
44 */
45struct Ego
46{
47 /**
48 * We keep egos in a DLL.
49 */
50 struct Ego *next;
51
52 /**
53 * We keep egos in a DLL.
54 */
55 struct Ego *prev;
56
57 /**
58 * Private key of the ego.
59 */
60 struct GNUNET_IDENTITY_PrivateKey pk;
61
62 /**
63 * String identifier for the ego.
64 */
65 char *identifier;
66};
67
68
69/**
70 * Handle to our current configuration.
71 */
72static const struct GNUNET_CONFIGURATION_Handle *cfg;
73
74/**
75 * Handle to subsystem configuration which for each subsystem contains
76 * the name of the default ego.
77 */
78static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg;
79
80/**
81 * Handle to the statistics service.
82 */
83static struct GNUNET_STATISTICS_Handle *stats;
84
85/**
86 * Notification context, simplifies client broadcasts.
87 */
88static struct GNUNET_NotificationContext *nc;
89
90/**
91 * Directory where we store the identities.
92 */
93static char *ego_directory;
94
95/**
96 * Configuration file name where subsystem information is kept.
97 */
98static char *subsystem_cfg_file;
99
100/**
101 * Head of DLL of all egos.
102 */
103static struct Ego *ego_head;
104
105/**
106 * Tail of DLL of all egos.
107 */
108static struct Ego *ego_tail;
109
110
111/**
112 * Get the name of the file we use to store a given ego.
113 *
114 * @param ego ego for which we need the filename
115 * @return full filename for the given ego
116 */
117static char *
118get_ego_filename (struct Ego *ego)
119{
120 char *filename;
121
122 GNUNET_asprintf (&filename,
123 "%s%s%s",
124 ego_directory,
125 DIR_SEPARATOR_STR,
126 ego->identifier);
127 return filename;
128}
129
130
131/**
132 * Called whenever a client is disconnected.
133 *
134 * @param cls closure
135 * @param client identification of the client
136 * @param app_ctx @a client
137 */
138static void
139client_disconnect_cb (void *cls,
140 struct GNUNET_SERVICE_Client *client,
141 void *app_ctx)
142{
143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
144 "Client %p disconnected\n",
145 client);
146}
147
148
149/**
150 * Add a client to our list of active clients.
151 *
152 * @param cls NULL
153 * @param client client to add
154 * @param mq message queue for @a client
155 * @return internal namestore client structure for this client
156 */
157static void *
158client_connect_cb (void *cls,
159 struct GNUNET_SERVICE_Client *client,
160 struct GNUNET_MQ_Handle *mq)
161{
162 return client;
163}
164
165
166/**
167 * Task run during shutdown.
168 *
169 * @param cls unused
170 */
171static void
172shutdown_task (void *cls)
173{
174 struct Ego *e;
175
176 if (NULL != nc)
177 {
178 GNUNET_notification_context_destroy (nc);
179 nc = NULL;
180 }
181 if (NULL != stats)
182 {
183 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
184 stats = NULL;
185 }
186 GNUNET_CONFIGURATION_destroy (subsystem_cfg);
187 subsystem_cfg = NULL;
188 GNUNET_free (subsystem_cfg_file);
189 subsystem_cfg_file = NULL;
190 GNUNET_free (ego_directory);
191 ego_directory = NULL;
192 while (NULL != (e = ego_head))
193 {
194 GNUNET_CONTAINER_DLL_remove (ego_head,
195 ego_tail,
196 e);
197 GNUNET_free (e->identifier);
198 GNUNET_free (e);
199 }
200}
201
202
203/**
204 * Send a result code back to the client.
205 *
206 * @param client client that should receive the result code
207 * @param result_code code to transmit
208 * @param emsg error message to include (or NULL for none)
209 */
210static void
211send_result_code (struct GNUNET_SERVICE_Client *client,
212 uint32_t result_code,
213 const char *emsg)
214{
215 struct ResultCodeMessage *rcm;
216 struct GNUNET_MQ_Envelope *env;
217 size_t elen;
218
219 if (NULL == emsg)
220 elen = 0;
221 else
222 elen = strlen (emsg) + 1;
223 env =
224 GNUNET_MQ_msg_extra (rcm, elen, GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE);
225 rcm->result_code = htonl (result_code);
226 if (0 < elen)
227 GNUNET_memcpy (&rcm[1], emsg, elen);
228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229 "Sending result %d (%s) to client\n",
230 (int) result_code,
231 emsg);
232 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
233}
234
235
236/**
237 * Create an update message with information about the current state of an ego.
238 *
239 * @param ego ego to create message for
240 * @return corresponding update message
241 */
242static struct GNUNET_MQ_Envelope *
243create_update_message (struct Ego *ego)
244{
245 struct UpdateMessage *um;
246 struct GNUNET_MQ_Envelope *env;
247 size_t name_len;
248
249 name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
250 env = GNUNET_MQ_msg_extra (um, name_len, GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
251 um->name_len = htons (name_len);
252 um->end_of_list = htons (GNUNET_NO);
253 um->private_key = ego->pk;
254 GNUNET_memcpy (&um[1], ego->identifier, name_len);
255 return env;
256}
257
258
259/**
260 * Create a set default message with information about the current state of an ego.
261 *
262 * @param ego ego to create message for
263 * @param servicename name of the service to provide in the message
264 * @return corresponding set default message
265 */
266static struct GNUNET_MQ_Envelope *
267create_set_default_message (struct Ego *ego,
268 const char *servicename)
269{
270 struct SetDefaultMessage *sdm;
271 struct GNUNET_MQ_Envelope *env;
272 size_t name_len;
273
274 name_len = (NULL == servicename) ? 0 : (strlen (servicename) + 1);
275 env = GNUNET_MQ_msg_extra (sdm,
276 name_len,
277 GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT);
278 sdm->name_len = htons (name_len);
279 sdm->reserved = htons (0);
280 sdm->private_key = ego->pk;
281 GNUNET_memcpy (&sdm[1], servicename, name_len);
282 return env;
283}
284
285
286/**
287 * Handler for START message from client, sends information
288 * about all identities to the client immediately and
289 * adds the client to the notification context for future
290 * updates.
291 *
292 * @param cls a `struct GNUNET_SERVICE_Client *`
293 * @param message the message received
294 */
295static void
296handle_start_message (void *cls,
297 const struct GNUNET_MessageHeader *message)
298{
299 struct GNUNET_SERVICE_Client *client = cls;
300
301 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
302 "Received START message from client\n");
303 GNUNET_SERVICE_client_mark_monitor (client);
304 GNUNET_SERVICE_client_disable_continue_warning (client);
305 GNUNET_notification_context_add (nc,
306 GNUNET_SERVICE_client_get_mq (client));
307 for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next)
308 {
309 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
310 create_update_message (ego));
311 }
312 {
313 struct UpdateMessage *ume;
314 struct GNUNET_MQ_Envelope *env;
315
316 env = GNUNET_MQ_msg_extra (ume,
317 0,
318 GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
319 ume->end_of_list = htons (GNUNET_YES);
320 ume->name_len = htons (0);
321 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
322 env);
323 }
324 GNUNET_SERVICE_client_continue (client);
325}
326
327
328/**
329 * Handler for LOOKUP message from client, sends information
330 * about ONE identity to the client immediately.
331 *
332 * @param cls unused
333 * @param message the message received
334 * @return #GNUNET_SYSERR if message was ill-formed
335 */
336static int
337check_lookup_message (void *cls,
338 const struct LookupMessage *message)
339{
340 GNUNET_MQ_check_zero_termination (message);
341 return GNUNET_OK;
342}
343
344
345/**
346 * Handler for LOOKUP message from client, sends information
347 * about ONE identity to the client immediately.
348 *
349 * @param cls a `struct GNUNET_SERVICE_Client *`
350 * @param message the message received
351 */
352static void
353handle_lookup_message (void *cls,
354 const struct LookupMessage *message)
355{
356 struct GNUNET_SERVICE_Client *client = cls;
357 const char *name;
358 struct GNUNET_MQ_Envelope *env;
359 struct Ego *ego;
360
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362 "Received LOOKUP message from client\n");
363 name = (const char *) &message[1];
364 for (ego = ego_head; NULL != ego; ego = ego->next)
365 {
366 if (0 != strcasecmp (name, ego->identifier))
367 continue;
368 env = create_update_message (ego);
369 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
370 GNUNET_SERVICE_client_continue (client);
371 return;
372 }
373 send_result_code (client, 0, "ego not found");
374 GNUNET_SERVICE_client_continue (client);
375}
376
377
378/**
379 * Handler for LOOKUP message from client, sends information
380 * about ONE identity to the client immediately.
381 *
382 * @param cls unused
383 * @param message the message received
384 * @return #GNUNET_SYSERR if message was ill-formed
385 */
386static int
387check_lookup_by_suffix_message (void *cls,
388 const struct LookupMessage *message)
389{
390 GNUNET_MQ_check_zero_termination (message);
391 return GNUNET_OK;
392}
393
394
395/**
396 * Handler for LOOKUP_BY_SUFFIX message from client, sends information
397 * about ONE identity to the client immediately.
398 *
399 * @param cls a `struct GNUNET_SERVICE_Client *`
400 * @param message the message received
401 */
402static void
403handle_lookup_by_suffix_message (void *cls,
404 const struct LookupMessage *message)
405{
406 struct GNUNET_SERVICE_Client *client = cls;
407 const char *name;
408 struct GNUNET_MQ_Envelope *env;
409 struct Ego *lprefix;
410
411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
412 "Received LOOKUP_BY_SUFFIX message from client\n");
413 name = (const char *) &message[1];
414 lprefix = NULL;
415 for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next)
416 {
417 if ((strlen (ego->identifier) <= strlen (name)) &&
418 (0 == strcmp (ego->identifier,
419 &name[strlen (name) - strlen (ego->identifier)])) &&
420 ((strlen (name) == strlen (ego->identifier)) ||
421 ('.' == name[strlen (name) - strlen (ego->identifier) - 1])) &&
422 ((NULL == lprefix) ||
423 (strlen (ego->identifier) > strlen (lprefix->identifier))))
424 {
425 /* found better match, update! */
426 lprefix = ego;
427 }
428 }
429 if (NULL != lprefix)
430 {
431 env = create_update_message (lprefix);
432 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
433 GNUNET_SERVICE_client_continue (client);
434 return;
435 }
436 send_result_code (client, 0, "ego not found");
437 GNUNET_SERVICE_client_continue (client);
438}
439
440
441/**
442 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message
443 *
444 * @param cls client sending the message
445 * @param msg message of type `struct GetDefaultMessage`
446 * @return #GNUNET_OK if @a msg is well-formed
447 */
448static int
449check_get_default_message (void *cls,
450 const struct GetDefaultMessage *msg)
451{
452 uint16_t size;
453 uint16_t name_len;
454 const char *name;
455
456 size = ntohs (msg->header.size);
457 if (size <= sizeof(struct GetDefaultMessage))
458 {
459 GNUNET_break (0);
460 return GNUNET_SYSERR;
461 }
462 name = (const char *) &msg[1];
463 name_len = ntohs (msg->name_len);
464 if ((name_len + sizeof(struct GetDefaultMessage) != size) ||
465 (0 != ntohs (msg->reserved)) || ('\0' != name[name_len - 1]))
466 {
467 GNUNET_break (0);
468 return GNUNET_SYSERR;
469 }
470 return GNUNET_OK;
471}
472
473
474/**
475 * Handler for GET_DEFAULT message from client, returns
476 * default identity for some service.
477 *
478 * @param cls unused
479 * @param client who sent the message
480 * @param message the message received
481 */
482static void
483handle_get_default_message (void *cls,
484 const struct GetDefaultMessage *gdm)
485{
486 struct GNUNET_MQ_Envelope *env;
487 struct GNUNET_SERVICE_Client *client = cls;
488 char *name;
489 char *identifier;
490
491 name = GNUNET_strdup ((const char *) &gdm[1]);
492 GNUNET_STRINGS_utf8_tolower ((const char *) &gdm[1],
493 name);
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "Received GET_DEFAULT for service `%s' from client\n",
496 name);
497 if (GNUNET_OK !=
498 GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
499 name,
500 "DEFAULT_IDENTIFIER",
501 &identifier))
502 {
503 send_result_code (client, 1, gettext_noop ("no default known"));
504 GNUNET_SERVICE_client_continue (client);
505 GNUNET_free (name);
506 return;
507 }
508 for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next)
509 {
510 if (0 == strcmp (ego->identifier, identifier))
511 {
512 env = create_set_default_message (ego, name);
513 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
514 GNUNET_SERVICE_client_continue (client);
515 GNUNET_free (identifier);
516 GNUNET_free (name);
517 return;
518 }
519 }
520 GNUNET_free (identifier);
521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
522 "Failed to find ego `%s'\n",
523 name);
524 GNUNET_free (name);
525 send_result_code (client,
526 1,
527 gettext_noop (
528 "default configured, but ego unknown (internal error)"));
529 GNUNET_SERVICE_client_continue (client);
530}
531
532
533/**
534 * Compare the given two private keys for equality.
535 *
536 * @param pk1 one private key
537 * @param pk2 another private key
538 * @return 0 if the keys are equal
539 */
540static int
541key_cmp (const struct GNUNET_IDENTITY_PrivateKey *pk1,
542 const struct GNUNET_IDENTITY_PrivateKey *pk2)
543{
544 return GNUNET_memcmp (pk1, pk2);
545}
546
547
548/**
549 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT message
550 *
551 * @param cls client sending the message
552 * @param msg message of type `struct SetDefaultMessage`
553 * @return #GNUNET_OK if @a msg is well-formed
554 */
555static int
556check_set_default_message (void *cls,
557 const struct SetDefaultMessage *msg)
558{
559 uint16_t size;
560 uint16_t name_len;
561 const char *str;
562
563 size = ntohs (msg->header.size);
564 if (size <= sizeof(struct SetDefaultMessage))
565 {
566 GNUNET_break (0);
567 return GNUNET_SYSERR;
568 }
569 name_len = ntohs (msg->name_len);
570 GNUNET_break (0 == ntohs (msg->reserved));
571 if (name_len + sizeof(struct SetDefaultMessage) != size)
572 {
573 GNUNET_break (0);
574 return GNUNET_SYSERR;
575 }
576 str = (const char *) &msg[1];
577 if ('\0' != str[name_len - 1])
578 {
579 GNUNET_break (0);
580 return GNUNET_SYSERR;
581 }
582 return GNUNET_OK;
583}
584
585
586/**
587 * Handler for SET_DEFAULT message from client, updates
588 * default identity for some service.
589 *
590 * @param cls unused
591 * @param client who sent the message
592 * @param message the message received
593 */
594static void
595handle_set_default_message (void *cls,
596 const struct SetDefaultMessage *sdm)
597{
598 struct Ego *ego;
599 struct GNUNET_SERVICE_Client *client = cls;
600 char *str;
601
602 str = GNUNET_strdup ((const char *) &sdm[1]);
603 GNUNET_STRINGS_utf8_tolower ((const char *) &sdm[1], str);
604
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "Received SET_DEFAULT for service `%s' from client\n",
607 str);
608 for (ego = ego_head; NULL != ego; ego = ego->next)
609 {
610 if (0 == key_cmp (&ego->pk,
611 &sdm->private_key))
612 {
613 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
614 str,
615 "DEFAULT_IDENTIFIER",
616 ego->identifier);
617 if (GNUNET_OK !=
618 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
619 GNUNET_log (
620 GNUNET_ERROR_TYPE_ERROR,
621 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
622 subsystem_cfg_file);
623 send_result_code (client, 0, NULL);
624 GNUNET_SERVICE_client_continue (client);
625 GNUNET_free (str);
626 return;
627 }
628 }
629 send_result_code (client,
630 1,
631 _ ("Unknown ego specified for service (internal error)"));
632 GNUNET_free (str);
633 GNUNET_SERVICE_client_continue (client);
634}
635
636
637/**
638 * Send an updated message for the given ego to all listeners.
639 *
640 * @param ego ego to send the update for
641 */
642static void
643notify_listeners (struct Ego *ego)
644{
645 struct UpdateMessage *um;
646 size_t name_len;
647
648 name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1);
649 um = GNUNET_malloc (sizeof(struct UpdateMessage) + name_len);
650 um->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE);
651 um->header.size = htons (sizeof(struct UpdateMessage) + name_len);
652 um->name_len = htons (name_len);
653 um->end_of_list = htons (GNUNET_NO);
654 um->private_key = ego->pk;
655 GNUNET_memcpy (&um[1], ego->identifier, name_len);
656 GNUNET_notification_context_broadcast (nc, &um->header, GNUNET_NO);
657 GNUNET_free (um);
658}
659
660
661/**
662 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_CREATE message
663 *
664 * @param cls client sending the message
665 * @param msg message of type `struct CreateRequestMessage`
666 * @return #GNUNET_OK if @a msg is well-formed
667 */
668static int
669check_create_message (void *cls,
670 const struct CreateRequestMessage *msg)
671{
672 uint16_t size;
673 uint16_t name_len;
674 const char *str;
675
676 size = ntohs (msg->header.size);
677 if (size <= sizeof(struct CreateRequestMessage))
678 {
679 GNUNET_break (0);
680 return GNUNET_SYSERR;
681 }
682 name_len = ntohs (msg->name_len);
683 GNUNET_break (0 == ntohs (msg->reserved));
684 if (name_len + sizeof(struct CreateRequestMessage) != size)
685 {
686 GNUNET_break (0);
687 return GNUNET_SYSERR;
688 }
689 str = (const char *) &msg[1];
690 if ('\0' != str[name_len - 1])
691 {
692 GNUNET_break (0);
693 return GNUNET_SYSERR;
694 }
695 return GNUNET_OK;
696}
697
698
699/**
700 * Handler for CREATE message from client, creates new identity.
701 *
702 * @param cls unused
703 * @param client who sent the message
704 * @param message the message received
705 */
706static void
707handle_create_message (void *cls,
708 const struct CreateRequestMessage *crm)
709{
710 struct GNUNET_SERVICE_Client *client = cls;
711 struct Ego *ego;
712 char *str;
713 char *fn;
714
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREATE message from client\n");
716 str = GNUNET_strdup ((const char *) &crm[1]);
717 GNUNET_STRINGS_utf8_tolower ((const char *) &crm[1], str);
718 for (ego = ego_head; NULL != ego; ego = ego->next)
719 {
720 if (0 == strcmp (ego->identifier, str))
721 {
722 send_result_code (client,
723 1,
724 gettext_noop (
725 "identifier already in use for another ego"));
726 GNUNET_SERVICE_client_continue (client);
727 GNUNET_free (str);
728 return;
729 }
730 }
731 ego = GNUNET_new (struct Ego);
732 ego->pk = crm->private_key;
733 ego->identifier = GNUNET_strdup (str);
734 GNUNET_CONTAINER_DLL_insert (ego_head,
735 ego_tail,
736 ego);
737 send_result_code (client, 0, NULL);
738 fn = get_ego_filename (ego);
739 if (GNUNET_OK !=
740 GNUNET_DISK_fn_write (fn,
741 &crm->private_key,
742 sizeof(struct GNUNET_IDENTITY_PrivateKey),
743 GNUNET_DISK_PERM_USER_READ
744 | GNUNET_DISK_PERM_USER_WRITE))
745 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn);
746 GNUNET_free (fn);
747 GNUNET_free (str);
748 notify_listeners (ego);
749 GNUNET_SERVICE_client_continue (client);
750}
751
752
753/**
754 * Closure for 'handle_ego_rename'.
755 */
756struct RenameContext
757{
758 /**
759 * Old name.
760 */
761 const char *old_name;
762
763 /**
764 * New name.
765 */
766 const char *new_name;
767};
768
769/**
770 * An ego was renamed; rename it in all subsystems where it is
771 * currently set as the default.
772 *
773 * @param cls the 'struct RenameContext'
774 * @param section a section in the configuration to process
775 */
776static void
777handle_ego_rename (void *cls, const char *section)
778{
779 struct RenameContext *rc = cls;
780 char *id;
781
782 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
783 section,
784 "DEFAULT_IDENTIFIER",
785 &id))
786 return;
787 if (0 != strcmp (id, rc->old_name))
788 {
789 GNUNET_free (id);
790 return;
791 }
792 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
793 section,
794 "DEFAULT_IDENTIFIER",
795 rc->new_name);
796 GNUNET_free (id);
797}
798
799
800/**
801 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME message
802 *
803 * @param cls client sending the message
804 * @param msg message of type `struct RenameMessage`
805 * @return #GNUNET_OK if @a msg is well-formed
806 */
807static int
808check_rename_message (void *cls, const struct RenameMessage *msg)
809{
810 uint16_t size;
811 uint16_t old_name_len;
812 uint16_t new_name_len;
813 const char *old_name;
814 const char *new_name;
815
816 size = ntohs (msg->header.size);
817 if (size <= sizeof(struct RenameMessage))
818 {
819 GNUNET_break (0);
820 return GNUNET_SYSERR;
821 }
822 old_name_len = ntohs (msg->old_name_len);
823 new_name_len = ntohs (msg->new_name_len);
824 old_name = (const char *) &msg[1];
825 new_name = &old_name[old_name_len];
826 if ((old_name_len + new_name_len + sizeof(struct RenameMessage) != size) ||
827 ('\0' != old_name[old_name_len - 1]) ||
828 ('\0' != new_name[new_name_len - 1]))
829 {
830 GNUNET_break (0);
831 return GNUNET_SYSERR;
832 }
833
834 return GNUNET_OK;
835}
836
837
838/**
839 * Handler for RENAME message from client, creates
840 * new identity.
841 *
842 * @param cls unused
843 * @param client who sent the message
844 * @param message the message received
845 */
846static void
847handle_rename_message (void *cls, const struct RenameMessage *rm)
848{
849 uint16_t old_name_len;
850 struct Ego *ego;
851 char *old_name;
852 char *new_name;
853 struct RenameContext rename_ctx;
854 struct GNUNET_SERVICE_Client *client = cls;
855 char *fn_old;
856 char *fn_new;
857 const char *old_name_tmp;
858
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received RENAME message from client\n");
860 old_name_len = ntohs (rm->old_name_len);
861 old_name_tmp = (const char *) &rm[1];
862 old_name = GNUNET_strdup (old_name_tmp);
863 GNUNET_STRINGS_utf8_tolower (old_name_tmp, old_name);
864 new_name = GNUNET_strdup (&old_name_tmp[old_name_len]);
865 GNUNET_STRINGS_utf8_tolower (&old_name_tmp[old_name_len], new_name);
866
867 /* check if new name is already in use */
868 for (ego = ego_head; NULL != ego; ego = ego->next)
869 {
870 if (0 == strcmp (ego->identifier, new_name))
871 {
872 send_result_code (client, 1, gettext_noop ("target name already exists"));
873 GNUNET_SERVICE_client_continue (client);
874 GNUNET_free (old_name);
875 GNUNET_free (new_name);
876 return;
877 }
878 }
879
880 /* locate old name and, if found, perform rename */
881 for (ego = ego_head; NULL != ego; ego = ego->next)
882 {
883 if (0 == strcmp (ego->identifier, old_name))
884 {
885 fn_old = get_ego_filename (ego);
886 GNUNET_free (ego->identifier);
887 rename_ctx.old_name = old_name;
888 rename_ctx.new_name = new_name;
889 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
890 &handle_ego_rename,
891 &rename_ctx);
892 if (GNUNET_OK !=
893 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
894 GNUNET_log (
895 GNUNET_ERROR_TYPE_ERROR,
896 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
897 subsystem_cfg_file);
898 ego->identifier = GNUNET_strdup (new_name);
899 fn_new = get_ego_filename (ego);
900 if (0 != rename (fn_old, fn_new))
901 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old);
902 GNUNET_free (fn_old);
903 GNUNET_free (fn_new);
904 GNUNET_free (old_name);
905 GNUNET_free (new_name);
906 notify_listeners (ego);
907 send_result_code (client, 0, NULL);
908 GNUNET_SERVICE_client_continue (client);
909 return;
910 }
911 }
912
913 /* failed to locate old name */
914 send_result_code (client, 1, gettext_noop ("no matching ego found"));
915 GNUNET_free (old_name);
916 GNUNET_free (new_name);
917 GNUNET_SERVICE_client_continue (client);
918}
919
920
921/**
922 * An ego was removed, remove it from all subsystems where it is
923 * currently set as the default.
924 *
925 * @param cls name of the removed ego (const char *)
926 * @param section a section in the configuration to process
927 */
928static void
929handle_ego_delete (void *cls, const char *section)
930{
931 const char *identifier = cls;
932 char *id;
933
934 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg,
935 section,
936 "DEFAULT_IDENTIFIER",
937 &id))
938 return;
939 if (0 != strcmp (id, identifier))
940 {
941 GNUNET_free (id);
942 return;
943 }
944 GNUNET_CONFIGURATION_set_value_string (subsystem_cfg,
945 section,
946 "DEFAULT_IDENTIFIER",
947 NULL);
948 GNUNET_free (id);
949}
950
951
952/**
953 * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE message
954 *
955 * @param cls client sending the message
956 * @param msg message of type `struct DeleteMessage`
957 * @return #GNUNET_OK if @a msg is well-formed
958 */
959static int
960check_delete_message (void *cls, const struct DeleteMessage *msg)
961{
962 uint16_t size;
963 uint16_t name_len;
964 const char *name;
965
966 size = ntohs (msg->header.size);
967 if (size <= sizeof(struct DeleteMessage))
968 {
969 GNUNET_break (0);
970 return GNUNET_SYSERR;
971 }
972 name = (const char *) &msg[1];
973 name_len = ntohs (msg->name_len);
974 if ((name_len + sizeof(struct DeleteMessage) != size) ||
975 (0 != ntohs (msg->reserved)) || ('\0' != name[name_len - 1]))
976 {
977 GNUNET_break (0);
978 return GNUNET_SYSERR;
979 }
980 return GNUNET_OK;
981}
982
983
984/**
985 * Handler for DELETE message from client, creates
986 * new identity.
987 *
988 * @param cls unused
989 * @param client who sent the message
990 * @param message the message received
991 */
992static void
993handle_delete_message (void *cls, const struct DeleteMessage *dm)
994{
995 struct Ego *ego;
996 char *name;
997 char *fn;
998 struct GNUNET_SERVICE_Client *client = cls;
999
1000 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DELETE message from client\n");
1001 name = GNUNET_strdup ((const char *) &dm[1]);
1002 GNUNET_STRINGS_utf8_tolower ((const char *) &dm[1], name);
1003
1004 for (ego = ego_head; NULL != ego; ego = ego->next)
1005 {
1006 if (0 == strcmp (ego->identifier, name))
1007 {
1008 GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, ego);
1009 GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg,
1010 &handle_ego_delete,
1011 ego->identifier);
1012 if (GNUNET_OK !=
1013 GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file))
1014 GNUNET_log (
1015 GNUNET_ERROR_TYPE_ERROR,
1016 _ ("Failed to write subsystem default identifier map to `%s'.\n"),
1017 subsystem_cfg_file);
1018 fn = get_ego_filename (ego);
1019 if (0 != unlink (fn))
1020 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
1021 GNUNET_free (fn);
1022 GNUNET_free (ego->identifier);
1023 ego->identifier = NULL;
1024 notify_listeners (ego);
1025 GNUNET_free (ego);
1026 GNUNET_free (name);
1027 send_result_code (client, 0, NULL);
1028 GNUNET_SERVICE_client_continue (client);
1029 return;
1030 }
1031 }
1032
1033 send_result_code (client, 1, gettext_noop ("no matching ego found"));
1034 GNUNET_free (name);
1035 GNUNET_SERVICE_client_continue (client);
1036}
1037
1038
1039static int
1040read_from_file (const char *filename,
1041 void *buf,
1042 size_t buf_size)
1043{
1044 int fd;
1045 struct stat sb;
1046
1047 fd = open (filename,
1048 O_RDONLY);
1049 if (-1 == fd)
1050 {
1051 memset (buf,
1052 0,
1053 buf_size);
1054 return GNUNET_SYSERR;
1055 }
1056 if (0 != fstat (fd,
1057 &sb))
1058 {
1059 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1060 "stat",
1061 filename);
1062 GNUNET_assert (0 == close (fd));
1063 memset (buf,
1064 0,
1065 buf_size);
1066 return GNUNET_SYSERR;
1067 }
1068 if (sb.st_size != buf_size)
1069 {
1070 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1071 "File `%s' has wrong size (%llu), expected %llu bytes\n",
1072 filename,
1073 (unsigned long long) sb.st_size,
1074 (unsigned long long) buf_size);
1075 GNUNET_assert (0 == close (fd));
1076 memset (buf,
1077 0,
1078 buf_size);
1079 return GNUNET_SYSERR;
1080 }
1081 if (buf_size !=
1082 read (fd,
1083 buf,
1084 buf_size))
1085 {
1086 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
1087 "read",
1088 filename);
1089 GNUNET_assert (0 == close (fd));
1090 memset (buf,
1091 0,
1092 buf_size);
1093 return GNUNET_SYSERR;
1094 }
1095 GNUNET_assert (0 == close (fd));
1096 return GNUNET_OK;
1097}
1098
1099
1100/**
1101 * Process the given file from the "EGODIR". Parses the file
1102 * and creates the respective 'struct Ego' in memory.
1103 *
1104 * @param cls NULL
1105 * @param filename name of the file to parse
1106 * @return #GNUNET_OK to continue to iterate,
1107 * #GNUNET_NO to stop iteration with no error,
1108 * #GNUNET_SYSERR to abort iteration with error!
1109 */
1110static int
1111process_ego_file (void *cls,
1112 const char *filename)
1113{
1114 struct Ego *ego;
1115 const char *fn;
1116
1117 fn = strrchr (filename, (int) DIR_SEPARATOR);
1118 if (NULL == fn)
1119 {
1120 GNUNET_break (0);
1121 return GNUNET_OK;
1122 }
1123 ego = GNUNET_new (struct Ego);
1124 if (GNUNET_OK !=
1125 read_from_file (filename,
1126 &ego->pk,
1127 sizeof (ego->pk)))
1128 {
1129 GNUNET_free (ego);
1130 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1131 _ ("Failed to parse ego information in `%s'\n"),
1132 filename);
1133 return GNUNET_OK;
1134 }
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136 "Loaded ego `%s'\n",
1137 fn + 1);
1138 ego->identifier = GNUNET_strdup (fn + 1);
1139 GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego);
1140 return GNUNET_OK;
1141}
1142
1143
1144/**
1145 * Handle network size estimate clients.
1146 *
1147 * @param cls closure
1148 * @param server the initialized server
1149 * @param c configuration to use
1150 */
1151static void
1152run (void *cls,
1153 const struct GNUNET_CONFIGURATION_Handle *c,
1154 struct GNUNET_SERVICE_Handle *service)
1155{
1156 cfg = c;
1157 nc = GNUNET_notification_context_create (1);
1158 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1159 "identity",
1160 "EGODIR",
1161 &ego_directory))
1162 {
1163 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR");
1164 GNUNET_SCHEDULER_shutdown ();
1165 return;
1166 }
1167 if (GNUNET_OK !=
1168 GNUNET_CONFIGURATION_get_value_filename (cfg,
1169 "identity",
1170 "SUBSYSTEM_CFG",
1171 &subsystem_cfg_file))
1172 {
1173 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1174 "identity",
1175 "SUBSYSTEM_CFG");
1176 GNUNET_SCHEDULER_shutdown ();
1177 return;
1178 }
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1180 "Loading subsystem configuration `%s'\n",
1181 subsystem_cfg_file);
1182 subsystem_cfg = GNUNET_CONFIGURATION_create ();
1183 if ((GNUNET_YES == GNUNET_DISK_file_test (subsystem_cfg_file)) &&
1184 (GNUNET_OK !=
1185 GNUNET_CONFIGURATION_parse (subsystem_cfg, subsystem_cfg_file)))
1186 {
1187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1188 _ (
1189 "Failed to parse subsystem identity configuration file `%s'\n"),
1190 subsystem_cfg_file);
1191 GNUNET_SCHEDULER_shutdown ();
1192 return;
1193 }
1194 stats = GNUNET_STATISTICS_create ("identity", cfg);
1195 if (GNUNET_OK != GNUNET_DISK_directory_create (ego_directory))
1196 {
1197 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1198 _ ("Failed to create directory `%s' for storing egos\n"),
1199 ego_directory);
1200 }
1201 GNUNET_DISK_directory_scan (ego_directory,
1202 &process_ego_file,
1203 NULL);
1204 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1205}
1206
1207
1208/**
1209 * Define "main" method using service macro.
1210 */
1211GNUNET_SERVICE_MAIN (
1212 "identity",
1213 GNUNET_SERVICE_OPTION_NONE,
1214 &run,
1215 &client_connect_cb,
1216 &client_disconnect_cb,
1217 NULL,
1218 GNUNET_MQ_hd_fixed_size (start_message,
1219 GNUNET_MESSAGE_TYPE_IDENTITY_START,
1220 struct GNUNET_MessageHeader,
1221 NULL),
1222 GNUNET_MQ_hd_var_size (lookup_message,
1223 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP,
1224 struct LookupMessage,
1225 NULL),
1226 GNUNET_MQ_hd_var_size (lookup_by_suffix_message,
1227 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX,
1228 struct LookupMessage,
1229 NULL),
1230 GNUNET_MQ_hd_var_size (get_default_message,
1231 GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT,
1232 struct GetDefaultMessage,
1233 NULL),
1234 GNUNET_MQ_hd_var_size (set_default_message,
1235 GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
1236 struct SetDefaultMessage,
1237 NULL),
1238 GNUNET_MQ_hd_var_size (create_message,
1239 GNUNET_MESSAGE_TYPE_IDENTITY_CREATE,
1240 struct CreateRequestMessage,
1241 NULL),
1242 GNUNET_MQ_hd_var_size (rename_message,
1243 GNUNET_MESSAGE_TYPE_IDENTITY_RENAME,
1244 struct RenameMessage,
1245 NULL),
1246 GNUNET_MQ_hd_var_size (delete_message,
1247 GNUNET_MESSAGE_TYPE_IDENTITY_DELETE,
1248 struct DeleteMessage,
1249 NULL),
1250 GNUNET_MQ_handler_end ());
1251
1252
1253/* end of gnunet-service-identity.c */
diff --git a/src/identity/identity.conf.in b/src/identity/identity.conf.in
deleted file mode 100644
index f5d454323..000000000
--- a/src/identity/identity.conf.in
+++ /dev/null
@@ -1,17 +0,0 @@
1[identity]
2START_ON_DEMAND = @START_ON_DEMAND@
3RUN_PER_USER = YES
4@JAVAPORT@PORT = 2108
5HOSTNAME = localhost
6BINARY = gnunet-service-identity
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12
13# Directory where we store information about our egos
14EGODIR = $GNUNET_DATA_HOME/identity/egos/
15
16# File where we store default identities for subsystems
17SUBSYSTEM_CFG = $GNUNET_CONFIG_HOME/identity/subsystem_defaults.conf
diff --git a/src/identity/identity.h b/src/identity/identity.h
deleted file mode 100644
index 11c5883bc..000000000
--- a/src/identity/identity.h
+++ /dev/null
@@ -1,281 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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 */
20
21/**
22 * @author Christian Grothoff
23 * @file identity/identity.h
24 *
25 * @brief Common type definitions for the identity
26 * service and API.
27 */
28#ifndef IDENTITY_H
29#define IDENTITY_H
30
31#include "gnunet_common.h"
32
33/**
34 * Handle for an ego.
35 */
36struct GNUNET_IDENTITY_Ego
37{
38 /**
39 * Hash of the private key of this ego.
40 */
41 struct GNUNET_HashCode id;
42
43 /**
44 * The identity key pair
45 */
46 struct GNUNET_IDENTITY_PublicKey pub;
47
48 /**
49 * The identity key pair
50 */
51 struct GNUNET_IDENTITY_PrivateKey pk;
52
53 /**
54 * Current name associated with this ego.
55 */
56 char *name;
57
58 /**
59 * Client context associated with this ego.
60 */
61 void *ctx;
62
63 /**
64 * Set to true once @e pub was initialized
65 */
66 bool pub_initialized;
67};
68
69
70
71
72GNUNET_NETWORK_STRUCT_BEGIN
73
74
75/**
76 * Answer from service to client about last operation;
77 * GET_DEFAULT maybe answered with this message on failure;
78 * CREATE and RENAME will always be answered with this message.
79 */
80struct ResultCodeMessage
81{
82 /**
83 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE
84 */
85 struct GNUNET_MessageHeader header;
86
87 /**
88 * Status code for the last operation, in NBO.
89 * (currently not used).
90 */
91 uint32_t result_code GNUNET_PACKED;
92
93 /* followed by 0-terminated error message (on error) */
94};
95
96
97/**
98 * Client informs service about desire to lookup a (single) pseudonym.
99 */
100struct LookupMessage
101{
102 /**
103 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP or
104 * #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX
105 */
106 struct GNUNET_MessageHeader header;
107
108 /* followed by 0-terminated ego name */
109};
110
111
112/**
113 * Service informs client about status of a pseudonym.
114 */
115struct UpdateMessage
116{
117 /**
118 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE
119 */
120 struct GNUNET_MessageHeader header;
121
122 /**
123 * Number of bytes in ego name string including 0-termination, in NBO;
124 * 0 if the ego was deleted.
125 */
126 uint16_t name_len GNUNET_PACKED;
127
128 /**
129 * Usually #GNUNET_NO, #GNUNET_YES to signal end of list.
130 */
131 uint16_t end_of_list GNUNET_PACKED;
132
133 /**
134 * The private key
135 */
136 struct GNUNET_IDENTITY_PrivateKey private_key;
137
138 /* followed by 0-terminated ego name */
139};
140
141
142/**
143 * Client requests knowledge about default identity for
144 * a subsystem from identity service.
145 */
146struct GetDefaultMessage
147{
148 /**
149 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT
150 */
151 struct GNUNET_MessageHeader header;
152
153 /**
154 * Number of bytes in service name string including 0-termination, in NBO.
155 */
156 uint16_t name_len GNUNET_PACKED;
157
158 /**
159 * Always zero.
160 */
161 uint16_t reserved GNUNET_PACKED;
162
163
164 /* followed by 0-terminated service name */
165};
166
167
168/**
169 * Used from service to client as a result to the GET_DEFAULT
170 * message, used from client to service to SET_DEFAULT.
171 */
172struct SetDefaultMessage
173{
174 /**
175 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
176 */
177 struct GNUNET_MessageHeader header;
178
179 /**
180 * Number of bytes in service name string including 0-termination, in NBO.
181 */
182 uint16_t name_len GNUNET_PACKED;
183
184 /**
185 * Always zero.
186 */
187 uint16_t reserved GNUNET_PACKED;
188
189 /**
190 * The private key
191 */
192 struct GNUNET_IDENTITY_PrivateKey private_key;
193
194 /* followed by 0-terminated service name */
195};
196
197
198/**
199 * Client requests creation of an identity. Service
200 * will respond with a result code.
201 */
202struct CreateRequestMessage
203{
204 /**
205 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_CREATE
206 */
207 struct GNUNET_MessageHeader header;
208
209 /**
210 * Number of bytes in identity name string including 0-termination, in NBO.
211 */
212 uint16_t name_len GNUNET_PACKED;
213
214 /**
215 * Always zero.
216 */
217 uint16_t reserved GNUNET_PACKED;
218
219 /**
220 * The private key
221 */
222 struct GNUNET_IDENTITY_PrivateKey private_key;
223
224 /* followed by 0-terminated identity name */
225};
226
227
228/**
229 * Client requests renaming of an identity. Service
230 * will respond with a result code.
231 */
232struct RenameMessage
233{
234 /**
235 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME
236 */
237 struct GNUNET_MessageHeader header;
238
239 /**
240 * Number of characters in the old name including 0-termination, in NBO.
241 */
242 uint16_t old_name_len GNUNET_PACKED;
243
244 /**
245 * Number of characters in the new name including 0-termination, in NBO.
246 */
247 uint16_t new_name_len GNUNET_PACKED;
248
249 /* followed by 0-terminated old name */
250 /* followed by 0-terminated new name */
251};
252
253
254/**
255 * Client requests deletion of an identity. Service
256 * will respond with a result code.
257 */
258struct DeleteMessage
259{
260 /**
261 * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE
262 */
263 struct GNUNET_MessageHeader header;
264
265 /**
266 * Number of characters in the name including 0-termination, in NBO.
267 */
268 uint16_t name_len GNUNET_PACKED;
269
270 /**
271 * Always zero.
272 */
273 uint16_t reserved GNUNET_PACKED;
274
275 /* followed by 0-terminated name */
276};
277
278GNUNET_NETWORK_STRUCT_END
279
280
281#endif
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
deleted file mode 100644
index 08a975e65..000000000
--- a/src/identity/identity_api.c
+++ /dev/null
@@ -1,1267 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2016, 2021 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 */
20
21/**
22 * @file identity/identity_api.c
23 * @brief api to interact with the identity service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_protocols.h"
30#include "gnunet_identity_service.h"
31#include "identity.h"
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
34
35
36/**
37 * Handle for an operation with the identity service.
38 */
39struct GNUNET_IDENTITY_Operation
40{
41 /**
42 * Main identity handle.
43 */
44 struct GNUNET_IDENTITY_Handle *h;
45
46 /**
47 * We keep operations in a DLL.
48 */
49 struct GNUNET_IDENTITY_Operation *next;
50
51 /**
52 * We keep operations in a DLL.
53 */
54 struct GNUNET_IDENTITY_Operation *prev;
55
56 /**
57 * Message to send to the identity service.
58 * Allocated at the end of this struct.
59 */
60 const struct GNUNET_MessageHeader *msg;
61
62 /**
63 * Continuation to invoke with the result of the transmission; @e cb
64 * and @e create_cont will be NULL in this case.
65 */
66 GNUNET_IDENTITY_Continuation cont;
67
68 /**
69 * Continuation to invoke with the result of the transmission; @e cb
70 * and @a cb will be NULL in this case.
71 */
72 GNUNET_IDENTITY_CreateContinuation create_cont;
73
74 /**
75 * Private key to return to @e create_cont, or NULL.
76 */
77 struct GNUNET_IDENTITY_PrivateKey pk;
78
79 /**
80 * Continuation to invoke with the result of the transmission for
81 * 'get' operations (@e cont and @a create_cont will be NULL in this case).
82 */
83 GNUNET_IDENTITY_Callback cb;
84
85 /**
86 * Closure for @e cont or @e cb.
87 */
88 void *cls;
89};
90
91
92/**
93 * Handle for the service.
94 */
95struct GNUNET_IDENTITY_Handle
96{
97 /**
98 * Configuration to use.
99 */
100 const struct GNUNET_CONFIGURATION_Handle *cfg;
101
102 /**
103 * Connection to service.
104 */
105 struct GNUNET_MQ_Handle *mq;
106
107 /**
108 * Hash map from the hash of the private key to the
109 * respective `GNUNET_IDENTITY_Ego` handle.
110 */
111 struct GNUNET_CONTAINER_MultiHashMap *egos;
112
113 /**
114 * Function to call when we receive updates.
115 */
116 GNUNET_IDENTITY_Callback cb;
117
118 /**
119 * Closure for @e cb.
120 */
121 void *cb_cls;
122
123 /**
124 * Head of active operations.
125 */
126 struct GNUNET_IDENTITY_Operation *op_head;
127
128 /**
129 * Tail of active operations.
130 */
131 struct GNUNET_IDENTITY_Operation *op_tail;
132
133 /**
134 * Task doing exponential back-off trying to reconnect.
135 */
136 struct GNUNET_SCHEDULER_Task *reconnect_task;
137
138 /**
139 * Time for next connect retry.
140 */
141 struct GNUNET_TIME_Relative reconnect_delay;
142
143 /**
144 * Are we polling for incoming messages right now?
145 */
146 int in_receive;
147};
148
149
150/**
151 * Obtain the ego representing 'anonymous' users.
152 *
153 * @return handle for the anonymous user, MUST NOT be freed
154 */
155struct GNUNET_IDENTITY_Ego *
156GNUNET_IDENTITY_ego_get_anonymous ()
157{
158 static struct GNUNET_IDENTITY_Ego anon;
159 static int setup;
160
161 if (setup)
162 return &anon;
163 anon.pk.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
164 anon.pub.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
165 anon.pk.ecdsa_key = *GNUNET_CRYPTO_ecdsa_key_get_anonymous ();
166 GNUNET_CRYPTO_hash (&anon.pk,
167 sizeof(anon.pk),
168 &anon.id);
169 setup = 1;
170 return &anon;
171}
172
173
174enum GNUNET_GenericReturnValue
175GNUNET_IDENTITY_key_get_public (const struct
176 GNUNET_IDENTITY_PrivateKey *privkey,
177 struct GNUNET_IDENTITY_PublicKey *key)
178{
179 key->type = privkey->type;
180 switch (ntohl (privkey->type))
181 {
182 case GNUNET_IDENTITY_TYPE_ECDSA:
183 GNUNET_CRYPTO_ecdsa_key_get_public (&privkey->ecdsa_key,
184 &key->ecdsa_key);
185 break;
186 case GNUNET_IDENTITY_TYPE_EDDSA:
187 GNUNET_CRYPTO_eddsa_key_get_public (&privkey->eddsa_key,
188 &key->eddsa_key);
189 break;
190 default:
191 GNUNET_break (0);
192 return GNUNET_SYSERR;
193 }
194 return GNUNET_OK;
195}
196
197
198static int
199private_key_create (enum GNUNET_IDENTITY_KeyType ktype,
200 struct GNUNET_IDENTITY_PrivateKey *key)
201{
202 key->type = htonl (ktype);
203 switch (ktype)
204 {
205 case GNUNET_IDENTITY_TYPE_ECDSA:
206 GNUNET_CRYPTO_ecdsa_key_create (&key->ecdsa_key);
207 break;
208 case GNUNET_IDENTITY_TYPE_EDDSA:
209 GNUNET_CRYPTO_eddsa_key_create (&key->eddsa_key);
210 break;
211 default:
212 GNUNET_break (0);
213 return GNUNET_SYSERR;
214 }
215 return GNUNET_OK;
216}
217
218
219/**
220 * Try again to connect to the identity service.
221 *
222 * @param cls handle to the identity service.
223 */
224static void
225reconnect (void *cls);
226
227
228/**
229 * Free ego from hash map.
230 *
231 * @param cls identity service handle
232 * @param key unused
233 * @param value ego to free
234 * @return #GNUNET_OK (continue to iterate)
235 */
236static int
237free_ego (void *cls,
238 const struct GNUNET_HashCode *key,
239 void *value)
240{
241 struct GNUNET_IDENTITY_Handle *h = cls;
242 struct GNUNET_IDENTITY_Ego *ego = value;
243
244 if (NULL != h->cb)
245 h->cb (h->cb_cls, ego,
246 &ego->ctx,
247 NULL);
248 GNUNET_free (ego->name);
249 GNUNET_assert (GNUNET_YES ==
250 GNUNET_CONTAINER_multihashmap_remove (h->egos,
251 key,
252 value));
253 GNUNET_free (ego);
254 return GNUNET_OK;
255}
256
257
258/**
259 * Reschedule a connect attempt to the service.
260 *
261 * @param h transport service to reconnect
262 */
263static void
264reschedule_connect (struct GNUNET_IDENTITY_Handle *h)
265{
266 struct GNUNET_IDENTITY_Operation *op;
267
268 GNUNET_assert (NULL == h->reconnect_task);
269
270 if (NULL != h->mq)
271 {
272 GNUNET_MQ_destroy (h->mq);
273 h->mq = NULL;
274 }
275 while (NULL != (op = h->op_head))
276 {
277 GNUNET_CONTAINER_DLL_remove (h->op_head,
278 h->op_tail,
279 op);
280 if (NULL != op->cont)
281 op->cont (op->cls,
282 "Error in communication with the identity service");
283 else if (NULL != op->cb)
284 op->cb (op->cls, NULL, NULL, NULL);
285 else if (NULL != op->create_cont)
286 op->create_cont (op->cls,
287 NULL,
288 "Failed to communicate with the identity service");
289 GNUNET_free (op);
290 }
291 GNUNET_CONTAINER_multihashmap_iterate (h->egos,
292 &free_ego,
293 h);
294 LOG (GNUNET_ERROR_TYPE_DEBUG,
295 "Scheduling task to reconnect to identity service in %s.\n",
296 GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay,
297 GNUNET_YES));
298 h->reconnect_task =
299 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
300 &reconnect,
301 h);
302 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
303}
304
305
306/**
307 * Generic error handler, called with the appropriate error code and
308 * the same closure specified at the creation of the message queue.
309 * Not every message queue implementation supports an error handler.
310 *
311 * @param cls closure with the `struct GNUNET_IDENTITY_Handle *`
312 * @param error error code
313 */
314static void
315mq_error_handler (void *cls,
316 enum GNUNET_MQ_Error error)
317{
318 struct GNUNET_IDENTITY_Handle *h = cls;
319
320 reschedule_connect (h);
321}
322
323
324/**
325 * We received a result code from the service. Check the message
326 * is well-formed.
327 *
328 * @param cls closure
329 * @param rcm result message received
330 * @return #GNUNET_OK if the message is well-formed
331 */
332static int
333check_identity_result_code (void *cls,
334 const struct ResultCodeMessage *rcm)
335{
336 if (sizeof(*rcm) != htons (rcm->header.size))
337 GNUNET_MQ_check_zero_termination (rcm);
338 return GNUNET_OK;
339}
340
341
342/**
343 * We received a result code from the service.
344 *
345 * @param cls closure
346 * @param rcm result message received
347 */
348static void
349handle_identity_result_code (void *cls,
350 const struct ResultCodeMessage *rcm)
351{
352 struct GNUNET_IDENTITY_Handle *h = cls;
353 struct GNUNET_IDENTITY_Operation *op;
354 uint16_t size = ntohs (rcm->header.size) - sizeof(*rcm);
355 const char *str = (0 == size) ? NULL : (const char *) &rcm[1];
356
357 op = h->op_head;
358 if (NULL == op)
359 {
360 GNUNET_break (0);
361 reschedule_connect (h);
362 return;
363 }
364 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
365 if (NULL != op->cont)
366 op->cont (op->cls, str);
367 else if (NULL != op->cb)
368 op->cb (op->cls, NULL, NULL, NULL);
369 else if (NULL != op->create_cont)
370 op->create_cont (op->cls, (NULL == str) ? &op->pk : NULL, str);
371 GNUNET_free (op);
372}
373
374
375/**
376 * Check validity of identity update message.
377 *
378 * @param cls closure
379 * @param um message received
380 * @return #GNUNET_OK if the message is well-formed
381 */
382static int
383check_identity_update (void *cls,
384 const struct UpdateMessage *um)
385{
386 uint16_t size = ntohs (um->header.size);
387 uint16_t name_len = ntohs (um->name_len);
388 const char *str = (const char *) &um[1];
389
390 if ((size != name_len + sizeof(struct UpdateMessage)) ||
391 ((0 != name_len) && ('\0' != str[name_len - 1])))
392 {
393 GNUNET_break (0);
394 return GNUNET_SYSERR;
395 }
396 return GNUNET_OK;
397}
398
399
400/**
401 * Handle identity update message.
402 *
403 * @param cls closure
404 * @param um message received
405 */
406static void
407handle_identity_update (void *cls,
408 const struct UpdateMessage *um)
409{
410 struct GNUNET_IDENTITY_Handle *h = cls;
411 uint16_t name_len = ntohs (um->name_len);
412 const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
413 struct GNUNET_HashCode id;
414 struct GNUNET_IDENTITY_Ego *ego;
415
416 if (GNUNET_YES == ntohs (um->end_of_list))
417 {
418 /* end of initial list of data */
419 if (NULL != h->cb)
420 h->cb (h->cb_cls, NULL, NULL, NULL);
421 return;
422 }
423 GNUNET_CRYPTO_hash (&um->private_key,
424 sizeof (um->private_key),
425 &id);
426 ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
427 &id);
428 if (NULL == ego)
429 {
430 /* ego was created */
431 if (NULL == str)
432 {
433 /* deletion of unknown ego? not allowed */
434 GNUNET_break (0);
435 reschedule_connect (h);
436 return;
437 }
438 ego = GNUNET_new (struct GNUNET_IDENTITY_Ego);
439 ego->pub_initialized = GNUNET_NO;
440 ego->pk = um->private_key;
441 ego->name = GNUNET_strdup (str);
442 ego->id = id;
443 GNUNET_assert (GNUNET_YES ==
444 GNUNET_CONTAINER_multihashmap_put (
445 h->egos,
446 &ego->id,
447 ego,
448 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
449 }
450 if (NULL == str)
451 {
452 /* ego was deleted */
453 GNUNET_assert (GNUNET_YES ==
454 GNUNET_CONTAINER_multihashmap_remove (h->egos,
455 &ego->id,
456 ego));
457 }
458 else
459 {
460 /* ego changed name */
461 GNUNET_free (ego->name);
462 ego->name = GNUNET_strdup (str);
463 }
464 /* inform application about change */
465 if (NULL != h->cb)
466 h->cb (h->cb_cls,
467 ego,
468 &ego->ctx,
469 str);
470 /* complete deletion */
471 if (NULL == str)
472 {
473 GNUNET_free (ego->name);
474 GNUNET_free (ego);
475 }
476}
477
478
479/**
480 * Function called when we receive a set default message from the
481 * service.
482 *
483 * @param cls closure
484 * @param sdm message received
485 * @return #GNUNET_OK if the message is well-formed
486 */
487static int
488check_identity_set_default (void *cls,
489 const struct SetDefaultMessage *sdm)
490{
491 uint16_t size = ntohs (sdm->header.size) - sizeof(*sdm);
492 uint16_t name_len = ntohs (sdm->name_len);
493 const char *str = (const char *) &sdm[1];
494
495 if ((size != name_len) || ((0 != name_len) && ('\0' != str[name_len - 1])))
496 {
497 GNUNET_break (0);
498 return GNUNET_SYSERR;
499 }
500 GNUNET_break (0 == ntohs (sdm->reserved));
501 return GNUNET_OK;
502}
503
504
505/**
506 * Type of a function to call when we receive a message
507 * from the service.
508 *
509 * @param cls closure
510 * @param sdm message received
511 */
512static void
513handle_identity_set_default (void *cls,
514 const struct SetDefaultMessage *sdm)
515{
516 struct GNUNET_IDENTITY_Handle *h = cls;
517 struct GNUNET_IDENTITY_Operation *op;
518 struct GNUNET_HashCode id;
519 struct GNUNET_IDENTITY_Ego *ego;
520
521 GNUNET_CRYPTO_hash (&sdm->private_key,
522 sizeof(sdm->private_key),
523 &id);
524 ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
525 &id);
526 if (NULL == ego)
527 {
528 GNUNET_break (0);
529 reschedule_connect (h);
530 return;
531 }
532 op = h->op_head;
533 if (NULL == op)
534 {
535 GNUNET_break (0);
536 reschedule_connect (h);
537 return;
538 }
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Received SET_DEFAULT message from identity service\n");
541 GNUNET_CONTAINER_DLL_remove (h->op_head,
542 h->op_tail,
543 op);
544 if (NULL != op->cb)
545 op->cb (op->cls,
546 ego,
547 &ego->ctx,
548 ego->name);
549 GNUNET_free (op);
550}
551
552
553/**
554 * Try again to connect to the identity service.
555 *
556 * @param cls handle to the identity service.
557 */
558static void
559reconnect (void *cls)
560{
561 struct GNUNET_IDENTITY_Handle *h = cls;
562 struct GNUNET_MQ_MessageHandler handlers[] = {
563 GNUNET_MQ_hd_var_size (identity_result_code,
564 GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
565 struct ResultCodeMessage,
566 h),
567 GNUNET_MQ_hd_var_size (identity_update,
568 GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
569 struct UpdateMessage,
570 h),
571 GNUNET_MQ_hd_var_size (identity_set_default,
572 GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
573 struct SetDefaultMessage,
574 h),
575 GNUNET_MQ_handler_end ()
576 };
577 struct GNUNET_MQ_Envelope *env;
578 struct GNUNET_MessageHeader *msg;
579
580 h->reconnect_task = NULL;
581 LOG (GNUNET_ERROR_TYPE_DEBUG,
582 "Connecting to identity service.\n");
583 GNUNET_assert (NULL == h->mq);
584 h->mq = GNUNET_CLIENT_connect (h->cfg,
585 "identity",
586 handlers,
587 &mq_error_handler,
588 h);
589 if (NULL == h->mq)
590 return;
591 if (NULL != h->cb)
592 {
593 env = GNUNET_MQ_msg (msg,
594 GNUNET_MESSAGE_TYPE_IDENTITY_START);
595 GNUNET_MQ_send (h->mq,
596 env);
597 }
598}
599
600
601/**
602 * Connect to the identity service.
603 *
604 * @param cfg the configuration to use
605 * @param cb function to call on all identity events, can be NULL
606 * @param cb_cls closure for @a cb
607 * @return handle to use
608 */
609struct GNUNET_IDENTITY_Handle *
610GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
611 GNUNET_IDENTITY_Callback cb,
612 void *cb_cls)
613{
614 struct GNUNET_IDENTITY_Handle *h;
615
616 h = GNUNET_new (struct GNUNET_IDENTITY_Handle);
617 h->cfg = cfg;
618 h->cb = cb;
619 h->cb_cls = cb_cls;
620 h->egos = GNUNET_CONTAINER_multihashmap_create (16,
621 GNUNET_YES);
622 reconnect (h);
623 if (NULL == h->mq)
624 {
625 GNUNET_free (h);
626 return NULL;
627 }
628 return h;
629}
630
631
632/**
633 * Obtain the ECC key associated with a ego.
634 *
635 * @param ego the ego
636 * @return associated ECC key, valid as long as the ego is valid
637 */
638const struct GNUNET_IDENTITY_PrivateKey *
639GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego)
640{
641 return &ego->pk;
642}
643
644
645/**
646 * Get the identifier (public key) of an ego.
647 *
648 * @param ego identity handle with the private key
649 * @param pk set to ego's public key
650 */
651void
652GNUNET_IDENTITY_ego_get_public_key (struct GNUNET_IDENTITY_Ego *ego,
653 struct GNUNET_IDENTITY_PublicKey *pk)
654{
655 if (GNUNET_NO == ego->pub_initialized)
656 {
657 GNUNET_IDENTITY_key_get_public (&ego->pk, &ego->pub);
658 ego->pub_initialized = GNUNET_YES;
659 }
660 *pk = ego->pub;
661}
662
663
664/**
665 * Obtain the identity that is currently preferred/default
666 * for a service.
667 *
668 * @param h identity service to query
669 * @param service_name for which service is an identity wanted
670 * @param cb function to call with the result (will only be called once)
671 * @param cb_cls closure for @a cb
672 * @return handle to abort the operation
673 */
674struct GNUNET_IDENTITY_Operation *
675GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *h,
676 const char *service_name,
677 GNUNET_IDENTITY_Callback cb,
678 void *cb_cls)
679{
680 struct GNUNET_IDENTITY_Operation *op;
681 struct GNUNET_MQ_Envelope *env;
682 struct GetDefaultMessage *gdm;
683 size_t slen;
684
685 if (NULL == h->mq)
686 return NULL;
687 GNUNET_assert (NULL != h->cb);
688 slen = strlen (service_name) + 1;
689 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct GetDefaultMessage))
690 {
691 GNUNET_break (0);
692 return NULL;
693 }
694 op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
695 op->h = h;
696 op->cb = cb;
697 op->cls = cb_cls;
698 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
699 env =
700 GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT);
701 gdm->name_len = htons (slen);
702 gdm->reserved = htons (0);
703 GNUNET_memcpy (&gdm[1], service_name, slen);
704 GNUNET_MQ_send (h->mq, env);
705 return op;
706}
707
708
709/**
710 * Set the preferred/default identity for a service.
711 *
712 * @param h identity service to inform
713 * @param service_name for which service is an identity set
714 * @param ego new default identity to be set for this service
715 * @param cont function to call once the operation finished
716 * @param cont_cls closure for @a cont
717 * @return handle to abort the operation
718 */
719struct GNUNET_IDENTITY_Operation *
720GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *h,
721 const char *service_name,
722 struct GNUNET_IDENTITY_Ego *ego,
723 GNUNET_IDENTITY_Continuation cont,
724 void *cont_cls)
725{
726 struct GNUNET_IDENTITY_Operation *op;
727 struct GNUNET_MQ_Envelope *env;
728 struct SetDefaultMessage *sdm;
729 size_t slen;
730
731 if (NULL == h->mq)
732 return NULL;
733 GNUNET_assert (NULL != h->cb);
734 slen = strlen (service_name) + 1;
735 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct SetDefaultMessage))
736 {
737 GNUNET_break (0);
738 return NULL;
739 }
740 op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
741 op->h = h;
742 op->cont = cont;
743 op->cls = cont_cls;
744 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
745 env =
746 GNUNET_MQ_msg_extra (sdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT);
747 sdm->name_len = htons (slen);
748 sdm->reserved = htons (0);
749 sdm->private_key = ego->pk;
750 GNUNET_memcpy (&sdm[1], service_name, slen);
751 GNUNET_MQ_send (h->mq, env);
752 return op;
753}
754
755
756struct GNUNET_IDENTITY_Operation *
757GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *h,
758 const char *name,
759 const struct GNUNET_IDENTITY_PrivateKey *privkey,
760 enum GNUNET_IDENTITY_KeyType ktype,
761 GNUNET_IDENTITY_CreateContinuation cont,
762 void *cont_cls)
763{
764 struct GNUNET_IDENTITY_Operation *op;
765 struct GNUNET_MQ_Envelope *env;
766 struct CreateRequestMessage *crm;
767 size_t slen;
768
769 if (NULL == h->mq)
770 return NULL;
771 slen = strlen (name) + 1;
772 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct CreateRequestMessage))
773 {
774 GNUNET_break (0);
775 return NULL;
776 }
777 op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
778 op->h = h;
779 op->create_cont = cont;
780 op->cls = cont_cls;
781 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
782 env = GNUNET_MQ_msg_extra (crm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_CREATE);
783 crm->name_len = htons (slen);
784 crm->reserved = htons (0);
785 if (NULL == privkey)
786 {
787 GNUNET_assert (GNUNET_OK ==
788 private_key_create (ktype, &crm->private_key));
789 }
790 else
791 crm->private_key = *privkey;
792 op->pk = crm->private_key;
793 GNUNET_memcpy (&crm[1], name, slen);
794 GNUNET_MQ_send (h->mq, env);
795 return op;
796}
797
798
799/**
800 * Renames an existing identity.
801 *
802 * @param h identity service to use
803 * @param old_name old name
804 * @param new_name desired new name
805 * @param cb function to call with the result (will only be called once)
806 * @param cb_cls closure for @a cb
807 * @return handle to abort the operation
808 */
809struct GNUNET_IDENTITY_Operation *
810GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *h,
811 const char *old_name,
812 const char *new_name,
813 GNUNET_IDENTITY_Continuation cb,
814 void *cb_cls)
815{
816 struct GNUNET_IDENTITY_Operation *op;
817 struct GNUNET_MQ_Envelope *env;
818 struct RenameMessage *grm;
819 size_t slen_old;
820 size_t slen_new;
821 char *dst;
822
823 if (NULL == h->mq)
824 return NULL;
825 slen_old = strlen (old_name) + 1;
826 slen_new = strlen (new_name) + 1;
827 if ((slen_old >= GNUNET_MAX_MESSAGE_SIZE) ||
828 (slen_new >= GNUNET_MAX_MESSAGE_SIZE) ||
829 (slen_old + slen_new >=
830 GNUNET_MAX_MESSAGE_SIZE - sizeof(struct RenameMessage)))
831 {
832 GNUNET_break (0);
833 return NULL;
834 }
835 op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
836 op->h = h;
837 op->cont = cb;
838 op->cls = cb_cls;
839 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
840 env = GNUNET_MQ_msg_extra (grm,
841 slen_old + slen_new,
842 GNUNET_MESSAGE_TYPE_IDENTITY_RENAME);
843 grm->old_name_len = htons (slen_old);
844 grm->new_name_len = htons (slen_new);
845 dst = (char *) &grm[1];
846 GNUNET_memcpy (dst, old_name, slen_old);
847 GNUNET_memcpy (&dst[slen_old], new_name, slen_new);
848 GNUNET_MQ_send (h->mq, env);
849 return op;
850}
851
852
853/**
854 * Delete an existing identity.
855 *
856 * @param h identity service to use
857 * @param name name of the identity to delete
858 * @param cb function to call with the result (will only be called once)
859 * @param cb_cls closure for @a cb
860 * @return handle to abort the operation
861 */
862struct GNUNET_IDENTITY_Operation *
863GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *h,
864 const char *name,
865 GNUNET_IDENTITY_Continuation cb,
866 void *cb_cls)
867{
868 struct GNUNET_IDENTITY_Operation *op;
869 struct GNUNET_MQ_Envelope *env;
870 struct DeleteMessage *gdm;
871 size_t slen;
872
873 if (NULL == h->mq)
874 return NULL;
875 slen = strlen (name) + 1;
876 if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct DeleteMessage))
877 {
878 GNUNET_break (0);
879 return NULL;
880 }
881 op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
882 op->h = h;
883 op->cont = cb;
884 op->cls = cb_cls;
885 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
886 env = GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_DELETE);
887 gdm->name_len = htons (slen);
888 gdm->reserved = htons (0);
889 GNUNET_memcpy (&gdm[1], name, slen);
890 GNUNET_MQ_send (h->mq, env);
891 return op;
892}
893
894
895/**
896 * Cancel an identity operation. Note that the operation MAY still
897 * be executed; this merely cancels the continuation; if the request
898 * was already transmitted, the service may still choose to complete
899 * the operation.
900 *
901 * @param op operation to cancel
902 */
903void
904GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op)
905{
906 op->cont = NULL;
907 op->cb = NULL;
908 op->create_cont = NULL;
909 memset (&op->pk,
910 0,
911 sizeof (op->pk));
912}
913
914
915/**
916 * Disconnect from identity service
917 *
918 * @param h handle to destroy
919 */
920void
921GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h)
922{
923 struct GNUNET_IDENTITY_Operation *op;
924
925 GNUNET_assert (NULL != h);
926 if (h->reconnect_task != NULL)
927 {
928 GNUNET_SCHEDULER_cancel (h->reconnect_task);
929 h->reconnect_task = NULL;
930 }
931 if (NULL != h->egos)
932 {
933 GNUNET_CONTAINER_multihashmap_iterate (h->egos,
934 &free_ego,
935 h);
936 GNUNET_CONTAINER_multihashmap_destroy (h->egos);
937 h->egos = NULL;
938 }
939 while (NULL != (op = h->op_head))
940 {
941 GNUNET_break (NULL == op->cont);
942 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
943 memset (&op->pk,
944 0,
945 sizeof (op->pk));
946 GNUNET_free (op);
947 }
948 if (NULL != h->mq)
949 {
950 GNUNET_MQ_destroy (h->mq);
951 h->mq = NULL;
952 }
953 GNUNET_free (h);
954}
955
956
957ssize_t
958private_key_get_length (const struct GNUNET_IDENTITY_PrivateKey *key)
959{
960 switch (ntohl (key->type))
961 {
962 case GNUNET_IDENTITY_TYPE_ECDSA:
963 return sizeof (key->type) + sizeof (key->ecdsa_key);
964 break;
965 case GNUNET_IDENTITY_TYPE_EDDSA:
966 return sizeof (key->type) + sizeof (key->eddsa_key);
967 break;
968 default:
969 GNUNET_break (0);
970 }
971 return -1;
972}
973
974
975ssize_t
976GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key)
977{
978 switch (ntohl (key->type))
979 {
980 case GNUNET_IDENTITY_TYPE_ECDSA:
981 return sizeof (key->type) + sizeof (key->ecdsa_key);
982 break;
983 case GNUNET_IDENTITY_TYPE_EDDSA:
984 return sizeof (key->type) + sizeof (key->eddsa_key);
985 break;
986 default:
987 GNUNET_break (0);
988 }
989 return -1;
990}
991
992
993ssize_t
994GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
995 const void*buffer,
996 size_t len)
997{
998 if (len < sizeof (key->type))
999 return -1;
1000 GNUNET_memcpy (&(key->type), buffer, sizeof (key->type));
1001 const ssize_t length = GNUNET_IDENTITY_key_get_length (key);
1002 if (len < length)
1003 return -1;
1004 if (length < 0)
1005 return -2;
1006 GNUNET_memcpy (&(key->ecdsa_key), buffer + sizeof (key->type), length
1007 - sizeof (key->type));
1008 return length;
1009}
1010
1011
1012ssize_t
1013GNUNET_IDENTITY_write_key_to_buffer (const struct
1014 GNUNET_IDENTITY_PublicKey *key,
1015 void*buffer,
1016 size_t len)
1017{
1018 const ssize_t length = GNUNET_IDENTITY_key_get_length (key);
1019 if (len < length)
1020 return -1;
1021 if (length < 0)
1022 return -2;
1023 GNUNET_memcpy (buffer, &(key->type), sizeof (key->type));
1024 GNUNET_memcpy (buffer + sizeof (key->type), &(key->ecdsa_key), length
1025 - sizeof (key->type));
1026 return length;
1027}
1028
1029
1030ssize_t
1031GNUNET_IDENTITY_signature_get_length (const struct
1032 GNUNET_IDENTITY_Signature *sig)
1033{
1034 switch (ntohl (sig->type))
1035 {
1036 case GNUNET_IDENTITY_TYPE_ECDSA:
1037 return sizeof (sig->type) + sizeof (sig->ecdsa_signature);
1038 break;
1039 case GNUNET_IDENTITY_TYPE_EDDSA:
1040 return sizeof (sig->type) + sizeof (sig->eddsa_signature);
1041 break;
1042 default:
1043 GNUNET_break (0);
1044 }
1045 return -1;
1046}
1047
1048
1049ssize_t
1050GNUNET_IDENTITY_read_signature_from_buffer (struct
1051 GNUNET_IDENTITY_Signature *sig,
1052 const void*buffer,
1053 size_t len)
1054{
1055 if (len < sizeof (sig->type))
1056 return -1;
1057 GNUNET_memcpy (&(sig->type), buffer, sizeof (sig->type));
1058 const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
1059 if (len < length)
1060 return -1;
1061 if (length < 0)
1062 return -2;
1063 GNUNET_memcpy (&(sig->ecdsa_signature), buffer + sizeof (sig->type), length
1064 - sizeof (sig->type));
1065 return length;
1066}
1067
1068
1069ssize_t
1070GNUNET_IDENTITY_write_signature_to_buffer (const struct
1071 GNUNET_IDENTITY_Signature *sig,
1072 void*buffer,
1073 size_t len)
1074{
1075 const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
1076 if (len < length)
1077 return -1;
1078 if (length < 0)
1079 return -2;
1080 GNUNET_memcpy (buffer, &(sig->type), sizeof (sig->type));
1081 GNUNET_memcpy (buffer + sizeof (sig->type), &(sig->ecdsa_signature), length
1082 - sizeof (sig->type));
1083 return length;
1084}
1085
1086
1087int
1088GNUNET_IDENTITY_sign_ (const struct
1089 GNUNET_IDENTITY_PrivateKey *priv,
1090 const struct
1091 GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1092 struct GNUNET_IDENTITY_Signature *sig)
1093{
1094 sig->type = priv->type;
1095 switch (ntohl (priv->type))
1096 {
1097 case GNUNET_IDENTITY_TYPE_ECDSA:
1098 return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
1099 &(sig->ecdsa_signature));
1100 break;
1101 case GNUNET_IDENTITY_TYPE_EDDSA:
1102 return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
1103 &(sig->eddsa_signature));
1104 break;
1105 default:
1106 GNUNET_break (0);
1107 }
1108
1109 return GNUNET_SYSERR;
1110}
1111
1112
1113int
1114GNUNET_IDENTITY_signature_verify_ (uint32_t purpose,
1115 const struct
1116 GNUNET_CRYPTO_EccSignaturePurpose *validate,
1117 const struct GNUNET_IDENTITY_Signature *sig,
1118 const struct GNUNET_IDENTITY_PublicKey *pub)
1119{
1120 /* check type matching of 'sig' and 'pub' */
1121 GNUNET_assert (ntohl (pub->type) == ntohl (sig->type));
1122 switch (ntohl (pub->type))
1123 {
1124 case GNUNET_IDENTITY_TYPE_ECDSA:
1125 return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
1126 &(sig->ecdsa_signature),
1127 &(pub->ecdsa_key));
1128 break;
1129 case GNUNET_IDENTITY_TYPE_EDDSA:
1130 return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
1131 &(sig->eddsa_signature),
1132 &(pub->eddsa_key));
1133 break;
1134 default:
1135 GNUNET_break (0);
1136 }
1137
1138 return GNUNET_SYSERR;
1139}
1140
1141
1142ssize_t
1143GNUNET_IDENTITY_encrypt (const void *block,
1144 size_t size,
1145 const struct GNUNET_IDENTITY_PublicKey *pub,
1146 struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
1147 void *result)
1148{
1149 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
1150 GNUNET_CRYPTO_ecdhe_key_create (&pk);
1151 struct GNUNET_HashCode hash;
1152 switch (ntohl (pub->type))
1153 {
1154 case GNUNET_IDENTITY_TYPE_ECDSA:
1155 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&pk, &(pub->ecdsa_key),
1156 &hash))
1157 return -1;
1158 break;
1159 case GNUNET_IDENTITY_TYPE_EDDSA:
1160 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_eddsa (&pk, &(pub->eddsa_key),
1161 &hash))
1162 return -1;
1163 break;
1164 default:
1165 return -1;
1166 }
1167 GNUNET_CRYPTO_ecdhe_key_get_public (&pk, ecc);
1168 GNUNET_CRYPTO_ecdhe_key_clear (&pk);
1169 struct GNUNET_CRYPTO_SymmetricSessionKey key;
1170 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1171 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
1172 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
1173 const ssize_t encrypted = GNUNET_CRYPTO_symmetric_encrypt (block, size, &key,
1174 &iv, result);
1175 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
1176 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
1177 return encrypted;
1178}
1179
1180
1181ssize_t
1182GNUNET_IDENTITY_decrypt (const void *block,
1183 size_t size,
1184 const struct GNUNET_IDENTITY_PrivateKey *priv,
1185 const struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
1186 void *result)
1187{
1188 struct GNUNET_HashCode hash;
1189 switch (ntohl (priv->type))
1190 {
1191 case GNUNET_IDENTITY_TYPE_ECDSA:
1192 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_ecdh (&(priv->ecdsa_key), ecc,
1193 &hash))
1194 return -1;
1195 break;
1196 case GNUNET_IDENTITY_TYPE_EDDSA:
1197 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_ecdh (&(priv->eddsa_key), ecc,
1198 &hash))
1199 return -1;
1200 break;
1201 default:
1202 return -1;
1203 }
1204 struct GNUNET_CRYPTO_SymmetricSessionKey key;
1205 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1206 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
1207 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
1208 const ssize_t decrypted = GNUNET_CRYPTO_symmetric_decrypt (block, size, &key,
1209 &iv, result);
1210 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
1211 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
1212 return decrypted;
1213}
1214
1215
1216char *
1217GNUNET_IDENTITY_public_key_to_string (const struct
1218 GNUNET_IDENTITY_PublicKey *key)
1219{
1220 size_t size = GNUNET_IDENTITY_key_get_length (key);
1221 return GNUNET_STRINGS_data_to_string_alloc (key,
1222 size);
1223}
1224
1225
1226char *
1227GNUNET_IDENTITY_private_key_to_string (const struct
1228 GNUNET_IDENTITY_PrivateKey *key)
1229{
1230 size_t size = private_key_get_length (key);
1231 return GNUNET_STRINGS_data_to_string_alloc (key,
1232 size);
1233}
1234
1235
1236enum GNUNET_GenericReturnValue
1237GNUNET_IDENTITY_public_key_from_string (const char *str,
1238 struct GNUNET_IDENTITY_PublicKey *key)
1239{
1240 enum GNUNET_GenericReturnValue ret;
1241 ret = GNUNET_STRINGS_string_to_data (str,
1242 strlen (str),
1243 key,
1244 sizeof (*key));
1245 if (GNUNET_OK != ret)
1246 return GNUNET_SYSERR;
1247 return GNUNET_OK;
1248
1249}
1250
1251
1252enum GNUNET_GenericReturnValue
1253GNUNET_IDENTITY_private_key_from_string (const char *str,
1254 struct GNUNET_IDENTITY_PrivateKey *key)
1255{
1256 enum GNUNET_GenericReturnValue ret;
1257 ret = GNUNET_STRINGS_string_to_data (str,
1258 strlen (str),
1259 key,
1260 sizeof (*key));
1261 if (GNUNET_OK != ret)
1262 return GNUNET_SYSERR;
1263 return GNUNET_OK;
1264}
1265
1266
1267/* end of identity_api.c */
diff --git a/src/identity/identity_api_lookup.c b/src/identity/identity_api_lookup.c
deleted file mode 100644
index 51afb2515..000000000
--- a/src/identity/identity_api_lookup.c
+++ /dev/null
@@ -1,229 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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 */
20
21/**
22 * @file identity/identity_api_lookup.c
23 * @brief api to lookup an ego
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_identity_service.h"
29#include "identity.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
32
33
34/**
35 * Handle for ego lookup.
36 */
37struct GNUNET_IDENTITY_EgoLookup
38{
39 /**
40 * Connection to service.
41 */
42 struct GNUNET_MQ_Handle *mq;
43
44 /**
45 * Name of the ego we are looking up.
46 */
47 char *name;
48
49 /**
50 * Function to call with the result.
51 */
52 GNUNET_IDENTITY_EgoCallback cb;
53
54 /**
55 * Closure for @e cb
56 */
57 void *cb_cls;
58};
59
60
61/**
62 * We received a result code from the service. Check the message
63 * is well-formed.
64 *
65 * @param cls closure
66 * @param rcm result message received
67 * @return #GNUNET_OK if the message is well-formed
68 */
69static int
70check_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
71{
72 if (sizeof(*rcm) != htons (rcm->header.size))
73 GNUNET_MQ_check_zero_termination (rcm);
74 return GNUNET_OK;
75}
76
77
78/**
79 * We received a result code from the service.
80 *
81 * @param cls closure
82 * @param rcm result message received
83 */
84static void
85handle_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
86{
87 struct GNUNET_IDENTITY_EgoLookup *el = cls;
88
89 el->cb (el->cb_cls, NULL);
90 GNUNET_IDENTITY_ego_lookup_cancel (el);
91}
92
93
94/**
95 * Check validity of identity update message.
96 *
97 * @param cls closure
98 * @param um message received
99 * @return #GNUNET_OK if the message is well-formed
100 */
101static int
102check_identity_update (void *cls, const struct UpdateMessage *um)
103{
104 uint16_t size = ntohs (um->header.size);
105 uint16_t name_len = ntohs (um->name_len);
106 const char *str = (const char *) &um[1];
107
108 if ((size != name_len + sizeof(struct UpdateMessage)) ||
109 ((0 != name_len) && ('\0' != str[name_len - 1])))
110 {
111 GNUNET_break (0);
112 return GNUNET_SYSERR;
113 }
114 return GNUNET_OK;
115}
116
117
118/**
119 * Handle identity update message.
120 *
121 * @param cls closure
122 * @param um message received
123 */
124static void
125handle_identity_update (void *cls, const struct UpdateMessage *um)
126{
127 struct GNUNET_IDENTITY_EgoLookup *el = cls;
128 uint16_t name_len = ntohs (um->name_len);
129 const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
130 struct GNUNET_HashCode id;
131 struct GNUNET_IDENTITY_Ego ego;
132 memset (&ego, 0, sizeof (ego));
133
134 GNUNET_break (GNUNET_YES != ntohs (um->end_of_list));
135 GNUNET_CRYPTO_hash (&um->private_key, sizeof(um->private_key), &id);
136 ego.pk = um->private_key;
137 ego.name = (char *) str;
138 ego.id = id;
139 el->cb (el->cb_cls, &ego);
140 GNUNET_IDENTITY_ego_lookup_cancel (el);
141}
142
143
144/**
145 * Generic error handler, called with the appropriate error code and
146 * the same closure specified at the creation of the message queue.
147 * Not every message queue implementation supports an error handler.
148 *
149 * @param cls closure with the `struct GNUNET_IDENTITY_EgoLookup *`
150 * @param error error code
151 */
152static void
153mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
154{
155 struct GNUNET_IDENTITY_EgoLookup *el = cls;
156
157 el->cb (el->cb_cls, NULL);
158}
159
160
161/**
162 * Lookup an ego by name.
163 *
164 * @param cfg configuration to use
165 * @param name name to look up
166 * @param cb callback to invoke with the result
167 * @param cb_cls closure for @a cb
168 * @return NULL on error
169 */
170struct GNUNET_IDENTITY_EgoLookup *
171GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg,
172 const char *name,
173 GNUNET_IDENTITY_EgoCallback cb,
174 void *cb_cls)
175{
176 struct GNUNET_IDENTITY_EgoLookup *el;
177 struct GNUNET_MQ_Envelope *env;
178 struct GNUNET_MessageHeader *req;
179 size_t nlen;
180
181 GNUNET_assert (NULL != cb);
182 el = GNUNET_new (struct GNUNET_IDENTITY_EgoLookup);
183 el->cb = cb;
184 el->cb_cls = cb_cls;
185 {
186 struct GNUNET_MQ_MessageHandler handlers[] =
187 { GNUNET_MQ_hd_var_size (identity_result_code,
188 GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
189 struct ResultCodeMessage,
190 el),
191 GNUNET_MQ_hd_var_size (identity_update,
192 GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
193 struct UpdateMessage,
194 el),
195 GNUNET_MQ_handler_end () };
196
197 el->mq =
198 GNUNET_CLIENT_connect (cfg, "identity", handlers, &mq_error_handler, el);
199 }
200 if (NULL == el->mq)
201 {
202 GNUNET_break (0);
203 GNUNET_free (el);
204 return NULL;
205 }
206 el->name = GNUNET_strdup (name);
207 nlen = strlen (name) + 1;
208 env = GNUNET_MQ_msg_extra (req, nlen, GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP);
209 memcpy (&req[1], name, nlen);
210 GNUNET_MQ_send (el->mq, env);
211 return el;
212}
213
214
215/**
216 * Abort ego lookup attempt.
217 *
218 * @param el handle for lookup to abort
219 */
220void
221GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el)
222{
223 GNUNET_MQ_destroy (el->mq);
224 GNUNET_free (el->name);
225 GNUNET_free (el);
226}
227
228
229/* end of identity_api_lookup.c */
diff --git a/src/identity/identity_api_suffix_lookup.c b/src/identity/identity_api_suffix_lookup.c
deleted file mode 100644
index 2667ddbc8..000000000
--- a/src/identity/identity_api_suffix_lookup.c
+++ /dev/null
@@ -1,229 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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 */
20
21/**
22 * @file identity/identity_api_suffix_lookup.c
23 * @brief api to lookup an ego
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_identity_service.h"
29#include "identity.h"
30
31#define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
32
33
34/**
35 * Handle for ego lookup.
36 */
37struct GNUNET_IDENTITY_EgoSuffixLookup
38{
39 /**
40 * Connection to service.
41 */
42 struct GNUNET_MQ_Handle *mq;
43
44 /**
45 * Suffix we are looking up.
46 */
47 char *suffix;
48
49 /**
50 * Function to call with the result.
51 */
52 GNUNET_IDENTITY_EgoSuffixCallback cb;
53
54 /**
55 * Closure for @e cb
56 */
57 void *cb_cls;
58};
59
60
61/**
62 * We received a result code from the service. Check the message
63 * is well-formed.
64 *
65 * @param cls closure
66 * @param rcm result message received
67 * @return #GNUNET_OK if the message is well-formed
68 */
69static int
70check_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
71{
72 (void) cls;
73 if (sizeof(*rcm) != htons (rcm->header.size))
74 GNUNET_MQ_check_zero_termination (rcm);
75 return GNUNET_OK;
76}
77
78
79/**
80 * We received a result code from the service.
81 *
82 * @param cls closure
83 * @param rcm result message received
84 */
85static void
86handle_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
87{
88 struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
89
90 (void) rcm;
91 el->cb (el->cb_cls, NULL, NULL);
92 GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
93}
94
95
96/**
97 * Check validity of identity update message.
98 *
99 * @param cls closure
100 * @param um message received
101 * @return #GNUNET_OK if the message is well-formed
102 */
103static int
104check_identity_update (void *cls, const struct UpdateMessage *um)
105{
106 uint16_t size = ntohs (um->header.size);
107 uint16_t name_len = ntohs (um->name_len);
108 const char *str = (const char *) &um[1];
109
110 (void) cls;
111 if ((size != name_len + sizeof(struct UpdateMessage)) ||
112 ((0 != name_len) && ('\0' != str[name_len - 1])))
113 {
114 GNUNET_break (0);
115 return GNUNET_SYSERR;
116 }
117 return GNUNET_OK;
118}
119
120
121/**
122 * Handle identity update message.
123 *
124 * @param cls closure
125 * @param um message received
126 */
127static void
128handle_identity_update (void *cls, const struct UpdateMessage *um)
129{
130 struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
131 uint16_t name_len = ntohs (um->name_len);
132 const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
133
134 el->cb (el->cb_cls, &um->private_key, str);
135 GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
136}
137
138
139/**
140 * Generic error handler, called with the appropriate error code and
141 * the same closure specified at the creation of the message queue.
142 * Not every message queue implementation supports an error handler.
143 *
144 * @param cls closure with the `struct GNUNET_IDENTITY_EgoSuffixLookup *`
145 * @param error error code
146 */
147static void
148mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
149{
150 struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
151
152 (void) error;
153 el->cb (el->cb_cls, NULL, NULL);
154 GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
155}
156
157
158/**
159 * Lookup an ego by name.
160 *
161 * @param cfg configuration to use
162 * @param name name to look up
163 * @param cb callback to invoke with the result
164 * @param cb_cls closure for @a cb
165 * @return NULL on error
166 */
167struct GNUNET_IDENTITY_EgoSuffixLookup *
168GNUNET_IDENTITY_ego_lookup_by_suffix (const struct
169 GNUNET_CONFIGURATION_Handle *cfg,
170 const char *suffix,
171 GNUNET_IDENTITY_EgoSuffixCallback cb,
172 void *cb_cls)
173{
174 struct GNUNET_IDENTITY_EgoSuffixLookup *el;
175 struct GNUNET_MQ_Envelope *env;
176 struct GNUNET_MessageHeader *req;
177 size_t nlen;
178
179 GNUNET_assert (NULL != cb);
180 el = GNUNET_new (struct GNUNET_IDENTITY_EgoSuffixLookup);
181 el->cb = cb;
182 el->cb_cls = cb_cls;
183 {
184 struct GNUNET_MQ_MessageHandler handlers[] =
185 { GNUNET_MQ_hd_var_size (identity_result_code,
186 GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
187 struct ResultCodeMessage,
188 el),
189 GNUNET_MQ_hd_var_size (identity_update,
190 GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
191 struct UpdateMessage,
192 el),
193 GNUNET_MQ_handler_end () };
194
195 el->mq =
196 GNUNET_CLIENT_connect (cfg, "identity", handlers, &mq_error_handler, el);
197 }
198 if (NULL == el->mq)
199 {
200 GNUNET_break (0);
201 GNUNET_free (el);
202 return NULL;
203 }
204 el->suffix = GNUNET_strdup (suffix);
205 nlen = strlen (suffix) + 1;
206 env = GNUNET_MQ_msg_extra (req, nlen,
207 GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX);
208 memcpy (&req[1], suffix, nlen);
209 GNUNET_MQ_send (el->mq, env);
210 return el;
211}
212
213
214/**
215 * Abort ego lookup attempt.
216 *
217 * @param el handle for lookup to abort
218 */
219void
220GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (struct
221 GNUNET_IDENTITY_EgoSuffixLookup *el)
222{
223 GNUNET_MQ_destroy (el->mq);
224 GNUNET_free (el->suffix);
225 GNUNET_free (el);
226}
227
228
229/* end of identity_api_suffix_lookup.c */
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
deleted file mode 100644
index d7cd0e826..000000000
--- a/src/identity/plugin_rest_identity.c
+++ /dev/null
@@ -1,1442 +0,0 @@
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 */
20/**
21 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
23 * @file identity/plugin_rest_identity.c
24 * @brief GNUnet Identity REST plugin
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include "gnunet_identity_service.h"
30#include "gnunet_rest_lib.h"
31#include "microhttpd.h"
32#include <jansson.h>
33
34/**
35 * Identity Namespace
36 */
37#define GNUNET_REST_API_NS_IDENTITY "/identity"
38
39/**
40 * Identity Namespace with public key specifier
41 */
42#define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
43
44/**
45 * Identity Namespace with public key specifier
46 */
47#define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
48
49/**
50 * Identity Subsystem Namespace
51 */
52#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
53
54/**
55 * Parameter public key
56 */
57#define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
58
59/**
60 * Parameter private key
61 */
62#define GNUNET_REST_IDENTITY_PARAM_PRIVKEY "privkey"
63
64/**
65 * Parameter subsystem
66 */
67#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
68
69/**
70 * Parameter name
71 */
72#define GNUNET_REST_IDENTITY_PARAM_NAME "name"
73
74/**
75 * Parameter new name
76 */
77#define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
78
79/**
80 * Error message Unknown Error
81 */
82#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
83
84/**
85 * Error message No identity found
86 */
87#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
88
89/**
90 * Error message Missing identity name
91 */
92#define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
93
94/**
95 * Error message Missing identity name
96 */
97#define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
98
99/**
100 * Error message No data
101 */
102#define GNUNET_REST_ERROR_NO_DATA "No data"
103
104/**
105 * Error message Data invalid
106 */
107#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
108
109/**
110 * State while collecting all egos
111 */
112#define ID_REST_STATE_INIT 0
113
114/**
115 * Done collecting egos
116 */
117#define ID_REST_STATE_POST_INIT 1
118
119/**
120 * The configuration handle
121 */
122const struct GNUNET_CONFIGURATION_Handle *cfg;
123
124/**
125 * HTTP methods allows for this plugin
126 */
127static char *allow_methods;
128
129/**
130 * Ego list
131 */
132static struct EgoEntry *ego_head;
133
134/**
135 * Ego list
136 */
137static struct EgoEntry *ego_tail;
138
139/**
140 * The processing state
141 */
142static int state;
143
144/**
145 * Handle to Identity service.
146 */
147static struct GNUNET_IDENTITY_Handle *identity_handle;
148
149/**
150 * @brief struct returned by the initialization function of the plugin
151 */
152struct Plugin
153{
154 const struct GNUNET_CONFIGURATION_Handle *cfg;
155};
156
157/**
158 * The ego list
159 */
160struct EgoEntry
161{
162 /**
163 * DLL
164 */
165 struct EgoEntry *next;
166
167 /**
168 * DLL
169 */
170 struct EgoEntry *prev;
171
172 /**
173 * Ego Identifier
174 */
175 char *identifier;
176
177 /**
178 * Public key string
179 */
180 char *keystring;
181
182 /**
183 * The Ego
184 */
185 struct GNUNET_IDENTITY_Ego *ego;
186};
187
188/**
189 * The request handle
190 */
191struct RequestHandle
192{
193 /**
194 * DLL
195 */
196 struct RequestHandle *next;
197
198 /**
199 * DLL
200 */
201 struct RequestHandle *prev;
202
203 /**
204 * The data from the REST request
205 */
206 const char *data;
207
208 /**
209 * The name to look up
210 */
211 char *name;
212
213 /**
214 * the length of the REST data
215 */
216 size_t data_size;
217
218 /**
219 * IDENTITY Operation
220 */
221 struct GNUNET_IDENTITY_Operation *op;
222
223 /**
224 * Rest connection
225 */
226 struct GNUNET_REST_RequestHandle *rest_handle;
227
228 /**
229 * Desired timeout for the lookup (default is no timeout).
230 */
231 struct GNUNET_TIME_Relative timeout;
232
233 /**
234 * ID of a task associated with the resolution process.
235 */
236 struct GNUNET_SCHEDULER_Task *timeout_task;
237
238 /**
239 * The plugin result processor
240 */
241 GNUNET_REST_ResultProcessor proc;
242
243 /**
244 * The closure of the result processor
245 */
246 void *proc_cls;
247
248 /**
249 * The url
250 */
251 char *url;
252
253 /**
254 * Error response message
255 */
256 char *emsg;
257
258 /**
259 * Response code
260 */
261 int response_code;
262};
263
264/**
265 * DLL
266 */
267static struct RequestHandle *requests_head;
268
269/**
270 * DLL
271 */
272static struct RequestHandle *requests_tail;
273
274/**
275 * Cleanup lookup handle
276 * @param handle Handle to clean up
277 */
278static void
279cleanup_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);
296 GNUNET_CONTAINER_DLL_remove (requests_head,
297 requests_tail,
298 handle);
299 GNUNET_free (handle);
300}
301
302
303/**
304 * Task run on errors. Reports an error and cleans up everything.
305 *
306 * @param cls the `struct RequestHandle`
307 */
308static void
309do_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)
317 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
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 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);
330 GNUNET_free (response);
331 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
332}
333
334
335/**
336 * Get EgoEntry from list with either a public key or a name
337 * If public key and name are not NULL, it returns the public key result first
338 *
339 * @param handle the RequestHandle
340 * @param pubkey the public key of an identity (only one can be NULL)
341 * @param name the name of an identity (only one can be NULL)
342 * @return EgoEntry or NULL if not found
343 */
344struct EgoEntry *
345get_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
373/**
374 * Callback for GET Request with subsystem
375 *
376 * @param cls the RequestHandle
377 * @param ego the Ego found
378 * @param ctx the context
379 * @param name the id of the ego
380 */
381static void
382ego_get_for_subsystem (void *cls,
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;
397 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
398 GNUNET_SCHEDULER_add_now (&do_error, handle);
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,
408 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
409 json_string (public_key_string));
410 json_object_set_new (json_root,
411 GNUNET_REST_IDENTITY_PARAM_NAME,
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);
424 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
425}
426
427
428/**
429 * Handle identity GET request for subsystem
430 *
431 * @param con_handle the connection handle
432 * @param url the url
433 * @param cls the RequestHandle
434 */
435void
436ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
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");
446 GNUNET_SCHEDULER_add_now (&do_error, handle);
447 return;
448 }
449 subsystem = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
450 // requested default identity of subsystem
451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
452
453 handle->op = GNUNET_IDENTITY_get (identity_handle,
454 subsystem,
455 &ego_get_for_subsystem,
456 handle);
457
458 if (NULL == handle->op)
459 {
460 handle->response_code = MHD_HTTP_NOT_FOUND;
461 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
462 GNUNET_SCHEDULER_add_now (&do_error, handle);
463 return;
464 }
465}
466
467
468/**
469 * Handle identity GET request - responds with all identities
470 *
471 * @param con_handle the connection handle
472 * @param url the url
473 * @param cls the RequestHandle
474 */
475void
476ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
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,
496 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
497 json_string (ego_entry->keystring));
498 GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
499 if (GNUNET_YES ==
500 GNUNET_CONTAINER_multihashmap_contains (
501 handle->rest_handle->url_param_map, &key))
502 {
503 privkey_str = GNUNET_IDENTITY_private_key_to_string (
504 GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego));
505 json_object_set_new (json_ego,
506 GNUNET_REST_IDENTITY_PARAM_PRIVKEY,
507 json_string (privkey_str));
508 GNUNET_free (privkey_str);
509 }
510
511 json_object_set_new (json_ego,
512 GNUNET_REST_IDENTITY_PARAM_NAME,
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);
527 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
528}
529
530
531/**
532 * Responds with the ego_entry identity
533 *
534 * @param handle the struct RequestHandle
535 * @param ego_entry the struct EgoEntry for the response
536 */
537void
538ego_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,
548 GNUNET_REST_IDENTITY_PARAM_PUBKEY,
549 json_string (ego_entry->keystring));
550 json_object_set_new (json_ego,
551 GNUNET_REST_IDENTITY_PARAM_NAME,
552 json_string (ego_entry->identifier));
553 GNUNET_CRYPTO_hash ("private", strlen ("private"), &key);
554 if (GNUNET_YES ==
555 GNUNET_CONTAINER_multihashmap_contains (
556 handle->rest_handle->url_param_map, &key))
557 {
558 privkey_str = GNUNET_IDENTITY_private_key_to_string (
559 GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego));
560 json_object_set_new (json_ego,
561 GNUNET_REST_IDENTITY_PARAM_PRIVKEY,
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);
575 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
576}
577
578
579/**
580 * Handle identity GET request with a public key
581 *
582 * @param con_handle the connection handle
583 * @param url the url
584 * @param cls the RequestHandle
585 */
586void
587ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
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;
600 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
601 GNUNET_SCHEDULER_add_now (&do_error, handle);
602 return;
603 }
604 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
605 ego_entry = get_egoentry (handle, keystring, NULL);
606
607 if (NULL == ego_entry)
608 {
609 handle->response_code = MHD_HTTP_NOT_FOUND;
610 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
611 GNUNET_SCHEDULER_add_now (&do_error, handle);
612 return;
613 }
614
615 ego_get_response (handle, ego_entry);
616}
617
618
619/**
620 * Handle identity GET request with a name
621 *
622 * @param con_handle the connection handle
623 * @param url the url
624 * @param cls the RequestHandle
625 */
626void
627ego_get_name (struct GNUNET_REST_RequestHandle *con_handle,
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;
640 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
641 GNUNET_SCHEDULER_add_now (&do_error, handle);
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;
650 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
651 GNUNET_SCHEDULER_add_now (&do_error, handle);
652 return;
653 }
654
655 ego_get_response (handle, ego_entry);
656}
657
658
659/**
660 * Processing finished
661 *
662 * @param cls request handle
663 * @param emsg error message
664 */
665static void
666do_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);
675 GNUNET_SCHEDULER_add_now (&do_error, handle);
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);
684 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
685}
686
687
688/**
689 * Processing finished, when creating an ego.
690 *
691 * @param cls request handle
692 * @param private key of the ego, or NULL on error
693 * @param emsg error message
694 */
695static void
696do_finished_create (void *cls,
697 const struct GNUNET_IDENTITY_PrivateKey *pk,
698 const char *emsg)
699{
700 struct RequestHandle *handle = cls;
701
702 (void) pk;
703 do_finished (handle, emsg);
704}
705
706
707/**
708 * Processing edit ego with EgoEntry ego_entry
709 *
710 * @param handle the struct RequestHandle
711 * @param ego_entry the struct EgoEntry we want to edit
712 */
713void
714ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
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 {
727 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
728 GNUNET_SCHEDULER_add_now (&do_error, handle);
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 {
738 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
739 GNUNET_SCHEDULER_add_now (&do_error, handle);
740 return;
741 }
742
743 newname = NULL;
744 // NEW NAME
745 json_state = 0;
746 json_state = json_unpack (data_js,
747 "{s:s!}",
748 GNUNET_REST_IDENTITY_PARAM_NEWNAME,
749 &newname);
750 // Change name with pubkey or name identifier
751 if (0 != json_state)
752 {
753 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
754 GNUNET_SCHEDULER_add_now (&do_error, handle);
755 json_decref (data_js);
756 return;
757 }
758
759 if (NULL == newname)
760 {
761 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
762 GNUNET_SCHEDULER_add_now (&do_error, handle);
763 json_decref (data_js);
764 return;
765 }
766
767 if (0 >= strlen (newname))
768 {
769 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
770 GNUNET_SCHEDULER_add_now (&do_error, handle);
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);
781 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
782 json_decref (data_js);
783 return;
784 }
785 handle->op = GNUNET_IDENTITY_rename (identity_handle,
786 ego_entry->identifier,
787 newname,
788 &do_finished,
789 handle);
790 if (NULL == handle->op)
791 {
792 handle->emsg = GNUNET_strdup ("Rename failed");
793 GNUNET_SCHEDULER_add_now (&do_error, handle);
794 json_decref (data_js);
795 return;
796 }
797 json_decref (data_js);
798 return;
799}
800
801
802/**
803 * Handle identity PUT request with public key
804 *
805 * @param con_handle the connection handle
806 * @param url the url
807 * @param cls the RequestHandle
808 */
809void
810ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
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;
823 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
824 GNUNET_SCHEDULER_add_now (&do_error, handle);
825 return;
826 }
827 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) + 1];
828 ego_entry = get_egoentry (handle, keystring, NULL);
829
830 if (NULL == ego_entry)
831 {
832 handle->response_code = MHD_HTTP_NOT_FOUND;
833 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
834 GNUNET_SCHEDULER_add_now (&do_error, handle);
835 return;
836 }
837
838 ego_edit (handle, ego_entry);
839}
840
841
842/**
843 * Handle identity PUT request with name
844 *
845 * @param con_handle the connection handle
846 * @param url the url
847 * @param cls the RequestHandle
848 */
849void
850ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle,
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;
863 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
864 GNUNET_SCHEDULER_add_now (&do_error, handle);
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;
873 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
874 GNUNET_SCHEDULER_add_now (&do_error, handle);
875 return;
876 }
877
878 ego_edit (handle, ego_entry);
879}
880
881
882/**
883 * Handle identity subsystem PUT request with name
884 *
885 * @param con_handle the connection handle
886 * @param url the url
887 * @param cls the RequestHandle
888 */
889void
890ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
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;
908 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
909 GNUNET_SCHEDULER_add_now (&do_error, handle);
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;
918 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
919 GNUNET_SCHEDULER_add_now (&do_error, handle);
920 return;
921 }
922
923 // if no data
924 if (0 >= handle->data_size)
925 {
926 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
927 GNUNET_SCHEDULER_add_now (&do_error, handle);
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 {
937 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
938 GNUNET_SCHEDULER_add_now (&do_error, handle);
939 return;
940 }
941
942 newsubsys = NULL;
943 // SUBSYSTEM
944 json_state = 0;
945 json_state = json_unpack (data_js,
946 "{s:s!}",
947 GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM,
948 &newsubsys);
949 // Change subsystem with pubkey or name identifier
950 if (0 != json_state)
951 {
952 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
953 GNUNET_SCHEDULER_add_now (&do_error, handle);
954 json_decref (data_js);
955 return;
956 }
957
958 if (NULL == newsubsys)
959 {
960 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
961 GNUNET_SCHEDULER_add_now (&do_error, handle);
962 json_decref (data_js);
963 return;
964 }
965
966 if (0 >= strlen (newsubsys))
967 {
968 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
969 GNUNET_SCHEDULER_add_now (&do_error, handle);
970 json_decref (data_js);
971 return;
972 }
973
974 handle->response_code = MHD_HTTP_NO_CONTENT;
975 handle->op = GNUNET_IDENTITY_set (identity_handle,
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");
983 GNUNET_SCHEDULER_add_now (&do_error, handle);
984 return;
985 }
986 json_decref (data_js);
987 return;
988}
989
990
991/**
992 * Handle identity POST request
993 *
994 * @param con_handle the connection handle
995 * @param url the url
996 * @param cls the RequestHandle
997 */
998void
999ego_create (struct GNUNET_REST_RequestHandle *con_handle,
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;
1010 struct GNUNET_IDENTITY_PrivateKey pk;
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 {
1017 GNUNET_SCHEDULER_add_now (&do_error, handle);
1018 return;
1019 }
1020
1021 if (0 >= handle->data_size)
1022 {
1023 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
1024 GNUNET_SCHEDULER_add_now (&do_error, handle);
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 {
1032 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA);
1033 GNUNET_SCHEDULER_add_now (&do_error, handle);
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!}",
1041 GNUNET_REST_IDENTITY_PARAM_NAME, &egoname,
1042 GNUNET_REST_IDENTITY_PARAM_PRIVKEY, &privkey);
1043 if (0 != json_unpack_state)
1044 {
1045 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
1046 GNUNET_SCHEDULER_add_now (&do_error, handle);
1047 json_decref (data_js);
1048 return;
1049 }
1050
1051 if (NULL == egoname)
1052 {
1053 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
1054 GNUNET_SCHEDULER_add_now (&do_error, handle);
1055 json_decref (data_js);
1056 return;
1057 }
1058 if (0 >= strlen (egoname))
1059 {
1060 json_decref (data_js);
1061 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID);
1062 GNUNET_SCHEDULER_add_now (&do_error, handle);
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);
1073 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
1074 json_decref (data_js);
1075 return;
1076 }
1077 }
1078 handle->name = GNUNET_strdup (egoname);
1079 if (NULL != privkey)
1080 {
1081 GNUNET_STRINGS_string_to_data (privkey,
1082 strlen (privkey),
1083 &pk,
1084 sizeof(struct
1085 GNUNET_IDENTITY_PrivateKey));
1086 pk_ptr = &pk;
1087 }
1088 else
1089 pk_ptr = NULL;
1090 json_decref (data_js);
1091 handle->response_code = MHD_HTTP_CREATED;
1092 handle->op = GNUNET_IDENTITY_create (identity_handle,
1093 handle->name,
1094 pk_ptr,
1095 GNUNET_IDENTITY_TYPE_ECDSA,
1096 &do_finished_create,
1097 handle);
1098}
1099
1100
1101/**
1102 * Handle identity DELETE request with public key
1103 *
1104 * @param con_handle the connection handle
1105 * @param url the url
1106 * @param cls the RequestHandle
1107 */
1108void
1109ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
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;
1122 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_PUBKEY);
1123 GNUNET_SCHEDULER_add_now (&do_error, handle);
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;
1132 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
1133 GNUNET_SCHEDULER_add_now (&do_error, handle);
1134 return;
1135 }
1136
1137 handle->response_code = MHD_HTTP_NO_CONTENT;
1138 handle->op = GNUNET_IDENTITY_delete (identity_handle,
1139 ego_entry->identifier,
1140 &do_finished,
1141 handle);
1142}
1143
1144
1145/**
1146 * Handle identity DELETE request with name
1147 *
1148 * @param con_handle the connection handle
1149 * @param url the url
1150 * @param cls the RequestHandle
1151 */
1152void
1153ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
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;
1166 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_MISSING_NAME);
1167 GNUNET_SCHEDULER_add_now (&do_error, handle);
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;
1176 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
1177 GNUNET_SCHEDULER_add_now (&do_error, handle);
1178 return;
1179 }
1180
1181 handle->response_code = MHD_HTTP_NO_CONTENT;
1182 handle->op = GNUNET_IDENTITY_delete (identity_handle,
1183 ego_entry->identifier,
1184 &do_finished,
1185 handle);
1186}
1187
1188
1189/**
1190 * Respond to OPTIONS request
1191 *
1192 * @param con_handle the connection handle
1193 * @param url the url
1194 * @param cls the RequestHandle
1195 */
1196static void
1197options_cont (struct GNUNET_REST_RequestHandle *con_handle,
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);
1210 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
1211 return;
1212}
1213
1214
1215static void
1216list_ego (void *cls,
1217 struct GNUNET_IDENTITY_Ego *ego,
1218 void **ctx,
1219 const char *identifier)
1220{
1221 struct EgoEntry *ego_entry;
1222 struct GNUNET_IDENTITY_PublicKey pk;
1223
1224 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1225 {
1226 state = ID_REST_STATE_POST_INIT;
1227 return;
1228 }
1229 if (NULL == ego)
1230 {
1231 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1232 "Called with NULL ego\n");
1233 return;
1234 }
1235 if (ID_REST_STATE_INIT == state)
1236 {
1237 ego_entry = GNUNET_new (struct EgoEntry);
1238 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1239 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
1240 ego_entry->ego = ego;
1241 ego_entry->identifier = GNUNET_strdup (identifier);
1242 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
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);
1264 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
1265 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
1266 ego_entry->ego = ego;
1267 ego_entry->identifier = GNUNET_strdup (identifier);
1268 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
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
1285 GNUNET_CONTAINER_DLL_remove (ego_head,
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
1297/**
1298 * Function processing the REST call
1299 *
1300 * @param method HTTP method
1301 * @param url URL of the HTTP request
1302 * @param data body of the HTTP request (optional)
1303 * @param data_size length of the body
1304 * @param proc callback function for the result
1305 * @param proc_cls closure for callback function
1306 * @return GNUNET_OK if request accepted
1307 */
1308static enum GNUNET_GenericReturnValue
1309rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1310 GNUNET_REST_ResultProcessor proc,
1311 void *proc_cls)
1312{
1313 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1314 struct GNUNET_REST_RequestHandlerError err;
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,
1320 GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
1321 &ego_get_subsystem },
1322 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1323 { MHD_HTTP_METHOD_PUT,
1324 GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1325 &ego_edit_pubkey },
1326 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
1327 { MHD_HTTP_METHOD_PUT,
1328 GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
1329 &ego_edit_subsystem },
1330 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
1331 { MHD_HTTP_METHOD_DELETE,
1332 GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1333 &ego_delete_pubkey },
1334 { MHD_HTTP_METHOD_DELETE,
1335 GNUNET_REST_API_NS_IDENTITY_NAME,
1336 &ego_delete_name },
1337 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
1338 GNUNET_REST_HANDLER_END };
1339
1340
1341 handle->response_code = 0;
1342 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
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 =
1353 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1354 GNUNET_CONTAINER_DLL_insert (requests_head,
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 {
1361 cleanup_handle (handle);
1362 return GNUNET_NO;
1363 }
1364
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1366 return GNUNET_YES;
1367}
1368
1369
1370/**
1371 * Entry point for the plugin.
1372 *
1373 * @param cls Config info
1374 * @return NULL on error, otherwise the plugin context
1375 */
1376void *
1377libgnunet_plugin_rest_identity_init (void *cls)
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;
1389 api->name = GNUNET_REST_API_NS_IDENTITY;
1390 api->process_request = &rest_process_request;
1391 GNUNET_asprintf (&allow_methods,
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);
1398 state = ID_REST_STATE_INIT;
1399 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1400
1401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
1402 return api;
1403}
1404
1405
1406/**
1407 * Exit point from the plugin.
1408 *
1409 * @param cls the plugin context (as returned by "init")
1410 * @return always NULL
1411 */
1412void *
1413libgnunet_plugin_rest_identity_done (void *cls)
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)
1422 cleanup_handle (requests_head);
1423 if (NULL != identity_handle)
1424 GNUNET_IDENTITY_disconnect (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
1435 GNUNET_free (allow_methods);
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 */
diff --git a/src/identity/test_identity.c b/src/identity/test_identity.c
deleted file mode 100644
index 4954fe7be..000000000
--- a/src/identity/test_identity.c
+++ /dev/null
@@ -1,306 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2016 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 */
20
21/**
22 * @file identity/test_identity.c
23 * @brief testcase for identity service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_identity_service.h"
29#include "gnunet_testing_lib.h"
30
31
32#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
33
34
35/**
36 * Return value from 'main'.
37 */
38static int res;
39
40/**
41 * Handle to identity service.
42 */
43static struct GNUNET_IDENTITY_Handle *h;
44
45/**
46 * Handle to identity operation.
47 */
48static struct GNUNET_IDENTITY_Operation *op;
49
50/**
51 * Handle for task for timeout termination.
52 */
53static struct GNUNET_SCHEDULER_Task *endbadly_task;
54
55#define CHECK(cond) \
56 do \
57 { \
58 if (! (cond)) \
59 { \
60 GNUNET_break (0); \
61 end (); \
62 return; \
63 } \
64 } while (0)
65
66
67/**
68 * Clean up all resources used.
69 */
70static void
71cleanup (void *cls)
72{
73 (void) cls;
74 if (NULL != op)
75 {
76 GNUNET_IDENTITY_cancel (op);
77 op = NULL;
78 }
79 if (NULL != h)
80 {
81 GNUNET_IDENTITY_disconnect (h);
82 h = NULL;
83 }
84}
85
86
87/**
88 * Termiante the testcase (failure).
89 *
90 * @param cls NULL
91 */
92static void
93endbadly (void *cls)
94{
95 GNUNET_SCHEDULER_shutdown ();
96}
97
98
99/**
100 * Finish the testcase (successfully).
101 */
102static void
103end ()
104{
105 if (NULL != endbadly_task)
106 {
107 GNUNET_SCHEDULER_cancel (endbadly_task);
108 endbadly_task = NULL;
109 }
110 GNUNET_SCHEDULER_shutdown ();
111}
112
113
114/**
115 * Called with events about egos.
116 *
117 * @param cls NULL
118 * @param ego ego handle
119 * @param ego_ctx context for application to store data for this ego
120 * (during the lifetime of this process, initially NULL)
121 * @param identifier identifier assigned by the user for this ego,
122 * NULL if the user just deleted the ego and it
123 * must thus no longer be used
124 */
125static void
126notification_cb (void *cls,
127 struct GNUNET_IDENTITY_Ego *ego,
128 void **ctx,
129 const char *identifier)
130{
131 static struct GNUNET_IDENTITY_Ego *my_ego;
132 static int round;
133
134 switch (round)
135 {
136 case 0: /* end of initial iteration */
137 CHECK (NULL == ego);
138 CHECK (NULL == identifier);
139 break;
140
141 case 1: /* create */
142 CHECK (NULL != ego);
143 CHECK (NULL != identifier);
144 CHECK (0 == strcmp (identifier, "test-id"));
145 my_ego = ego;
146 *ctx = &round;
147 break;
148
149 case 2: /* rename */
150 CHECK (my_ego == ego);
151 CHECK (NULL != identifier);
152 CHECK (0 == strcmp (identifier, "test"));
153 CHECK (*ctx == &round);
154 break;
155
156 case 3: /* reconnect-down */
157 CHECK (my_ego == ego);
158 CHECK (NULL == identifier);
159 CHECK (*ctx == &round);
160 *ctx = NULL;
161 break;
162
163 case 4: /* reconnect-up */
164 CHECK (NULL != identifier);
165 CHECK (0 == strcmp (identifier, "test"));
166 my_ego = ego;
167 *ctx = &round;
168 break;
169
170 case 5: /* end of iteration after reconnect */
171 CHECK (NULL == ego);
172 CHECK (NULL == identifier);
173 break;
174
175 case 6: /* delete */
176 CHECK (my_ego == ego);
177 CHECK (*ctx == &round);
178 *ctx = NULL;
179 break;
180
181 default:
182 CHECK (0);
183 }
184 round++;
185}
186
187
188/**
189 * Continuation called from successful delete operation.
190 *
191 * @param cls NULL
192 * @param emsg (should also be NULL)
193 */
194static void
195delete_cont (void *cls, const char *emsg)
196{
197 op = NULL;
198 CHECK (NULL == emsg);
199 res = 0;
200 end ();
201}
202
203
204/**
205 * Continue by deleting the "test" identity.
206 *
207 * @param cls NULL
208 */
209static void
210finally_delete (void *cls)
211{
212 op = GNUNET_IDENTITY_delete (h, "test", &delete_cont, NULL);
213}
214
215
216/**
217 * Continuation called from expected-to-fail rename operation.
218 *
219 * @param cls NULL
220 * @param emsg (should also be NULL)
221 */
222static void
223fail_rename_cont (void *cls, const char *emsg)
224{
225 CHECK (NULL != emsg);
226 op = NULL;
227 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
228 &finally_delete,
229 NULL);
230}
231
232
233/**
234 * Continuation called from successful rename operation.
235 *
236 * @param cls NULL
237 * @param emsg (should also be NULL)
238 */
239static void
240success_rename_cont (void *cls, const char *emsg)
241{
242 CHECK (NULL == emsg);
243 op = GNUNET_IDENTITY_rename (h, "test-id", "test", &fail_rename_cont, NULL);
244}
245
246
247/**
248 * Called with events about created ego.
249 *
250 * @param cls NULL
251 * @param pk private key of the ego, or NULL on error
252 * @param emsg error message
253 */
254static void
255create_cb (void *cls,
256 const struct GNUNET_IDENTITY_PrivateKey *pk,
257 const char *emsg)
258{
259 CHECK (NULL != pk);
260 CHECK (NULL == emsg);
261 op =
262 GNUNET_IDENTITY_rename (h, "test-id", "test", &success_rename_cont, NULL);
263}
264
265
266/**
267 * Main function of the test, run from scheduler.
268 *
269 * @param cls NULL
270 * @param cfg configuration we use (also to connect to identity service)
271 * @param peer handle to access more of the peer (not used)
272 */
273static void
274run (void *cls,
275 const struct GNUNET_CONFIGURATION_Handle *cfg,
276 struct GNUNET_TESTING_Peer *peer)
277{
278 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL);
279 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
280 h = GNUNET_IDENTITY_connect (cfg, &notification_cb, NULL);
281 CHECK (NULL != h);
282 op = GNUNET_IDENTITY_create (h,
283 "test-id",
284 NULL,
285 GNUNET_IDENTITY_TYPE_ECDSA,
286 &create_cb, NULL);
287}
288
289
290int
291main (int argc, char *argv[])
292{
293 GNUNET_DISK_directory_remove ("/tmp/gnunet/test-identity-service");
294 res = 1;
295 if (0 != GNUNET_TESTING_service_run ("test-identity",
296 "identity",
297 "test_identity.conf",
298 &run,
299 NULL))
300 return 1;
301 GNUNET_DISK_directory_remove ("/tmp/gnunet/test-identity-service");
302 return res;
303}
304
305
306/* end of test_identity.c */
diff --git a/src/identity/test_identity.conf b/src/identity/test_identity.conf
deleted file mode 100644
index 9c433da77..000000000
--- a/src/identity/test_identity.conf
+++ /dev/null
@@ -1,8 +0,0 @@
1[arm]
2PORT = 12000
3UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
4
5[identity]
6# need to overwrite paths to ensure they stay the same between runs...
7EGODIR = $GNUNET_TMP/test-identity-service/egos/
8SUBSYSTEM_CFG = $GNUNET_TMP/test-identity-service/s.conf
diff --git a/src/identity/test_identity_defaults.c b/src/identity/test_identity_defaults.c
deleted file mode 100644
index 2d5244d1b..000000000
--- a/src/identity/test_identity_defaults.c
+++ /dev/null
@@ -1,299 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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 */
20
21/**
22 * @file identity/test_identity.c
23 * @brief testcase for identity service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_identity_service.h"
29#include "gnunet_testing_lib.h"
30
31
32#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
33
34
35/**
36 * Return value from 'main'.
37 */
38static int res;
39
40/**
41 * Handle to identity service.
42 */
43static struct GNUNET_IDENTITY_Handle *h;
44
45/**
46 * Handle to identity operation.
47 */
48static struct GNUNET_IDENTITY_Operation *op;
49
50/**
51 * Handle for task for timeout termination.
52 */
53static struct GNUNET_SCHEDULER_Task *endbadly_task;
54
55#define CHECK(cond) \
56 do \
57 { \
58 if (! (cond)) \
59 { \
60 GNUNET_break (0); \
61 end (); \
62 return; \
63 } \
64 } while (0)
65
66
67/**
68 * Clean up all resources used.
69 */
70static void
71cleanup (void *cls)
72{
73 (void) cls;
74 if (NULL != op)
75 {
76 GNUNET_IDENTITY_cancel (op);
77 op = NULL;
78 }
79 if (NULL != h)
80 {
81 GNUNET_IDENTITY_disconnect (h);
82 h = NULL;
83 }
84}
85
86
87/**
88 * Termiante the testcase (failure).
89 *
90 * @param cls NULL
91 */
92static void
93endbadly (void *cls)
94{
95 GNUNET_SCHEDULER_shutdown ();
96 res = 1;
97}
98
99
100/**
101 * Termiante the testcase.
102 */
103static void
104end ()
105{
106 if (NULL != endbadly_task)
107 {
108 GNUNET_SCHEDULER_cancel (endbadly_task);
109 endbadly_task = NULL;
110 }
111 GNUNET_SCHEDULER_shutdown ();
112}
113
114
115/**
116 * Continuation called from successful delete operation.
117 *
118 * @param cls NULL
119 * @param emsg (should also be NULL)
120 */
121static void
122delete_cont (void *cls, const char *emsg)
123{
124 op = NULL;
125 CHECK (NULL == emsg);
126 res = 0;
127 end ();
128}
129
130
131/**
132 * Continuation called from expected-to-fail rename operation.
133 *
134 * @param cls NULL
135 * @param emsg (should also be NULL)
136 */
137static void
138get_cb (void *cls,
139 struct GNUNET_IDENTITY_Ego *ego,
140 void **ctx,
141 const char *identifier)
142{
143 op = NULL;
144 CHECK (NULL != ego);
145 CHECK (NULL != identifier);
146 CHECK (0 == strcmp (identifier, "test-id"));
147 op = GNUNET_IDENTITY_delete (h, "test-id", &delete_cont, NULL);
148}
149
150
151/**
152 * Called with events about egos.
153 *
154 * @param cls NULL
155 * @param ego ego handle
156 * @param ego_ctx context for application to store data for this ego
157 * (during the lifetime of this process, initially NULL)
158 * @param identifier identifier assigned by the user for this ego,
159 * NULL if the user just deleted the ego and it
160 * must thus no longer be used
161 */
162static void
163dummy_cb (void *cls,
164 struct GNUNET_IDENTITY_Ego *ego,
165 void **ctx,
166 const char *identifier)
167{
168 (void) cls;
169 (void) ego;
170 (void) ctx;
171 (void) identifier;
172}
173
174
175/**
176 * Main function of the test, run from scheduler.
177 *
178 * @param cls NULL
179 * @param cfg configuration we use (also to connect to identity service)
180 * @param peer handle to access more of the peer (not used)
181 */
182static void
183run_get (void *cls,
184 const struct GNUNET_CONFIGURATION_Handle *cfg,
185 struct GNUNET_TESTING_Peer *peer)
186{
187 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL);
188 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
189 h = GNUNET_IDENTITY_connect (cfg, &dummy_cb, NULL);
190 CHECK (NULL != h);
191 op = GNUNET_IDENTITY_get (h, "test-service", &get_cb, NULL);
192}
193
194
195/**
196 * Continuation called from successful rename operation.
197 *
198 * @param cls NULL
199 * @param emsg (should also be NULL)
200 */
201static void
202success_set_cont (void *cls, const char *emsg)
203{
204 op = NULL;
205 CHECK (NULL == emsg);
206 end ();
207}
208
209
210/**
211 * Called with events about egos.
212 *
213 * @param cls NULL
214 * @param ego ego handle
215 * @param ego_ctx context for application to store data for this ego
216 * (during the lifetime of this process, initially NULL)
217 * @param identifier identifier assigned by the user for this ego,
218 * NULL if the user just deleted the ego and it
219 * must thus no longer be used
220 */
221static void
222notification_cb (void *cls,
223 struct GNUNET_IDENTITY_Ego *ego,
224 void **ctx,
225 const char *identifier)
226{
227 if (NULL == ego)
228 return; /* skip first call */
229 if (NULL == identifier)
230 return; /* deletion / shutdown */
231 op = GNUNET_IDENTITY_set (h, "test-service", ego, &success_set_cont, NULL);
232}
233
234
235/**
236 * Called with events about created ego.
237 *
238 * @param cls NULL
239 * @param pk private key of the ego, or NULL on error
240 * @param emsg error message
241 */
242static void
243create_cb (void *cls,
244 const struct GNUNET_IDENTITY_PrivateKey *pk,
245 const char *emsg)
246{
247 CHECK (NULL == emsg);
248 CHECK (NULL != pk);
249 op = NULL;
250}
251
252
253/**
254 * Main function of the test, run from scheduler.
255 *
256 * @param cls NULL
257 * @param cfg configuration we use (also to connect to identity service)
258 * @param peer handle to access more of the peer (not used)
259 */
260static void
261run_set (void *cls,
262 const struct GNUNET_CONFIGURATION_Handle *cfg,
263 struct GNUNET_TESTING_Peer *peer)
264{
265 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL);
266 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
267 h = GNUNET_IDENTITY_connect (cfg, &notification_cb, NULL);
268 CHECK (NULL != h);
269 op = GNUNET_IDENTITY_create (h,
270 "test-id",
271 NULL,
272 GNUNET_IDENTITY_TYPE_ECDSA,
273 &create_cb, NULL);
274}
275
276
277int
278main (int argc, char *argv[])
279{
280 GNUNET_DISK_directory_remove ("/tmp/gnunet/test-identity-service");
281 res = 1;
282 if (0 != GNUNET_TESTING_service_run ("test-identity-defaults",
283 "identity",
284 "test_identity.conf",
285 &run_set,
286 NULL))
287 return 1;
288 if (0 != GNUNET_TESTING_service_run ("test-identity-defaults",
289 "identity",
290 "test_identity.conf",
291 &run_get,
292 NULL))
293 return 1;
294 GNUNET_DISK_directory_remove ("/tmp/gnunet/test-identity-service");
295 return res;
296}
297
298
299/* end of test_identity_defaults.c */
diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh
deleted file mode 100755
index a5879dd7e..000000000
--- a/src/identity/test_plugin_rest_identity.sh
+++ /dev/null
@@ -1,157 +0,0 @@
1#!/usr/bin/bash
2
3#First, start gnunet-arm and the rest-service.
4#Exit 0 means success, exit 1 means failed test
5
6identity_link="http://localhost:7776/identity"
7wrong_link="http://localhost:7776/identityandmore"
8
9
10curl_get () {
11 #$1 is link
12 #$2 is grep
13 cache="$(curl -v "$1" 2>&1 | grep "$2")"
14 #echo $cache
15 if [ "" == "$cache" ]
16 then
17 exit 1
18 fi
19}
20
21curl_post () {
22 #$1 is link
23 #$2 is data
24 #$3 is grep
25 cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")"
26 #echo $cache
27 if [ "" == "$cache" ]
28 then
29 exit 1
30 fi
31}
32
33curl_delete () {
34 #$1 is link
35 #$2 is grep
36 cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")"
37 #echo $cache
38 if [ "" == "$cache" ]
39 then
40 exit 1
41 fi
42}
43
44curl_put () {
45 #$1 is link
46 #$2 is data
47 #$3 is grep
48 cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")"
49 #echo $cache
50 if [ "" == "$cache" ]
51 then
52 exit 1
53 fi
54}
55
56#Test GET
57test="$(gnunet-identity -d)"
58#if no identity exists
59if [ "" == "$test" ]
60then
61 curl_get "$identity_link/all" "error"
62 gnunet-identity -C "test_plugin_rest_identity"
63 name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
64 public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
65
66 curl_get "${identity_link}/name/$name" "$public"
67 curl_get "${identity_link}/name/$public" "error"
68 curl_get "${identity_link}/name/" "error"
69
70 curl_get "${identity_link}/pubkey/$public" "$name"
71 curl_get "${identity_link}/pubkey/$name" "error"
72 curl_get "${identity_link}/pubkey/" "error"
73
74 gnunet-identity -D "test_plugin_rest_identity"
75else
76 name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
77 public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
78
79 curl_get "${identity_link}/name/$name" "$public"
80 curl_get "${identity_link}/name/$public" "error"
81 curl_get "${identity_link}/name/" "error"
82
83 curl_get "${identity_link}/pubkey/$public" "$name"
84 curl_get "${identity_link}/pubkey/$name" "error"
85 curl_get "${identity_link}/pubkey/" "error"
86fi
87
88#Test POST
89gnunet-identity -D "test_plugin_rest_identity" > /dev/null 2>&1
90gnunet-identity -D "test_plugin_rest_identity1" > /dev/null 2>&1
91
92curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created"
93curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409"
94curl_post "${identity_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409"
95curl_post "${identity_link}" '{}' "error"
96curl_post "${identity_link}" '' "error"
97curl_post "${identity_link}" '{"name":""}' "error"
98curl_post "${identity_link}" '{"name":123}' "error"
99curl_post "${identity_link}" '{"name":[]}' "error"
100curl_post "${identity_link}" '{"name1":"test_plugin_rest_identity"}' "error"
101curl_post "${identity_link}" '{"other":""}' "error"
102curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error"
103
104#Test PUT
105name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')"
106public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
107
108curl_put "${identity_link}/pubkey/$public" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
109curl_put "${identity_link}/pubkey/$public" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
110curl_put "${identity_link}/pubkey/${public}xx" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
111curl_put "${identity_link}/pubkey/" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
112curl_put "${identity_link}/pubke" '{"newname":"test_plugin_rest_identity1"}' "error"
113curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","other":"sdfdsf"}' "error"
114curl_put "${identity_link}/pubkey/$name" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
115curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 204"
116curl_put "${identity_link}/pubkey/$public" '{"newnam":"test_plugin_rest_identity"}' "error"
117curl_put "${identity_link}/name/test_plugin_rest_identity" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
118curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"TEST_plugin_rest_identity1"}' "HTTP/1.1 409"
119curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
120curl_put "${identity_link}/name/test_plugin_rest_identityxxx" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 404"
121curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 204"
122curl_put "${identity_link}/name/test_plugin_rest_identity" '{"newnam":"test_plugin_rest_identityfail"}' "error"
123
124#Test subsystem
125curl_put "${identity_link}/subsystem/test_plugin_rest_identity" '{"subsystem":"namestore"}' "HTTP/1.1 204"
126curl_put "${identity_link}/subsystem/test_plugin_rest_identity" '{"subsystem":"namestore"}' "HTTP/1.1 204"
127curl_get "${identity_link}/subsystem/namestore" "test_plugin_rest_identity"
128public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
129curl_put "${identity_link}/subsystem/$public" '{"subsystem":"namestore"}' "HTTP/1.1 404"
130curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
131curl_get "${identity_link}/subsystem/test_plugin_rest_identity_no_subsystem" "error"
132curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsystem":"test_plugin_rest_identity_no_subsystem"}' "HTTP/1.1 204"
133curl_get "${identity_link}/subsystem/test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1"
134
135curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsyste":"test_plugin_rest_identity_no_subsystem"}' "error"
136curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsystem":"test_plugin_rest_identity_no_subsystem"}' "HTTP/1.1 204"
137
138#Test DELETE
139curl_delete "${identity_link}/name/test_plugin_rest_identity" "HTTP/1.1 204"
140curl_get "${identity_link}/name/test_plugin_rest_identity" "error"
141curl_delete "${identity_link}/name/TEST_plugin_rest_identity1" "HTTP/1.1 204"
142curl_delete "${identity_link}/name/test_plugin_rest_identity1" "HTTP/1.1 404"
143curl_get "${identity_link}/name/test_plugin_rest_identity1" "error"
144curl_delete "${identity_link}/name/test_plugin_rest_identity_not_found" "HTTP/1.1 404"
145curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
146public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')"
147curl_delete "${identity_link}/pubkey/$public" "HTTP/1.1 204"
148curl_delete "${identity_link}/pubke/$public" "error"
149curl_delete "${identity_link}/pubkey/${public}other=232" "HTTP/1.1 404"
150
151#Test wrong_link
152curl_get "$wrong_link" "HTTP/1.1 404"
153curl_post "$wrong_link" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 404"
154curl_put "$wrong_link/name/test_plugin_rest_identity" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
155curl_delete "$wrong_link/name/test_plugin_rest_identity1" "HTTP/1.1 404"
156
157exit 0;