diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-01-12 20:30:37 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-02-19 12:39:55 +0100 |
commit | af252f5c3d4e62f4db39bbc65f3eea4f853d04bc (patch) | |
tree | 616629ee96494f49469162563ee6c90424c871e9 /src | |
parent | 3e3081cfd22f5dacbeaba2843131c4aec530b562 (diff) | |
download | gnunet-af252f5c3d4e62f4db39bbc65f3eea4f853d04bc.tar.gz gnunet-af252f5c3d4e62f4db39bbc65f3eea4f853d04bc.zip |
-conclude hello-uri implementation and test
Diffstat (limited to 'src')
-rw-r--r-- | src/hello/.gitignore | 2 | ||||
-rw-r--r-- | src/hello/Makefile.am | 7 | ||||
-rw-r--r-- | src/hello/hello-uri.c | 459 | ||||
-rw-r--r-- | src/hello/test_hello-ng.c | 23 | ||||
-rw-r--r-- | src/hello/test_hello-uri.c | 176 | ||||
-rw-r--r-- | src/include/gnunet_hello_uri_lib.h | 13 | ||||
-rw-r--r-- | src/include/gnunet_strings_lib.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_time_lib.h | 13 | ||||
-rw-r--r-- | src/util/strings.c | 9 | ||||
-rw-r--r-- | src/util/time.c | 7 |
10 files changed, 649 insertions, 62 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 @@ | |||
1 | gnunet-hello | 1 | gnunet-hello |
2 | test_friend_hello | 2 | test_friend_hello |
3 | test_hello | 3 | test_hello |
4 | test_hello-uri | ||
5 | test_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 | ||
26 | check_PROGRAMS = \ | 26 | check_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 | ||
49 | test_hello_uri_SOURCES = \ | ||
50 | test_hello-uri.c | ||
51 | test_hello_uri_LDADD = \ | ||
52 | libgnunethello.la \ | ||
53 | $(top_builddir)/src/util/libgnunetutil.la | ||
54 | |||
48 | 55 | ||
49 | test_friend_hello_SOURCES = \ | 56 | test_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 | |||
32 | GNUNET_NETWORK_STRUCT_BEGIN | 50 | GNUNET_NETWORK_STRUCT_BEGIN |
33 | 51 | ||
34 | /** | 52 | /** |
53 | * Message signed as part of a HELLO block/URL. | ||
54 | */ | ||
55 | struct 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 | */ |
37 | struct HelloUriMessage | 77 | struct 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 | */ | ||
101 | struct 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 | |||
59 | GNUNET_NETWORK_STRUCT_END | 120 | GNUNET_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 | */ | ||
184 | static void | ||
185 | hash_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 | */ | ||
213 | static void | ||
214 | sign_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 | */ | ||
242 | static enum GNUNET_GenericReturnValue | ||
243 | verify_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 | |||
117 | struct GNUNET_HELLO_Builder * | 270 | struct GNUNET_HELLO_Builder * |
118 | GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid) | 271 | GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid) |
119 | { | 272 | { |
@@ -147,29 +300,45 @@ struct GNUNET_HELLO_Builder * | |||
147 | GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg) | 300 | GNUNET_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 | |||
322 | struct GNUNET_HELLO_Builder * | ||
323 | GNUNET_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 | ||
202 | struct GNUNET_HELLO_Builder * | 378 | struct GNUNET_HELLO_Builder * |
203 | GNUNET_HELLO_builder_from_block (const void *block, | 379 | GNUNET_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 | ||
245 | struct GNUNET_HELLO_Builder * | 502 | ret = verify_hello (b, |
246 | GNUNET_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 | ||
253 | struct GNUNET_MQ_Envelope * | 516 | struct GNUNET_MQ_Envelope * |
254 | GNUNET_HELLO_builder_to_env (struct GNUNET_HELLO_Builder *builder) | 517 | GNUNET_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 | ||
277 | char * | 542 | char * |
278 | GNUNET_HELLO_builder_to_url (struct GNUNET_HELLO_Builder *builder) | 543 | GNUNET_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 | ||
285 | enum GNUNET_GenericReturnValue | 607 | enum GNUNET_GenericReturnValue |
286 | GNUNET_HELLO_builder_to_block (struct GNUNET_HELLO_Builder *builder, | 608 | GNUNET_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 | */ | ||
37 | static void | ||
38 | check_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 | |||
54 | int | ||
55 | main (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 | } | ||
diff --git a/src/include/gnunet_hello_uri_lib.h b/src/include/gnunet_hello_uri_lib.h index dbf4dc35e..ec9cdfa5e 100644 --- a/src/include/gnunet_hello_uri_lib.h +++ b/src/include/gnunet_hello_uri_lib.h | |||
@@ -103,26 +103,30 @@ GNUNET_HELLO_builder_from_url (const char *url); | |||
103 | * Generate HELLO message from a @a builder | 103 | * Generate HELLO message from a @a builder |
104 | * | 104 | * |
105 | * @param builder builder to serialize | 105 | * @param builder builder to serialize |
106 | * @param priv private key to use to sign the result | ||
106 | * @return HELLO message matching @a builder | 107 | * @return HELLO message matching @a builder |
107 | */ | 108 | */ |
108 | struct GNUNET_MQ_Envelope * | 109 | struct GNUNET_MQ_Envelope * |
109 | GNUNET_HELLO_builder_to_env (struct GNUNET_HELLO_Builder *builder); | 110 | GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder, |
111 | const struct GNUNET_CRYPTO_EddsaPrivateKey *priv); | ||
110 | 112 | ||
111 | 113 | ||
112 | /** | 114 | /** |
113 | * Generate GNUnet HELLO URI from a @a builder | 115 | * Generate GNUnet HELLO URI from a @a builder |
114 | * | 116 | * |
115 | * @param builder builder to serialize | 117 | * @param builder builder to serialize |
118 | * @param priv private key to use to sign the result | ||
116 | * @return hello URI | 119 | * @return hello URI |
117 | */ | 120 | */ |
118 | char * | 121 | char * |
119 | GNUNET_HELLO_builder_to_url (struct GNUNET_HELLO_Builder *builder); | 122 | GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder, |
120 | 123 | const struct GNUNET_CRYPTO_EddsaPrivateKey *priv); | |
121 | 124 | ||
122 | /** | 125 | /** |
123 | * Generate DHT block from a @a builder | 126 | * Generate DHT block from a @a builder |
124 | * | 127 | * |
125 | * @param builder the builder to serialize | 128 | * @param builder the builder to serialize |
129 | * @param priv private key to use to sign the result | ||
126 | * @param[out] block where to write the block, NULL to only calculate @a block_size | 130 | * @param[out] block where to write the block, NULL to only calculate @a block_size |
127 | * @param[in,out] block_size input is number of bytes available in @a block, | 131 | * @param[in,out] block_size input is number of bytes available in @a block, |
128 | * output is number of bytes needed in @a block | 132 | * output is number of bytes needed in @a block |
@@ -130,7 +134,8 @@ GNUNET_HELLO_builder_to_url (struct GNUNET_HELLO_Builder *builder); | |||
130 | * or if @a block was NULL | 134 | * or if @a block was NULL |
131 | */ | 135 | */ |
132 | enum GNUNET_GenericReturnValue | 136 | enum GNUNET_GenericReturnValue |
133 | GNUNET_HELLO_builder_to_block (struct GNUNET_HELLO_Builder *builder, | 137 | GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder, |
138 | const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, | ||
134 | void *block, | 139 | void *block, |
135 | size_t *block_size); | 140 | size_t *block_size); |
136 | 141 | ||
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 09c547b09..bb8577b7a 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h | |||
@@ -458,7 +458,7 @@ GNUNET_STRINGS_base64url_decode (const char *data, | |||
458 | * | 458 | * |
459 | * @param data the data to encode | 459 | * @param data the data to encode |
460 | * @param len the length of the input | 460 | * @param len the length of the input |
461 | * @param output where to write the output (*output should be NULL, | 461 | * @param[out] out where to write the output (*output should be NULL, |
462 | * is allocated) | 462 | * is allocated) |
463 | * @return the size of the output | 463 | * @return the size of the output |
464 | */ | 464 | */ |
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h index b14439462..96413c3cc 100644 --- a/src/include/gnunet_time_lib.h +++ b/src/include/gnunet_time_lib.h | |||
@@ -762,11 +762,22 @@ GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch); | |||
762 | * | 762 | * |
763 | * @param s_after_epoch seconds after epoch to convert | 763 | * @param s_after_epoch seconds after epoch to convert |
764 | * @return converted time value | 764 | * @return converted time value |
765 | */struct GNUNET_TIME_Timestamp | 765 | */ |
766 | struct GNUNET_TIME_Timestamp | ||
766 | GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch); | 767 | GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch); |
767 | 768 | ||
768 | 769 | ||
769 | /** | 770 | /** |
771 | * Convert timestamp to number of seconds after the UNIX epoch. | ||
772 | * | ||
773 | * @param ts timestamp to convert | ||
774 | * @return converted time value | ||
775 | */ | ||
776 | uint64_t | ||
777 | GNUNET_TIME_timestamp_to_s (struct GNUNET_TIME_Timestamp ts); | ||
778 | |||
779 | |||
780 | /** | ||
770 | * Convert absolute time from network byte order. | 781 | * Convert absolute time from network byte order. |
771 | * | 782 | * |
772 | * @param a time to convert | 783 | * @param a time to convert |
diff --git a/src/util/strings.c b/src/util/strings.c index a77f09022..7e218cc59 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -1813,12 +1813,19 @@ GNUNET_STRINGS_urldecode (const char *data, | |||
1813 | char *wpos = *out; | 1813 | char *wpos = *out; |
1814 | size_t resl = 0; | 1814 | size_t resl = 0; |
1815 | 1815 | ||
1816 | while ('\0' != *rpos) | 1816 | while ( ('\0' != *rpos) && |
1817 | (data + len != rpos) ) | ||
1817 | { | 1818 | { |
1818 | unsigned int num; | 1819 | unsigned int num; |
1819 | switch (*rpos) | 1820 | switch (*rpos) |
1820 | { | 1821 | { |
1821 | case '%': | 1822 | case '%': |
1823 | if (rpos + 3 > data + len) | ||
1824 | { | ||
1825 | GNUNET_break_op (0); | ||
1826 | GNUNET_free (*out); | ||
1827 | return 0; | ||
1828 | } | ||
1822 | if (1 != sscanf (rpos + 1, "%2x", &num)) | 1829 | if (1 != sscanf (rpos + 1, "%2x", &num)) |
1823 | break; | 1830 | break; |
1824 | *wpos = (char) ((unsigned char) num); | 1831 | *wpos = (char) ((unsigned char) num); |
diff --git a/src/util/time.c b/src/util/time.c index 83b39b4e8..68a6937a0 100644 --- a/src/util/time.c +++ b/src/util/time.c | |||
@@ -695,6 +695,13 @@ GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch) | |||
695 | } | 695 | } |
696 | 696 | ||
697 | 697 | ||
698 | uint64_t | ||
699 | GNUNET_TIME_timestamp_to_s (struct GNUNET_TIME_Timestamp ts) | ||
700 | { | ||
701 | return ts.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us; | ||
702 | } | ||
703 | |||
704 | |||
698 | struct GNUNET_TIME_Absolute | 705 | struct GNUNET_TIME_Absolute |
699 | GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) | 706 | GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) |
700 | { | 707 | { |