aboutsummaryrefslogtreecommitdiff
path: root/src/hello
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-12 20:30:37 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-19 12:39:55 +0100
commitaf252f5c3d4e62f4db39bbc65f3eea4f853d04bc (patch)
tree616629ee96494f49469162563ee6c90424c871e9 /src/hello
parent3e3081cfd22f5dacbeaba2843131c4aec530b562 (diff)
downloadgnunet-af252f5c3d4e62f4db39bbc65f3eea4f853d04bc.tar.gz
gnunet-af252f5c3d4e62f4db39bbc65f3eea4f853d04bc.zip
-conclude hello-uri implementation and test
Diffstat (limited to 'src/hello')
-rw-r--r--src/hello/.gitignore2
-rw-r--r--src/hello/Makefile.am7
-rw-r--r--src/hello/hello-uri.c459
-rw-r--r--src/hello/test_hello-ng.c23
-rw-r--r--src/hello/test_hello-uri.c176
5 files changed, 612 insertions, 55 deletions
diff --git a/src/hello/.gitignore b/src/hello/.gitignore
index bb49ceb20..d175d148e 100644
--- a/src/hello/.gitignore
+++ b/src/hello/.gitignore
@@ -1,3 +1,5 @@
1gnunet-hello 1gnunet-hello
2test_friend_hello 2test_friend_hello
3test_hello 3test_hello
4test_hello-uri
5test_hello-ng
diff --git a/src/hello/Makefile.am b/src/hello/Makefile.am
index f97ede97c..08d976260 100644
--- a/src/hello/Makefile.am
+++ b/src/hello/Makefile.am
@@ -25,6 +25,7 @@ noinst_PROGRAMS = \
25 25
26check_PROGRAMS = \ 26check_PROGRAMS = \
27 test_hello \ 27 test_hello \
28 test_hello-uri \
28 test_friend_hello \ 29 test_friend_hello \
29 test_hello-ng 30 test_hello-ng
30 31
@@ -45,6 +46,12 @@ test_hello_ng_LDADD = \
45 libgnunethello.la \ 46 libgnunethello.la \
46 $(top_builddir)/src/util/libgnunetutil.la 47 $(top_builddir)/src/util/libgnunetutil.la
47 48
49test_hello_uri_SOURCES = \
50 test_hello-uri.c
51test_hello_uri_LDADD = \
52 libgnunethello.la \
53 $(top_builddir)/src/util/libgnunetutil.la
54
48 55
49test_friend_hello_SOURCES = \ 56test_friend_hello_SOURCES = \
50 test_friend_hello.c 57 test_friend_hello.c
diff --git a/src/hello/hello-uri.c b/src/hello/hello-uri.c
index 347c4bf0c..49e4f6ed3 100644
--- a/src/hello/hello-uri.c
+++ b/src/hello/hello-uri.c
@@ -22,6 +22,17 @@
22 * @file hello/hello-uri.c 22 * @file hello/hello-uri.c
23 * @brief helper library for handling URI-based HELLOs 23 * @brief helper library for handling URI-based HELLOs
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * Note:
27 * - Current API does not support deserializing HELLO of
28 * another peer and then serializing it into another
29 * format (we always require the private key).
30 * Not sure if we need this, but if we do, we need
31 * to extend the builder and the API.
32 * - Current API does not allow overriding the default
33 * HELLO expiration time. We may want to add a function
34 * that does this to create bootstrap HELLOs shipped with
35 * the TGZ.
25 */ 36 */
26#include "platform.h" 37#include "platform.h"
27#include "gnunet_signatures.h" 38#include "gnunet_signatures.h"
@@ -29,15 +40,44 @@
29#include "gnunet_protocols.h" 40#include "gnunet_protocols.h"
30#include "gnunet_util_lib.h" 41#include "gnunet_util_lib.h"
31 42
43/**
44 * For how long are HELLO signatures valid?
45 */
46#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
47 GNUNET_TIME_UNIT_DAYS, 2)
48
49
32GNUNET_NETWORK_STRUCT_BEGIN 50GNUNET_NETWORK_STRUCT_BEGIN
33 51
34/** 52/**
53 * Message signed as part of a HELLO block/URL.
54 */
55struct HelloSignaturePurpose
56{
57 /**
58 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_HELLO
59 */
60 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
61
62 /**
63 * When does the signature expire?
64 */
65 struct GNUNET_TIME_AbsoluteNBO expiration_time;
66
67 /**
68 * Hash over all addresses.
69 */
70 struct GNUNET_HashCode h_addrs;
71
72};
73
74/**
35 * Binary block we sign when we sign an address. 75 * Binary block we sign when we sign an address.
36 */ 76 */
37struct HelloUriMessage 77struct HelloUriMessage
38{ 78{
39 /** 79 /**
40 * Purpose must be #GNUNET_MESSAGE_TYPE_HELLO_URI 80 * Type must be #GNUNET_MESSAGE_TYPE_HELLO_URI
41 */ 81 */
42 struct GNUNET_MessageHeader header; 82 struct GNUNET_MessageHeader header;
43 83
@@ -51,11 +91,32 @@ struct HelloUriMessage
51 */ 91 */
52 uint16_t url_counter GNUNET_PACKED; 92 uint16_t url_counter GNUNET_PACKED;
53 93
94 /* followed by a 'block' */
95};
96
97
98/**
99 * Start of a 'block'.
100 */
101struct BlockHeader
102{
54 /** 103 /**
55 * Public key of the peer. 104 * Public key of the peer.
56 */ 105 */
57 struct GNUNET_PeerIdentity pid; 106 struct GNUNET_PeerIdentity pid;
107
108 /**
109 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
110 */
111 struct GNUNET_CRYPTO_EddsaSignature sig;
112
113 /**
114 * When does the HELLO expire?
115 */
116 struct GNUNET_TIME_AbsoluteNBO expiration_time;
117
58}; 118};
119
59GNUNET_NETWORK_STRUCT_END 120GNUNET_NETWORK_STRUCT_END
60 121
61 122
@@ -114,6 +175,98 @@ struct GNUNET_HELLO_Builder
114}; 175};
115 176
116 177
178/**
179 * Compute @a hash over addresses in @a builder.
180 *
181 * @param builder the builder to hash addresses of
182 * @param[out] hash where to write the hash
183 */
184static void
185hash_addresses (const struct GNUNET_HELLO_Builder *builder,
186 struct GNUNET_HashCode *hash)
187{
188 struct GNUNET_HashContext *hc;
189
190 hc = GNUNET_CRYPTO_hash_context_start ();
191 for (struct Address *a = builder->a_head;
192 NULL != a;
193 a = a->next)
194 {
195 GNUNET_CRYPTO_hash_context_read (hc,
196 a->uri,
197 a->uri_len);
198 }
199 GNUNET_CRYPTO_hash_context_finish (hc,
200 hash);
201
202}
203
204
205/**
206 * Create HELLO signature.
207 *
208 * @param builder the builder to use
209 * @param et expiration time to sign
210 * @param priv key to sign with
211 * @param[out] sig where to write the signature
212 */
213static void
214sign_hello (const struct GNUNET_HELLO_Builder *builder,
215 struct GNUNET_TIME_Timestamp et,
216 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
217 struct GNUNET_CRYPTO_EddsaSignature *sig)
218{
219 struct HelloSignaturePurpose hsp = {
220 .purpose.size = htonl (sizeof (hsp)),
221 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
222 .expiration_time = GNUNET_TIME_absolute_hton (et.abs_time)
223 };
224
225 hash_addresses (builder,
226 &hsp.h_addrs);
227 GNUNET_CRYPTO_eddsa_sign (priv,
228 &hsp,
229 sig);
230}
231
232
233/**
234 * Verify HELLO signature.
235 *
236 * @param builder the builder to use
237 * @param et expiration time to verify
238 * @param sig signature to verify
239 * @return #GNUNET_OK if everything is ok, #GNUNET_NO if the
240 * HELLO expired, #GNUNET_SYSERR if the signature is wrong
241 */
242static enum GNUNET_GenericReturnValue
243verify_hello (const struct GNUNET_HELLO_Builder *builder,
244 struct GNUNET_TIME_Absolute et,
245 const struct GNUNET_CRYPTO_EddsaSignature *sig)
246{
247 struct HelloSignaturePurpose hsp = {
248 .purpose.size = htonl (sizeof (hsp)),
249 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
250 .expiration_time = GNUNET_TIME_absolute_hton (et)
251 };
252
253 hash_addresses (builder,
254 &hsp.h_addrs);
255 if (GNUNET_OK !=
256 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_HELLO,
257 &hsp,
258 sig,
259 &builder->pid.public_key))
260 {
261 GNUNET_break_op (0);
262 return GNUNET_SYSERR;
263 }
264 if (GNUNET_TIME_absolute_is_past (et))
265 return GNUNET_NO;
266 return GNUNET_OK;
267}
268
269
117struct GNUNET_HELLO_Builder * 270struct GNUNET_HELLO_Builder *
118GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid) 271GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid)
119{ 272{
@@ -147,29 +300,45 @@ struct GNUNET_HELLO_Builder *
147GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg) 300GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg)
148{ 301{
149 const struct HelloUriMessage *h; 302 const struct HelloUriMessage *h;
150 struct GNUNET_HELLO_Builder *b;
151 uint16_t size = ntohs (msg->size); 303 uint16_t size = ntohs (msg->size);
152 const char *pos;
153 304
154 if (GNUNET_MESSAGE_TYPE_HELLO_URI != ntohs (msg->type)) 305 if (GNUNET_MESSAGE_TYPE_HELLO_URI != ntohs (msg->type))
155 { 306 {
156 GNUNET_break (0); 307 GNUNET_break (0);
157 return NULL; 308 return NULL;
158 } 309 }
159 if (sizeof (struct HelloUriMessage) < size) 310 if (sizeof (struct HelloUriMessage) > size)
160 { 311 {
161 GNUNET_break_op (0); 312 GNUNET_break_op (0);
162 return NULL; 313 return NULL;
163 } 314 }
164 h = (const struct HelloUriMessage *) msg; 315 h = (const struct HelloUriMessage *) msg;
165 pos = (const char *) &h[1];
166 size -= sizeof (*h); 316 size -= sizeof (*h);
167 b = GNUNET_HELLO_builder_new (&h->pid); 317 return GNUNET_HELLO_builder_from_block (&h[1],
168 for (unsigned int i = 0; i<ntohs (h->url_counter); i++) 318 size);
319}
320
321
322struct GNUNET_HELLO_Builder *
323GNUNET_HELLO_builder_from_block (const void *block,
324 size_t block_size)
325{
326 const struct BlockHeader *bh = block;
327 struct GNUNET_HELLO_Builder *b;
328
329 if (block_size < sizeof (*bh))
169 { 330 {
170 const char *end = memchr (pos, 331 GNUNET_break_op (0);
332 return NULL;
333 }
334 b = GNUNET_HELLO_builder_new (&bh->pid);
335 block += sizeof (*bh);
336 block_size -= sizeof (*bh);
337 while (block_size > 0)
338 {
339 const void *end = memchr (block,
171 '\0', 340 '\0',
172 size); 341 block_size);
173 342
174 if (NULL == end) 343 if (NULL == end)
175 { 344 {
@@ -179,79 +348,174 @@ GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg)
179 } 348 }
180 if (GNUNET_OK != 349 if (GNUNET_OK !=
181 GNUNET_HELLO_builder_add_address (b, 350 GNUNET_HELLO_builder_add_address (b,
182 pos)) 351 block))
183 { 352 {
184 GNUNET_break_op (0); 353 GNUNET_break_op (0);
185 GNUNET_HELLO_builder_free (b); 354 GNUNET_HELLO_builder_free (b);
186 return NULL; 355 return NULL;
187 } 356 }
188 end++; /* skip '\0' */ 357 end++;
189 size -= (end - pos); 358 block_size -= (end - block);
190 pos = end; 359 block = end;
191 } 360 }
192 if (0 != size)
193 { 361 {
194 GNUNET_break_op (0); 362 enum GNUNET_GenericReturnValue ret;
195 GNUNET_HELLO_builder_free (b); 363
196 return NULL; 364 ret = verify_hello (b,
365 GNUNET_TIME_absolute_ntoh (bh->expiration_time),
366 &bh->sig);
367 GNUNET_break (GNUNET_SYSERR != ret);
368 if (GNUNET_OK != ret)
369 {
370 GNUNET_HELLO_builder_free (b);
371 return NULL;
372 }
197 } 373 }
198 return b; 374 return b;
199} 375}
200 376
201 377
202struct GNUNET_HELLO_Builder * 378struct GNUNET_HELLO_Builder *
203GNUNET_HELLO_builder_from_block (const void *block, 379GNUNET_HELLO_builder_from_url (const char *url)
204 size_t block_size)
205{ 380{
206 const struct GNUNET_PeerIdentity *pid = block; 381 const char *q;
382 const char *s1;
383 const char *s2;
384 struct GNUNET_PeerIdentity pid;
385 struct GNUNET_CRYPTO_EddsaSignature sig;
386 struct GNUNET_TIME_Absolute et;
387 size_t len;
207 struct GNUNET_HELLO_Builder *b; 388 struct GNUNET_HELLO_Builder *b;
208 389
209 if (block_size < sizeof (*pid)) 390 if (0 != strncasecmp (url,
391 "gnunet://hello/",
392 strlen ("gnunet://hello/")))
393 return NULL;
394 url += strlen ("gnunet://hello/");
395 s1 = strchr (url, '/');
396 if (NULL == s1)
210 { 397 {
211 GNUNET_break_op (0); 398 GNUNET_break_op (0);
212 return NULL; 399 return NULL;
213 } 400 }
214 b = GNUNET_HELLO_builder_new (pid); 401 s2 = strchr (s1 + 1, '/');
215 block += sizeof (*pid); 402 if (NULL == s1)
216 block_size -= sizeof (*pid);
217 while (block_size > 0)
218 { 403 {
219 const void *end = memchr (block, 404 GNUNET_break_op (0);
220 '\0', 405 return NULL;
221 block_size); 406 }
407 q = strchr (url, '?');
408 if (NULL == q)
409 q = url + strlen (url);
410 if (GNUNET_OK !=
411 GNUNET_STRINGS_string_to_data (url,
412 s1 - url,
413 &pid,
414 sizeof(pid)))
415 {
416 GNUNET_break_op (0);
417 return NULL;
418 }
419 if (GNUNET_OK !=
420 GNUNET_STRINGS_string_to_data (s1 + 1,
421 s2 - (s1 + 1),
422 &sig,
423 sizeof(sig)))
424 {
425 GNUNET_break_op (0);
426 return NULL;
427 }
428 {
429 unsigned long long sec;
430 char dummy = '?';
431
432 if ( (0 == sscanf (s2 + 1,
433 "%llu%c",
434 &sec,
435 &dummy)) ||
436 ('?' != dummy) )
437 {
438 GNUNET_break_op (0);
439 return NULL;
440 }
441 et = GNUNET_TIME_absolute_from_s (sec);
442 }
222 443
223 if (NULL == end) 444 b = GNUNET_HELLO_builder_new (&pid);
445 len = strlen (q);
446 while (len > 0)
447 {
448 const char *eq;
449 const char *amp;
450 char *addr = NULL;
451 char *uri;
452
453 /* skip ?/& separator */
454 len--;
455 q++;
456 eq = strchr (q, '=');
457 if ( (eq == q) ||
458 (NULL == eq) )
224 { 459 {
225 GNUNET_break_op (0); 460 GNUNET_break_op (0);
226 GNUNET_HELLO_builder_free (b); 461 GNUNET_HELLO_builder_free (b);
227 return NULL; 462 return NULL;
228 } 463 }
464 amp = strchr (eq, '&');
465 if (NULL == amp)
466 amp = &q[len];
467 GNUNET_STRINGS_urldecode (eq + 1,
468 amp - (eq + 1),
469 &addr);
470 if ( (NULL == addr) ||
471 (0 == strlen (addr)) )
472 {
473 GNUNET_free (addr);
474 GNUNET_break_op (0);
475 GNUNET_HELLO_builder_free (b);
476 return NULL;
477 }
478 GNUNET_asprintf (&uri,
479 "%.*s://%s",
480 (int) (eq - q),
481 q,
482 addr);
483 GNUNET_free (addr);
229 if (GNUNET_OK != 484 if (GNUNET_OK !=
230 GNUNET_HELLO_builder_add_address (b, 485 GNUNET_HELLO_builder_add_address (b,
231 block)) 486 uri))
232 { 487 {
233 GNUNET_break_op (0); 488 GNUNET_break_op (0);
489 GNUNET_free (uri);
234 GNUNET_HELLO_builder_free (b); 490 GNUNET_HELLO_builder_free (b);
235 return NULL; 491 return NULL;
236 } 492 }
237 end++; 493 GNUNET_free (uri);
238 block_size -= (end - block); 494 /* move to next URL */
239 block = end; 495 len -= (amp - q);
496 q = amp;
240 } 497 }
241 return b;
242}
243 498
499 {
500 enum GNUNET_GenericReturnValue ret;
244 501
245struct GNUNET_HELLO_Builder * 502 ret = verify_hello (b,
246GNUNET_HELLO_builder_from_url (const char *url) 503 et,
247{ 504 &sig);
248 // FIXME! 505 GNUNET_break (GNUNET_SYSERR != ret);
249 return NULL; 506 if (GNUNET_OK != ret)
507 {
508 GNUNET_HELLO_builder_free (b);
509 return NULL;
510 }
511 }
512 return b;
250} 513}
251 514
252 515
253struct GNUNET_MQ_Envelope * 516struct GNUNET_MQ_Envelope *
254GNUNET_HELLO_builder_to_env (struct GNUNET_HELLO_Builder *builder) 517GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
518 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
255{ 519{
256 struct GNUNET_MQ_Envelope *env; 520 struct GNUNET_MQ_Envelope *env;
257 struct HelloUriMessage *msg; 521 struct HelloUriMessage *msg;
@@ -260,14 +524,15 @@ GNUNET_HELLO_builder_to_env (struct GNUNET_HELLO_Builder *builder)
260 blen = 0; 524 blen = 0;
261 GNUNET_assert (GNUNET_NO == 525 GNUNET_assert (GNUNET_NO ==
262 GNUNET_HELLO_builder_to_block (builder, 526 GNUNET_HELLO_builder_to_block (builder,
527 priv,
263 NULL, 528 NULL,
264 &blen)); 529 &blen));
265 env = GNUNET_MQ_msg_extra (msg, 530 env = GNUNET_MQ_msg_extra (msg,
266 blen, 531 blen,
267 GNUNET_MESSAGE_TYPE_HELLO_URI); 532 GNUNET_MESSAGE_TYPE_HELLO_URI);
268 msg->pid = builder->pid;
269 GNUNET_assert (GNUNET_OK == 533 GNUNET_assert (GNUNET_OK ==
270 GNUNET_HELLO_builder_to_block (builder, 534 GNUNET_HELLO_builder_to_block (builder,
535 priv,
271 &msg[1], 536 &msg[1],
272 &blen)); 537 &blen));
273 return env; 538 return env;
@@ -275,20 +540,80 @@ GNUNET_HELLO_builder_to_env (struct GNUNET_HELLO_Builder *builder)
275 540
276 541
277char * 542char *
278GNUNET_HELLO_builder_to_url (struct GNUNET_HELLO_Builder *builder) 543GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
544 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
279{ 545{
280 // FIXME! 546 struct GNUNET_CRYPTO_EddsaSignature sig;
281 return NULL; 547 struct GNUNET_TIME_Timestamp et;
548 char *result;
549 char *pids;
550 char *sigs;
551 const char *sep = "?";
552
553 et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION);
554 sign_hello (builder,
555 et,
556 priv,
557 &sig);
558 pids = GNUNET_STRINGS_data_to_string_alloc (&builder->pid,
559 sizeof (builder->pid));
560 sigs = GNUNET_STRINGS_data_to_string_alloc (&sig,
561 sizeof (sig));
562 GNUNET_asprintf (&result,
563 "gnunet://hello/%s/%s/%llu",
564 pids,
565 sigs,
566 (unsigned long long) GNUNET_TIME_timestamp_to_s (et));
567 GNUNET_free (sigs);
568 GNUNET_free (pids);
569 for (struct Address *a = builder->a_head;
570 NULL != a;
571 a = a->next)
572 {
573 char *ue;
574 char *tmp;
575 int pfx_len;
576 const char *eou;
577
578 eou = strstr (a->uri,
579 "://");
580 if (NULL == eou)
581 {
582 GNUNET_break (0);
583 GNUNET_free (result);
584 return NULL;
585 }
586 pfx_len = eou - a->uri;
587 eou += 3;
588 GNUNET_STRINGS_urlencode (eou,
589 a->uri_len - 4 - pfx_len,
590 &ue);
591 GNUNET_asprintf (&tmp,
592 "%s%s%.*s=%s",
593 result,
594 sep,
595 pfx_len,
596 a->uri,
597 ue);
598 GNUNET_free (ue);
599 GNUNET_free (result);
600 result = tmp;
601 sep = "&";
602 }
603 return result;
282} 604}
283 605
284 606
285enum GNUNET_GenericReturnValue 607enum GNUNET_GenericReturnValue
286GNUNET_HELLO_builder_to_block (struct GNUNET_HELLO_Builder *builder, 608GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
609 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
287 void *block, 610 void *block,
288 size_t *block_size) 611 size_t *block_size)
289{ 612{
290 size_t needed = sizeof (struct GNUNET_PeerIdentity); 613 struct BlockHeader bh;
614 size_t needed = sizeof (bh);
291 char *pos; 615 char *pos;
616 struct GNUNET_TIME_Timestamp et;
292 617
293 for (struct Address *a = builder->a_head; 618 for (struct Address *a = builder->a_head;
294 NULL != a; 619 NULL != a;
@@ -303,10 +628,17 @@ GNUNET_HELLO_builder_to_block (struct GNUNET_HELLO_Builder *builder,
303 *block_size = needed; 628 *block_size = needed;
304 return GNUNET_NO; 629 return GNUNET_NO;
305 } 630 }
631 bh.pid = builder->pid;
632 et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION);
633 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
634 sign_hello (builder,
635 et,
636 priv,
637 &bh.sig);
306 memcpy (block, 638 memcpy (block,
307 &builder->pid, 639 &bh,
308 sizeof (builder->pid)); 640 sizeof (bh));
309 pos = block + sizeof (builder->pid); 641 pos = block + sizeof (bh);
310 for (struct Address *a = builder->a_head; 642 for (struct Address *a = builder->a_head;
311 NULL != a; 643 NULL != a;
312 a = a->next) 644 a = a->next)
@@ -327,7 +659,26 @@ GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
327{ 659{
328 size_t alen = strlen (address) + 1; 660 size_t alen = strlen (address) + 1;
329 struct Address *a; 661 struct Address *a;
662 const char *e;
330 663
664 if (NULL == (e = strstr (address,
665 "://")))
666 {
667 GNUNET_break_op (0);
668 return GNUNET_SYSERR;
669 }
670 if (e == address)
671 {
672 GNUNET_break_op (0);
673 return GNUNET_SYSERR;
674 }
675 for (const char *p = address; p != e; p++)
676 if ( (! isalpha ((unsigned char) *p)) &&
677 ('+' != *p) )
678 {
679 GNUNET_break_op (0);
680 return GNUNET_SYSERR;
681 }
331 /* check for duplicates */ 682 /* check for duplicates */
332 for (a = builder->a_head; 683 for (a = builder->a_head;
333 NULL != a; 684 NULL != a;
@@ -341,9 +692,10 @@ GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
341 address, 692 address,
342 alen); 693 alen);
343 a->uri = (const char *) &a[1]; 694 a->uri = (const char *) &a[1];
344 GNUNET_CONTAINER_DLL_insert (builder->a_head, 695 GNUNET_CONTAINER_DLL_insert_tail (builder->a_head,
345 builder->a_tail, 696 builder->a_tail,
346 a); 697 a);
698 builder->a_length++;
347 return GNUNET_OK; 699 return GNUNET_OK;
348} 700}
349 701
@@ -366,6 +718,7 @@ GNUNET_HELLO_builder_del_address (struct GNUNET_HELLO_Builder *builder,
366 GNUNET_CONTAINER_DLL_remove (builder->a_head, 718 GNUNET_CONTAINER_DLL_remove (builder->a_head,
367 builder->a_tail, 719 builder->a_tail,
368 a); 720 a);
721 builder->a_length--;
369 GNUNET_free (a); 722 GNUNET_free (a);
370 return GNUNET_OK; 723 return GNUNET_OK;
371} 724}
diff --git a/src/hello/test_hello-ng.c b/src/hello/test_hello-ng.c
index e6b1d42a0..4ace9439f 100644
--- a/src/hello/test_hello-ng.c
+++ b/src/hello/test_hello-ng.c
@@ -1,3 +1,22 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 */
1#include "platform.h" 20#include "platform.h"
2#include "gnunet_util_lib.h" 21#include "gnunet_util_lib.h"
3#include "gnunet_nt_lib.h" 22#include "gnunet_nt_lib.h"
@@ -23,12 +42,12 @@ main (int argc,
23 GNUNET_NT_LAN, 42 GNUNET_NT_LAN,
24 t, 43 t,
25 &privKey, 44 &privKey,
26 (void**)&res, 45 (void**) &res,
27 &res_len); 46 &res_len);
28 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 47 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
29 "%s\n", res); 48 "%s\n", res);
30 GNUNET_assert (NULL != 49 GNUNET_assert (NULL !=
31 GNUNET_HELLO_extract_address ((void**)res, 50 GNUNET_HELLO_extract_address ((void**) res,
32 res_len, 51 res_len,
33 &pid, 52 &pid,
34 &nt, 53 &nt,
diff --git a/src/hello/test_hello-uri.c b/src/hello/test_hello-uri.c
new file mode 100644
index 000000000..295c08ea3
--- /dev/null
+++ b/src/hello/test_hello-uri.c
@@ -0,0 +1,176 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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 hello/test_hello-uri.c
22 * @brief test for helper library for handling URI-based HELLOs
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_signatures.h"
27#include "gnunet_hello_uri_lib.h"
28#include "gnunet_util_lib.h"
29
30
31/**
32 * Check for expected URIs.
33 *
34 * @param cls a `unsigned int*`, bitmask set to found URIs
35 * @param uri URI to check for
36 */
37static void
38check_uris (void *cls,
39 const char *uri)
40{
41 unsigned int *found = cls;
42
43 if (0 == strcmp (uri,
44 "test://address"))
45 *found |= 1;
46 else if (0 == strcmp (uri,
47 "test://more"))
48 *found |= 2;
49 else
50 *found = (unsigned int) -1;
51}
52
53
54int
55main (int argc,
56 char *argv[])
57{
58 struct GNUNET_PeerIdentity pid;
59 struct GNUNET_HELLO_Builder *b;
60 struct GNUNET_CRYPTO_EddsaPrivateKey priv;
61
62 GNUNET_log_setup ("test-hell-uri",
63 "WARNING",
64 NULL);
65 GNUNET_CRYPTO_eddsa_key_create (&priv);
66 GNUNET_CRYPTO_eddsa_key_get_public (&priv,
67 &pid.public_key);
68 b = GNUNET_HELLO_builder_new (&pid);
69 GNUNET_assert (GNUNET_SYSERR ==
70 GNUNET_HELLO_builder_add_address (b,
71 "invalid"));
72 GNUNET_assert (GNUNET_SYSERR ==
73 GNUNET_HELLO_builder_add_address (b,
74 "i%v://bla"));
75 GNUNET_assert (GNUNET_SYSERR ==
76 GNUNET_HELLO_builder_add_address (b,
77 "://empty"));
78 GNUNET_assert (GNUNET_OK ==
79 GNUNET_HELLO_builder_add_address (b,
80 "test://address"));
81 GNUNET_assert (GNUNET_NO ==
82 GNUNET_HELLO_builder_add_address (b,
83 "test://address"));
84 GNUNET_assert (GNUNET_OK ==
85 GNUNET_HELLO_builder_add_address (b,
86 "test://more"));
87 {
88 void *block;
89 size_t block_size = 0;
90 struct GNUNET_HELLO_Builder *b2;
91 struct GNUNET_PeerIdentity p2;
92 unsigned int found;
93
94 GNUNET_assert (GNUNET_NO ==
95 GNUNET_HELLO_builder_to_block (b,
96 &priv,
97 NULL,
98 &block_size));
99 GNUNET_assert (GNUNET_NO ==
100 GNUNET_HELLO_builder_to_block (b,
101 &priv,
102 NULL,
103 &block_size));
104 GNUNET_assert (0 != block_size);
105 block = GNUNET_malloc (block_size);
106 GNUNET_assert (GNUNET_OK ==
107 GNUNET_HELLO_builder_to_block (b,
108 &priv,
109 block,
110 &block_size));
111 b2 = GNUNET_HELLO_builder_from_block (block,
112 block_size);
113 GNUNET_free (block);
114 GNUNET_assert (NULL != b2);
115 found = 0;
116 GNUNET_HELLO_builder_iterate (b2,
117 &p2,
118 &check_uris,
119 &found);
120 GNUNET_assert (3 == found);
121 GNUNET_assert (0 ==
122 GNUNET_memcmp (&p2,
123 &pid));
124 GNUNET_HELLO_builder_free (b2);
125 }
126
127 {
128 char *url;
129 struct GNUNET_HELLO_Builder *b2;
130 struct GNUNET_PeerIdentity p2;
131 unsigned int found;
132
133 url = GNUNET_HELLO_builder_to_url (b,
134 &priv);
135 b2 = GNUNET_HELLO_builder_from_url (url);
136 GNUNET_free (url);
137 GNUNET_assert (NULL != b2);
138 found = 0;
139 GNUNET_HELLO_builder_iterate (b2,
140 &p2,
141 &check_uris,
142 &found);
143 GNUNET_assert (3 == found);
144 GNUNET_assert (0 ==
145 GNUNET_memcmp (&p2,
146 &pid));
147 GNUNET_HELLO_builder_free (b2);
148 }
149
150 {
151 struct GNUNET_MQ_Envelope *env;
152 struct GNUNET_HELLO_Builder *b2;
153 struct GNUNET_PeerIdentity p2;
154 unsigned int found;
155
156 env = GNUNET_HELLO_builder_to_env (b,
157 &priv);
158 b2 = GNUNET_HELLO_builder_from_msg (GNUNET_MQ_env_get_msg (env));
159 GNUNET_free (env);
160 GNUNET_assert (NULL != b2);
161 found = 0;
162 GNUNET_HELLO_builder_iterate (b2,
163 &p2,
164 &check_uris,
165 &found);
166 GNUNET_assert (3 == found);
167 GNUNET_assert (0 ==
168 GNUNET_memcmp (&p2,
169 &pid));
170 GNUNET_HELLO_builder_free (b2);
171 }
172
173
174 GNUNET_HELLO_builder_free (b);
175 return 0;
176}