aboutsummaryrefslogtreecommitdiff
path: root/src/service/gns/gnunet-gns-import.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/gns/gnunet-gns-import.c')
-rw-r--r--src/service/gns/gnunet-gns-import.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/src/service/gns/gnunet-gns-import.c b/src/service/gns/gnunet-gns-import.c
new file mode 100644
index 000000000..5d4602682
--- /dev/null
+++ b/src/service/gns/gnunet-gns-import.c
@@ -0,0 +1,498 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-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 * @file gnunet-gns.c
22 * @brief binary version of gnunet-gns-import.sh
23 * (for OSes that have no POSIX shell).
24 * @author LRN
25 */
26#include "platform.h"
27#include <gnunet_util_lib.h>
28#include <gnunet_gnsrecord_lib.h>
29#include <gnunet_identity_service.h>
30#include <gnunet_namestore_service.h>
31
32/**
33 * Configuration we are using.
34 */
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37/**
38 * Handle to IDENTITY service.
39 */
40static struct GNUNET_IDENTITY_Handle *sh;
41
42/**
43 * Zone iterator for master zone
44 */
45struct GNUNET_NAMESTORE_ZoneIterator *list_it;
46
47/**
48 * Handle to the namestore.
49 */
50static struct GNUNET_NAMESTORE_Handle *ns;
51
52/**
53 * String version of PKEY for master-zone.
54 */
55static char *master_zone_pkey;
56
57/**
58 * Binary version of PKEY for master-zone.
59 */
60static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk;
61
62/**
63 * String version of PKEY for private-zone.
64 */
65static char *private_zone_pkey;
66
67/**
68 * String version of PKEY for pin-zone.
69 */
70static char *pin_zone_pkey =
71 "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRKOG";
72
73/**
74 * Set to GNUNET_YES if private record was found;
75 */
76static int found_private_rec = GNUNET_NO;
77
78/**
79 * Set to GNUNET_YES if pin record was found;
80 */
81static int found_pin_rec = GNUNET_NO;
82
83/**
84 * Exit code.
85 */
86static int ret;
87
88
89static int
90run_process_and_wait (enum GNUNET_OS_InheritStdioFlags std_inheritance,
91 struct GNUNET_DISK_PipeHandle *pipe_stdin,
92 struct GNUNET_DISK_PipeHandle *pipe_stdout,
93 enum GNUNET_OS_ProcessStatusType *st,
94 unsigned long *code,
95 const char *filename, ...)
96{
97 static struct GNUNET_OS_Process *p;
98 int arglen;
99 char *arg;
100 char *args;
101 char *argp;
102 va_list ap, apc1, apc2;
103
104 va_start (ap, filename);
105 va_copy (apc1, ap);
106 va_copy (apc2, ap);
107 arglen = 0;
108 while (NULL != (arg = va_arg (apc1, char *)))
109 arglen += strlen (arg) + 1;
110 va_end (apc1);
111 args = argp = GNUNET_malloc (arglen);
112 while (NULL != (arg = va_arg (apc2, char *)))
113 {
114 strcpy (argp, arg);
115 argp += strlen (arg);
116 *argp = ' ';
117 argp += 1;
118 }
119 va_end (apc2);
120 if (arglen > 0)
121 argp[-1] = '\0';
122 p = GNUNET_OS_start_process_va (std_inheritance,
123 pipe_stdin,
124 pipe_stdout,
125 NULL,
126 filename, ap);
127 va_end (ap);
128 if (NULL == p)
129 {
130 ret = 3;
131 fprintf (stderr, "Failed to run `%s'\n", args);
132 GNUNET_free (args);
133 return 1;
134 }
135
136 if (GNUNET_OK != GNUNET_OS_process_wait (p))
137 {
138 ret = 4;
139 fprintf (stderr, "Failed to wait for `%s'\n", args);
140 GNUNET_free (args);
141 return 1;
142 }
143
144 switch (GNUNET_OS_process_status (p, st, code))
145 {
146 case GNUNET_OK:
147 break;
148
149 case GNUNET_NO:
150 ret = 5;
151 fprintf (stderr, "`%s' is still running\n", args);
152 GNUNET_free (args);
153 return 1;
154
155 default:
156 case GNUNET_SYSERR:
157 ret = 6;
158 fprintf (stderr, "Failed to check the status of `%s'\n", args);
159 GNUNET_free (args);
160 return 1;
161 }
162 return 0;
163}
164
165
166static void
167check_pkey (unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd,
168 char *pk, int *found_rec)
169{
170 int i;
171 struct GNUNET_CRYPTO_PublicKey pubkey;
172
173 for (i = 0; i < rd_len; i++)
174 {
175 char *s;
176 if (sizeof (uint32_t) > rd[i].data_size)
177 continue;
178 if (GNUNET_OK != GNUNET_GNSRECORD_identity_from_data (rd[i].data,
179 rd[i].data_size,
180 rd[i].record_type,
181 &pubkey))
182 continue;
183 s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
184 rd[i].data,
185 rd[i].data_size);
186 if (NULL == s)
187 continue;
188 if (0 == strcmp (s, pk))
189 *found_rec = GNUNET_YES;
190 GNUNET_free (s);
191 }
192}
193
194
195/**
196 * Process a record that was stored in the namestore.
197 *
198 * @param cls closure
199 * @param zone_key private key of the zone
200 * @param rname name that is being mapped (at most 255 characters long)
201 * @param rd_len number of entries in @a rd array
202 * @param rd array of records with data to store
203 */
204static void
205zone_iterator (void *cls,
206 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
207 const char *rname, unsigned int rd_len,
208 const struct GNUNET_GNSRECORD_Data *rd)
209{
210 if (NULL != rname)
211 {
212 if (0 == strcmp (rname, "private"))
213 check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec);
214 else if (0 == strcmp (rname, "pin"))
215 check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec);
216 }
217 GNUNET_NAMESTORE_zone_iterator_next (list_it);
218}
219
220
221static void
222zone_iteration_error (void *cls)
223{
224 enum GNUNET_OS_ProcessStatusType st;
225 unsigned long code;
226
227 if (! found_private_rec)
228 {
229 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
230 NULL, NULL, &st, &code,
231 "gnunet-namestore",
232 "gnunet-namestore", "-z", "master-zone",
233 "-a", "-e", "never", "-n", "private", "-p",
234 "-t", "PKEY", "-V",
235 private_zone_pkey, NULL))
236 {
237 ret = 8;
238 return;
239 }
240 }
241 if (! found_pin_rec)
242 {
243 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
244 NULL, NULL, &st, &code,
245 "gnunet-namestore",
246 "gnunet-namestore", "-z", "master-zone",
247 "-a", "-e", "never", "-n", "pin", "-p", "-t",
248 "PKEY", "-V", pin_zone_pkey,
249 NULL))
250 {
251 ret = 10;
252 return;
253 }
254 }
255 list_it = NULL;
256 GNUNET_SCHEDULER_shutdown ();
257}
258
259
260static void
261zone_iteration_finished (void *cls)
262{
263}
264
265
266/**
267 * Get master-zone and private-zone keys.
268 *
269 * This function is initially called for all egos and then again
270 * whenever a ego's identifier changes or if it is deleted. At the
271 * end of the initial pass over all egos, the function is once called
272 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
273 * be invoked in the future or that there was an error.
274 *
275 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
276 * function is only called ONCE, and 'NULL' being passed in 'ego' does
277 * indicate an error (for example because name is taken or no default value is
278 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
279 * value WILL be passed to a subsequent call to the identity callback of
280 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
281 *
282 * When an identity is renamed, this function is called with the
283 * (known) ego but the NEW identifier.
284 *
285 * When an identity is deleted, this function is called with the
286 * (known) ego and "NULL" for the 'identifier'. In this case,
287 * the 'ego' is henceforth invalid (and the 'ctx' should also be
288 * cleaned up).
289 *
290 * @param cls closure
291 * @param ego ego handle
292 * @param ctx context for application to store data for this ego
293 * (during the lifetime of this process, initially NULL)
294 * @param identifier identifier assigned by the user for this ego,
295 * NULL if the user just deleted the ego and it
296 * must thus no longer be used
297 */
298static void
299get_ego (void *cls,
300 struct GNUNET_IDENTITY_Ego *ego,
301 void **ctx,
302 const char *identifier)
303{
304 static struct GNUNET_CRYPTO_EcdsaPublicKey pk;
305
306 if (NULL == ego)
307 {
308 if ((NULL == master_zone_pkey) ||
309 (NULL == private_zone_pkey) )
310 {
311 ret = 11;
312 GNUNET_SCHEDULER_shutdown ();
313 return;
314 }
315 list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
316 &master_pk,
317 &zone_iteration_error,
318 NULL, &zone_iterator, NULL,
319 &zone_iteration_finished,
320 NULL);
321 if (NULL == list_it)
322 {
323 ret = 12;
324 GNUNET_SCHEDULER_shutdown ();
325 }
326 return;
327 }
328 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
329 if (NULL != identifier)
330 {
331 if ((NULL == master_zone_pkey) && (0 == strcmp ("master-zone",
332 identifier)) )
333 {
334 master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
335 master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego);
336 }
337 else if ((NULL == private_zone_pkey) && (0 == strcmp ("private-zone",
338 identifier)) )
339 private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
340 }
341}
342
343
344/**
345 * Task run on shutdown.
346 *
347 * @param cls NULL
348 */
349static void
350shutdown_task (void *cls)
351{
352 GNUNET_free (master_zone_pkey);
353 master_zone_pkey = NULL;
354 GNUNET_free (private_zone_pkey);
355 private_zone_pkey = NULL;
356 if (NULL != list_it)
357 {
358 GNUNET_NAMESTORE_zone_iteration_stop (list_it);
359 list_it = NULL;
360 }
361 if (NULL != ns)
362 {
363 GNUNET_NAMESTORE_disconnect (ns);
364 ns = NULL;
365 }
366 if (NULL != sh)
367 {
368 GNUNET_IDENTITY_disconnect (sh);
369 sh = NULL;
370 }
371}
372
373
374/**
375 * Main function that will be run.
376 *
377 * @param cls closure
378 * @param args remaining command-line arguments
379 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
380 * @param c configuration
381 */
382static void
383run (void *cls, char *const *args, const char *cfgfile,
384 const struct GNUNET_CONFIGURATION_Handle *c)
385{
386 enum GNUNET_OS_ProcessStatusType st;
387 unsigned long code;
388
389 cfg = c;
390
391 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_NONE,
392 NULL, NULL, &st, &code,
393 "gnunet-arm",
394 "gnunet-arm", "-I", NULL))
395 {
396 if (7 == ret)
397 fprintf (stderr,
398 "GNUnet is not running, please start GNUnet before running import\n");
399 return;
400 }
401
402 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
403 NULL, NULL, &st, &code,
404 "gnunet-identity",
405 "gnunet-identity", "-C", "master-zone", NULL))
406 return;
407
408 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
409 NULL, NULL, &st, &code,
410 "gnunet-identity",
411 "gnunet-identity", "-C", "private-zone", NULL))
412 return;
413
414 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
415 NULL, NULL, &st, &code,
416 "gnunet-identity",
417 "gnunet-identity", "-C", "sks-zone", NULL))
418 return;
419
420 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
421 NULL, NULL, &st, &code,
422 "gnunet-identity",
423 "gnunet-identity", "-e", "master-zone", "-s",
424 "gns-master", NULL))
425 return;
426
427 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
428 NULL, NULL, &st, &code,
429 "gnunet-identity",
430 "gnunet-identity", "-e", "master-zone", "-s",
431 "namestore", NULL))
432 return;
433
434 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
435 NULL, NULL, &st, &code,
436 "gnunet-identity",
437 "gnunet-identity", "-e", "master-zone", "-s",
438 "gns-proxy", NULL))
439 return;
440
441 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
442 NULL, NULL, &st, &code,
443 "gnunet-identity",
444 "gnunet-identity", "-e", "master-zone", "-s",
445 "gns-intercept", NULL))
446 return;
447
448 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
449 NULL, NULL, &st, &code,
450 "gnunet-identity",
451 "gnunet-identity", "-e", "private-zone", "-s",
452 "gns-private", NULL))
453 return;
454
455 if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
456 NULL, NULL, &st, &code,
457 "gnunet-identity",
458 "gnunet-identity", "-e", "sks-zone", "-s",
459 "fs-sks", NULL))
460 return;
461
462 ns = GNUNET_NAMESTORE_connect (cfg);
463 sh = GNUNET_IDENTITY_connect (cfg, &get_ego, NULL);
464 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
465}
466
467
468/**
469 * The main function for gnunet-gns.
470 *
471 * @param argc number of arguments from the command line
472 * @param argv command line arguments
473 * @return 0 ok, 1 on error
474 */
475int
476main (int argc, char *const *argv)
477{
478 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
479 GNUNET_GETOPT_OPTION_END
480 };
481 int r;
482
483 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
484 return 2;
485
486 GNUNET_log_setup ("gnunet-gns-import", "WARNING", NULL);
487 ret = 0;
488 r = GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-import",
489 _ (
490 "This program will import some GNS authorities into your GNS namestore."),
491 options,
492 &run, NULL);
493 GNUNET_free_nz ((void *) argv);
494 return GNUNET_OK == r ? ret : 1;
495}
496
497
498/* end of gnunet-gns-import.c */