aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_signatures.h26
-rw-r--r--src/transport/gnunet-service-transport.c426
-rw-r--r--src/transport/plugin_transport.h28
-rw-r--r--src/transport/plugin_transport_http.c22
-rw-r--r--src/transport/plugin_transport_tcp.c5
-rw-r--r--src/transport/test_transport_api.c2
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf2
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf1
8 files changed, 409 insertions, 103 deletions
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index 0dd795dd2..a3199c735 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -43,53 +43,59 @@ extern "C"
43#define GNUNET_SIGNATURE_PURPOSE_TEST 0 43#define GNUNET_SIGNATURE_PURPOSE_TEST 0
44 44
45/** 45/**
46 * Signature for confirming HELLOs for transport. 46 * Signature for confirming that this peer uses a particular address.
47 */ 47 */
48#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PING 1 48#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN 1
49
50/**
51 * Signature for confirming that this peer connected to another peer
52 * using a particular address.
53 */
54#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING 2
49 55
50 56
51/** 57/**
52 * Purpose is to set a session key. 58 * Purpose is to set a session key.
53 */ 59 */
54#define GNUNET_SIGNATURE_PURPOSE_SET_KEY 2 60#define GNUNET_SIGNATURE_PURPOSE_SET_KEY 3
55 61
56/** 62/**
57 * Signature for a namespace/pseudonym advertisement (by 63 * Signature for a namespace/pseudonym advertisement (by
58 * the namespace owner). 64 * the namespace owner).
59 */ 65 */
60#define GNUNET_SIGNATURE_PURPOSE_NAMESPACE_ADVERTISEMENT 3 66#define GNUNET_SIGNATURE_PURPOSE_NAMESPACE_ADVERTISEMENT 4
61 67
62/** 68/**
63 * Signature by which a peer affirms that it is 69 * Signature by which a peer affirms that it is
64 * providing a certain bit of content (used 70 * providing a certain bit of content (used
65 * in LOCation URIs). 71 * in LOCation URIs).
66 */ 72 */
67#define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT 4 73#define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT 5
68 74
69/** 75/**
70 * Signature in a KBlock of the FS module. 76 * Signature in a KBlock of the FS module.
71 */ 77 */
72#define GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK 5 78#define GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK 6
73 79
74/** 80/**
75 * Signature of content URI placed into a namespace. 81 * Signature of content URI placed into a namespace.
76 */ 82 */
77#define GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK 6 83#define GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK 7
78 84
79/** 85/**
80 * Signature of advertisment for a namespace. 86 * Signature of advertisment for a namespace.
81 */ 87 */
82#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK 7 88#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK 8
83 89
84/** 90/**
85 * Keyword-based signature of advertisment for a namespace. 91 * Keyword-based signature of advertisment for a namespace.
86 */ 92 */
87#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG 8 93#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG 9
88 94
89/** 95/**
90 * 96 *
91 */ 97 */
92#define GNUNET_SIGNATURE_PURPOSE_RESOLVER_RESPONSE 9 98#define GNUNET_SIGNATURE_PURPOSE_RESOLVER_RESPONSE 10
93 99
94 100
95#if 0 /* keep Emacsens' auto-indent happy */ 101#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index eaca6b592..3a6fcf925 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -103,6 +103,15 @@
103#define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 103#define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
104 104
105/** 105/**
106 * How long is a PONG signature valid? We'll recycle a signature until
107 * 1/4 of this time is remaining. PONGs should expire so that if our
108 * external addresses change an adversary cannot replay them indefinitely.
109 * OTOH, we don't want to spend too much time generating PONG signatures,
110 * so they must have some lifetime to reduce our CPU usage.
111 */
112#define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
113
114/**
106 * Priority to use for PONG messages. 115 * Priority to use for PONG messages.
107 */ 116 */
108#define TRANSPORT_PONG_PRIORITY 4 117#define TRANSPORT_PONG_PRIORITY 4
@@ -241,7 +250,8 @@ struct ForeignAddressList
241 250
242 251
243/** 252/**
244 * Entry in linked list of network addresses for ourselves. 253 * Entry in linked list of network addresses for ourselves. Also
254 * includes a cached signature for 'struct TransportPongMessage's.
245 */ 255 */
246struct OwnAddressList 256struct OwnAddressList
247{ 257{
@@ -251,21 +261,26 @@ struct OwnAddressList
251 struct OwnAddressList *next; 261 struct OwnAddressList *next;
252 262
253 /** 263 /**
254 * The address, actually a pointer to the end 264 * How long until we actually auto-expire this address (unless it is
255 * of this struct. Do not free!
256 */
257 const void *addr;
258
259 /**
260 * How long until we auto-expire this address (unless it is
261 * re-confirmed by the transport)? 265 * re-confirmed by the transport)?
262 */ 266 */
263 struct GNUNET_TIME_Absolute expires; 267 struct GNUNET_TIME_Absolute expires;
264 268
265 /** 269 /**
270 * How long until the current signature expires? (ZERO if the
271 * signature was never created).
272 */
273 struct GNUNET_TIME_Absolute pong_sig_expires;
274
275 /**
276 * Signature for a 'struct TransportPongMessage' for this address.
277 */
278 struct GNUNET_CRYPTO_RsaSignature pong_signature;
279
280 /**
266 * Length of addr. 281 * Length of addr.
267 */ 282 */
268 uint16_t addrlen; 283 uint32_t addrlen;
269 284
270}; 285};
271 286
@@ -553,7 +568,9 @@ struct NeighbourList
553 568
554/** 569/**
555 * Message used to ask a peer to validate receipt (to check an address 570 * Message used to ask a peer to validate receipt (to check an address
556 * from a HELLO). 571 * from a HELLO). Followed by the address we are trying to validate,
572 * or an empty address if we are just sending a PING to confirm that a
573 * connection which the receiver (of the PING) initiated is still valid.
557 */ 574 */
558struct TransportPingMessage 575struct TransportPingMessage
559{ 576{
@@ -564,7 +581,7 @@ struct TransportPingMessage
564 struct GNUNET_MessageHeader header; 581 struct GNUNET_MessageHeader header;
565 582
566 /** 583 /**
567 * Random challenge number (in network byte order). 584 * Challenge code (to ensure fresh reply).
568 */ 585 */
569 uint32_t challenge GNUNET_PACKED; 586 uint32_t challenge GNUNET_PACKED;
570 587
@@ -579,14 +596,12 @@ struct TransportPingMessage
579/** 596/**
580 * Message used to validate a HELLO. The challenge is included in the 597 * Message used to validate a HELLO. The challenge is included in the
581 * confirmation to make matching of replies to requests possible. The 598 * confirmation to make matching of replies to requests possible. The
582 * signature signs the original challenge number, our public key, the 599 * signature signs our public key, an expiration time and our address.<p>
583 * sender's address (so that the sender can check that the address we
584 * saw is plausible for him and possibly detect a MiM attack) and a
585 * timestamp (to limit replay).<p>
586 * 600 *
587 * This message is followed by the address of the 601 * This message is followed by our transport address that the PING tried
588 * client that we are observing (which is part of what 602 * to confirm (if we liked it). The address can be empty (zero bytes)
589 * is being signed). 603 * if the PING had not address either (and we received the request via
604 * a connection that we initiated).
590 */ 605 */
591struct TransportPongMessage 606struct TransportPongMessage
592{ 607{
@@ -597,9 +612,10 @@ struct TransportPongMessage
597 struct GNUNET_MessageHeader header; 612 struct GNUNET_MessageHeader header;
598 613
599 /** 614 /**
600 * For padding, always zero. 615 * Challenge code from PING (showing freshness). Not part of what
616 * is signed so that we can re-use signatures.
601 */ 617 */
602 uint32_t reserved GNUNET_PACKED; 618 uint32_t challenge GNUNET_PACKED;
603 619
604 /** 620 /**
605 * Signature. 621 * Signature.
@@ -607,24 +623,31 @@ struct TransportPongMessage
607 struct GNUNET_CRYPTO_RsaSignature signature; 623 struct GNUNET_CRYPTO_RsaSignature signature;
608 624
609 /** 625 /**
610 * What are we signing and why? 626 * What are we signing and why? Two possible reason codes can be here:
627 * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a
628 * plausible address for this peer (pid is set to identity of signer); or
629 * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING to confirm that this is
630 * an address we used to connect to the peer with the given pid.
611 */ 631 */
612 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; 632 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
613 633
614 /** 634 /**
615 * Random challenge number (in network byte order). 635 * When does this signature expire?
616 */ 636 */
617 uint32_t challenge GNUNET_PACKED; 637 struct GNUNET_TIME_AbsoluteNBO expiration;
618 638
619 /** 639 /**
620 * Who signed this message? 640 * Either the identity of the peer Who signed this message, or the
641 * identity of the peer that we're connected to using the given
642 * address (depending on purpose.type).
621 */ 643 */
622 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded signer; 644 struct GNUNET_PeerIdentity pid;
623 645
624 /** 646 /**
625 * Size of address appended to this message 647 * Size of address appended to this message (part of what is
648 * being signed, hence not redundant).
626 */ 649 */
627 uint16_t addrlen; 650 uint32_t addrlen;
628 651
629}; 652};
630 653
@@ -877,7 +900,6 @@ static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
877 */ 900 */
878static struct GNUNET_STATISTICS_Handle *stats; 901static struct GNUNET_STATISTICS_Handle *stats;
879 902
880
881/** 903/**
882 * The peer specified by the given neighbour has timed-out or a plugin 904 * The peer specified by the given neighbour has timed-out or a plugin
883 * has disconnected. We may either need to do nothing (other plugins 905 * has disconnected. We may either need to do nothing (other plugins
@@ -1526,9 +1548,11 @@ find_ready_address(struct NeighbourList *neighbour)
1526#if DEBUG_TRANSPORT 1548#if DEBUG_TRANSPORT
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1528 "Best address found (`%s') has latency of %llu ms.\n", 1550 "Best address found (`%s') has latency of %llu ms.\n",
1529 a2s (best_address->ready_list->plugin->short_name, 1551 (best_address->addrlen > 0)
1552 ? a2s (best_address->ready_list->plugin->short_name,
1530 best_address->addr, 1553 best_address->addr,
1531 best_address->addrlen), 1554 best_address->addrlen)
1555 : "<inbound>",
1532 best_address->latency.value); 1556 best_address->latency.value);
1533#endif 1557#endif
1534 } 1558 }
@@ -1800,7 +1824,7 @@ address_generator (void *cls, size_t max, void *buf)
1800 } 1824 }
1801 ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name, 1825 ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1802 gc->expiration, 1826 gc->expiration,
1803 gc->addr_pos->addr, 1827 &gc->addr_pos[1],
1804 gc->addr_pos->addrlen, buf, max); 1828 gc->addr_pos->addrlen, buf, max);
1805 gc->addr_pos = gc->addr_pos->next; 1829 gc->addr_pos = gc->addr_pos->next;
1806 return ret; 1830 return ret;
@@ -2097,7 +2121,6 @@ plugin_env_notify_address (void *cls,
2097 } 2121 }
2098 2122
2099 al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen); 2123 al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
2100 al->addr = &al[1];
2101 al->next = p->addresses; 2124 al->next = p->addresses;
2102 p->addresses = al; 2125 p->addresses = al;
2103 al->expires = abex; 2126 al->expires = abex;
@@ -3076,6 +3099,7 @@ send_periodic_ping (void *cls,
3076 struct CheckAddressExistsClosure caec; 3099 struct CheckAddressExistsClosure caec;
3077 char * message_buf; 3100 char * message_buf;
3078 uint16_t hello_size; 3101 uint16_t hello_size;
3102 size_t slen;
3079 size_t tsize; 3103 size_t tsize;
3080 3104
3081 peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK; 3105 peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
@@ -3143,18 +3167,39 @@ send_periodic_ping (void *cls,
3143 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 3167 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3144 hello_size = GNUNET_HELLO_size(our_hello); 3168 hello_size = GNUNET_HELLO_size(our_hello);
3145 tsize = sizeof(struct TransportPingMessage) + hello_size; 3169 tsize = sizeof(struct TransportPingMessage) + hello_size;
3170 if (peer_address->addr != NULL)
3171 {
3172 slen = strlen (tp->short_name) + 1;
3173 tsize += slen + peer_address->addrlen;
3174 }
3146 message_buf = GNUNET_malloc(tsize); 3175 message_buf = GNUNET_malloc(tsize);
3147 ping.challenge = htonl(va->challenge);
3148 ping.header.size = htons(sizeof(struct TransportPingMessage));
3149 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING); 3176 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3177 ping.challenge = htonl(va->challenge);
3150 memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity)); 3178 memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3151 memcpy(message_buf, our_hello, hello_size); 3179 memcpy(message_buf, our_hello, hello_size);
3180 if (peer_address->addr != NULL)
3181 {
3182 ping.header.size = htons(sizeof(struct TransportPingMessage) +
3183 peer_address->addrlen +
3184 slen);
3185 memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3186 tp->short_name,
3187 slen);
3188 memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3189 peer_address->addr,
3190 peer_address->addrlen);
3191 }
3192 else
3193 {
3194 ping.header.size = htons(sizeof(struct TransportPingMessage));
3195 }
3152 memcpy(&message_buf[hello_size], 3196 memcpy(&message_buf[hello_size],
3153 &ping, 3197 &ping,
3154 sizeof(struct TransportPingMessage)); 3198 sizeof(struct TransportPingMessage));
3199
3155#if DEBUG_TRANSPORT_REVALIDATION 3200#if DEBUG_TRANSPORT_REVALIDATION
3156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3157 "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n", 3202 "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s'\n",
3158 (peer_address->addr != NULL) 3203 (peer_address->addr != NULL)
3159 ? a2s (peer_address->plugin->short_name, 3204 ? a2s (peer_address->plugin->short_name,
3160 peer_address->addr, 3205 peer_address->addr,
@@ -3163,7 +3208,7 @@ send_periodic_ping (void *cls,
3163 tp->short_name, 3208 tp->short_name,
3164 GNUNET_i2s (&neighbour->id), 3209 GNUNET_i2s (&neighbour->id),
3165 "HELLO", hello_size, 3210 "HELLO", hello_size,
3166 "PING", sizeof (struct TransportPingMessage)); 3211 "PING");
3167#endif 3212#endif
3168 GNUNET_STATISTICS_update (stats, 3213 GNUNET_STATISTICS_update (stats,
3169 gettext_noop ("# PING messages sent for re-validation"), 3214 gettext_noop ("# PING messages sent for re-validation"),
@@ -3321,34 +3366,133 @@ check_pending_validation (void *cls,
3321 struct GNUNET_PeerIdentity target; 3366 struct GNUNET_PeerIdentity target;
3322 struct NeighbourList *n; 3367 struct NeighbourList *n;
3323 struct ForeignAddressList *fal; 3368 struct ForeignAddressList *fal;
3369 struct OwnAddressList *oal;
3370 struct TransportPlugin *tp;
3324 struct GNUNET_MessageHeader *prem; 3371 struct GNUNET_MessageHeader *prem;
3372 uint16_t ps;
3373 const char *addr;
3374 size_t slen;
3375 size_t alen;
3325 3376
3326 if (ve->challenge != challenge) 3377 ps = ntohs (pong->header.size);
3327 return GNUNET_YES; 3378 if (ps < sizeof (struct TransportPongMessage))
3328
3329#if SIGN_USELESS
3330 if (GNUNET_OK !=
3331 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PING,
3332 &pong->purpose,
3333 &pong->signature,
3334 &ve->publicKey))
3335 { 3379 {
3336 GNUNET_break_op (0); 3380 GNUNET_break_op (0);
3337 return GNUNET_YES; 3381 return GNUNET_NO;
3338 } 3382 }
3383 addr = (const char*) &pong[1];
3384 slen = strlen (ve->transport_name) + 1;
3385 if ( (ps - sizeof (struct TransportPongMessage) != ve->addrlen + slen) ||
3386 (ve->challenge != challenge) ||
3387 (addr[slen-1] != '\0') ||
3388 (0 != strcmp (addr, ve->transport_name)) ||
3389 (ntohl (pong->purpose.size)
3390 != sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3391 sizeof (uint32_t) +
3392 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3393 sizeof (struct GNUNET_PeerIdentity) + ve->addrlen + slen) )
3394 return GNUNET_YES;
3395 alen = ps - sizeof (struct TransportPongMessage) - slen;
3396 switch (ntohl (pong->purpose.purpose))
3397 {
3398 case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN:
3399 if ( (ve->addrlen + slen != ntohl (pong->addrlen)) ||
3400 (0 != memcmp (&addr[slen],
3401 ve->addr,
3402 ve->addrlen)) )
3403 return GNUNET_YES; /* different entry, keep trying! */
3404 if ( (0 != memcmp (&pong->pid,
3405 key,
3406 sizeof (struct GNUNET_PeerIdentity))) ||
3407 (ve->addrlen == 0) )
3408 {
3409 GNUNET_break_op (0);
3410 return GNUNET_NO;
3411 }
3412 if (GNUNET_OK !=
3413 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
3414 &pong->purpose,
3415 &pong->signature,
3416 &ve->publicKey))
3417 {
3418 GNUNET_break_op (0);
3419 return GNUNET_NO;
3420 }
3421#if DEBUG_TRANSPORT
3422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3423 "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
3424 GNUNET_h2s (key),
3425 a2s (ve->transport_name,
3426 (const struct sockaddr *) ve->addr,
3427 ve->addrlen),
3428 ve->transport_name);
3339#endif 3429#endif
3340 3430 break;
3431 case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING:
3432 if (ve->addrlen != 0)
3433 return GNUNET_YES; /* different entry, keep trying */
3434 if ( (0 != memcmp (&pong->pid,
3435 &my_identity,
3436 sizeof (struct GNUNET_PeerIdentity))) ||
3437 (ve->addrlen != 0) )
3438 {
3439 GNUNET_break_op (0);
3440 return GNUNET_NO;
3441 }
3442 tp = find_transport (ve->transport_name);
3443 if (tp == NULL)
3444 {
3445 GNUNET_break (0);
3446 return GNUNET_YES;
3447 }
3448 oal = tp->addresses;
3449 while (NULL != oal)
3450 {
3451 if ( (oal->addrlen == alen) &&
3452 (0 == memcmp (&oal[1],
3453 &addr[slen],
3454 alen)) )
3455 break;
3456 oal = oal->next;
3457 }
3458 if (oal == NULL)
3459 {
3460 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3461 _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"),
3462 a2s (ve->transport_name,
3463 &addr[slen],
3464 alen));
3465 return GNUNET_NO;
3466 }
3467 if (GNUNET_OK !=
3468 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
3469 &pong->purpose,
3470 &pong->signature,
3471 &ve->publicKey))
3472 {
3473 GNUNET_break_op (0);
3474 return GNUNET_NO;
3475 }
3341#if DEBUG_TRANSPORT 3476#if DEBUG_TRANSPORT
3342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3343 "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n", 3478 "Confirmed that peer `%4s' is talking to us using address `%s' (%s) for us.\n",
3344 GNUNET_h2s (key), 3479 GNUNET_h2s (key),
3345 (ve->addr != NULL) 3480 a2s (ve->transport_name,
3346 ? a2s (ve->transport_name, 3481 &addr[slen],
3347 (const struct sockaddr *) ve->addr, 3482 alen),
3348 ve->addrlen) 3483 ve->transport_name);
3349 : "<inbound>",
3350 ve->transport_name);
3351#endif 3484#endif
3485 break;
3486 default:
3487 GNUNET_break_op (0);
3488 return GNUNET_NO;
3489 }
3490 if (GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (pong->expiration)).value == 0)
3491 {
3492 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3493 _("Received expired signature. Check system time.\n"));
3494 return GNUNET_NO;
3495 }
3352 GNUNET_STATISTICS_update (stats, 3496 GNUNET_STATISTICS_update (stats,
3353 gettext_noop ("# address validation successes"), 3497 gettext_noop ("# address validation successes"),
3354 1, 3498 1,
@@ -3498,6 +3642,7 @@ transmit_hello_and_ping (void *cls,
3498 size_t tsize; 3642 size_t tsize;
3499 char * message_buf; 3643 char * message_buf;
3500 struct GNUNET_PeerIdentity id; 3644 struct GNUNET_PeerIdentity id;
3645 size_t slen;
3501 3646
3502 GNUNET_CRYPTO_hash (&va->publicKey, 3647 GNUNET_CRYPTO_hash (&va->publicKey,
3503 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 3648 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
@@ -3532,25 +3677,34 @@ transmit_hello_and_ping (void *cls,
3532 return; 3677 return;
3533 } 3678 }
3534 hello_size = GNUNET_HELLO_size(our_hello); 3679 hello_size = GNUNET_HELLO_size(our_hello);
3535 tsize = sizeof(struct TransportPingMessage) + hello_size; 3680 slen = strlen(va->transport_name) + 1;
3681 tsize = sizeof(struct TransportPingMessage) + hello_size + va->addrlen + slen;
3536 message_buf = GNUNET_malloc(tsize); 3682 message_buf = GNUNET_malloc(tsize);
3537 ping.challenge = htonl(va->challenge); 3683 ping.challenge = htonl(va->challenge);
3538 ping.header.size = htons(sizeof(struct TransportPingMessage)); 3684 ping.header.size = htons(sizeof(struct TransportPingMessage) + slen + va->addrlen);
3539 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING); 3685 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3540 memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity)); 3686 memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3541 memcpy(message_buf, our_hello, hello_size); 3687 memcpy(message_buf, our_hello, hello_size);
3542 memcpy(&message_buf[hello_size], 3688 memcpy(&message_buf[hello_size],
3543 &ping, 3689 &ping,
3544 sizeof(struct TransportPingMessage)); 3690 sizeof(struct TransportPingMessage));
3691 memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3692 va->transport_name,
3693 slen);
3694 memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3695 &va[1],
3696 va->addrlen);
3545#if DEBUG_TRANSPORT 3697#if DEBUG_TRANSPORT
3546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3547 "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n", 3699 "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
3548 a2s (va->transport_name, 3700 (va->addrlen == 0)
3549 (const void*) &va[1], va->addrlen), 3701 ? "<inbound>"
3702 : a2s (va->transport_name,
3703 (const void*) &va[1], va->addrlen),
3550 va->transport_name, 3704 va->transport_name,
3551 GNUNET_i2s (&neighbour->id), 3705 GNUNET_i2s (&neighbour->id),
3552 "HELLO", hello_size, 3706 "HELLO", hello_size,
3553 "PING", sizeof (struct TransportPingMessage)); 3707 "PING", sizeof (struct TransportPingMessage) + va->addrlen + slen);
3554#endif 3708#endif
3555 3709
3556 GNUNET_STATISTICS_update (stats, 3710 GNUNET_STATISTICS_update (stats,
@@ -3618,7 +3772,7 @@ run_validation (void *cls,
3618 while (NULL != oal) 3772 while (NULL != oal)
3619 { 3773 {
3620 if ( (oal->addrlen == addrlen) && 3774 if ( (oal->addrlen == addrlen) &&
3621 (0 == memcmp (oal->addr, 3775 (0 == memcmp (&oal[1],
3622 addr, 3776 addr,
3623 addrlen)) ) 3777 addrlen)) )
3624 { 3778 {
@@ -4073,17 +4227,23 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4073static int 4227static int
4074handle_ping(void *cls, const struct GNUNET_MessageHeader *message, 4228handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
4075 const struct GNUNET_PeerIdentity *peer, 4229 const struct GNUNET_PeerIdentity *peer,
4230 struct Session *session,
4076 const char *sender_address, 4231 const char *sender_address,
4077 uint16_t sender_address_len) 4232 uint16_t sender_address_len)
4078{ 4233{
4079 struct TransportPlugin *plugin = cls; 4234 struct TransportPlugin *plugin = cls;
4235 struct SessionHeader *session_header = (struct SessionHeader*) session;
4080 struct TransportPingMessage *ping; 4236 struct TransportPingMessage *ping;
4081 struct TransportPongMessage *pong; 4237 struct TransportPongMessage *pong;
4082 struct NeighbourList *n; 4238 struct NeighbourList *n;
4083 struct ReadyList *rl; 4239 struct ReadyList *rl;
4084 struct ForeignAddressList *fal; 4240 struct ForeignAddressList *fal;
4241 struct OwnAddressList *oal;
4242 const char *addr;
4243 size_t alen;
4244 size_t slen;
4085 4245
4086 if (ntohs (message->size) != sizeof (struct TransportPingMessage)) 4246 if (ntohs (message->size) < sizeof (struct TransportPingMessage))
4087 { 4247 {
4088 GNUNET_break_op (0); 4248 GNUNET_break_op (0);
4089 return GNUNET_SYSERR; 4249 return GNUNET_SYSERR;
@@ -4113,26 +4273,126 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
4113 gettext_noop ("# PING messages received"), 4273 gettext_noop ("# PING messages received"),
4114 1, 4274 1,
4115 GNUNET_NO); 4275 GNUNET_NO);
4116 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len); 4276 addr = (const char*) &ping[1];
4117 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len); 4277 alen = ntohs (message->size) - sizeof (struct TransportPingMessage);
4118 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); 4278 slen = strlen (plugin->short_name) + 1;
4119 pong->purpose.size = 4279 if (alen == 0)
4120 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + 4280 {
4121 sizeof (uint32_t) + 4281 /* peer wants to confirm that we have an outbound connection to him */
4122 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len); 4282 if (session == NULL)
4123 pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PING); 4283 {
4124 pong->challenge = ping->challenge; 4284 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4125 pong->addrlen = htons(sender_address_len); 4285 _("Refusing to create PONG since I do not have a session with `%s'.\n"),
4126 memcpy(&pong->signer, 4286 GNUNET_i2s (peer));
4127 &my_public_key, 4287 return GNUNET_SYSERR;
4128 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); 4288 }
4129 if (sender_address != NULL) 4289 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4130 memcpy (&pong[1], sender_address, sender_address_len); 4290 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4131#if SIGN_USELESS 4291 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4132 GNUNET_assert (GNUNET_OK == 4292 pong->purpose.size =
4133 GNUNET_CRYPTO_rsa_sign (my_private_key, 4293 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4134 &pong->purpose, &pong->signature)); 4294 sizeof (uint32_t) +
4295 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4296 sizeof (struct GNUNET_PeerIdentity) + sender_address_len + slen);
4297 pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING);
4298 pong->challenge = ping->challenge;
4299 pong->addrlen = htonl(sender_address_len + slen);
4300 memcpy(&pong->pid,
4301 peer,
4302 sizeof(struct GNUNET_PeerIdentity));
4303 memcpy (&pong[1],
4304 plugin->short_name,
4305 slen);
4306 memcpy (&((char*)&pong[1])[slen],
4307 sender_address,
4308 sender_address_len);
4309 if (GNUNET_TIME_absolute_get_remaining (session_header->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4)
4310 {
4311 /* create / update cached sig */
4312#if DEBUG_TRANSPORT
4313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4314 "Creating PONG signature to indicate active connection.\n");
4315#endif
4316 session_header->pong_sig_expires = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
4317 pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4318 GNUNET_assert (GNUNET_OK ==
4319 GNUNET_CRYPTO_rsa_sign (my_private_key,
4320 &pong->purpose,
4321 &session_header->pong_signature));
4322 }
4323 else
4324 {
4325 pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4326 }
4327 memcpy (&pong->signature,
4328 &session_header->pong_signature,
4329 sizeof (struct GNUNET_CRYPTO_RsaSignature));
4330
4331
4332 }
4333 else
4334 {
4335 /* peer wants to confirm that this is one of our addresses */
4336 addr += slen;
4337 alen -= slen;
4338 oal = plugin->addresses;
4339 while (NULL != oal)
4340 {
4341 if ( (oal->addrlen == alen) &&
4342 (0 == memcmp (addr,
4343 &oal[1],
4344 alen)) )
4345 break;
4346 oal = oal->next;
4347 }
4348 if (oal == NULL)
4349 {
4350 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4351 _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
4352 a2s (plugin->short_name,
4353 addr,
4354 alen));
4355 return GNUNET_NO;
4356 }
4357 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
4358 pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen);
4359 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4360 pong->purpose.size =
4361 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4362 sizeof (uint32_t) +
4363 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4364 sizeof (struct GNUNET_PeerIdentity) + alen + slen);
4365 pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
4366 pong->challenge = ping->challenge;
4367 pong->addrlen = htonl(alen + slen);
4368 memcpy(&pong->pid,
4369 &my_identity,
4370 sizeof(struct GNUNET_PeerIdentity));
4371 memcpy (&pong[1], plugin->short_name, slen);
4372 memcpy (&((char*)&pong[1])[slen], &oal[1], alen);
4373 if (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4)
4374 {
4375 /* create / update cached sig */
4376#if DEBUG_TRANSPORT
4377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4378 "Creating PONG signature to indicate ownership.\n");
4135#endif 4379#endif
4380 oal->pong_sig_expires = GNUNET_TIME_absolute_min (oal->expires,
4381 GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
4382 pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4383 GNUNET_assert (GNUNET_OK ==
4384 GNUNET_CRYPTO_rsa_sign (my_private_key,
4385 &pong->purpose,
4386 &oal->pong_signature));
4387 }
4388 else
4389 {
4390 pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4391 }
4392 memcpy (&pong->signature,
4393 &oal->pong_signature,
4394 sizeof (struct GNUNET_CRYPTO_RsaSignature));
4395 }
4136 n = find_neighbour(peer); 4396 n = find_neighbour(peer);
4137 GNUNET_assert (n != NULL); 4397 GNUNET_assert (n != NULL);
4138 /* first try reliable response transmission */ 4398 /* first try reliable response transmission */
@@ -4304,7 +4564,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
4304 process_hello (plugin, message); 4564 process_hello (plugin, message);
4305 break; 4565 break;
4306 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: 4566 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
4307 handle_ping (plugin, message, peer, sender_address, sender_address_len); 4567 handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
4308 break; 4568 break;
4309 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: 4569 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
4310 handle_pong (plugin, message, peer, sender_address, sender_address_len); 4570 handle_pong (plugin, message, peer, sender_address, sender_address_len);
diff --git a/src/transport/plugin_transport.h b/src/transport/plugin_transport.h
index 43b59e6cf..bb64a1bfc 100644
--- a/src/transport/plugin_transport.h
+++ b/src/transport/plugin_transport.h
@@ -47,6 +47,24 @@
47 */ 47 */
48struct Session; 48struct Session;
49 49
50/**
51 * Every 'struct Session' must begin with this header.
52 */
53struct SessionHeader
54{
55
56 /**
57 * Cached signature for PONG generation for the session. Do not use
58 * in the plugin!
59 */
60 struct GNUNET_CRYPTO_RsaSignature pong_signature;
61
62 /**
63 * Expiration time for signature. Do not use in the plugin!
64 */
65 struct GNUNET_TIME_Absolute pong_sig_expires;
66
67};
50 68
51/** 69/**
52 * Function that will be called whenever the plugin internally 70 * Function that will be called whenever the plugin internally
@@ -74,8 +92,14 @@ typedef void (*GNUNET_TRANSPORT_SessionEnd) (void *cls,
74 * @param message the message, NULL if we only care about 92 * @param message the message, NULL if we only care about
75 * learning about the delay until we should receive again -- FIXME! 93 * learning about the delay until we should receive again -- FIXME!
76 * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL) 94 * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
77 * @param session identifier used for this session (can be NULL) 95 * @param session identifier used for this session (NULL for plugins
78 * @param sender_address binary address of the sender (if observed) 96 * that do not offer bi-directional communication to the sender
97 * using the same "connection")
98 * @param sender_address binary address of the sender (if we established the
99 * connection or are otherwise sure of it; should be NULL
100 * for inbound TCP/UDP connections since it it not clear
101 * that we could establish ourselves a connection to that
102 * IP address and get the same system)
79 * @param sender_address_len number of bytes in sender_address 103 * @param sender_address_len number of bytes in sender_address
80 * @return how long the plugin should wait until receiving more data 104 * @return how long the plugin should wait until receiving more data
81 * (plugins that do not support this, can ignore the return value) 105 * (plugins that do not support this, can ignore the return value)
diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c
index 85224b827..326dcf62f 100644
--- a/src/transport/plugin_transport_http.c
+++ b/src/transport/plugin_transport_http.c
@@ -187,6 +187,11 @@ struct Session
187{ 187{
188 188
189 /** 189 /**
190 * API requirement.
191 */
192 struct SessionHeader header;
193
194 /**
190 * Stored in a linked list. 195 * Stored in a linked list.
191 */ 196 */
192 struct Session *next; 197 struct Session *next;
@@ -346,7 +351,13 @@ struct Plugin
346 * @param peer identity 351 * @param peer identity
347 * @return created session object 352 * @return created session object
348 */ 353 */
349static struct Session * create_session (void * cls, char * addr_in, size_t addrlen_in, char * addr_out, size_t addrlen_out, const struct GNUNET_PeerIdentity *peer) 354static struct Session *
355create_session (void * cls,
356 char * addr_in,
357 size_t addrlen_in,
358 char * addr_out,
359 size_t addrlen_out,
360 const struct GNUNET_PeerIdentity *peer)
350{ 361{
351 struct Plugin *plugin = cls; 362 struct Plugin *plugin = cls;
352 struct Session * cs = GNUNET_malloc ( sizeof( struct Session) ); 363 struct Session * cs = GNUNET_malloc ( sizeof( struct Session) );
@@ -404,10 +415,11 @@ static void messageTokenizerCallback (void *cls,
404 ntohs(message->type), 415 ntohs(message->type),
405 ntohs(message->size), 416 ntohs(message->size),
406 GNUNET_i2s(&(cs->identity))); 417 GNUNET_i2s(&(cs->identity)));
407 cs->plugin->env->receive(cs->plugin->env->cls, 418 cs->plugin->env->receive (cs->plugin->env->cls,
408 &cs->identity, 419 &cs->identity,
409 message, 1, NULL, 420 message, 1, cs,
410 NULL, 0); 421 cs->addr_out,
422 cs->addr_out_len);
411} 423}
412 424
413/** 425/**
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index dec803885..bb720124c 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -205,6 +205,11 @@ struct Session
205{ 205{
206 206
207 /** 207 /**
208 * API requirement.
209 */
210 struct SessionHeader header;
211
212 /**
208 * Stored in a linked list. 213 * Stored in a linked list.
209 */ 214 */
210 struct Session *next; 215 struct Session *next;
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index f449d375c..50d0d36e0 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -36,7 +36,7 @@
36#include "gnunet_transport_service.h" 36#include "gnunet_transport_service.h"
37#include "transport.h" 37#include "transport.h"
38 38
39#define VERBOSE GNUNET_YES 39#define VERBOSE GNUNET_NO
40 40
41#define VERBOSE_ARM GNUNET_NO 41#define VERBOSE_ARM GNUNET_NO
42 42
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
index e3778cd8e..363791e1c 100644
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ b/src/transport/test_transport_api_tcp_peer1.conf
@@ -32,7 +32,7 @@ MINIMUM-FRIENDS = 0
32 32
33[transport] 33[transport]
34PLUGINS = tcp 34PLUGINS = tcp
35DEBUG = NO 35#DEBUG = YES
36#PREFIX = xterm -T transport2 -e gdb --command=cmd --args 36#PREFIX = xterm -T transport2 -e gdb --command=cmd --args
37#PREFIX = valgrind --leak-check=full 37#PREFIX = valgrind --leak-check=full
38ACCEPT_FROM6 = ::1; 38ACCEPT_FROM6 = ::1;
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf
index 6362ebd27..3c7a8b8ff 100644
--- a/src/transport/test_transport_api_tcp_peer2.conf
+++ b/src/transport/test_transport_api_tcp_peer2.conf
@@ -32,7 +32,6 @@ MINIMUM-FRIENDS = 0
32 32
33[transport] 33[transport]
34PLUGINS = tcp 34PLUGINS = tcp
35DEBUG = NO
36#DEBUG = YES 35#DEBUG = YES
37ACCEPT_FROM6 = ::1; 36ACCEPT_FROM6 = ::1;
38ACCEPT_FROM = 127.0.0.1; 37ACCEPT_FROM = 127.0.0.1;