aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Nadler <sebastian.nadler@tum.de>2023-12-14 19:22:11 +0100
committerSebastian Nadler <sebastian.nadler@tum.de>2023-12-14 19:22:11 +0100
commitb92af915f4d96e621cfdbbaf58bbf73a2fd6cb53 (patch)
treebee07019239c5826b26a54c467fcddf06f227beb
parent55acf39e2e7152888dfdbeb21991398964b99a44 (diff)
parentbcc1b977db2b322280fc1df8d074e3c29b134754 (diff)
downloadgnunet-b92af915f4d96e621cfdbbaf58bbf73a2fd6cb53.tar.gz
gnunet-b92af915f4d96e621cfdbbaf58bbf73a2fd6cb53.zip
Merge branch 'dev/sebi/sbox'
m---------contrib/gana0
-rwxr-xr-xsrc/cli/gns/test_gns_box_sbox.sh59
-rwxr-xr-xsrc/cli/gns/test_gns_sbox.sh40
-rw-r--r--src/include/gnunet_gnsrecord_lib.h41
-rw-r--r--src/plugin/gns/plugin_gnsrecord_gns.c101
-rw-r--r--src/service/gns/gnunet-service-gns_resolver.c110
6 files changed, 325 insertions, 26 deletions
diff --git a/contrib/gana b/contrib/gana
Subproject f5577937ddfe880a49c8bcfce6e531959d62fdd Subproject cbc4ad2394fc4bc8adaad4897759dfc5b345c3e
diff --git a/src/cli/gns/test_gns_box_sbox.sh b/src/cli/gns/test_gns_box_sbox.sh
new file mode 100755
index 000000000..1f226dce9
--- /dev/null
+++ b/src/cli/gns/test_gns_box_sbox.sh
@@ -0,0 +1,59 @@
1#!/bin/bash
2# This file is in the public domain.
3trap "gnunet-arm -e -c test_gns_lookup.conf" INT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
18which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
19TEST_B="TXT_record_in_BOX"
20TEST_S="TXT_record_in_SBOX"
21TEST_A="10.1.11.10"
22MY_EGO="myego"
23LABEL="testsbox"
24SERVICE="443"
25SERVICE_TEXT="_443"
26PROTOCOL="6"
27PROTOCOL_TEXT="_tcp"
28gnunet-arm -s -c test_gns_lookup.conf
29gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
30gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t SBOX -V "$SERVICE_TEXT.$PROTOCOL_TEXT 16 $TEST_S" -e never -c test_gns_lookup.conf
31gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 16 $TEST_B" -e never -c test_gns_lookup.conf
32gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t SBOX -V "$SERVICE_TEXT.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf
33gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 1 $TEST_A" -e never -c test_gns_lookup.conf
34sleep 0.5
35RES_B_S=`$DO_TIMEOUT gnunet-gns --raw -u $SERVICE_TEXT.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t TXT -c test_gns_lookup.conf`
36RES_A=`$DO_TIMEOUT gnunet-gns --raw -u $SERVICE_TEXT.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t A -c test_gns_lookup.conf`
37gnunet-namestore -z $MY_EGO -d -n $LABEL -t SBOX -V "$SERVICE_TEXT.$PROTOCOL_TEXT 16 $TEST_S" -e never -c test_gns_lookup.conf
38gnunet-namestore -z $MY_EGO -d -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 16 $TEST_B" -e never -c test_gns_lookup.conf
39gnunet-namestore -p -z $MY_EGO -d -n $LABEL -t SBOX -V "$SERVICE_TEXT.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf
40gnunet-namestore -p -z $MY_EGO -d -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 1 $TEST_A" -e never -c test_gns_lookup.conf
41gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
42gnunet-arm -e -c test_gns_lookup.conf
43rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
44
45{ read RES_B; read RES_S;} <<< "${RES_B_S}"
46if [ "$RES_B" = "$RES_S" ]
47then
48 echo "Failed to resolve to diffrent TXT records, got '$RES_B' and '$RES_S'."
49 exit 1
50fi
51
52{ read RES_S_A; read RES_B_A;} <<< "${RES_A}"
53if [ "$RES_S_A" = "$TEST_A" ] && [ "$RES_B_A" = "$TEST_A" ]
54then
55 exit 0
56else
57 echo "Failed to resolve to proper A '$TEST_A', got '$RES_S_A' and '$RES_S_B'."
58 exit 1
59fi
diff --git a/src/cli/gns/test_gns_sbox.sh b/src/cli/gns/test_gns_sbox.sh
new file mode 100755
index 000000000..54e51fa2c
--- /dev/null
+++ b/src/cli/gns/test_gns_sbox.sh
@@ -0,0 +1,40 @@
1#!/bin/sh
2# This file is in the public domain.
3trap "gnunet-arm -e -c test_gns_lookup.conf" INT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
18which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
19TEST_A="139.134.54.9"
20MY_EGO="myego"
21LABEL="testsbox"
22HASH="c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6"
23PROTOCOL_TEXT="_smimecert"
24gnunet-arm -s -c test_gns_lookup.conf
25gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
26gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t SBOX -V "$HASH.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf
27sleep 0.5
28RES_A=`$DO_TIMEOUT gnunet-gns --raw -u $HASH.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t A -c test_gns_lookup.conf`
29gnunet-namestore -z $MY_EGO -d -n $LABEL -t SBOX -V "$HASH.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf
30gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
31gnunet-arm -e -c test_gns_lookup.conf
32rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
33
34if [ "$RES_A" = "$TEST_A" ]
35then
36 exit 0
37else
38 echo "Failed to resolve to proper A, got '$RES_A'."
39 exit 1
40fi
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 813409340..b4e45727b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -331,6 +331,31 @@ struct GNUNET_GNSRECORD_BoxRecord
331 /* followed by the 'original' record */ 331 /* followed by the 'original' record */
332}; 332};
333 333
334
335/**
336 * Record type used to box up SMIMEA records. For example, a
337 * SMIMEA record for "c93f1e400f26708f98cb19d936620da35eec8f72e57
338 * f9eec01c1afd6._smimecert.foo.gnu" will be stored under
339 * "foo.gnu" as a SBOX record with the local-path of the associated
340 * e-mails hash turnicated to 28 octets encoded as hex and protocol _smimecert
341 * and record_type "SMIMEA". When a BOX record is received, GNS
342 * unboxes it if the name contained "hash._PROTO", otherwise GNS
343 * leaves it untouched. This is done to ensure that SMIMEA
344 * records do not require a separate network request, thus making SMIMEA
345 * records inseparable from the "main" A/AAAA/VPN/etc. records.
346 */
347struct GNUNET_GNSRECORD_SBoxRecord
348{
349 /**
350 * GNS record type of the boxed record. In NBO.
351 */
352 uint32_t record_type GNUNET_PACKED;
353
354 /* followed by the zero terminated hostname prefix */
355 /* followed by the 'original' record */
356};
357
358
334/** 359/**
335 * Record type used internally to keep track of reverse mappings into a 360 * Record type used internally to keep track of reverse mappings into a
336 * namespace. 361 * namespace.
@@ -836,9 +861,9 @@ GNUNET_GNSRECORD_label_check (const char*label, char **emsg);
836/** 861/**
837 * Maximum length of a revocation 862 * Maximum length of a revocation
838 */ 863 */
839#define GNUNET_MAX_POW_SIZE sizeof(struct GNUNET_GNSRECORD_PowP) +\ 864#define GNUNET_MAX_POW_SIZE sizeof(struct GNUNET_GNSRECORD_PowP) \
840 sizeof(struct GNUNET_CRYPTO_PublicKey) +\ 865 + sizeof(struct GNUNET_CRYPTO_PublicKey) \
841 1024 //FIXME max sig_len 866 + 1024 // FIXME max sig_len
842 867
843/** 868/**
844 * The proof-of-work narrowing factor. 869 * The proof-of-work narrowing factor.
@@ -910,8 +935,8 @@ struct GNUNET_GNSRECORD_PowCalculationHandle;
910 */ 935 */
911enum GNUNET_GenericReturnValue 936enum GNUNET_GenericReturnValue
912GNUNET_GNSRECORD_check_pow (const struct GNUNET_GNSRECORD_PowP *pow, 937GNUNET_GNSRECORD_check_pow (const struct GNUNET_GNSRECORD_PowP *pow,
913 unsigned int matching_bits, 938 unsigned int matching_bits,
914 struct GNUNET_TIME_Relative epoch_duration); 939 struct GNUNET_TIME_Relative epoch_duration);
915 940
916 941
917/** 942/**
@@ -922,7 +947,7 @@ GNUNET_GNSRECORD_check_pow (const struct GNUNET_GNSRECORD_PowP *pow,
922 */ 947 */
923void 948void
924GNUNET_GNSRECORD_pow_init (const struct GNUNET_CRYPTO_PrivateKey *key, 949GNUNET_GNSRECORD_pow_init (const struct GNUNET_CRYPTO_PrivateKey *key,
925 struct GNUNET_GNSRECORD_PowP *pow); 950 struct GNUNET_GNSRECORD_PowP *pow);
926 951
927 952
928/** 953/**
@@ -936,8 +961,8 @@ GNUNET_GNSRECORD_pow_init (const struct GNUNET_CRYPTO_PrivateKey *key,
936 */ 961 */
937struct GNUNET_GNSRECORD_PowCalculationHandle* 962struct GNUNET_GNSRECORD_PowCalculationHandle*
938GNUNET_GNSRECORD_pow_start (struct GNUNET_GNSRECORD_PowP *pow, 963GNUNET_GNSRECORD_pow_start (struct GNUNET_GNSRECORD_PowP *pow,
939 int epochs, 964 int epochs,
940 unsigned int difficulty); 965 unsigned int difficulty);
941 966
942 967
943/** 968/**
diff --git a/src/plugin/gns/plugin_gnsrecord_gns.c b/src/plugin/gns/plugin_gnsrecord_gns.c
index 65587172d..2803d32a4 100644
--- a/src/plugin/gns/plugin_gnsrecord_gns.c
+++ b/src/plugin/gns/plugin_gnsrecord_gns.c
@@ -132,6 +132,36 @@ gns_value_to_string (void *cls,
132 GNUNET_free (ival); 132 GNUNET_free (ival);
133 return box_str; 133 return box_str;
134 } 134 }
135 case GNUNET_GNSRECORD_TYPE_SBOX: {
136 struct GNUNET_GNSRECORD_SBoxRecord box;
137 uint32_t rt;
138 char *box_str;
139 char *ival;
140 char *prefix;
141
142 cdata = data;
143 if (data_size < sizeof(struct GNUNET_GNSRECORD_SBoxRecord))
144 return NULL; /* malformed */
145 GNUNET_memcpy (&box, data, sizeof(box));
146 rt = ntohl (box.record_type);
147
148 prefix = GNUNET_strdup (&cdata[sizeof(box)]);
149 ival = GNUNET_GNSRECORD_value_to_string (rt, &cdata[sizeof(box)
150 + strlen (prefix)
151 + 1],
152 data_size - sizeof(box)
153 - strlen (prefix) - 1);
154 if (NULL == ival)
155 return NULL; /* malformed */
156 GNUNET_asprintf (&box_str,
157 "%s %u %s",
158 prefix,
159 (unsigned int) rt,
160 ival);
161 GNUNET_free (prefix);
162 GNUNET_free (ival);
163 return box_str;
164 }
135 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: { 165 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
136 return GNUNET_strdup (_ ( 166 return GNUNET_strdup (_ (
137 "This is a memento of an older block for internal maintenance.")); 167 "This is a memento of an older block for internal maintenance."));
@@ -302,6 +332,76 @@ gns_string_to_value (void *cls,
302 GNUNET_free (bval); 332 GNUNET_free (bval);
303 return GNUNET_OK; 333 return GNUNET_OK;
304 } 334 }
335 case GNUNET_GNSRECORD_TYPE_SBOX: {
336 struct GNUNET_GNSRECORD_SBoxRecord *box;
337 size_t rest;
338 char *prefix;
339 unsigned int protocol;
340 unsigned int record_type;
341 void *bval;
342 size_t bval_size;
343 prefix = GNUNET_malloc (strlen (s)); // TODO The allocated memory is bigger than needed
344 size_t prefix_size;
345 if (2 != sscanf (s, "%s %u ", prefix, &record_type))
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
348 _ ("Unable to parse SBOX record string `%s'\n"),
349 s);
350 return GNUNET_SYSERR;
351 }
352 if (prefix == NULL)
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
355 _ (
356 "Unable to parse SBOX record string `%s', no prefix found\n"),
357 s);
358 return GNUNET_SYSERR;
359 }
360 char *last_underscore = strrchr (prefix, (int) '_');
361 if (last_underscore == NULL)
362 {
363 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
364 _ (
365 "Unable to parse SBOX record string `%s', no underscore fund\n"),
366 prefix);
367 return GNUNET_SYSERR;
368 }
369 char *dot_in_last_prefix = strchr (last_underscore, '.');
370 if (dot_in_last_prefix != NULL)
371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
373 _ (
374 "Unable to parse SBOX record string `%s', the last label does not have an underscore\n"),
375 prefix);
376 return GNUNET_SYSERR;
377 }
378 if (prefix < last_underscore && last_underscore[-1] != '.')
379 {
380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
381 _ (
382 "Unable to parse SBOX record string `%s', the last label does not start with an underscore\n"),
383 prefix);
384 return GNUNET_SYSERR;
385 }
386 rest = snprintf (NULL, 0, "%s %u ", prefix, record_type);
387 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type,
388 &s[rest],
389 &bval,
390 &bval_size))
391 return GNUNET_SYSERR;
392 prefix_size = strlen (prefix) + 1; // with NULL terminator
393 *data_size = sizeof(struct GNUNET_GNSRECORD_SBoxRecord) + prefix_size
394 + bval_size;
395 void *p = *data = box = GNUNET_malloc (*data_size);
396 box->record_type = htonl (record_type);
397 p += sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
398 GNUNET_memcpy (p, prefix, prefix_size);
399 p += prefix_size;
400 GNUNET_memcpy (p, bval, bval_size);
401 GNUNET_free (bval);
402 GNUNET_free (prefix);
403 return GNUNET_OK;
404 }
305 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: { 405 case GNUNET_GNSRECORD_TYPE_TOMBSTONE: {
306 *data_size = 0; 406 *data_size = 0;
307 *data = NULL; 407 *data = NULL;
@@ -330,6 +430,7 @@ static struct
330 { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, 430 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
331 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, 431 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
332 { "BOX", GNUNET_GNSRECORD_TYPE_BOX }, 432 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
433 { "SBOX", GNUNET_GNSRECORD_TYPE_SBOX },
333 { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT }, 434 { "REDIRECT", GNUNET_GNSRECORD_TYPE_REDIRECT },
334 /* Tombstones should never be added manually 435 /* Tombstones should never be added manually
335 * so this makes sense, kind of */ 436 * so this makes sense, kind of */
diff --git a/src/service/gns/gnunet-service-gns_resolver.c b/src/service/gns/gnunet-service-gns_resolver.c
index 445ae3346..906bb6aba 100644
--- a/src/service/gns/gnunet-service-gns_resolver.c
+++ b/src/service/gns/gnunet-service-gns_resolver.c
@@ -369,6 +369,12 @@ struct GNS_ResolverHandle
369 int service; 369 int service;
370 370
371 /** 371 /**
372 * For SMIMEA,OPENPGPKEY... records. NULL if no _ prefix was given.
373 */
374 char *prefix;
375
376
377 /**
372 * Desired type for the resolution. 378 * Desired type for the resolution.
373 */ 379 */
374 int record_type; 380 int record_type;
@@ -620,15 +626,16 @@ resolver_getservbyname (const char *name, const char *proto)
620 * Get the next, rightmost label from the name that we are trying to resolve, 626 * Get the next, rightmost label from the name that we are trying to resolve,
621 * and update the resolution position accordingly. Labels usually consist 627 * and update the resolution position accordingly. Labels usually consist
622 * of up to 63 characters without a period ("."); however, we use a special 628 * of up to 63 characters without a period ("."); however, we use a special
623 * convention to support SRV and TLSA records where the domain name 629 * convention to support resource records where the domain name
624 * includes an encoding for a service and protocol in the name. The 630 * includes a label starting with '_'. The syntax (see RFC 8552) here is
625 * syntax (see RFC 2782) here is "_Service._Proto.Name" and in this 631 * "someLabel._Label.Name" and in this special case we include the "someLabel._Label" in the rightmost label.
626 * special case we include the "_Service._Proto" in the rightmost label.
627 * Thus, for "_443._tcp.foo.bar" we first return the label "bar" and then 632 * Thus, for "_443._tcp.foo.bar" we first return the label "bar" and then
628 * the label "_443._tcp.foo". The special case is detected by the 633 * the label "_443._tcp.foo". The special case is detected by the
629 * presence of labels beginning with an underscore. Whenever a label 634 * presence of one label beginning with an underscore. The rightmost label
630 * begins with an underscore, it is combined with the label to its right 635 * beginning with an underscore, is combined with the label to its right
631 * (and the "." is preserved). 636 * (and the "." is preserved). If the label is in the syntax of
637 * "_PORT._PROTOCOL" (e.g. "_443._tcp") we also extract the port and protocol.
638 * In this implementation, the more specific case is handled first.
632 * 639 *
633 * @param rh handle to the resolution operation to get the next label from 640 * @param rh handle to the resolution operation to get the next label from
634 * @return NULL if there are no more labels 641 * @return NULL if there are no more labels
@@ -657,14 +664,13 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
657 rp = rh->name; 664 rp = rh->name;
658 rh->name_resolution_pos = 0; 665 rh->name_resolution_pos = 0;
659 } 666 }
660 else if (('_' == dot[1]) && 667 else if ('_' == dot[1])
661 ('_' == rh->name[0]) &&
662 (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
663 { 668 {
664 /** 669 /**
665 * Do not advance a label. This seems to be a name only consisting 670 * Do not advance a label. This seems to be a name only consisting
666 * of a BOX indicator (_443,_tcp). 671 * of a prefix. Indicating a BOX record (_443,_tcp)
667 * Which means, it is a BOX under the empty label. 672 * Or some version of an SBOX record (HEX,_smimeacert)
673 * Which means, it is a BOX/SBOX under the empty label.
668 * leaving name_resolution_pos as is and returning empty label. 674 * leaving name_resolution_pos as is and returning empty label.
669 */ 675 */
670 rp = GNUNET_GNS_EMPTY_LABEL_AT; 676 rp = GNUNET_GNS_EMPTY_LABEL_AT;
@@ -679,8 +685,9 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
679 } 685 }
680 rh->protocol = 0; 686 rh->protocol = 0;
681 rh->service = 0; 687 rh->service = 0;
688 rh->prefix = NULL;
682 ret = GNUNET_strndup (rp, len); 689 ret = GNUNET_strndup (rp, len);
683 /* If we have labels starting with underscore with label on 690 /** If we have labels starting with underscore with label on
684 * the right (SRV/DANE/BOX case), determine port/protocol; 691 * the right (SRV/DANE/BOX case), determine port/protocol;
685 * The format of `rh->name` must be "_PORT._PROTOCOL". 692 * The format of `rh->name` must be "_PORT._PROTOCOL".
686 */ 693 */
@@ -703,10 +710,12 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
703 if (0 == protocol) 710 if (0 == protocol)
704 { 711 {
705 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 712 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
706 _ ("Protocol `%s' unknown, skipping labels.\n"), 713 _ (
714 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
707 proto_name); 715 proto_name);
708 GNUNET_free (proto_name); 716 GNUNET_free (proto_name);
709 GNUNET_free (srv_name); 717 GNUNET_free (srv_name);
718 rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
710 return ret; 719 return ret;
711 } 720 }
712 service = resolver_getservbyname (srv_name, 721 service = resolver_getservbyname (srv_name,
@@ -721,10 +730,12 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
721 if (1 != sscanf (srv_name, "%u", &rh->service)) 730 if (1 != sscanf (srv_name, "%u", &rh->service))
722 { 731 {
723 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 732 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
724 _ ("Service `%s' not a port, skipping service labels.\n"), 733 _ (
734 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
725 srv_name); 735 srv_name);
726 GNUNET_free (proto_name); 736 GNUNET_free (proto_name);
727 GNUNET_free (srv_name); 737 GNUNET_free (srv_name);
738 rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
728 return ret; 739 return ret;
729 } 740 }
730 } 741 }
@@ -736,6 +747,20 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
736 GNUNET_free (proto_name); 747 GNUNET_free (proto_name);
737 GNUNET_free (srv_name); 748 GNUNET_free (srv_name);
738 } 749 }
750 /**
751 * If we have labels starting with underscore with label on
752 * the right, copy prefix to rh->prefix;
753 * The format of `rh->name` must be "*._label",
754 * where label is a string without '.'.
755 */
756 if ((NULL != (dot = memrchr (rh->name,
757 (int) '.',
758 rh->name_resolution_pos)) && '_' == dot[1]) ||
759 '_' == rh->name[0])
760 {
761 rh->name_resolution_pos = 0;
762 rh->prefix = GNUNET_strndup (rh->name, strlen (rh->name) - len - 1);
763 }
739 return ret; 764 return ret;
740} 765}
741 766
@@ -2040,9 +2065,10 @@ handle_gns_resolution_result (void *cls,
2040 for (unsigned int i = 0; i < rd_count; i++) 2065 for (unsigned int i = 0; i < rd_count; i++)
2041 { 2066 {
2042 GNUNET_assert (rd_off <= i); 2067 GNUNET_assert (rd_off <= i);
2043 if ((0 != rh->protocol) && 2068 if ((((0 != rh->protocol) &&
2044 (0 != rh->service) && 2069 (0 != rh->service)) || (NULL != rh->prefix)) &&
2045 (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type)) 2070 (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type &&
2071 GNUNET_GNSRECORD_TYPE_SBOX != rd[i].record_type))
2046 if (GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type && 2072 if (GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type &&
2047 GNUNET_GNSRECORD_TYPE_EDKEY != rd[i].record_type) 2073 GNUNET_GNSRECORD_TYPE_EDKEY != rd[i].record_type)
2048 continue; 2074 continue;
@@ -2357,13 +2383,56 @@ handle_gns_resolution_result (void *cls,
2357 } 2383 }
2358 break; 2384 break;
2359 } 2385 }
2386 case GNUNET_GNSRECORD_TYPE_SBOX:
2387 {
2388 /* unbox SBOX records if a specific one was requested */
2389 if ((rh->prefix != NULL) &&
2390 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2391 {
2392 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2360 2393
2394 box = rd[i].data;
2395 char *prefix = GNUNET_strdup (&box[1]);
2396 size_t prefix_len = strlen (prefix) + 1;
2397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2398 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2399 prefix, rh->prefix);
2400 if (strcmp (rh->prefix, prefix) == 0)
2401 {
2402 /* Box matches, unbox! */
2403 GNUNET_assert (rd_off < rd_count);
2404 rd_new[rd_off].record_type = ntohl (box->record_type);
2405 rd_new[rd_off].data_size -= sizeof(struct
2406 GNUNET_GNSRECORD_SBoxRecord)
2407 + prefix_len;
2408 rd_new[rd_off].data = &rd[i].data[sizeof(struct
2409 GNUNET_GNSRECORD_SBoxRecord)
2410 + prefix_len];
2411 rd_off++;
2412 }
2413 GNUNET_free (prefix);
2414 }
2415 else
2416 {
2417 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2418 _ (
2419 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2420 rh->name);
2421 /* no specific protocol/service specified, preserve all SBOX
2422 records (for modern, GNS-enabled applications) */
2423 rd_off++;
2424 }
2425 break;
2426 }
2361 default: 2427 default:
2362 rd_off++; 2428 rd_off++;
2363 break; 2429 break;
2364 } /* end: switch */ 2430 } /* end: switch */
2365 } /* end: for rd_count */ 2431 } /* end: for rd_count */
2366 2432
2433 GNUNET_free (rh->prefix);
2434 rh->prefix = NULL;
2435
2367 /* yes, we are done, return result */ 2436 /* yes, we are done, return result */
2368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2369 "Returning GNS response for `%s' with %u answers\n", 2438 "Returning GNS response for `%s' with %u answers\n",
@@ -3014,6 +3083,11 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
3014 dr); 3083 dr);
3015 GNUNET_free (dr); 3084 GNUNET_free (dr);
3016 } 3085 }
3086 if (NULL != rh->prefix)
3087 {
3088 GNUNET_free (rh->prefix);
3089 rh->prefix = NULL;
3090 }
3017 GNUNET_free (rh->leho); 3091 GNUNET_free (rh->leho);
3018 GNUNET_free (rh->name); 3092 GNUNET_free (rh->name);
3019 GNUNET_free (rh); 3093 GNUNET_free (rh);