GNUnet 0.28.1-dev.4-47-g3e168ca2d
 
Loading...
Searching...
No Matches
hello-uri.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022, 2026 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
37#include "gnunet_time_lib.h"
38#include "platform.h"
39#include "gnunet_util_lib.h"
40#include "gnunet_signatures.h"
42#include "gnunet_protocols.h"
43
44
46
68
73{
78
83
88
89 /* followed by a 'block' */
90};
91
92
114
115
121{
126
131
136
141
146
147 /* followed by the serialized addresses of the 'block' */
148};
149
150
152
153
158{
162 struct Address *next;
163
167 struct Address *prev;
168
172 const char *uri;
173
177 size_t uri_len;
178};
179
180
185{
190
195
199 unsigned int a_length;
200
201};
202
207{
212
216 const char *address_uri;
217
221 unsigned int found;
222
226 unsigned int merged;
227};
228
233{
238
243
248
252 unsigned int a_length;
253
258
263};
264
265
266static void
267hash_addresses (const struct Address *addr_start,
268 struct GNUNET_HashCode *hash)
269{
270 struct GNUNET_HashContext *hc;
271
273
274#if HELLO_DETERMINISTIC_PID_DERIVATION
275 for (const struct Address *a = addr_start;
276 NULL != a;
277 a = a->next)
278 {
280 "Hashing over %.*s\n",
281 (int) a->uri_len,
282 a->uri);
284 a->uri,
285 a->uri_len);
286 }
287#endif
289 hash);
290
291}
292
293
304verify_hello (const struct GNUNET_HELLO_Parser *parser,
305 struct GNUNET_TIME_Absolute et,
306 const struct GNUNET_CRYPTO_EddsaSignature *sig)
307{
308 struct PilsHelloSignaturePurpose hsp = {
309 .purpose.size = htonl (sizeof (hsp)),
310 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
311 .expiration_time = GNUNET_TIME_absolute_hton (et)
312 };
313
314 hash_addresses (parser->a_head,
315 &hsp.h_addrs);
316 if (GNUNET_OK !=
318 &hsp,
319 sig,
320 &parser->pid.public_key))
321 {
323 "HELLO signature invalid, rejecting.\n");
324 return GNUNET_SYSERR;
325 }
327 return GNUNET_NO;
328 return GNUNET_OK;
329}
330
331
332static struct GNUNET_HELLO_Parser *
334{
335 struct GNUNET_HELLO_Parser *p;
336
338 p->pid = *pid;
339 return p;
340}
341
342
351
352
353const struct GNUNET_PeerIdentity *
355{
356 return &parser->pid;
357}
358
359
362 struct GNUNET_PeerIdentity *pid)
363{
365 struct Address *a;
366
368 if (NULL != pid)
369 *pid = p->pid;
370 /* check for duplicates */
371 for (a = p->a_head;
372 NULL != a;
373 a = a->next)
375 return builder;
376}
377
378
379void
381{
382 struct Address *a;
383
384 while (NULL != (a = parser->a_head))
385 {
386 GNUNET_CONTAINER_DLL_remove (parser->a_head,
387 parser->a_tail,
388 a);
389 parser->a_length--;
390 GNUNET_free (a);
391 }
392 GNUNET_assert (0 == parser->a_length);
393 GNUNET_free (parser);
394}
395
396
397void
399{
400 struct Address *a;
401
402 while (NULL != (a = builder->a_head))
403 {
405 builder->a_tail,
406 a);
407 builder->a_length--;
408 GNUNET_free (a);
409 }
410 GNUNET_assert (0 == builder->a_length);
412}
413
414
415struct GNUNET_HELLO_Parser *
423
424
425struct GNUNET_HELLO_Parser *
427 const struct GNUNET_PeerIdentity *pid,
428 int noverify)
429{
430 uint16_t size;
431
432 /* Callers routinely pass the value of a PEERSTORE record straight in,
433 and a zero-length record has a NULL value. Failing that the same way
434 as any other unusable input beats dereferencing it. */
435 if (NULL == msg)
436 {
437 GNUNET_break (0);
438 return NULL;
439 }
440 size = ntohs (msg->size);
441 switch (ntohs (msg->type))
442 {
444 {
445 const struct HelloUriMessage *h;
446
447 if (sizeof (struct HelloUriMessage) > size)
448 {
449 GNUNET_break_op (0);
450 return NULL;
451 }
452
453 h = (const struct HelloUriMessage *) msg;
454 size -= sizeof (*h);
456 size,
457 noverify);
458 }
460 {
461 struct GNUNET_TIME_Absolute block_expiration;
462 struct GNUNET_HELLO_Parser *p;
463 size_t block_size;
464 void *block;
465
466 if (sizeof (struct DhtHelloMessage) > size)
467 {
468 GNUNET_break_op (0);
469 return NULL;
470 }
471
473 msg,
474 pid,
475 &block,
476 &block_size,
477 &block_expiration))
478 {
479 GNUNET_break_op (0);
480 return NULL;
481 }
482
484 block_size,
485 noverify);
486 GNUNET_free (block);
487 return p;
488 }
489 default:
490 GNUNET_break_op (0);
491 return NULL;
492 }
493}
494
495
498{
499 const char *e;
500
501 if (NULL == (e = strstr (address,
502 "://")))
503 {
504 GNUNET_break_op (0);
506 "Invalid address `%s'\n",
507 address);
508 return GNUNET_SYSERR;
509 }
510 if (e == address)
511 {
512 GNUNET_break_op (0);
513 return GNUNET_SYSERR;
514 }
515 for (const char *p = address; p != e; p++)
516 if ( (! isalpha ((unsigned char) *p)) &&
517 ('+' != *p) )
518 {
519 GNUNET_break_op (0);
520 return GNUNET_SYSERR;
521 }
522 return GNUNET_OK;
523}
524
525
534int
535static
536cmp_address (void*cls, struct Address *a, struct Address *b)
537{
538 return strcmp (a->uri, b->uri);
539}
540
541
544 const char *address)
545{
546 struct Address *a;
548 size_t alen = strlen (address) + 1;
549
551 if (GNUNET_OK != ret)
552 {
554 "Failed to add address to builder\n");
555 return ret;
556 }
557 /* check for duplicates */
558 for (a = parser->a_head;
559 NULL != a;
560 a = a->next)
561 if (0 == strcmp (address,
562 a->uri))
563 return GNUNET_NO;
564 a = GNUNET_malloc (sizeof (struct Address) + alen);
565 a->uri_len = alen;
566 memcpy (&a[1],
567 address,
568 alen);
569 a->uri = (const char *) &a[1];
572 NULL,
573 parser->a_head,
574 parser->a_tail,
575 a);
576 parser->a_length++;
577 return GNUNET_OK;
578}
579
580
581struct GNUNET_HELLO_Parser *
583 size_t block_size)
584{
586 block_size,
587 GNUNET_NO);
588}
589
590
591struct GNUNET_HELLO_Parser *
593 size_t block_size,
594 int noverify)
595{
596 const struct BlockHeader *bh = block;
597 struct GNUNET_HELLO_Parser *p;
598
599 if (block_size < sizeof (*bh))
600 {
601 GNUNET_break_op (0);
602 return NULL;
603 }
604 p = parser_new (&bh->pid);
605 block += sizeof (*bh);
606 block_size -= sizeof (*bh);
607 while (block_size > 0)
608 {
609 const void *end = memchr (block,
610 '\0',
611 block_size);
612
613 if (NULL == end)
614 {
615 GNUNET_break_op (0);
617 return NULL;
618 }
619 if (GNUNET_OK !=
621 block))
622 {
623 GNUNET_break_op (0);
625 return NULL;
626 }
627 end++;
628 block_size -= (end - block);
629 block = end;
630 }
631 {
632 struct GNUNET_TIME_Absolute et;
634 if (GNUNET_YES != noverify)
635 {
637 ret = verify_hello (p,
638 et,
639 &bh->sig);
641 if (GNUNET_OK != ret)
642 {
644 return NULL;
645 }
646 }
647 p->et = et;
648 p->sig = bh->sig;
649 }
650 return p;
651}
652
653
657{
658 struct GNUNET_TIME_Absolute et;
659 if (GNUNET_MESSAGE_TYPE_HELLO_URI == ntohs (msg->type))
660 {
661 const struct HelloUriMessage *h = (const struct HelloUriMessage *) msg;
662 const struct BlockHeader *bh = (const struct BlockHeader *) &h[1];
663 if (ntohs (msg->size) <
664 sizeof (struct HelloUriMessage) + sizeof (struct BlockHeader))
665 {
666 GNUNET_break_op (0);
668 }
669 if (ntohs (msg->size) ==
670 sizeof (struct HelloUriMessage) + sizeof (struct BlockHeader))
671 {
672 /* Well-formed, but carries no address: nothing worth keeping. This is
673 what our own HELLO looks like before a communicator has reported an
674 address, so it is not a protocol violation. */
676 }
677
679 return et;
680 }
681 else if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO == ntohs (msg->type))
682 {
683 const struct DhtHelloMessage *dht_hello
684 = (const struct DhtHelloMessage *) msg;
685 if (ntohs (msg->size) < sizeof (struct DhtHelloMessage))
686 {
687 GNUNET_break_op (0);
689 }
690
692 return et;
693 }
694 else
695 GNUNET_break_op (0);
697}
698
699
702 const char *address)
703{
704 struct Address *a;
706 size_t alen = strlen (address) + 1;
707
709 if (GNUNET_OK != ret)
710 {
712 "Failed to add address to builder\n");
713 return ret;
714 }
715 /* check for duplicates */
716 for (a = builder->a_head;
717 NULL != a;
718 a = a->next)
719 if (0 == strcmp (address,
720 a->uri))
721 return GNUNET_NO;
722 a = GNUNET_malloc (sizeof (struct Address) + alen);
723 a->uri_len = alen;
724 memcpy (&a[1],
725 address,
726 alen);
727 a->uri = (const char *) &a[1];
730 NULL,
731 builder->a_head,
732 builder->a_tail,
733 a);
734 builder->a_length++;
735 return GNUNET_OK;
736}
737
738
739struct GNUNET_HELLO_Parser *
741{
742 const char *q;
743 const char *s1;
744 const char *s2;
745 struct GNUNET_PeerIdentity pid;
746 struct GNUNET_TIME_Absolute et;
747 size_t len;
748 struct GNUNET_HELLO_Parser *p;
750
751 if (0 != strncasecmp (url,
752 "gnunet://hello/",
753 strlen ("gnunet://hello/")))
754 return NULL;
755 url += strlen ("gnunet://hello/");
756 s1 = strchr (url, '/');
757 if (NULL == s1)
758 {
759 GNUNET_break_op (0);
760 return NULL;
761 }
762 s2 = strchr (s1 + 1, '/');
763 if (NULL == s2)
764 {
765 GNUNET_break_op (0);
766 return NULL;
767 }
768 q = strchr (url, '?');
769 if (NULL == q)
770 q = url + strlen (url);
771 if (GNUNET_OK !=
773 s1 - url,
774 &pid,
775 sizeof(pid)))
776 {
777 GNUNET_break_op (0);
778 return NULL;
779 }
780 if (GNUNET_OK !=
782 s2 - (s1 + 1),
783 &sig,
784 sizeof(sig)))
785 {
786 GNUNET_break_op (0);
787 return NULL;
788 }
789 {
790 uint64_t sec;
791 char dummy = '?';
792
793 if ( (0 == sscanf (s2 + 1,
794 "%" PRIu64 "%c",
795 &sec,
796 &dummy)) ||
797 ('?' != dummy) )
798 {
799 GNUNET_break_op (0);
800 return NULL;
801 }
802 et.abs_value_us = sec;
803 }
804
805 p = parser_new (&pid);
806 p->et = et;
807 p->sig = sig;
808 len = strlen (q);
809 while (len > 0)
810 {
811 const char *eq;
812 const char *amp;
813 char *addr = NULL;
814 char *uri;
815
816 /* skip ?/& separator */
817 len--;
818 q++;
819 eq = strchr (q, '=');
820 if ( (eq == q) ||
821 (NULL == eq) )
822 {
823 GNUNET_break_op (0);
825 return NULL;
826 }
827 amp = strchr (eq, '&');
828 if (NULL == amp)
829 amp = &q[len];
831 amp - (eq + 1),
832 &addr);
833 if ( (NULL == addr) ||
834 (0 == strlen (addr)) )
835 {
836 GNUNET_free (addr);
837 GNUNET_break_op (0);
839 return NULL;
840 }
842 "%.*s://%s",
843 (int) (eq - q),
844 q,
845 addr);
846 GNUNET_free (addr);
847 if (GNUNET_OK !=
849 uri))
850 {
851 GNUNET_break_op (0);
854 return NULL;
855 }
857 /* move to next URL */
858 len -= (amp - q);
859 q = amp;
860 }
861
862 {
864
865 ret = verify_hello (p,
866 et,
867 &p->sig);
869 if (GNUNET_OK != ret)
870 {
872 return NULL;
873 }
874 }
875 return p;
876}
877
878
879char *
881{
882 char *result;
883 char *pids;
884 char *sigs;
885 const char *sep = "?";
886
887 pids = GNUNET_STRINGS_data_to_string_alloc (&parser->pid,
888 sizeof (parser->pid));
889 sigs = GNUNET_STRINGS_data_to_string_alloc (&parser->sig,
890 sizeof (parser->sig));
892 "gnunet://hello/%s/%s/%" PRIu64,
893 pids,
894 sigs,
895 parser->et.abs_value_us);
896 GNUNET_free (sigs);
897 GNUNET_free (pids);
898 for (struct Address *a = parser->a_head;
899 NULL != a;
900 a = a->next)
901 {
902 char *eou_url_encoded;
903 char *tmp;
904 int pfx_len;
905 const char *eou;
906
907 eou = strstr (a->uri,
908 "://");
909 if (NULL == eou)
910 {
911 GNUNET_break_op (0);
913 return NULL;
914 }
915 pfx_len = eou - a->uri;
916 eou += 3;
917 GNUNET_STRINGS_urlencode (a->uri_len - 4 - pfx_len,
918 eou,
919 &eou_url_encoded);
920 GNUNET_asprintf (&tmp,
921 "%s%s%.*s=%s",
922 result,
923 sep,
924 pfx_len,
925 a->uri,
926 eou_url_encoded);
927 GNUNET_free (eou_url_encoded);
929 result = tmp;
930 sep = "&";
931 }
932 return result;
933}
934
935
938 void *block,
939 size_t *block_size)
940{
941 struct BlockHeader bh;
942 size_t needed = sizeof (bh);
943 char *pos;
944
945 for (struct Address *a = parser->a_head;
946 NULL != a;
947 a = a->next)
948 {
949 GNUNET_assert (needed + a->uri_len > needed);
950 needed += a->uri_len;
951 }
952 if ( (NULL == block) ||
953 (needed > *block_size) )
954 {
955 *block_size = needed;
956 return GNUNET_NO;
957 }
958 bh.pid = parser->pid;
959 bh.sig = parser->sig;
961 memcpy (block,
962 &bh,
963 sizeof (bh));
964 pos = block + sizeof (bh);
965 for (struct Address *a = parser->a_head;
966 NULL != a;
967 a = a->next)
968 {
969 memcpy (pos,
970 a->uri,
971 a->uri_len);
972 pos += a->uri_len;
973 }
974 *block_size = needed;
975 return GNUNET_OK;
976}
977
978
979struct GNUNET_MQ_Envelope *
981{
982 struct GNUNET_MQ_Envelope *env;
983 struct HelloUriMessage *msg;
984 size_t blen;
985
986 if (parser->a_length > UINT16_MAX)
987 {
988 GNUNET_break_op (0);
989 return NULL;
990 }
991 blen = 0;
994 NULL,
995 &blen));
997 blen,
999 msg->url_counter = htons ((uint16_t) parser->a_length);
1002 &msg[1],
1003 &blen));
1004 return env;
1005}
1006
1007
1010 const char *address)
1011{
1012 struct Address *a;
1013
1014 /* check for duplicates */
1015 for (a = builder->a_head;
1016 NULL != a;
1017 a = a->next)
1018 if (0 == strcmp (address,
1019 a->uri))
1020 break;
1021 if (NULL == a)
1022 return GNUNET_NO;
1024 builder->a_tail,
1025 a);
1026 builder->a_length--;
1027 GNUNET_free (a);
1028 return GNUNET_OK;
1029}
1030
1031
1032void
1035 void *uc_cls)
1036{
1037 struct Address *nxt;
1038
1039 for (struct Address *a = builder->a_head;
1040 NULL != a;
1041 a = nxt)
1042 {
1043 nxt = a->next;
1044 uc (uc_cls,
1045 NULL,
1046 a->uri);
1047 }
1048}
1049
1050
1051const struct GNUNET_PeerIdentity*
1054 void *uc_cls)
1055{
1056 struct Address *nxt;
1057
1058 if (NULL == uc)
1059 return &parser->pid;
1060 for (struct Address *a = parser->a_head;
1061 NULL != a;
1062 a = nxt)
1063 {
1064 nxt = a->next;
1065 uc (uc_cls,
1066 &parser->pid,
1067 a->uri);
1068 }
1069 return &parser->pid;
1070}
1071
1072
1075 const struct GNUNET_PeerIdentity *pid,
1076 void **block,
1077 size_t *block_size,
1078 struct GNUNET_TIME_Absolute *block_expiration)
1079{
1080 const struct DhtHelloMessage *msg
1081 = (const struct DhtHelloMessage *) hello;
1082 uint16_t len = ntohs (hello->size);
1083 struct BlockHeader *bh;
1084 struct GNUNET_HELLO_Parser *b;
1086
1087 if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
1088 {
1089 GNUNET_break_op (0);
1090 return GNUNET_SYSERR;
1091 }
1092 if (len < sizeof (*msg))
1093 {
1094 GNUNET_break_op (0);
1095 return GNUNET_SYSERR;
1096 }
1097 len -= sizeof (*msg);
1098 *block_size = len + sizeof (*bh);
1099 *block = GNUNET_malloc (*block_size);
1100 bh = *block;
1101 bh->pid = *pid;
1102 bh->sig = msg->sig;
1103 bh->expiration_time = msg->expiration_time;
1104 *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
1105 memcpy (&bh[1],
1106 &msg[1],
1107 len);
1109 *block_size);
1110 if (NULL == b)
1111 {
1112 GNUNET_break_op (0);
1113 GNUNET_free (*block);
1114 *block_size = 0;
1115 return GNUNET_SYSERR;
1116 }
1117 ret = verify_hello (b,
1118 *block_expiration,
1119 &msg->sig);
1121 if (GNUNET_SYSERR == ret)
1122 {
1123 GNUNET_free (*block);
1124 *block_size = 0;
1125 return GNUNET_SYSERR;
1126 }
1127 return ret;
1128}
1129
1130
1138char *
1140{
1141 const char *dash;
1142
1143 dash = strchr (address, '-');
1144 if (NULL == dash)
1145 return NULL;
1146 return GNUNET_strndup (address, dash - address);
1147}
1148
1149
1152 const struct GNUNET_PeerIdentity *pid,
1153 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1155 char **result)
1156{
1157 char *pids;
1158 char *sigs;
1159 const char *sep = "?";
1160
1162 sizeof (*pid));
1164 sizeof (*sig));
1166 "gnunet://hello/%s/%s/%" PRIu64,
1167 pids,
1168 sigs,
1169 expiration.abs_value_us);
1170 GNUNET_free (sigs);
1171 GNUNET_free (pids);
1172 for (struct Address *a = builder->a_head;
1173 NULL != a;
1174 a = a->next)
1175 {
1176 char *eou_url_encoded;
1177 char *tmp;
1178 int pfx_len;
1179 const char *eou;
1180
1181 eou = strstr (a->uri,
1182 "://");
1183 if (NULL == eou)
1184 {
1185 GNUNET_break_op (0);
1187 return GNUNET_SYSERR;
1188 }
1189 pfx_len = eou - a->uri;
1190 eou += 3;
1191 GNUNET_STRINGS_urlencode (a->uri_len - 4 - pfx_len,
1192 eou,
1193 &eou_url_encoded);
1194 GNUNET_asprintf (&tmp,
1195 "%s%s%.*s=%s",
1196 *result,
1197 sep,
1198 pfx_len,
1199 a->uri,
1200 eou_url_encoded);
1201 GNUNET_free (eou_url_encoded);
1203 *result = tmp;
1204 sep = "&";
1205 }
1206 return GNUNET_OK;
1207}
1208
1209
1210void
1212 struct GNUNET_HashCode *hash)
1213{
1214 hash_addresses (builder->a_head, hash);
1215}
1216
1217
1218struct GNUNET_MQ_Envelope*
1220 const struct GNUNET_HELLO_Builder *builder,
1221 const struct GNUNET_PeerIdentity *pid,
1222 const struct GNUNET_CRYPTO_EddsaSignature *hello_sig,
1223 struct GNUNET_TIME_Absolute expiration_time)
1224{
1225 struct GNUNET_MQ_Envelope *env;
1226 struct HelloUriMessage *msg;
1227 size_t blen;
1228
1229 if (builder->a_length > UINT16_MAX)
1230 {
1231 GNUNET_break_op (0);
1232 return NULL;
1233 }
1236 blen,
1238 msg->url_counter = htons ((uint16_t) builder->a_length);
1240 pid,
1241 hello_sig,
1242 expiration_time,
1243 (char*) &msg[1]);
1244 return env;
1245}
1246
1247
1248struct GNUNET_MessageHeader *
1250{
1251 struct BlockHeader *block;
1252 struct DhtHelloMessage *msg;
1253 size_t block_size;
1254
1255
1256 block_size = 0;
1259 NULL,
1260 &block_size));
1261 msg = GNUNET_malloc (sizeof (*msg)
1262 + block_size);
1263 if (GNUNET_OK !=
1265 &msg[1],
1266 &block_size))
1267 {
1268 GNUNET_free (msg);
1269 return NULL;
1270 }
1271 block = (struct BlockHeader*) &msg[1];
1272 msg->sig = block->sig;
1273 msg->expiration_time = block->expiration_time;
1274 memmove (&msg[1],
1275 (char*) block + sizeof (*block),
1276 block_size - sizeof (*block));
1277 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
1278 msg->header.size = htons (sizeof (*msg)
1279 + block_size
1280 - sizeof (*block));
1281 msg->url_counter = htons ((uint16_t) parser->a_length);
1282 return &msg->header;
1283}
1284
1285
1286struct GNUNET_MessageHeader *
1288 const struct GNUNET_HELLO_Builder *builder,
1289 const struct GNUNET_PeerIdentity *pid,
1290 const struct GNUNET_CRYPTO_EddsaSignature *hello_sig,
1291 struct GNUNET_TIME_Absolute expiration_time)
1292{
1293 struct BlockHeader *block;
1294 struct DhtHelloMessage *msg;
1295 size_t block_size;
1296
1297
1299 msg = GNUNET_malloc (sizeof (*msg)
1300 + block_size);
1301 block = (struct BlockHeader*) &msg[1];
1303 pid,
1304 hello_sig,
1306 (char*) &msg[1]);
1307 msg->sig = block->sig;
1308 msg->expiration_time = block->expiration_time;
1309 memmove (&msg[1],
1310 (char*) block + sizeof (*block),
1311 block_size - sizeof (*block));
1312 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
1313 msg->header.size = htons (sizeof (*msg)
1314 + block_size
1315 - sizeof (*block));
1316 msg->url_counter = htons ((uint16_t) builder->a_length);
1317 return &msg->header;
1318}
1319
1320
1321void
1323 const struct GNUNET_HELLO_Builder *builder,
1324 const struct GNUNET_PeerIdentity *pid,
1325 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1327 char *block)
1328{
1329 struct BlockHeader bh = { 0 };
1330 char *pos;
1331 struct GNUNET_TIME_Absolute et;
1332
1333 if (NULL != pid)
1334 bh.pid = *pid;
1335 if (NULL != sig)
1336 bh.sig = *sig;
1337 if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == expiration_time.abs_value_us)
1339 else
1340 et = expiration_time;
1342 memcpy (block,
1343 &bh,
1344 sizeof (bh));
1345 pos = block + sizeof (bh);
1346 for (struct Address *a = builder->a_head; NULL != a; a = a->next)
1347 {
1348 memcpy (pos,
1349 a->uri,
1350 a->uri_len);
1351 pos += a->uri_len;
1352 }
1353}
1354
1355
1358 const struct GNUNET_PeerIdentity *pid,
1359 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1360 struct GNUNET_TIME_Absolute validity,
1361 char **result)
1362{
1364 pid,
1365 sig,
1366 validity,
1367 result);
1368}
1369
1370
1373 const struct GNUNET_PeerIdentity *pid,
1374 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1375 char **result)
1376{
1377 struct GNUNET_TIME_Absolute et;
1378
1380
1382 pid,
1383 sig,
1384 et,
1385 result);
1386}
1387
1388
1389size_t
1391 const struct GNUNET_HELLO_Builder *builder)
1392{
1393 struct BlockHeader bh;
1394 size_t needed = sizeof (bh);
1395
1396 for (struct Address *a = builder->a_head;
1397 NULL != a;
1398 a = a->next)
1399 {
1400 GNUNET_assert (needed + a->uri_len > needed);
1401 needed += a->uri_len;
1402 }
1403 return needed;
1404}
1405
1406
1409 abuilder,
1410 const struct GNUNET_HELLO_Builder *
1411 bbuilder)
1412{
1413 bool found = false;
1414 for (struct Address *a = abuilder->a_head; NULL != a; a = a->next)
1415 {
1416 for (struct Address *b = bbuilder->a_head; NULL != b; b = b->next)
1417 {
1418 if (0 != strcmp (b->uri, a->uri))
1419 continue;
1420 found = true;
1421 break;
1422 }
1423 if (! found)
1424 return GNUNET_NO;
1425 found = false;
1426 }
1427 return GNUNET_YES;
1428}
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition gnunet-arm.c:98
static int ret
Final status code.
Definition gnunet-arm.c:93
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static char * address
GNS address for this phone.
static struct HostSet * builder
NULL if we are not currently iterating over peer information.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static struct GNUNET_FS_UnindexContext * uc
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
Helper library for handling HELLO URIs.
Constants for network protocols.
#define GNUNET_SIGNATURE_PURPOSE_HELLO
Signature by which a peer affirms its address.
Functions related to time.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
void GNUNET_HELLO_builder_to_block(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time, char *block)
Generate DHT block from a builder.
Definition hello-uri.c:1322
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:398
char * GNUNET_HELLO_parser_to_url(const struct GNUNET_HELLO_Parser *parser)
Generate GNUnet HELLO URI from a parser.
Definition hello-uri.c:880
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:344
enum GNUNET_GenericReturnValue GNUNET_HELLO_dht_msg_to_block(const struct GNUNET_MessageHeader *hello, const struct GNUNET_PeerIdentity *pid, void **block, size_t *block_size, struct GNUNET_TIME_Absolute *block_expiration)
Convert a DHT hello message to a HELLO block.
Definition hello-uri.c:1074
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_block_(const void *block, size_t block_size, int noverify)
Parse block.
Definition hello-uri.c:592
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:1033
enum GNUNET_GenericReturnValue GNUNET_HELLO_parser_to_block(const struct GNUNET_HELLO_Parser *parser, void *block, size_t *block_size)
Generate DHT block from a parser.
Definition hello-uri.c:937
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_to_url(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, char **result)
Generate GNUnet HELLO URI from a builder.
Definition hello-uri.c:1372
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *p, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:361
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg_(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid, int noverify)
Parse msg.
Definition hello-uri.c:426
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition hello-uri.c:1052
struct GNUNET_MessageHeader * GNUNET_HELLO_parser_to_dht_hello_msg(const struct GNUNET_HELLO_Parser *parser)
Generate DHT HELLO message from a parser.
Definition hello-uri.c:1249
enum GNUNET_GenericReturnValue GNUNET_HELLO_build_url(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration, char **result)
Definition hello-uri.c:1151
struct GNUNET_MQ_Envelope * GNUNET_HELLO_parser_to_env(const struct GNUNET_HELLO_Parser *parser)
Generate envelope with GNUnet HELLO message (including peer ID) from a parser.
Definition hello-uri.c:980
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_address_list_cmp(const struct GNUNET_HELLO_Builder *abuilder, const struct GNUNET_HELLO_Builder *bbuilder)
Compare address lists of two builders.
Definition hello-uri.c:1408
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_del_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Remove individual address from the builder.
Definition hello-uri.c:1009
struct GNUNET_TIME_Absolute GNUNET_HELLO_get_expiration_time_from_msg(const struct GNUNET_MessageHeader *msg)
Get the expiration time for this HELLO.
Definition hello-uri.c:655
size_t GNUNET_HELLO_get_builder_to_block_size(const struct GNUNET_HELLO_Builder *builder)
Get projected block size for builder.
Definition hello-uri.c:1390
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:354
void(* GNUNET_HELLO_UriCallback)(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
Callback function used to extract URIs from a builder.
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_add_address(struct GNUNET_HELLO_Builder *builder, const char *address)
Add individual address to the builder.
Definition hello-uri.c:701
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_url(const char *url)
Parse GNUnet HELLO url.
Definition hello-uri.c:740
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_to_url2(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute validity, char **result)
Generate GNUnet HELLO URI from a builder.
Definition hello-uri.c:1357
struct GNUNET_MessageHeader * GNUNET_HELLO_builder_to_dht_hello_msg(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *hello_sig, struct GNUNET_TIME_Absolute expiration_time)
Generate DHT HELLO message (without peer ID) from a builder.
Definition hello-uri.c:1287
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_block(const void *block, size_t block_size)
Parse block.
Definition hello-uri.c:582
char * GNUNET_HELLO_address_to_prefix(const char *address)
Given an address as a string, extract the prefix that identifies the communicator offering transmissi...
Definition hello-uri.c:1139
void GNUNET_HELLO_builder_hash_addresses(const struct GNUNET_HELLO_Builder *builder, struct GNUNET_HashCode *hash)
Compute hash over addresses in builder.
Definition hello-uri.c:1211
struct GNUNET_MQ_Envelope * GNUNET_HELLO_builder_to_env(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *hello_sig, struct GNUNET_TIME_Absolute expiration_time)
Generate envelope with GNUnet HELLO message (including peer ID) from a builder.
Definition hello-uri.c:1219
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_CONTAINER_DLL_insert_sorted(TYPE, comparator, comparator_cls, head, tail, element)
Insertion sort of element into DLL from head to tail sorted by comparator.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
HELLO advertising a neighbours addresses.
#define GNUNET_MESSAGE_TYPE_HELLO_URI
Latest HELLO messages used for communicating peer addresses.
size_t GNUNET_STRINGS_urlencode(size_t len, const char data[static len], char **out)
url/percent encode (RFC3986).
Definition strings.c:1893
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition strings.c:818
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition strings.c:1838
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition strings.c:843
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition time.c:667
static enum GNUNET_GenericReturnValue verify_hello(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_TIME_Absolute et, const struct GNUNET_CRYPTO_EddsaSignature *sig)
Verify HELLO signature.
Definition hello-uri.c:304
static void hash_addresses(const struct Address *addr_start, struct GNUNET_HashCode *hash)
Definition hello-uri.c:267
static struct GNUNET_HELLO_Parser * parser_new(const struct GNUNET_PeerIdentity *pid)
Definition hello-uri.c:333
static int cmp_address(void *cls, struct Address *a, struct Address *b)
Alphanumeric sorting for addresses.
Definition hello-uri.c:536
static enum GNUNET_GenericReturnValue check_address(const char *address)
Definition hello-uri.c:497
static enum GNUNET_GenericReturnValue parser_add_address(struct GNUNET_HELLO_Parser *parser, const char *address)
Definition hello-uri.c:543
static unsigned int size
Size of the "table".
Definition peer.c:68
Struct to wrap data to do the merge of to hello uris.
Definition hello-uri.c:207
unsigned int merged
Did we found at least one address to merge.
Definition hello-uri.c:226
struct GNUNET_HELLO_Builder * builder
The builder of the hello uri we merge with.
Definition hello-uri.c:211
unsigned int found
Did we found the actual address to check.
Definition hello-uri.c:221
const char * address_uri
The actual address to check, if it is already in the hello uri we merge with.
Definition hello-uri.c:216
Address of a peer.
Definition hello-uri.c:158
struct Address * next
Kept in a DLL.
Definition hello-uri.c:162
size_t uri_len
Length of uri including 0-terminator.
Definition hello-uri.c:177
struct Address * prev
Kept in a DLL.
Definition hello-uri.c:167
const char * uri
Actual URI, allocated at the end of this struct.
Definition hello-uri.c:172
Start of a 'block'.
Definition hello-uri.c:97
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the HELLO expire?
Definition hello-uri.c:111
struct GNUNET_CRYPTO_EddsaSignature sig
Signature over the block, of purpose GNUNET_SIGNATURE_PURPOSE_HELLO.
Definition hello-uri.c:106
struct GNUNET_PeerIdentity pid
Public key of the peer.
Definition hello-uri.c:101
Message used when a DHT provides its HELLO to direct neighbours.
Definition hello-uri.c:121
uint16_t reserved
Reserved.
Definition hello-uri.c:130
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the HELLO expire?
Definition hello-uri.c:145
struct GNUNET_MessageHeader header
Type must be GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO.
Definition hello-uri.c:125
struct GNUNET_CRYPTO_EddsaSignature sig
Signature over the block, of purpose GNUNET_SIGNATURE_PURPOSE_HELLO.
Definition hello-uri.c:140
uint16_t url_counter
Number of URLs encoded after the end of the struct, in NBO.
Definition hello-uri.c:135
an ECC signature using EdDSA.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:185
struct Address * a_tail
Tail of the addresses DLL.
Definition hello-uri.c:194
struct Address * a_head
Head of the addresses DLL.
Definition hello-uri.c:189
unsigned int a_length
Length of the a_head DLL.
Definition hello-uri.c:199
Context for parsing HELLOs.
Definition hello-uri.c:233
struct GNUNET_PeerIdentity pid
Public key of the peer.
Definition hello-uri.c:237
struct GNUNET_TIME_Absolute et
Expiration time parsed.
Definition hello-uri.c:262
struct GNUNET_CRYPTO_EddsaSignature sig
The signature (may have been provided)
Definition hello-uri.c:257
struct Address * a_tail
Tail of the addresses DLL.
Definition hello-uri.c:247
unsigned int a_length
Length of the a_head DLL.
Definition hello-uri.c:252
struct Address * a_head
Head of the addresses DLL.
Definition hello-uri.c:242
A 512-bit hashcode.
Header for all communications.
The identity of the host (wraps the signing key of the peer).
pid_t pid
PID of the process.
Definition os_process.c:94
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Message used when gossiping HELLOs between peers.
Definition hello-uri.c:73
uint16_t reserved
Reserved.
Definition hello-uri.c:82
uint16_t url_counter
Number of URLs encoded after the end of the struct, in NBO.
Definition hello-uri.c:87
struct GNUNET_MessageHeader header
Type must be GNUNET_MESSAGE_TYPE_HELLO_URI.
Definition hello-uri.c:77
Message signed as part of a HELLO block/URL.
Definition hello-uri.c:51
struct GNUNET_HashCode h_addrs
Hash over all addresses.
Definition hello-uri.c:65
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the signature expire?
Definition hello-uri.c:60
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_HELLO.
Definition hello-uri.c:55