diff options
author | Sebastian Nadler <sebastian.nadler@tum.de> | 2023-12-14 19:22:11 +0100 |
---|---|---|
committer | Sebastian Nadler <sebastian.nadler@tum.de> | 2023-12-14 19:22:11 +0100 |
commit | b92af915f4d96e621cfdbbaf58bbf73a2fd6cb53 (patch) | |
tree | bee07019239c5826b26a54c467fcddf06f227beb | |
parent | 55acf39e2e7152888dfdbeb21991398964b99a44 (diff) | |
parent | bcc1b977db2b322280fc1df8d074e3c29b134754 (diff) | |
download | gnunet-b92af915f4d96e621cfdbbaf58bbf73a2fd6cb53.tar.gz gnunet-b92af915f4d96e621cfdbbaf58bbf73a2fd6cb53.zip |
Merge branch 'dev/sebi/sbox'
m--------- | contrib/gana | 0 | ||||
-rwxr-xr-x | src/cli/gns/test_gns_box_sbox.sh | 59 | ||||
-rwxr-xr-x | src/cli/gns/test_gns_sbox.sh | 40 | ||||
-rw-r--r-- | src/include/gnunet_gnsrecord_lib.h | 41 | ||||
-rw-r--r-- | src/plugin/gns/plugin_gnsrecord_gns.c | 101 | ||||
-rw-r--r-- | src/service/gns/gnunet-service-gns_resolver.c | 110 |
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. | ||
3 | trap "gnunet-arm -e -c test_gns_lookup.conf" INT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` | ||
18 | which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" | ||
19 | TEST_B="TXT_record_in_BOX" | ||
20 | TEST_S="TXT_record_in_SBOX" | ||
21 | TEST_A="10.1.11.10" | ||
22 | MY_EGO="myego" | ||
23 | LABEL="testsbox" | ||
24 | SERVICE="443" | ||
25 | SERVICE_TEXT="_443" | ||
26 | PROTOCOL="6" | ||
27 | PROTOCOL_TEXT="_tcp" | ||
28 | gnunet-arm -s -c test_gns_lookup.conf | ||
29 | gnunet-identity -C $MY_EGO -c test_gns_lookup.conf | ||
30 | gnunet-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 | ||
31 | gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 16 $TEST_B" -e never -c test_gns_lookup.conf | ||
32 | gnunet-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 | ||
33 | gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 1 $TEST_A" -e never -c test_gns_lookup.conf | ||
34 | sleep 0.5 | ||
35 | RES_B_S=`$DO_TIMEOUT gnunet-gns --raw -u $SERVICE_TEXT.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t TXT -c test_gns_lookup.conf` | ||
36 | RES_A=`$DO_TIMEOUT gnunet-gns --raw -u $SERVICE_TEXT.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t A -c test_gns_lookup.conf` | ||
37 | gnunet-namestore -z $MY_EGO -d -n $LABEL -t SBOX -V "$SERVICE_TEXT.$PROTOCOL_TEXT 16 $TEST_S" -e never -c test_gns_lookup.conf | ||
38 | gnunet-namestore -z $MY_EGO -d -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 16 $TEST_B" -e never -c test_gns_lookup.conf | ||
39 | gnunet-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 | ||
40 | gnunet-namestore -p -z $MY_EGO -d -n $LABEL -t BOX -V "$PROTOCOL $SERVICE 1 $TEST_A" -e never -c test_gns_lookup.conf | ||
41 | gnunet-identity -D $MY_EGO -c test_gns_lookup.conf | ||
42 | gnunet-arm -e -c test_gns_lookup.conf | ||
43 | rm -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}" | ||
46 | if [ "$RES_B" = "$RES_S" ] | ||
47 | then | ||
48 | echo "Failed to resolve to diffrent TXT records, got '$RES_B' and '$RES_S'." | ||
49 | exit 1 | ||
50 | fi | ||
51 | |||
52 | { read RES_S_A; read RES_B_A;} <<< "${RES_A}" | ||
53 | if [ "$RES_S_A" = "$TEST_A" ] && [ "$RES_B_A" = "$TEST_A" ] | ||
54 | then | ||
55 | exit 0 | ||
56 | else | ||
57 | echo "Failed to resolve to proper A '$TEST_A', got '$RES_S_A' and '$RES_S_B'." | ||
58 | exit 1 | ||
59 | fi | ||
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. | ||
3 | trap "gnunet-arm -e -c test_gns_lookup.conf" INT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` | ||
18 | which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30" | ||
19 | TEST_A="139.134.54.9" | ||
20 | MY_EGO="myego" | ||
21 | LABEL="testsbox" | ||
22 | HASH="c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6" | ||
23 | PROTOCOL_TEXT="_smimecert" | ||
24 | gnunet-arm -s -c test_gns_lookup.conf | ||
25 | gnunet-identity -C $MY_EGO -c test_gns_lookup.conf | ||
26 | gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t SBOX -V "$HASH.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf | ||
27 | sleep 0.5 | ||
28 | RES_A=`$DO_TIMEOUT gnunet-gns --raw -u $HASH.$PROTOCOL_TEXT.$LABEL.$MY_EGO -t A -c test_gns_lookup.conf` | ||
29 | gnunet-namestore -z $MY_EGO -d -n $LABEL -t SBOX -V "$HASH.$PROTOCOL_TEXT 1 $TEST_A" -e never -c test_gns_lookup.conf | ||
30 | gnunet-identity -D $MY_EGO -c test_gns_lookup.conf | ||
31 | gnunet-arm -e -c test_gns_lookup.conf | ||
32 | rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` | ||
33 | |||
34 | if [ "$RES_A" = "$TEST_A" ] | ||
35 | then | ||
36 | exit 0 | ||
37 | else | ||
38 | echo "Failed to resolve to proper A, got '$RES_A'." | ||
39 | exit 1 | ||
40 | fi | ||
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 | */ | ||
347 | struct 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 | */ |
911 | enum GNUNET_GenericReturnValue | 936 | enum GNUNET_GenericReturnValue |
912 | GNUNET_GNSRECORD_check_pow (const struct GNUNET_GNSRECORD_PowP *pow, | 937 | GNUNET_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 | */ |
923 | void | 948 | void |
924 | GNUNET_GNSRECORD_pow_init (const struct GNUNET_CRYPTO_PrivateKey *key, | 949 | GNUNET_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 | */ |
937 | struct GNUNET_GNSRECORD_PowCalculationHandle* | 962 | struct GNUNET_GNSRECORD_PowCalculationHandle* |
938 | GNUNET_GNSRECORD_pow_start (struct GNUNET_GNSRECORD_PowP *pow, | 963 | GNUNET_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); |