aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-10-06 21:32:05 +0000
committerChristian Grothoff <christian@grothoff.org>2011-10-06 21:32:05 +0000
commitca1cd117f6a59c0d19f841f72ac37340284ada57 (patch)
tree698e924a91c96d6ff79b738262a463f0d5004be6 /src/core
parent68f027903ee06b86c56c9f16dba9a83333936dbe (diff)
downloadgnunet-ca1cd117f6a59c0d19f841f72ac37340284ada57.tar.gz
gnunet-ca1cd117f6a59c0d19f841f72ac37340284ada57.zip
towards KX
Diffstat (limited to 'src/core')
-rw-r--r--src/core/gnunet-service-core-new.c31
-rw-r--r--src/core/gnunet-service-core_kx.c1307
-rw-r--r--src/core/gnunet-service-core_kx.h112
-rw-r--r--src/core/gnunet-service-core_neighbours.c6
-rw-r--r--src/core/gnunet-service-core_neighbours.h2
-rw-r--r--src/core/gnunet-service-core_sessions.c117
-rw-r--r--src/core/gnunet-service-core_sessions.h22
7 files changed, 699 insertions, 898 deletions
diff --git a/src/core/gnunet-service-core-new.c b/src/core/gnunet-service-core-new.c
index d67ae47b5..afdc22d9d 100644
--- a/src/core/gnunet-service-core-new.c
+++ b/src/core/gnunet-service-core-new.c
@@ -145,37 +145,6 @@
145#define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS 145#define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
146 146
147 147
148/**
149 * State machine for our P2P encryption handshake. Everyone starts in
150 * "DOWN", if we receive the other peer's key (other peer initiated)
151 * we start in state RECEIVED (since we will immediately send our
152 * own); otherwise we start in SENT. If we get back a PONG from
153 * within either state, we move up to CONFIRMED (the PONG will always
154 * be sent back encrypted with the key we sent to the other peer).
155 */
156enum PeerStateMachine
157{
158 /**
159 * No handshake yet.
160 */
161 PEER_STATE_DOWN,
162
163 /**
164 * We've sent our session key.
165 */
166 PEER_STATE_KEY_SENT,
167
168 /**
169 * We've received the other peers session key.
170 */
171 PEER_STATE_KEY_RECEIVED,
172
173 /**
174 * The other peer has confirmed our session key with a message
175 * encrypted with his session key (which we got). Session is now fully up.
176 */
177 PEER_STATE_KEY_CONFIRMED
178};
179 148
180/** 149/**
181 * Number of bytes (at the beginning) of "struct EncryptedMessage" 150 * Number of bytes (at the beginning) of "struct EncryptedMessage"
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index 1ab31cb2b..efc6ca1c2 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -199,6 +199,10 @@ static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
199 */ 199 */
200static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; 200static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
201 201
202/**
203 * Our message stream tokenizer (for encrypted payload).
204 */
205static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
202 206
203 207
204 208
@@ -258,7 +262,7 @@ derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
258 * Encrypt size bytes from in and write the result to out. Use the 262 * Encrypt size bytes from in and write the result to out. Use the
259 * key for outbound traffic of the given neighbour. 263 * key for outbound traffic of the given neighbour.
260 * 264 *
261 * @param n neighbour we are sending to 265 * @param kx key information context
262 * @param iv initialization vector to use 266 * @param iv initialization vector to use
263 * @param in ciphertext 267 * @param in ciphertext
264 * @param out plaintext 268 * @param out plaintext
@@ -266,7 +270,7 @@ derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
266 * @return GNUNET_OK on success 270 * @return GNUNET_OK on success
267 */ 271 */
268static int 272static int
269do_encrypt (struct Neighbour *n, 273do_encrypt (struct GSC_KeyExchangeInfo *kx,
270 const struct GNUNET_CRYPTO_AesInitializationVector *iv, 274 const struct GNUNET_CRYPTO_AesInitializationVector *iv,
271 const void *in, void *out, size_t size) 275 const void *in, void *out, size_t size)
272{ 276{
@@ -277,14 +281,14 @@ do_encrypt (struct Neighbour *n,
277 } 281 }
278 GNUNET_assert (size == 282 GNUNET_assert (size ==
279 GNUNET_CRYPTO_aes_encrypt (in, (uint16_t) size, 283 GNUNET_CRYPTO_aes_encrypt (in, (uint16_t) size,
280 &n->encrypt_key, iv, out)); 284 &kx->encrypt_key, iv, out));
281 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size, 285 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes encrypted"), size,
282 GNUNET_NO); 286 GNUNET_NO);
283#if DEBUG_CORE > 2 287#if DEBUG_CORE > 2
284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
285 "Encrypted %u bytes for `%4s' using key %u, IV %u\n", 289 "Encrypted %u bytes for `%4s' using key %u, IV %u\n",
286 (unsigned int) size, GNUNET_i2s (&n->peer), 290 (unsigned int) size, GNUNET_i2s (&kx->peer),
287 (unsigned int) n->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv, 291 (unsigned int) kx->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv,
288 sizeof 292 sizeof
289 (iv))); 293 (iv)));
290#endif 294#endif
@@ -299,7 +303,7 @@ do_encrypt (struct Neighbour *n,
299 * key for inbound traffic of the given neighbour. This function does 303 * key for inbound traffic of the given neighbour. This function does
300 * NOT do any integrity-checks on the result. 304 * NOT do any integrity-checks on the result.
301 * 305 *
302 * @param n neighbour we are receiving from 306 * @param kx key information context
303 * @param iv initialization vector to use 307 * @param iv initialization vector to use
304 * @param in ciphertext 308 * @param in ciphertext
305 * @param out plaintext 309 * @param out plaintext
@@ -307,7 +311,7 @@ do_encrypt (struct Neighbour *n,
307 * @return GNUNET_OK on success 311 * @return GNUNET_OK on success
308 */ 312 */
309static int 313static int
310do_decrypt (struct Neighbour *n, 314do_decrypt (struct GSC_KeyExchangeInfo *kx,
311 const struct GNUNET_CRYPTO_AesInitializationVector *iv, 315 const struct GNUNET_CRYPTO_AesInitializationVector *iv,
312 const void *in, void *out, size_t size) 316 const void *in, void *out, size_t size)
313{ 317{
@@ -316,14 +320,14 @@ do_decrypt (struct Neighbour *n,
316 GNUNET_break (0); 320 GNUNET_break (0);
317 return GNUNET_NO; 321 return GNUNET_NO;
318 } 322 }
319 if ((n->status != PEER_STATE_KEY_RECEIVED) && 323 if ((kx->status != KX_STATE_KEY_RECEIVED) &&
320 (n->status != PEER_STATE_KEY_CONFIRMED)) 324 (kx->status != KX_STATE_UP))
321 { 325 {
322 GNUNET_break_op (0); 326 GNUNET_break_op (0);
323 return GNUNET_SYSERR; 327 return GNUNET_SYSERR;
324 } 328 }
325 if (size != 329 if (size !=
326 GNUNET_CRYPTO_aes_decrypt (in, (uint16_t) size, &n->decrypt_key, iv, out)) 330 GNUNET_CRYPTO_aes_decrypt (in, (uint16_t) size, &kx->decrypt_key, iv, out))
327 { 331 {
328 GNUNET_break (0); 332 GNUNET_break (0);
329 return GNUNET_SYSERR; 333 return GNUNET_SYSERR;
@@ -333,8 +337,8 @@ do_decrypt (struct Neighbour *n,
333#if DEBUG_CORE > 1 337#if DEBUG_CORE > 1
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335 "Decrypted %u bytes from `%4s' using key %u, IV %u\n", 339 "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
336 (unsigned int) size, GNUNET_i2s (&n->peer), 340 (unsigned int) size, GNUNET_i2s (&kx->peer),
337 (unsigned int) n->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv, 341 (unsigned int) kx->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv,
338 sizeof 342 sizeof
339 (*iv))); 343 (*iv)));
340#endif 344#endif
@@ -342,6 +346,104 @@ do_decrypt (struct Neighbour *n,
342} 346}
343 347
344 348
349
350/**
351 * Task that will retry "send_key" if our previous attempt failed.
352 *
353 * @param cls our 'struct GSC_KeyExchangeInfo'
354 * @param tc scheduler context
355 */
356static void
357set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
358{
359 struct GSC_KeyExchangeInfo *kx = cls;
360
361 kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
362 kx->set_key_retry_frequency = GNUNET_TIME_relative_multiply (kx->set_key_retry_frequency, 2);
363 send_key (kx);
364}
365
366
367/**
368 * PEERINFO is giving us a HELLO for a peer. Add the public key to
369 * the neighbour's struct and continue with the key exchange. Or, if
370 * we did not get a HELLO, just do nothing.
371 *
372 * @param cls the 'struct GSC_KeyExchangeInfo' to retry sending the key for
373 * @param peer the peer for which this is the HELLO
374 * @param hello HELLO message of that peer
375 * @param err_msg NULL if successful, otherwise contains error message
376 */
377static void
378process_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
379 const struct GNUNET_HELLO_Message *hello,
380 const char *err_msg)
381{
382 struct GSC_KeyExchangeInfo *kx = cls;
383 struct SetKeyMessage *skm;
384
385 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task);
386 if (err_msg != NULL)
387 {
388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
389 _("Error in communication with PEERINFO service\n"));
390 kx->pitr = NULL;
391 return;
392 }
393 if (peer == NULL)
394 {
395 kx->pitr = NULL;
396 if (kx->public_key != NULL)
397 return; /* done here */
398#if DEBUG_CORE
399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400 "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
401 GNUNET_i2s (&kx->peer));
402#endif
403 GNUNET_STATISTICS_update (stats,
404 gettext_noop
405 ("# Delayed connecting due to lack of public key"),
406 1, GNUNET_NO);
407 kx->retry_set_key_task =
408 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
409 &set_key_retry_task, kx);
410 return;
411 }
412 if (kx->public_key != NULL)
413 {
414 /* already have public key, why are we here? */
415 GNUNET_break (0);
416 return;
417 }
418 kx->public_key =
419 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
420 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
421 {
422 GNUNET_break (0);
423 GNUNET_free (kx->public_key);
424 kx->public_key = NULL;
425 return;
426 }
427 send_key (kx);
428 if (NULL != kx->skm_received)
429 {
430 skm = kx->skm_received;
431 kx->skm_received = NULL;
432 GSC_KX_handle_set_key (kx, &skm->header);
433 GNUNET_free (skm);
434 }
435}
436
437
438/**
439 * Send our key (and encrypted PING) to the other peer.
440 *
441 * @param kx key exchange context
442 */
443static void
444send_key (struct GSC_KeyExchangeInfo *kx);
445
446
345/** 447/**
346 * Start the key exchange with the given peer. 448 * Start the key exchange with the given peer.
347 * 449 *
@@ -353,7 +455,14 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid)
353{ 455{
354 struct GSC_KeyExchangeInfo *kx; 456 struct GSC_KeyExchangeInfo *kx;
355 457
356 kx = NULL; 458 kx = GNUNET_malloc (sizeof (struct GSC_KeyExchangeInfo));
459 kx->peer = *pid;
460 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
461 kx->pitr = GNUNET_PEERINFO_iterate (peerinfo,
462 pid,
463 GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */,
464 &process_hello,
465 kx);
357 return kx; 466 return kx;
358} 467}
359 468
@@ -371,11 +480,19 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx)
371 GNUNET_PEERINFO_iterate_cancel (kx->pitr); 480 GNUNET_PEERINFO_iterate_cancel (kx->pitr);
372 kx->pitr = NULL; 481 kx->pitr = NULL;
373 } 482 }
374
375 GNUNET_SCHEDULER_cancel (n->dead_clean_task);
376 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
377 if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) 483 if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
484 {
378 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); 485 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
486 kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
487 }
488 if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
489 {
490 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
491 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
492 }
493 GNUNET_free_non_null (kx->skm_received);
494 GNUNET_free_non_null (kx->ping_received);
495 GNUNET_free_non_null (kx->pong_received);
379 GNUNET_free_non_null (kx->public_key); 496 GNUNET_free_non_null (kx->public_key);
380 GNUNET_free (kx); 497 GNUNET_free (kx);
381} 498}
@@ -385,15 +502,12 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx)
385 * We received a SET_KEY message. Validate and update 502 * We received a SET_KEY message. Validate and update
386 * our key material and status. 503 * our key material and status.
387 * 504 *
388 * @param n the neighbour from which we received message m 505 * @param kx key exchange status for the corresponding peer
389 * @param m the set key message we received 506 * @param msg the set key message we received
390 * @param ats performance data
391 * @param ats_count number of entries in ats (excluding 0-termination)
392 */ 507 */
393void 508void
394GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHandler *msg, 509GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx,
395 const struct GNUNET_TRANSPORT_ATS_Information *ats, 510 const struct GNUNET_MessageHandler *msg)
396 uint32_t ats_count)
397{ 511{
398 const struct SetKeyMessage *m; 512 const struct SetKeyMessage *m;
399 struct SetKeyMessage *m_cpy; 513 struct SetKeyMessage *m_cpy;
@@ -417,43 +531,19 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_Messag
417#if DEBUG_CORE 531#if DEBUG_CORE
418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
419 "Core service receives `%s' request from `%4s'.\n", "SET_KEY", 533 "Core service receives `%s' request from `%4s'.\n", "SET_KEY",
420 GNUNET_i2s (&n->peer)); 534 GNUNET_i2s (&kx->peer));
421#endif 535#endif
422 if (n->public_key == NULL) 536 if (kx->public_key == NULL)
423 { 537 {
424 if (n->pitr != NULL) 538 GNUNET_free_non_null (kx->skm_received);
425 { 539 kx->skm_received = GNUNET_copy_message (msg);
426#if DEBUG_CORE
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
428 "Ignoring `%s' message due to lack of public key for peer (still trying to obtain one).\n",
429 "SET_KEY");
430#endif
431 return;
432 }
433#if DEBUG_CORE
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
435 "Lacking public key for peer, trying to obtain one (handle_set_key).\n");
436#endif
437 m_cpy = GNUNET_malloc (sizeof (struct SetKeyMessage));
438 memcpy (m_cpy, m, sizeof (struct SetKeyMessage));
439 /* lookup n's public key, then try again */
440 GNUNET_assert (n->skm == NULL);
441 n->skm = m_cpy;
442 n->pitr =
443 GNUNET_PEERINFO_iterate (peerinfo, &n->peer, GNUNET_TIME_UNIT_MINUTES,
444 &process_hello_retry_handle_set_key, n);
445 GNUNET_STATISTICS_update (stats,
446 gettext_noop
447 ("# SET_KEY messages deferred (need public key)"),
448 1, GNUNET_NO);
449 return; 540 return;
450 } 541 }
451 if (0 != 542 if (0 !=
452 memcmp (&m->target, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 543 memcmp (&m->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
453 { 544 {
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 _ 546 _("`%s' is for `%s', not for me. Ignoring.\n"),
456 ("Received `%s' message that was for `%s', not for me. Ignoring.\n"),
457 "SET_KEY", GNUNET_i2s (&m->target)); 547 "SET_KEY", GNUNET_i2s (&m->target));
458 return; 548 return;
459 } 549 }
@@ -464,16 +554,16 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_Messag
464 sizeof (struct GNUNET_PeerIdentity)) || 554 sizeof (struct GNUNET_PeerIdentity)) ||
465 (GNUNET_OK != 555 (GNUNET_OK !=
466 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY, &m->purpose, 556 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY, &m->purpose,
467 &m->signature, n->public_key))) 557 &m->signature, kx->public_key)))
468 { 558 {
469 /* invalid signature */ 559 /* invalid signature */
470 GNUNET_break_op (0); 560 GNUNET_break_op (0);
471 return; 561 return;
472 } 562 }
473 t = GNUNET_TIME_absolute_ntoh (m->creation_time); 563 t = GNUNET_TIME_absolute_ntoh (m->creation_time);
474 if (((n->status == PEER_STATE_KEY_RECEIVED) || 564 if (((kx->status == KX_STATE_KEY_RECEIVED) ||
475 (n->status == PEER_STATE_KEY_CONFIRMED)) && 565 (kx->status == KX_STATE_UP)) &&
476 (t.abs_value < n->decrypt_key_created.abs_value)) 566 (t.abs_value < kx->decrypt_key_created.abs_value))
477 { 567 {
478 /* this could rarely happen due to massive re-ordering of 568 /* this could rarely happen due to massive re-ordering of
479 * messages on the network level, but is most likely either 569 * messages on the network level, but is most likely either
@@ -481,9 +571,6 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_Messag
481 GNUNET_break_op (0); 571 GNUNET_break_op (0);
482 return; 572 return;
483 } 573 }
484#if DEBUG_CORE
485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypting key material.\n");
486#endif
487 if ((GNUNET_CRYPTO_rsa_decrypt 574 if ((GNUNET_CRYPTO_rsa_decrypt
488 (my_private_key, &m->encrypted_key, &k, 575 (my_private_key, &m->encrypted_key, &k,
489 sizeof (struct GNUNET_CRYPTO_AesSessionKey)) != 576 sizeof (struct GNUNET_CRYPTO_AesSessionKey)) !=
@@ -497,68 +584,50 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_Messag
497 GNUNET_STATISTICS_update (stats, 584 GNUNET_STATISTICS_update (stats,
498 gettext_noop ("# SET_KEY messages decrypted"), 1, 585 gettext_noop ("# SET_KEY messages decrypted"), 1,
499 GNUNET_NO); 586 GNUNET_NO);
500 n->decrypt_key = k; 587 kx->decrypt_key = k;
501 if (n->decrypt_key_created.abs_value != t.abs_value) 588 if (kx->decrypt_key_created.abs_value != t.abs_value)
502 { 589 {
503 /* fresh key, reset sequence numbers */ 590 /* fresh key, reset sequence numbers */
504 n->last_sequence_number_received = 0; 591 kx->last_sequence_number_received = 0;
505 n->last_packets_bitmap = 0; 592 kx->last_packets_bitmap = 0;
506 n->decrypt_key_created = t; 593 kx->decrypt_key_created = t;
507 } 594 }
508 update_neighbour_performance (n, ats, ats_count);
509 sender_status = (enum PeerStateMachine) ntohl (m->sender_status); 595 sender_status = (enum PeerStateMachine) ntohl (m->sender_status);
510 switch (n->status) 596
597 switch (kx->status)
511 { 598 {
512 case PEER_STATE_DOWN: 599 case KX_STATE_DOWN:
513 n->status = PEER_STATE_KEY_RECEIVED; 600 kx->status = PEER_STATE_KEY_RECEIVED;
514#if DEBUG_CORE 601 /* we're not up, so we are already doing 'send_key' */
515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
516 "Responding to `%s' with my own key.\n", "SET_KEY");
517#endif
518 send_key (n);
519 break; 602 break;
520 case PEER_STATE_KEY_SENT: 603 case KX_STATE_KEY_SENT:
521 case PEER_STATE_KEY_RECEIVED:
522 n->status = PEER_STATE_KEY_RECEIVED; 604 n->status = PEER_STATE_KEY_RECEIVED;
523 if ((sender_status != PEER_STATE_KEY_RECEIVED) && 605 /* we're not up, so we are already doing 'send_key' */
524 (sender_status != PEER_STATE_KEY_CONFIRMED))
525 {
526#if DEBUG_CORE
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528 "Responding to `%s' with my own key (other peer has status %u).\n",
529 "SET_KEY", (unsigned int) sender_status);
530#endif
531 send_key (n);
532 }
533 break; 606 break;
534 case PEER_STATE_KEY_CONFIRMED: 607 case KX_STATE_KEY_RECEIVED:
535 if ((sender_status != PEER_STATE_KEY_RECEIVED) && 608 /* we're not up, so we are already doing 'send_key' */
536 (sender_status != PEER_STATE_KEY_CONFIRMED)) 609 break;
537 { 610 case KX_STATE_UP:
538#if DEBUG_CORE 611 if ( (sender_status == KX_STATE_DOWN) ||
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 612 (sender_status == KX_PEER_STATE_KEY_SENT) )
540 "Responding to `%s' with my own key (other peer has status %u), I was already fully up.\n", 613 send_key (kx); /* we are up, but other peer is not! */
541 "SET_KEY", (unsigned int) sender_status);
542#endif
543 send_key (n);
544 }
545 break; 614 break;
546 default: 615 default:
547 GNUNET_break (0); 616 GNUNET_break (0);
548 break; 617 break;
549 } 618 }
550 if (n->pending_ping != NULL) 619 if (kx->ping_received != NULL)
551 { 620 {
552 ping = n->pending_ping; 621 ping = kx->ping_received;
553 n->pending_ping = NULL; 622 kx->ping_received = NULL;
554 handle_ping (n, ping, NULL, 0); 623 GSC_KX_handle_ping (kx, &ping->header);
555 GNUNET_free (ping); 624 GNUNET_free (ping);
556 } 625 }
557 if (n->pending_pong != NULL) 626 if (kx->pong_received != NULL)
558 { 627 {
559 pong = n->pending_pong; 628 pong = kx->pong_received;
560 n->pending_pong = NULL; 629 kx->pong_received = NULL;
561 handle_pong (n, pong, NULL, 0); 630 GSC_KX_handle_pong (kx, &pong->header);
562 GNUNET_free (pong); 631 GNUNET_free (pong);
563 } 632 }
564} 633}
@@ -566,25 +635,20 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, const struct GNUNET_Messag
566 635
567/** 636/**
568 * We received a PING message. Validate and transmit 637 * We received a PING message. Validate and transmit
569 * PONG. 638 * a PONG message.
570 * 639 *
571 * @param n sender of the PING 640 * @param kx key exchange status for the corresponding peer
572 * @param m the encrypted PING message itself 641 * @param msg the encrypted PING message itself
573 * @param ats performance data
574 * @param ats_count number of entries in ats (excluding 0-termination)
575 */ 642 */
576void 643void
577GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHeader *msg, 644GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHeader *msg)
578 const struct GNUNET_TRANSPORT_ATS_Information *ats,
579 uint32_t ats_count)
580{ 645{
581 const struct PingMessage *m; 646 const struct PingMessage *m;
582 struct PingMessage t; 647 struct PingMessage t;
583 struct PongMessage tx; 648 struct PongMessage tx;
584 struct PongMessage *tp; 649 struct PongMessage tp;
585 struct MessageEntry *me;
586 struct GNUNET_CRYPTO_AesInitializationVector iv; 650 struct GNUNET_CRYPTO_AesInitializationVector iv;
587 size_t size; 651 uint16_t msize;
588 652
589 msize = ntohs (msg->size); 653 msize = ntohs (msg->size);
590 if (msize != sizeof (struct PingMessage)) 654 if (msize != sizeof (struct PingMessage))
@@ -592,49 +656,34 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHe
592 GNUNET_break_op (0); 656 GNUNET_break_op (0);
593 return; 657 return;
594 } 658 }
595 GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 659 GNUNET_STATISTICS_update (GSC_stats,
660 gettext_noop ("# PING messages received"),
596 1, GNUNET_NO); 661 1, GNUNET_NO);
597 662 if ( (kx->status != KX_STATE_KEY_RECEIVED) &&
598#if FIXME 663 (kx->status != KX_STATE_UP) )
599 if ((n->status != PEER_STATE_KEY_RECEIVED) &&
600 (n->status != PEER_STATE_KEY_CONFIRMED))
601 { 664 {
602#if DEBUG_CORE > 1 665 /* defer */
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
605 "PING", GNUNET_i2s (&n->peer));
606#endif
607 GNUNET_free_non_null (n->pending_ping); 666 GNUNET_free_non_null (n->pending_ping);
608 n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage)); 667 n->pending_ping = GNUNET_copy_message (msg);
609 memcpy (n->pending_ping, message, sizeof (struct PingMessage));
610 return; 668 return;
611 } 669 }
612#endif 670 m = (const struct PingMessage*) msg;
613 m = (const struct PingMessage*) msg;
614#if DEBUG_CORE 671#if DEBUG_CORE
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "Core service receives `%s' request from `%4s'.\n", "PING", 673 "Core service receives `%s' request from `%4s'.\n", "PING",
617 GNUNET_i2s (&n->peer)); 674 GNUNET_i2s (&n->peer));
618#endif 675#endif
619 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity); 676 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
620 if (GNUNET_OK != 677 if (GNUNET_OK !=
621 do_decrypt (n, &iv, &m->target, &t.target, 678 do_decrypt (kx, &iv, &m->target, &t.target,
622 sizeof (struct PingMessage) - ((void *) &m->target - 679 sizeof (struct PingMessage) - ((void *) &m->target -
623 (void *) m))) 680 (void *) m)))
681 {
682 GNUNET_break_op (0);
624 return; 683 return;
625#if DEBUG_HANDSHAKE 684 }
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
627 "Decrypted `%s' to `%4s' with challenge %u decrypted using key %u, IV %u (salt %u)\n",
628 "PING", GNUNET_i2s (&t.target), (unsigned int) t.challenge,
629 (unsigned int) n->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (&iv,
630 sizeof
631 (iv)),
632 m->iv_seed);
633#endif
634 GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages decrypted"),
635 1, GNUNET_NO);
636 if (0 != 685 if (0 !=
637 memcmp (&t.target, &my_identity, sizeof (struct GNUNET_PeerIdentity))) 686 memcmp (&t.target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
638 { 687 {
639 char sender[9]; 688 char sender[9];
640 char peer[9]; 689 char peer[9];
@@ -642,60 +691,135 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHe
642 GNUNET_snprintf (sender, sizeof (sender), "%8s", GNUNET_i2s (&n->peer)); 691 GNUNET_snprintf (sender, sizeof (sender), "%8s", GNUNET_i2s (&n->peer));
643 GNUNET_snprintf (peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target)); 692 GNUNET_snprintf (peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target));
644 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
645 _ 694 _("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"),
646 ("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"),
647 sender, GNUNET_i2s (&my_identity), peer); 695 sender, GNUNET_i2s (&my_identity), peer);
648 GNUNET_break_op (0); 696 GNUNET_break_op (0);
649 return; 697 return;
650 } 698 }
651 update_neighbour_performance (n, ats, ats_count); 699 /* construct PONG */
652 me = GNUNET_malloc (sizeof (struct MessageEntry) +
653 sizeof (struct PongMessage));
654 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head, n->encrypted_tail,
655 n->encrypted_tail, me);
656 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PONG_DELAY);
657 me->priority = PONG_PRIORITY;
658 me->size = sizeof (struct PongMessage);
659 tx.inbound_bw_limit = n->bw_in; 700 tx.inbound_bw_limit = n->bw_in;
660 tx.challenge = t.challenge; 701 tx.challenge = t.challenge;
661 tx.target = t.target; 702 tx.target = t.target;
662 tp = (struct PongMessage *) &me[1]; 703 tp.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
663 tp->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG); 704 tp.header.size = htons (sizeof (struct PongMessage));
664 tp->header.size = htons (sizeof (struct PongMessage)); 705 tp.iv_seed =
665 tp->iv_seed =
666 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); 706 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
667 derive_pong_iv (&iv, &n->encrypt_key, tp->iv_seed, t.challenge, &n->peer); 707 derive_pong_iv (&iv, &n->encrypt_key, tp.iv_seed, t.challenge, &kx->peer);
668 do_encrypt (n, &iv, &tx.challenge, &tp->challenge, 708 do_encrypt (n, &iv, &tx.challenge, &tp.challenge,
669 sizeof (struct PongMessage) - ((void *) &tp->challenge - 709 sizeof (struct PongMessage) - ((void *) &tp.challenge -
670 (void *) tp)); 710 (void *) tp));
671 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages created"), 1, 711 GNUNET_STATISTICS_update (GSC_stats,
712 gettext_noop ("# PONG messages created"), 1,
672 GNUNET_NO); 713 GNUNET_NO);
673#if DEBUG_HANDSHAKE 714 GSC_NEIGHBOURS_transmit (&kx->peer,
674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 715 &tp.header,
675 "Encrypting `%s' with challenge %u using key %u, IV %u (salt %u)\n", 716 GNUNET_TIME_UNIT_FOREVER_REL /* FIXME: timeout */);
676 "PONG", (unsigned int) t.challenge, 717}
677 (unsigned int) n->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (&iv, 718
678 sizeof 719
679 (iv)), 720/**
680 tp->iv_seed); 721 * Create a fresh SET KEY message for transmission to the other peer.
681#endif 722 * Also creates a new key.
682 /* trigger queue processing */ 723 *
683 process_encrypted_neighbour_queue (n); 724 * @param kx key exchange context to create SET KEY message for
725 */
726static void
727setup_fresh_setkey (struct GSC_KeyExchangeInfo *kx)
728{
729 struct SetKeyMessage *skm;
730
731 GNUNET_CRYPTO_aes_create_session_key (&kx->encrypt_key);
732 kx->encrypt_key_created = GNUNET_TIME_absolute_get ();
733 skm = &kx->skm;
734 skm->header.size = htons (sizeof (struct SetKeyMessage));
735 skm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
736 skm->purpose.size =
737 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
738 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
739 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
740 sizeof (struct GNUNET_PeerIdentity));
741 skm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
742 skm->creation_time = GNUNET_TIME_absolute_hton (kx->encrypt_key_created);
743 skm->target = kx->peer;
744 GNUNET_assert (GNUNET_OK ==
745 GNUNET_CRYPTO_rsa_encrypt (&kx->encrypt_key,
746 sizeof (struct
747 GNUNET_CRYPTO_AesSessionKey),
748 kx->public_key, &skm->encrypted_key));
749 GNUNET_assert (GNUNET_OK ==
750 GNUNET_CRYPTO_rsa_sign (my_private_key, &skm->purpose,
751 &skm->signature));
752}
753
754
755/**
756 * Create a fresh PING message for transmission to the other peer.
757 *
758 * @param kx key exchange context to create PING for
759 */
760static void
761setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
762{
763 struct PingMessage pp;
764 struct PingMessage *pm;
765
766 pm = &kx->ping;
767 pm->header.size = htons (sizeof (struct PingMessage));
768 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
769 pm->iv_seed =
770 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
771 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, &kx->peer);
772 pp.challenge = kx->ping_challenge;
773 pp.target = kx->peer;
774 do_encrypt (kx, &iv, &pp.target, &pm->target,
775 sizeof (struct PingMessage) - ((void *) &pm->target -
776 (void *) pm));
777}
778
779
780/**
781 * Task triggered when a neighbour entry is about to time out
782 * (and we should prevent this by sending a PING).
783 *
784 * @param cls the 'struct GSC_KeyExchangeInfo'
785 * @param tc scheduler context (not used)
786 */
787static void
788send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
789{
790 struct GSC_KeyExchangeInfo *kx = cls;
791 struct GNUNET_TIME_Relative retry;
792 struct GNUNET_TIME_Relative left;
793
794 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
795 left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
796 if (left.rel_value == 0)
797 {
798 GSC_SESSIONS_end (&kx->peer);
799 kx->status = KX_STATE_DOWN;
800 return;
801 }
802 setup_fresh_ping (kx);
803 GDS_NEIGHBOURS_transmit (&kx->peer,
804 &kx->ping.header,
805 kx->set_key_retry_frequency);
806 retry =
807 GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
808 MIN_PING_FREQUENCY);
809 kx->keep_alive_task =
810 GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx);
811
684} 812}
685 813
686 814
687/** 815/**
688 * We received a PONG message. Validate and update our status. 816 * We received a PONG message. Validate and update our status.
689 * 817 *
690 * @param n sender of the PONG 818 * @param kx key exchange context for the the PONG
691 * @param m the encrypted PONG message itself 819 * @param m the encrypted PONG message itself
692 * @param ats performance data
693 * @param ats_count number of entries in ats (excluding 0-termination)
694 */ 820 */
695void 821void
696GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHeader *msg, 822GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg)
697 const struct GNUNET_TRANSPORT_ATS_Information *ats,
698 uint32_t ats_count)
699{ 823{
700 const struct PongMessage *m; 824 const struct PongMessage *m;
701 struct PongMessage t; 825 struct PongMessage t;
@@ -708,41 +832,35 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHe
708 832
709 msize = ntohs (msg->size); 833 msize = ntohs (msg->size);
710 if (msize != sizeof (struct PongMessage)) 834 if (msize != sizeof (struct PongMessage))
711 { 835 {
712 GNUNET_break_op (0); 836 GNUNET_break_op (0);
713 return; 837 return;
714 } 838 }
715 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 839 GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages received"),
716 1, GNUNET_NO); 840 1, GNUNET_NO);
717 841
718#if FIXME 842 if ( (kx->status != KX_STATE_KEY_RECEIVED) &&
719 if ((n->status != PEER_STATE_KEY_RECEIVED) && 843 (kx->status != KX_STATE_UP) )
720 (n->status != PEER_STATE_KEY_CONFIRMED)) 844 {
845 if (kx->status == KX_STATE_KEY_SENT)
721 { 846 {
722#if DEBUG_CORE > 1
723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
724 "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
725 "PONG", GNUNET_i2s (&n->peer));
726#endif
727 GNUNET_free_non_null (n->pending_pong); 847 GNUNET_free_non_null (n->pending_pong);
728 n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage)); 848 n->pending_pong = GNUNET_copy_message (msg);
729 memcpy (n->pending_pong, message, sizeof (struct PongMessage));
730 return;
731 } 849 }
732#endif 850 return;
733 851 }
734 m = (const struct PongMessage*) msg; 852 m = (const struct PongMessage*) msg;
735#if DEBUG_HANDSHAKE 853#if DEBUG_HANDSHAKE
736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
737 "Core service receives `%s' response from `%4s'.\n", "PONG", 855 "Core service receives `%s' response from `%4s'.\n", "PONG",
738 GNUNET_i2s (&n->peer)); 856 GNUNET_i2s (&kx->peer));
739#endif 857#endif
740 /* mark as garbage, just to be sure */ 858 /* mark as garbage, just to be sure */
741 memset (&t, 255, sizeof (t)); 859 memset (&t, 255, sizeof (t));
742 derive_pong_iv (&iv, &n->decrypt_key, m->iv_seed, n->ping_challenge, 860 derive_pong_iv (&iv, &kx->decrypt_key, m->iv_seed, kx->ping_challenge,
743 &my_identity); 861 &my_identity);
744 if (GNUNET_OK != 862 if (GNUNET_OK !=
745 do_decrypt (n, &iv, &m->challenge, &t.challenge, 863 do_decrypt (kx, &iv, &m->challenge, &t.challenge,
746 sizeof (struct PongMessage) - ((void *) &m->challenge - 864 sizeof (struct PongMessage) - ((void *) &m->challenge -
747 (void *) m))) 865 (void *) m)))
748 { 866 {
@@ -751,17 +869,8 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHe
751 } 869 }
752 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages decrypted"), 870 GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages decrypted"),
753 1, GNUNET_NO); 871 1, GNUNET_NO);
754#if DEBUG_HANDSHAKE 872 if ((0 != memcmp (&t.target, &kx->peer, sizeof (struct GNUNET_PeerIdentity)))
755 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 873 || (kx->ping_challenge != t.challenge))
756 "Decrypted `%s' from `%4s' with challenge %u using key %u, IV %u (salt %u)\n",
757 "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge,
758 (unsigned int) n->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (&iv,
759 sizeof
760 (iv)),
761 m->iv_seed);
762#endif
763 if ((0 != memcmp (&t.target, &n->peer, sizeof (struct GNUNET_PeerIdentity)))
764 || (n->ping_challenge != t.challenge))
765 { 874 {
766 /* PONG malformed */ 875 /* PONG malformed */
767#if DEBUG_CORE 876#if DEBUG_CORE
@@ -773,490 +882,99 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *n, const struct GNUNET_MessageHe
773 "Received malformed `%s' received from `%4s' with challenge %u\n", 882 "Received malformed `%s' received from `%4s' with challenge %u\n",
774 "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge); 883 "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge);
775#endif 884#endif
776 GNUNET_break_op (n->ping_challenge != t.challenge);
777 return; 885 return;
778 } 886 }
779 switch (n->status) 887 switch (kx->status)
780 { 888 {
781 case PEER_STATE_DOWN: 889 case KX_STATE_DOWN:
782 GNUNET_break (0); /* should be impossible */ 890 GNUNET_break (0); /* should be impossible */
783 return; 891 return;
784 case PEER_STATE_KEY_SENT: 892 case KX_STATE_KEY_SENT:
785 GNUNET_break (0); /* should be impossible, how did we decrypt? */ 893 GNUNET_break (0); /* should be impossible */
786 return; 894 return;
787 case PEER_STATE_KEY_RECEIVED: 895 case KX_STATE_KEY_RECEIVED:
788 GNUNET_STATISTICS_update (stats, 896 GNUNET_STATISTICS_update (stats,
789 gettext_noop 897 gettext_noop
790 ("# Session keys confirmed via PONG"), 1, 898 ("# Session keys confirmed via PONG"), 1,
791 GNUNET_NO); 899 GNUNET_NO);
792 n->status = PEER_STATE_KEY_CONFIRMED; 900 kx->status = KX_STATE_UP;
793 { 901 GSC_SESSIONS_create (&kx->peer);
794 struct GNUNET_MessageHeader *hdr; 902 GNUNET_assert (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK);
795 903 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
796 hdr = compute_type_map_message (); 904 kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
797 send_type_map_to_neighbour (hdr, &n->peer.hashPubKey, n); 905 GNUNET_assert (kx->keep_alive_task == GNUNET_SCHEDULER_NO_TASK);
798 GNUNET_free (hdr); 906 update_timeout (kx);
799 } 907 break;
800 if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
801 {
802 n->bw_out_external_limit = t.inbound_bw_limit;
803 n->bw_out =
804 GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
805 n->bw_out_internal_limit);
806 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
807 n->bw_out);
808 GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out);
809 }
810#if DEBUG_CORE
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
812 "Confirmed key via `%s' message for peer `%4s'\n", "PONG",
813 GNUNET_i2s (&n->peer));
814#endif
815 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
816 {
817 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
818 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
819 }
820 update_neighbour_performance (n, ats, ats_count);
821 size =
822 sizeof (struct ConnectNotifyMessage) +
823 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
824 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
825 {
826 GNUNET_break (0);
827 /* recovery strategy: throw away performance data */
828 GNUNET_array_grow (n->ats, n->ats_count, 0);
829 size =
830 sizeof (struct PeerStatusNotifyMessage) +
831 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
832 }
833 cnm = (struct ConnectNotifyMessage *) buf;
834 cnm->header.size = htons (size);
835 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
836 cnm->ats_count = htonl (n->ats_count);
837 cnm->peer = n->peer;
838 mats = &cnm->ats;
839 memcpy (mats, n->ats,
840 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
841 mats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
842 mats[n->ats_count].value = htonl (0);
843 send_to_all_clients (&cnm->header, GNUNET_NO,
844 GNUNET_CORE_OPTION_SEND_CONNECT);
845 process_encrypted_neighbour_queue (n);
846 /* fall-through! */
847 case PEER_STATE_KEY_CONFIRMED: 908 case PEER_STATE_KEY_CONFIRMED:
848 n->last_activity = GNUNET_TIME_absolute_get (); 909 update_timeout (kx);
849 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
850 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
851 n->keep_alive_task =
852 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
853 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
854 2), &send_keep_alive, n);
855 handle_peer_status_change (n);
856 break; 910 break;
857 default: 911 default:
858 GNUNET_break (0); 912 GNUNET_break (0);
859 break; 913 break;
860 } 914 }
861
862#if FIXME
863 if (n->status == PEER_STATE_KEY_CONFIRMED)
864 {
865 now = GNUNET_TIME_absolute_get ();
866 n->last_activity = now;
867 changed = GNUNET_YES;
868 if (!up)
869 {
870 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"),
871 1, GNUNET_NO);
872 n->time_established = now;
873 }
874 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
875 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
876 n->keep_alive_task =
877 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
878 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
879 2), &send_keep_alive, n);
880 }
881 if (changed)
882 handle_peer_status_change (n);
883#endif
884}
885
886
887
888/**
889 * PEERINFO is giving us a HELLO for a peer. Add the public key to
890 * the neighbour's struct and retry send_key. Or, if we did not get a
891 * HELLO, just do nothing.
892 *
893 * @param cls the 'struct Neighbour' to retry sending the key for
894 * @param peer the peer for which this is the HELLO
895 * @param hello HELLO message of that peer
896 * @param err_msg NULL if successful, otherwise contains error message
897 */
898static void
899process_hello_retry_send_key (void *cls, const struct GNUNET_PeerIdentity *peer,
900 const struct GNUNET_HELLO_Message *hello,
901 const char *err_msg)
902{
903 struct Neighbour *n = cls;
904
905 if (err_msg != NULL)
906 {
907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
908 _("Error in communication with PEERINFO service\n"));
909 /* return; */
910 }
911
912 if (peer == NULL)
913 {
914#if DEBUG_CORE
915 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entered `%s' and `%s' is NULL!\n",
916 "process_hello_retry_send_key", "peer");
917#endif
918 n->pitr = NULL;
919 if (n->public_key != NULL)
920 {
921 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
922 {
923 GNUNET_SCHEDULER_cancel (n->retry_set_key_task);
924 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
925 }
926 GNUNET_STATISTICS_update (stats,
927 gettext_noop
928 ("# SET_KEY messages deferred (need public key)"),
929 -1, GNUNET_NO);
930 send_key (n);
931 }
932 else
933 {
934#if DEBUG_CORE
935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
936 "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n",
937 GNUNET_i2s (&n->peer));
938#endif
939 GNUNET_STATISTICS_update (stats,
940 gettext_noop
941 ("# Delayed connecting due to lack of public key"),
942 1, GNUNET_NO);
943 if (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task)
944 n->retry_set_key_task =
945 GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
946 &set_key_retry_task, n);
947 }
948 return;
949 }
950
951#if DEBUG_CORE
952 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entered `%s' for peer `%4s'\n",
953 "process_hello_retry_send_key", GNUNET_i2s (peer));
954#endif
955 if (n->public_key != NULL)
956 {
957 /* already have public key, why are we here? */
958 GNUNET_break (0);
959 return;
960 }
961
962#if DEBUG_CORE
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Received new `%s' message for `%4s', initiating key exchange.\n",
965 "HELLO", GNUNET_i2s (peer));
966#endif
967 n->public_key =
968 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
969 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
970 {
971 GNUNET_STATISTICS_update (stats,
972 gettext_noop
973 ("# Error extracting public key from HELLO"), 1,
974 GNUNET_NO);
975 GNUNET_free (n->public_key);
976 n->public_key = NULL;
977#if DEBUG_CORE
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
979 "GNUNET_HELLO_get_key returned awfully\n");
980#endif
981 return;
982 }
983} 915}
984 916
985 917
986/** 918/**
987 * Send our key (and encrypted PING) to the other peer. 919 * Send our key (and encrypted PING) to the other peer.
988 * 920 *
989 * @param n the other peer 921 * @param kx key exchange context
990 */ 922 */
991static void 923static void
992send_key (struct Neighbour *n) 924send_key (struct GSC_KeyExchangeInfo *kx)
993{ 925{
994 struct MessageEntry *pos;
995 struct SetKeyMessage *sm;
996 struct MessageEntry *me;
997 struct PingMessage pp;
998 struct PingMessage *pm;
999 struct GNUNET_CRYPTO_AesInitializationVector iv; 926 struct GNUNET_CRYPTO_AesInitializationVector iv;
1000 927
1001 if (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) 928 GNUNET_assert (kx->retry_set_key_task == GNUNET_SCHEDULER_NO_TASK);
1002 { 929 if (KX_STATE_UP == kx->status)
1003 GNUNET_SCHEDULER_cancel (n->retry_set_key_task); 930 return; /* nothing to do */
1004 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; 931 if (kx->public_key == NULL)
1005 }
1006 if (n->pitr != NULL)
1007 {
1008#if DEBUG_CORE
1009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010 "Key exchange in progress with `%4s'.\n",
1011 GNUNET_i2s (&n->peer));
1012#endif
1013 return; /* already in progress */
1014 }
1015 if (GNUNET_YES != n->is_connected)
1016 { 932 {
1017 GNUNET_STATISTICS_update (stats, 933 /* lookup public key, then try again */
1018 gettext_noop 934 kx->pitr =
1019 ("# Asking transport to connect (for SET_KEY)"), 935 GNUNET_PEERINFO_iterate (peerinfo, &kx->peer,
1020 1, GNUNET_NO); 936 GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */,
1021 GNUNET_TRANSPORT_try_connect (transport, &n->peer); 937 &process_hello, kx);
1022 return; 938 return;
1023 } 939 }
1024#if DEBUG_CORE
1025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1026 "Asked to perform key exchange with `%4s'.\n",
1027 GNUNET_i2s (&n->peer));
1028#endif
1029 if (n->public_key == NULL)
1030 {
1031 /* lookup n's public key, then try again */
1032#if DEBUG_CORE
1033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1034 "Lacking public key for `%4s', trying to obtain one (send_key).\n",
1035 GNUNET_i2s (&n->peer));
1036#endif
1037 GNUNET_assert (n->pitr == NULL);
1038 n->pitr =
1039 GNUNET_PEERINFO_iterate (peerinfo, &n->peer,
1040 GNUNET_TIME_relative_multiply
1041 (GNUNET_TIME_UNIT_SECONDS, 20),
1042 &process_hello_retry_send_key, n);
1043 return;
1044 }
1045 pos = n->encrypted_head;
1046 while (pos != NULL)
1047 {
1048 if (GNUNET_YES == pos->is_setkey)
1049 {
1050 if (pos->sender_status == n->status)
1051 {
1052#if DEBUG_CORE
1053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1054 "`%s' message for `%4s' queued already\n", "SET_KEY",
1055 GNUNET_i2s (&n->peer));
1056#endif
1057 goto trigger_processing;
1058 }
1059 GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, pos);
1060 GNUNET_free (pos);
1061#if DEBUG_CORE
1062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1063 "Removing queued `%s' message for `%4s', will create a new one\n",
1064 "SET_KEY", GNUNET_i2s (&n->peer));
1065#endif
1066 break;
1067 }
1068 pos = pos->next;
1069 }
1070 940
1071 /* update status */ 941 /* update status */
1072 switch (n->status) 942 switch (n->status)
1073 { 943 {
1074 case PEER_STATE_DOWN: 944 case KX_STATE_DOWN:
1075 n->status = PEER_STATE_KEY_SENT; 945 n->status = PEER_STATE_KEY_SENT;
1076 break; 946 /* setup SET KEY message */
1077 case PEER_STATE_KEY_SENT: 947 setup_fresh_set_key (kx);
948 setup_fresh_ping (kx);
949 GNUNET_STATISTICS_update (stats,
950 gettext_noop
951 ("# SET_KEY and PING messages created"), 1,
952 GNUNET_NO);
1078 break; 953 break;
1079 case PEER_STATE_KEY_RECEIVED: 954 case KX_STATE_KEY_SENT:
1080 break; 955 break;
1081 case PEER_STATE_KEY_CONFIRMED: 956 case KX_STATE_KEY_RECEIVED:
1082 break; 957 break;
958 case KX_STATE_KEY_CONFIRMED:
959 GNUNET_break (0);
960 return;
1083 default: 961 default:
1084 GNUNET_break (0); 962 GNUNET_break (0);
1085 break;
1086 }
1087
1088
1089 /* first, set key message */
1090 me = GNUNET_malloc (sizeof (struct MessageEntry) +
1091 sizeof (struct SetKeyMessage) +
1092 sizeof (struct PingMessage));
1093 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_SET_KEY_DELAY);
1094 me->priority = SET_KEY_PRIORITY;
1095 me->size = sizeof (struct SetKeyMessage) + sizeof (struct PingMessage);
1096 me->is_setkey = GNUNET_YES;
1097 me->got_slack = GNUNET_YES; /* do not defer this one! */
1098 me->sender_status = n->status;
1099 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head, n->encrypted_tail,
1100 n->encrypted_tail, me);
1101 sm = (struct SetKeyMessage *) &me[1];
1102 sm->header.size = htons (sizeof (struct SetKeyMessage));
1103 sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY);
1104 sm->sender_status =
1105 htonl ((int32_t)
1106 ((n->status ==
1107 PEER_STATE_DOWN) ? PEER_STATE_KEY_SENT : n->status));
1108 sm->purpose.size =
1109 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1110 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1111 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) +
1112 sizeof (struct GNUNET_PeerIdentity));
1113 sm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY);
1114 sm->creation_time = GNUNET_TIME_absolute_hton (n->encrypt_key_created);
1115 sm->target = n->peer;
1116 GNUNET_assert (GNUNET_OK ==
1117 GNUNET_CRYPTO_rsa_encrypt (&n->encrypt_key,
1118 sizeof (struct
1119 GNUNET_CRYPTO_AesSessionKey),
1120 n->public_key, &sm->encrypted_key));
1121 GNUNET_assert (GNUNET_OK ==
1122 GNUNET_CRYPTO_rsa_sign (my_private_key, &sm->purpose,
1123 &sm->signature));
1124 pm = (struct PingMessage *) &sm[1];
1125 pm->header.size = htons (sizeof (struct PingMessage));
1126 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1127 pm->iv_seed =
1128 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
1129 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1130 pp.challenge = n->ping_challenge;
1131 pp.target = n->peer;
1132#if DEBUG_HANDSHAKE
1133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1134 "Encrypting `%s' and `%s' messages with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1135 "SET_KEY", "PING", (unsigned int) n->ping_challenge,
1136 GNUNET_i2s (&n->peer), (unsigned int) n->encrypt_key.crc32,
1137 GNUNET_CRYPTO_crc32_n (&iv, sizeof (iv)), pm->iv_seed);
1138#endif
1139 do_encrypt (n, &iv, &pp.target, &pm->target,
1140 sizeof (struct PingMessage) - ((void *) &pm->target -
1141 (void *) pm));
1142 GNUNET_STATISTICS_update (stats,
1143 gettext_noop
1144 ("# SET_KEY and PING messages created"), 1,
1145 GNUNET_NO);
1146#if DEBUG_CORE
1147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148 "Have %llu ms left for `%s' transmission.\n",
1149 (unsigned long long)
1150 GNUNET_TIME_absolute_get_remaining (me->deadline).rel_value,
1151 "SET_KEY");
1152#endif
1153trigger_processing:
1154 /* trigger queue processing */
1155 process_encrypted_neighbour_queue (n);
1156 if ((n->status != PEER_STATE_KEY_CONFIRMED) &&
1157 (GNUNET_SCHEDULER_NO_TASK == n->retry_set_key_task))
1158 n->retry_set_key_task =
1159 GNUNET_SCHEDULER_add_delayed (n->set_key_retry_frequency,
1160 &set_key_retry_task, n);
1161}
1162
1163
1164/**
1165 * We received a SET_KEY message. Validate and update
1166 * our key material and status.
1167 *
1168 * @param n the neighbour from which we received message m
1169 * @param m the set key message we received
1170 * @param ats performance data
1171 * @param ats_count number of entries in ats (excluding 0-termination)
1172 */
1173static void
1174handle_set_key (struct Neighbour *n, const struct SetKeyMessage *m,
1175 const struct GNUNET_TRANSPORT_ATS_Information *ats,
1176 uint32_t ats_count);
1177
1178
1179
1180/**
1181 * PEERINFO is giving us a HELLO for a peer. Add the public key to
1182 * the neighbour's struct and retry handling the set_key message. Or,
1183 * if we did not get a HELLO, just free the set key message.
1184 *
1185 * @param cls pointer to the set key message
1186 * @param peer the peer for which this is the HELLO
1187 * @param hello HELLO message of that peer
1188 * @param err_msg NULL if successful, otherwise contains error message
1189 */
1190static void
1191process_hello_retry_handle_set_key (void *cls,
1192 const struct GNUNET_PeerIdentity *peer,
1193 const struct GNUNET_HELLO_Message *hello,
1194 const char *err_msg)
1195{
1196 struct Neighbour *n = cls;
1197 struct SetKeyMessage *sm = n->skm;
1198
1199 if (err_msg != NULL)
1200 {
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1202 _("Error in communication with PEERINFO service\n"));
1203 /* return; */
1204 }
1205
1206 if (peer == NULL)
1207 {
1208 n->skm = NULL;
1209 n->pitr = NULL;
1210 if (n->public_key != NULL)
1211 {
1212#if DEBUG_CORE
1213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 "Received `%s' for `%4s', continuing processing of `%s' message.\n",
1215 "HELLO", GNUNET_i2s (&n->peer), "SET_KEY");
1216#endif
1217 handle_set_key (n, sm, NULL, 0);
1218 }
1219 else
1220 {
1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1222 _
1223 ("Ignoring `%s' message due to lack of public key for peer `%4s' (failed to obtain one).\n"),
1224 "SET_KEY", GNUNET_i2s (&n->peer));
1225 }
1226 GNUNET_free (sm);
1227 return; 963 return;
1228 } 964 }
1229 if (n->public_key != NULL)
1230 return; /* multiple HELLOs match!? */
1231 n->public_key =
1232 GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1233 if (GNUNET_OK != GNUNET_HELLO_get_key (hello, n->public_key))
1234 {
1235 GNUNET_break_op (0);
1236 GNUNET_free (n->public_key);
1237 n->public_key = NULL;
1238 }
1239}
1240
1241
1242 965
1243/** 966 /* always update sender status in SET KEY message */
1244 * Task that will retry "send_key" if our previous attempt failed 967 kx->skm.sender_status = htonl ((int32_t) kx->status);
1245 * to yield a PONG.
1246 */
1247static void
1248set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1249{
1250 struct Neighbour *n = cls;
1251 968
1252#if DEBUG_CORE 969 GDS_NEIGHBOURS_transmit (&kx->peer,
1253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrying key transmission to `%4s'\n", 970 &kx->skm.header,
1254 GNUNET_i2s (&n->peer)); 971 kx->set_key_retry_frequency);
1255#endif 972 GDS_NEIGHBOURS_transmit (&kx->peer,
1256 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; 973 &kx->ping.header,
1257 n->set_key_retry_frequency = 974 kx->set_key_retry_frequency);
1258 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2); 975 kx->retry_set_key_task =
1259 send_key (n); 976 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
977 &set_key_retry_task, kx);
1260} 978}
1261 979
1262 980
@@ -1264,71 +982,53 @@ set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1264 * Encrypt and transmit a message with the given payload. 982 * Encrypt and transmit a message with the given payload.
1265 * 983 *
1266 * @param kx key exchange context 984 * @param kx key exchange context
985 * @param bw_in bandwidth limit to transmit to the other peer;
986 * the other peer shall not send us more than the
987 * given rate
1267 * @param payload payload of the message 988 * @param payload payload of the message
1268 * @param payload_size number of bytes in 'payload' 989 * @param payload_size number of bytes in 'payload'
1269 */ 990 */
1270void 991void
1271GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, 992GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
993 struct GNUNET_BANDWIDTH_Value32NBO bw_in,
1272 const void *payload, 994 const void *payload,
1273 size_t payload_size) 995 size_t payload_size)
1274{ 996{
1275 char pbuf[GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE + sizeof (struct EncryptedMessage)]; /* plaintext */ 997 size_t used = payload_size + sizeof (struct EncryptedMessage);
1276 size_t used; 998 char pbuf[used]; /* plaintext */
999 char cbuf[used]; /* ciphertext */
1277 struct EncryptedMessage *em; /* encrypted message */ 1000 struct EncryptedMessage *em; /* encrypted message */
1278 struct EncryptedMessage *ph; /* plaintext header */ 1001 struct EncryptedMessage *ph; /* plaintext header */
1279 struct MessageEntry *me;
1280 unsigned int priority;
1281 struct GNUNET_TIME_Absolute deadline;
1282 struct GNUNET_TIME_Relative retry_time;
1283 struct GNUNET_CRYPTO_AesInitializationVector iv; 1002 struct GNUNET_CRYPTO_AesInitializationVector iv;
1284 struct GNUNET_CRYPTO_AuthKey auth_key; 1003 struct GNUNET_CRYPTO_AuthKey auth_key;
1285 1004
1286#if DEBUG_CORE_QUOTA 1005#if DEBUG_CORE_QUOTA
1287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1288 "Sending %u b/s as new limit to peer `%4s'\n", 1007 "Sending %u b/s as new limit to peer `%4s'\n",
1289 (unsigned int) ntohl (n->bw_in.value__), GNUNET_i2s (&n->peer)); 1008 (unsigned int) ntohl (bw_in.value__),
1009 GNUNET_i2s (&kx->peer));
1290#endif 1010#endif
1011 ph = (struct EncryptedMessage*) pbuf;
1291 ph->iv_seed = 1012 ph->iv_seed =
1292 htonl (GNUNET_CRYPTO_random_u32 1013 htonl (GNUNET_CRYPTO_random_u32
1293 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); 1014 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
1294 ph->sequence_number = htonl (++n->last_sequence_number_sent); 1015 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1295 ph->inbound_bw_limit = n->bw_in; 1016 ph->inbound_bw_limit = bw_in;
1296 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 1017 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1018 memcpy (&ph[1], payload, payload_size);
1297 1019
1298 /* setup encryption message header */ 1020 em = (struct EncryptedMessage *) cbuf;
1299 me = GNUNET_malloc (sizeof (struct MessageEntry) + used);
1300 me->deadline = deadline;
1301 me->priority = priority;
1302 me->size = used;
1303 em = (struct EncryptedMessage *) &me[1];
1304 em->header.size = htons (used); 1021 em->header.size = htons (used);
1305 em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE); 1022 em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1306 em->iv_seed = ph->iv_seed; 1023 em->iv_seed = ph->iv_seed;
1307 derive_iv (&iv, &n->encrypt_key, ph->iv_seed, &n->peer); 1024 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, &kx->peer);
1308 /* encrypt */
1309#if DEBUG_HANDSHAKE
1310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1311 "Encrypting %u bytes of plaintext messages for `%4s' for transmission in %llums.\n",
1312 (unsigned int) used - ENCRYPTED_HEADER_SIZE,
1313 GNUNET_i2s (&n->peer),
1314 (unsigned long long)
1315 GNUNET_TIME_absolute_get_remaining (deadline).rel_value);
1316#endif
1317 GNUNET_assert (GNUNET_OK == 1025 GNUNET_assert (GNUNET_OK ==
1318 do_encrypt (n, &iv, &ph->sequence_number, &em->sequence_number, 1026 do_encrypt (kx, &iv, &ph->sequence_number, &em->sequence_number,
1319 used - ENCRYPTED_HEADER_SIZE)); 1027 used - ENCRYPTED_HEADER_SIZE));
1320 derive_auth_key (&auth_key, &n->encrypt_key, ph->iv_seed, 1028 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed,
1321 n->encrypt_key_created); 1029 kx->encrypt_key_created);
1322 GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number, 1030 GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number,
1323 used - ENCRYPTED_HEADER_SIZE, &em->hmac); 1031 used - ENCRYPTED_HEADER_SIZE, &em->hmac);
1324#if DEBUG_HANDSHAKE
1325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1326 "Authenticated %u bytes of ciphertext %u: `%s'\n",
1327 used - ENCRYPTED_HEADER_SIZE,
1328 GNUNET_CRYPTO_crc32_n (&em->sequence_number,
1329 used - ENCRYPTED_HEADER_SIZE),
1330 GNUNET_h2s (&em->hmac));
1331#endif
1332 GDS_NEIGHBOURS_transmit (&kx->peer, 1032 GDS_NEIGHBOURS_transmit (&kx->peer,
1333 &em->header, 1033 &em->header,
1334 GNUNET_TIME_UNIT_FOREVER_REL); 1034 GNUNET_TIME_UNIT_FOREVER_REL);
@@ -1336,19 +1036,39 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1336 1036
1337 1037
1338/** 1038/**
1039 * We've seen a valid message from the other peer.
1040 * Update the time when the session would time out
1041 * and delay sending our keep alive message further.
1042 *
1043 * @param kx key exchange where we saw activity
1044 */
1045static void
1046update_timeout (struct GSC_KeyExchangeInfo *kx)
1047{
1048 kx->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1049 if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1050 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1051 kx->keep_alive_task =
1052 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1053 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1054 2), &send_keep_alive, kx);
1055}
1056
1057
1058/**
1339 * We received an encrypted message. Decrypt, validate and 1059 * We received an encrypted message. Decrypt, validate and
1340 * pass on to the appropriate clients. 1060 * pass on to the appropriate clients.
1341 * 1061 *
1342 * @param n target of the message 1062 * @param n target of the message
1343 * @param m encrypted message 1063 * @param m encrypted message
1344 * @param ats performance data 1064 * @param atsi performance data
1345 * @param ats_count number of entries in ats (excluding 0-termination) 1065 * @param atsi_count number of entries in ats (excluding 0-termination)
1346 */ 1066 */
1347void 1067void
1348GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *n, 1068GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *n,
1349 const struct GNUNET_MessageHeader *msg, 1069 const struct GNUNET_MessageHeader *msg,
1350 const struct GNUNET_TRANSPORT_ATS_Information *ats, 1070 const struct GNUNET_TRANSPORT_ATS_Information *atsi,
1351 uint32_t ats_count) 1071 uint32_t atsi_count)
1352{ 1072{
1353 const struct EncryptedMessage *m; 1073 const struct EncryptedMessage *m;
1354 char buf[size]; 1074 char buf[size];
@@ -1362,86 +1082,68 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *n,
1362 1082
1363 if (size < 1083 if (size <
1364 sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader)) 1084 sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader))
1365 { 1085 {
1366 GNUNET_break_op (0); 1086 GNUNET_break_op (0);
1367 return; 1087 return;
1368 } 1088 }
1369 m = (const struct EncryptedMessage*) msg; 1089 m = (const struct EncryptedMessage*) msg;
1370#if FIXME 1090 if ( (kx->status != KX_STATE_KEY_RECEIVED) &&
1371 if ((n->status != PEER_STATE_KEY_RECEIVED) && 1091 (kx->status != KX_STATE_UP) )
1372 (n->status != PEER_STATE_KEY_CONFIRMED)) 1092 {
1373 { 1093 GNUNET_STATISTICS_update (stats,
1374 GNUNET_STATISTICS_update (stats, 1094 gettext_noop
1375 gettext_noop 1095 ("# failed to decrypt message (no session key)"),
1376 ("# failed to decrypt message (no session key)"), 1096 1, GNUNET_NO);
1377 1, GNUNET_NO); 1097 return;
1378 send_key (n); 1098 }
1379 return;
1380 }
1381#endif
1382
1383#if DEBUG_CORE
1384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1385 "Core service receives `%s' request from `%4s'.\n",
1386 "ENCRYPTED_MESSAGE", GNUNET_i2s (&n->peer));
1387#endif
1388 /* validate hash */ 1099 /* validate hash */
1389 derive_auth_key (&auth_key, &n->decrypt_key, m->iv_seed, 1100 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed,
1390 n->decrypt_key_created); 1101 kx->decrypt_key_created);
1391 GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number, 1102 GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number,
1392 size - ENCRYPTED_HEADER_SIZE, &ph); 1103 size - ENCRYPTED_HEADER_SIZE, &ph);
1393#if DEBUG_HANDSHAKE
1394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1395 "Re-Authenticated %u bytes of ciphertext (`%u'): `%s'\n",
1396 (unsigned int) size - ENCRYPTED_HEADER_SIZE,
1397 GNUNET_CRYPTO_crc32_n (&m->sequence_number,
1398 size - ENCRYPTED_HEADER_SIZE),
1399 GNUNET_h2s (&ph));
1400#endif
1401
1402 if (0 != memcmp (&ph, &m->hmac, sizeof (GNUNET_HashCode))) 1104 if (0 != memcmp (&ph, &m->hmac, sizeof (GNUNET_HashCode)))
1403 { 1105 {
1404 /* checksum failed */ 1106 /* checksum failed */
1405 GNUNET_break_op (0); 1107 GNUNET_break_op (0);
1406 return; 1108 return;
1407 } 1109 }
1408 derive_iv (&iv, &n->decrypt_key, m->iv_seed, &my_identity); 1110 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1409 /* decrypt */ 1111 /* decrypt */
1410 if (GNUNET_OK != 1112 if (GNUNET_OK !=
1411 do_decrypt (n, &iv, &m->sequence_number, &buf[ENCRYPTED_HEADER_SIZE], 1113 do_decrypt (kx, &iv, &m->sequence_number, &buf[ENCRYPTED_HEADER_SIZE],
1412 size - ENCRYPTED_HEADER_SIZE)) 1114 size - ENCRYPTED_HEADER_SIZE))
1413 return; 1115 return;
1414 pt = (struct EncryptedMessage *) buf; 1116 pt = (struct EncryptedMessage *) buf;
1415 1117
1416 /* validate sequence number */ 1118 /* validate sequence number */
1417 snum = ntohl (pt->sequence_number); 1119 snum = ntohl (pt->sequence_number);
1418 if (n->last_sequence_number_received == snum) 1120 if (kx->last_sequence_number_received == snum)
1419 { 1121 {
1420 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1122 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1421 "Received duplicate message, ignoring.\n"); 1123 "Received duplicate message, ignoring.\n");
1422 /* duplicate, ignore */ 1124 /* duplicate, ignore */
1423 GNUNET_STATISTICS_update (stats, 1125 GNUNET_STATISTICS_update (GSC_stats,
1424 gettext_noop ("# bytes dropped (duplicates)"), 1126 gettext_noop ("# bytes dropped (duplicates)"),
1425 size, GNUNET_NO); 1127 size, GNUNET_NO);
1426 return; 1128 return;
1427 } 1129 }
1428 if ((n->last_sequence_number_received > snum) && 1130 if ((kx->last_sequence_number_received > snum) &&
1429 (n->last_sequence_number_received - snum > 32)) 1131 (kx->last_sequence_number_received - snum > 32))
1430 { 1132 {
1431 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1133 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1432 "Received ancient out of sequence message, ignoring.\n"); 1134 "Received ancient out of sequence message, ignoring.\n");
1433 /* ancient out of sequence, ignore */ 1135 /* ancient out of sequence, ignore */
1434 GNUNET_STATISTICS_update (stats, 1136 GNUNET_STATISTICS_update (GSC_stats,
1435 gettext_noop 1137 gettext_noop
1436 ("# bytes dropped (out of sequence)"), size, 1138 ("# bytes dropped (out of sequence)"), size,
1437 GNUNET_NO); 1139 GNUNET_NO);
1438 return; 1140 return;
1439 } 1141 }
1440 if (n->last_sequence_number_received > snum) 1142 if (kx->last_sequence_number_received > snum)
1441 { 1143 {
1442 unsigned int rotbit = 1 << (n->last_sequence_number_received - snum - 1); 1144 unsigned int rotbit = 1 << (kx->last_sequence_number_received - snum - 1);
1443 1145
1444 if ((n->last_packets_bitmap & rotbit) != 0) 1146 if ((kx->last_packets_bitmap & rotbit) != 0)
1445 { 1147 {
1446 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1148 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1447 "Received duplicate message, ignoring.\n"); 1149 "Received duplicate message, ignoring.\n");
@@ -1451,17 +1153,17 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *n,
1451 /* duplicate, ignore */ 1153 /* duplicate, ignore */
1452 return; 1154 return;
1453 } 1155 }
1454 n->last_packets_bitmap |= rotbit; 1156 kx->last_packets_bitmap |= rotbit;
1455 } 1157 }
1456 if (n->last_sequence_number_received < snum) 1158 if (kx->last_sequence_number_received < snum)
1457 { 1159 {
1458 int shift = (snum - n->last_sequence_number_received); 1160 unsigned int shift = (snum - kx->last_sequence_number_received);
1459 1161
1460 if (shift >= 8 * sizeof (n->last_packets_bitmap)) 1162 if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1461 n->last_packets_bitmap = 0; 1163 kx->last_packets_bitmap = 0;
1462 else 1164 else
1463 n->last_packets_bitmap <<= shift; 1165 kx->last_packets_bitmap <<= shift;
1464 n->last_sequence_number_received = snum; 1166 kx->last_sequence_number_received = snum;
1465 } 1167 }
1466 1168
1467 /* check timestamp */ 1169 /* check timestamp */
@@ -1480,104 +1182,49 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *n,
1480 } 1182 }
1481 1183
1482 /* process decrypted message(s) */ 1184 /* process decrypted message(s) */
1483 if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__) 1185 update_timeout (kx);
1484 { 1186 GSC_SESSIONS_update (&kx->peer,
1485#if DEBUG_CORE_SET_QUOTA 1187 pt->inbound_bw_limit,
1486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1188 atsi, atsi_count); // FIXME: does 'SESSIONS' need atsi!?
1487 "Received %u b/s as new inbound limit for peer `%4s'\n",
1488 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
1489 GNUNET_i2s (&n->peer));
1490#endif
1491 n->bw_out_external_limit = pt->inbound_bw_limit;
1492 n->bw_out =
1493 GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
1494 n->bw_out_internal_limit);
1495 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
1496 n->bw_out);
1497 GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out);
1498 }
1499 n->last_activity = GNUNET_TIME_absolute_get ();
1500 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1501 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1502 n->keep_alive_task =
1503 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1504 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1505 2), &send_keep_alive, n);
1506 GNUNET_STATISTICS_update (stats, 1189 GNUNET_STATISTICS_update (stats,
1507 gettext_noop ("# bytes of payload decrypted"), 1190 gettext_noop ("# bytes of payload decrypted"),
1508 size - sizeof (struct EncryptedMessage), GNUNET_NO); 1191 size - sizeof (struct EncryptedMessage), GNUNET_NO);
1509 handle_peer_status_change (n);
1510 update_neighbour_performance (n, ats, ats_count);
1511 if (GNUNET_OK != 1192 if (GNUNET_OK !=
1512 GNUNET_SERVER_mst_receive (mst, n, &buf[sizeof (struct EncryptedMessage)], 1193 GNUNET_SERVER_mst_receive (mst, kx, &buf[sizeof (struct EncryptedMessage)],
1513 size - sizeof (struct EncryptedMessage), 1194 size - sizeof (struct EncryptedMessage),
1514 GNUNET_YES, GNUNET_NO)) 1195 GNUNET_YES, GNUNET_NO))
1515 GNUNET_break_op (0); 1196 GNUNET_break_op (0);
1516} 1197}
1517 1198
1518 1199
1200
1201
1519/** 1202/**
1520 * Task triggered when a neighbour entry is about to time out 1203 * Deliver P2P message to interested clients.
1521 * (and we should prevent this by sending a PING).
1522 * 1204 *
1523 * @param cls the 'struct Neighbour' 1205 * @param cls always NULL
1524 * @param tc scheduler context (not used) 1206 * @param client who sent us the message (struct GSC_KeyExchangeInfo)
1207 * @param m the message
1525 */ 1208 */
1526static void 1209static void
1527send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1210deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m)
1528{ 1211{
1529 struct Neighbour *n = cls; 1212 struct GSC_KeyExchangeInfo *kx = client;
1530 struct GNUNET_TIME_Relative retry; 1213
1531 struct GNUNET_TIME_Relative left; 1214 // FIXME (need to check stuff, need ATSI, etc.)
1532 struct MessageEntry *me; 1215 // FIXME: does clients work properly if never called with option 'NOTHING'!?
1533 struct PingMessage pp; 1216 GSC_CLIENTS_deliver_message (&kx->peer,
1534 struct PingMessage *pm; 1217 NULL, 0, // kx->atsi...
1535 struct GNUNET_CRYPTO_AesInitializationVector iv; 1218 m,
1536 1219 ntohs (m->size),
1537 n->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; 1220 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
1538 /* send PING */ 1221 GSC_CLIENTS_deliver_message (&kx->peer,
1539 me = GNUNET_malloc (sizeof (struct MessageEntry) + 1222 NULL, 0, // kx->atsi...
1540 sizeof (struct PingMessage)); 1223 m,
1541 me->deadline = GNUNET_TIME_relative_to_absolute (MAX_PING_DELAY); 1224 sizeof (struct GNUNET_MessageHeader),
1542 me->priority = PING_PRIORITY; 1225 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
1543 me->size = sizeof (struct PingMessage);
1544 GNUNET_CONTAINER_DLL_insert_after (n->encrypted_head, n->encrypted_tail,
1545 n->encrypted_tail, me);
1546 pm = (struct PingMessage *) &me[1];
1547 pm->header.size = htons (sizeof (struct PingMessage));
1548 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
1549 pm->iv_seed =
1550 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
1551 derive_iv (&iv, &n->encrypt_key, pm->iv_seed, &n->peer);
1552 pp.challenge = n->ping_challenge;
1553 pp.target = n->peer;
1554#if DEBUG_HANDSHAKE
1555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1556 "Encrypting `%s' message with challenge %u for `%4s' using key %u, IV %u (salt %u).\n",
1557 "PING", (unsigned int) n->ping_challenge, GNUNET_i2s (&n->peer),
1558 (unsigned int) n->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (&iv,
1559 sizeof
1560 (iv)),
1561 pm->iv_seed);
1562#endif
1563 do_encrypt (n, &iv, &pp.target, &pm->target,
1564 sizeof (struct PingMessage) - ((void *) &pm->target -
1565 (void *) pm));
1566 process_encrypted_neighbour_queue (n);
1567 /* reschedule PING job */
1568 left = GNUNET_TIME_absolute_get_remaining (get_neighbour_timeout (n));
1569 retry =
1570 GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1571 MIN_PING_FREQUENCY);
1572 n->keep_alive_task =
1573 GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, n);
1574
1575} 1226}
1576 1227
1577
1578
1579
1580
1581/** 1228/**
1582 * Initialize KX subsystem. 1229 * Initialize KX subsystem.
1583 * 1230 *
@@ -1616,6 +1263,7 @@ GSC_KX_init ()
1616 my_private_key = NULL; 1263 my_private_key = NULL;
1617 return GNUNET_SYSERR; 1264 return GNUNET_SYSERR;
1618 } 1265 }
1266 mst = GNUNET_SERVER_mst_create (&deliver_message, NULL);
1619 return GNUNET_OK; 1267 return GNUNET_OK;
1620} 1268}
1621 1269
@@ -1632,10 +1280,15 @@ GSC_KX_done ()
1632 my_private_key = NULL; 1280 my_private_key = NULL;
1633 } 1281 }
1634 if (peerinfo != NULL) 1282 if (peerinfo != NULL)
1635 { 1283 {
1636 GNUNET_PEERINFO_disconnect (peerinfo); 1284 GNUNET_PEERINFO_disconnect (peerinfo);
1637 peerinfo = NULL; 1285 peerinfo = NULL;
1638 } 1286 }
1287 if (mst != NULL)
1288 {
1289 GNUNET_SERVER_mst_destroy (mst);
1290 mst = NULL;
1291 }
1639} 1292}
1640 1293
1641/* end of gnunet-service-core_kx.c */ 1294/* end of gnunet-service-core_kx.c */
diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h
index 104aed5e4..071665a19 100644
--- a/src/core/gnunet-service-core_kx.h
+++ b/src/core/gnunet-service-core_kx.h
@@ -30,16 +30,76 @@
30 30
31 31
32/** 32/**
33 * State machine for our P2P encryption handshake. Everyone starts in
34 * "DOWN", if we receive the other peer's key (other peer initiated)
35 * we start in state RECEIVED (since we will immediately send our
36 * own); otherwise we start in SENT. If we get back a PONG from
37 * within either state, we move up to CONFIRMED (the PONG will always
38 * be sent back encrypted with the key we sent to the other peer).
39 */
40enum KxStateMachine
41{
42 /**
43 * No handshake yet.
44 */
45 KX_STATE_DOWN,
46
47 /**
48 * We've sent our session key.
49 */
50 KX_STATE_KEY_SENT,
51
52 /**
53 * We've received the other peers session key.
54 */
55 KX_STATE_KEY_RECEIVED,
56
57 /**
58 * The other peer has confirmed our session key with a message
59 * encrypted with his session key (which we got). Key exchange
60 * is done.
61 */
62 KX_STATE_UP
63};
64
65
66/**
33 * Information about the status of a key exchange with another peer. 67 * Information about the status of a key exchange with another peer.
34 */ 68 */
35struct GSC_KeyExchangeInfo 69struct GSC_KeyExchangeInfo
36{ 70{
71 /**
72 * Identity of the peer.
73 */
74 struct GNUNET_PeerIdentity peer;
37 75
38 /** 76 /**
39 * SetKeyMessage to transmit, NULL if we are not currently trying 77 * SetKeyMessage to transmit (initialized the first
40 * to send one. 78 * time our status goes past 'KX_STATE_KEY_SENT').
41 */ 79 */
42 struct SetKeyMessage *skm; 80 struct SetKeyMessage skm;
81
82 /**
83 * PING message we transmit to the other peer.
84 */
85 struct PingMessage ping;
86
87 /**
88 * SetKeyMessage we received and did not process yet.
89 */
90 struct SetKeyMessage *skm_received;
91
92 /**
93 * PING message we received from the other peer and
94 * did not process yet (or NULL).
95 */
96 struct PingMessage *ping_received;
97
98 /**
99 * PONG message we received from the other peer and
100 * did not process yet (or NULL).
101 */
102 struct PongMessage *pong_received;
43 103
44 /** 104 /**
45 * Non-NULL if we are currently looking up HELLOs for this peer. 105 * Non-NULL if we are currently looking up HELLOs for this peer.
@@ -53,13 +113,6 @@ struct GSC_KeyExchangeInfo
53 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key; 113 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key;
54 114
55 /** 115 /**
56 * We received a PING message before we got the "public_key"
57 * (or the SET_KEY). We keep it here until we have a key
58 * to decrypt it. NULL if no PING is pending.
59 */
60 struct PingMessage *pending_ping;
61
62 /**
63 * We received a PONG message before we got the "public_key" 116 * We received a PONG message before we got the "public_key"
64 * (or the SET_KEY). We keep it here until we have a key 117 * (or the SET_KEY). We keep it here until we have a key
65 * to decrypt it. NULL if no PONG is pending. 118 * to decrypt it. NULL if no PONG is pending.
@@ -89,6 +142,11 @@ struct GSC_KeyExchangeInfo
89 struct GNUNET_TIME_Absolute decrypt_key_created; 142 struct GNUNET_TIME_Absolute decrypt_key_created;
90 143
91 /** 144 /**
145 * When should the session time out (if there are no PONGs)?
146 */
147 struct GNUNET_TIME_Absolute timeout;
148
149 /**
92 * At what frequency are we currently re-trying SET_KEY messages? 150 * At what frequency are we currently re-trying SET_KEY messages?
93 */ 151 */
94 struct GNUNET_TIME_Relative set_key_retry_frequency; 152 struct GNUNET_TIME_Relative set_key_retry_frequency;
@@ -111,7 +169,7 @@ struct GSC_KeyExchangeInfo
111 /** 169 /**
112 * What is our connection status? 170 * What is our connection status?
113 */ 171 */
114 enum PeerStateMachine status; 172 enum KxStateMachine status;
115 173
116}; 174};
117 175
@@ -122,14 +180,10 @@ struct GSC_KeyExchangeInfo
122 * 180 *
123 * @param kx key exchange status for the corresponding peer 181 * @param kx key exchange status for the corresponding peer
124 * @param msg the set key message we received 182 * @param msg the set key message we received
125 * @param ats performance data
126 * @param ats_count number of entries in ats (excluding 0-termination)
127 */ 183 */
128void 184void
129GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n, 185GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx,
130 const struct GNUNET_MessageHandler *msg, 186 const struct GNUNET_MessageHandler *msg);
131 const struct GNUNET_TRANSPORT_ATS_Information *ats,
132 uint32_t ats_count);
133 187
134 188
135/** 189/**
@@ -138,14 +192,10 @@ GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *n,
138 * 192 *
139 * @param kx key exchange status for the corresponding peer 193 * @param kx key exchange status for the corresponding peer
140 * @param msg the encrypted PING message itself 194 * @param msg the encrypted PING message itself
141 * @param ats performance data
142 * @param ats_count number of entries in ats (excluding 0-termination)
143 */ 195 */
144void 196void
145GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, 197GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx,
146 const struct GNUNET_MessageHeader *msg, 198 const struct GNUNET_MessageHeader *msg);
147 const struct GNUNET_TRANSPORT_ATS_Information *ats,
148 uint32_t ats_count);
149 199
150 200
151/** 201/**
@@ -153,25 +203,25 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx,
153 * 203 *
154 * @param kx key exchange status for the corresponding peer 204 * @param kx key exchange status for the corresponding peer
155 * @param msg the encrypted PONG message itself 205 * @param msg the encrypted PONG message itself
156 * @param ats performance data
157 * @param ats_count number of entries in ats (excluding 0-termination)
158 */ 206 */
159void 207void
160GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, 208GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx,
161 const struct GNUNET_MessageHeader *msg, 209 const struct GNUNET_MessageHeader *msg);
162 const struct GNUNET_TRANSPORT_ATS_Information *ats,
163 uint32_t ats_count);
164 210
165 211
166/** 212/**
167 * Encrypt and transmit a message with the given payload. 213 * Encrypt and transmit a message with the given payload.
168 * 214 *
169 * @param kx key exchange context 215 * @param kx key exchange context
216 * @param bw_in bandwidth limit to transmit to the other peer;
217 * the other peer shall not send us more than the
218 * given rate
170 * @param payload payload of the message 219 * @param payload payload of the message
171 * @param payload_size number of bytes in 'payload' 220 * @param payload_size number of bytes in 'payload'
172 */ 221 */
173void 222void
174GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, 223GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
224 struct GNUNET_BANDWIDTH_Value32NBO bw_in,
175 const void *payload, 225 const void *payload,
176 size_t payload_size); 226 size_t payload_size);
177 227
@@ -182,14 +232,14 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
182 * 232 *
183 * @param kx key exchange information context 233 * @param kx key exchange information context
184 * @param msg encrypted message 234 * @param msg encrypted message
185 * @param ats performance data 235 * @param atsi performance data
186 * @param ats_count number of entries in ats (excluding 0-termination) 236 * @param atsi_count number of entries in ats (excluding 0-termination)
187 */ 237 */
188void 238void
189GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, 239GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx,
190 const struct GNUNET_MessageHeader *msg, 240 const struct GNUNET_MessageHeader *msg,
191 const struct GNUNET_TRANSPORT_ATS_Information *ats, 241 const struct GNUNET_TRANSPORT_ATS_Information *atsi,
192 uint32_t ats_count); 242 uint32_t atsi_count);
193 243
194 244
195/** 245/**
diff --git a/src/core/gnunet-service-core_neighbours.c b/src/core/gnunet-service-core_neighbours.c
index 8a0677c88..d78f696e6 100644
--- a/src/core/gnunet-service-core_neighbours.c
+++ b/src/core/gnunet-service-core_neighbours.c
@@ -428,13 +428,13 @@ handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
428 switch (type) 428 switch (type)
429 { 429 {
430 case GNUNET_MESSAGE_TYPE_CORE_SET_KEY: 430 case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
431 GSC_KX_handle_set_key (n->kxinfo, message, ats, ats_count); 431 GSC_KX_handle_set_key (n->kxinfo, message);
432 break; 432 break;
433 case GNUNET_MESSAGE_TYPE_CORE_PING: 433 case GNUNET_MESSAGE_TYPE_CORE_PING:
434 GSC_KX_handle_ping (n->kxinfo, message, ats, ats_count); 434 GSC_KX_handle_ping (n->kxinfo, message);
435 break; 435 break;
436 case GNUNET_MESSAGE_TYPE_CORE_PONG: 436 case GNUNET_MESSAGE_TYPE_CORE_PONG:
437 GSC_KX_handle_pong (n->kxinfo, message, ats, ats_count); 437 GSC_KX_handle_pong (n->kxinfo, message);
438 break; 438 break;
439 case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE: 439 case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
440 GSC_KX_handle_encrypted_message (peer, 440 GSC_KX_handle_encrypted_message (peer,
diff --git a/src/core/gnunet-service-core_neighbours.h b/src/core/gnunet-service-core_neighbours.h
index 8dad1aafe..36682770e 100644
--- a/src/core/gnunet-service-core_neighbours.h
+++ b/src/core/gnunet-service-core_neighbours.h
@@ -41,7 +41,7 @@
41 * @param timeout by when should the transmission be done? 41 * @param timeout by when should the transmission be done?
42 */ 42 */
43void 43void
44GDS_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target, 44GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
45 const struct GNUNET_MessageHeader *msg, 45 const struct GNUNET_MessageHeader *msg,
46 struct GNUNET_TIME_Relative timeout); 46 struct GNUNET_TIME_Relative timeout);
47 47
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
index b72a0e0b3..a2b662252 100644
--- a/src/core/gnunet-service-core_sessions.c
+++ b/src/core/gnunet-service-core_sessions.c
@@ -1123,11 +1123,7 @@ create_neighbour (const struct GNUNET_PeerIdentity *pid)
1123#endif 1123#endif
1124 n = GNUNET_malloc (sizeof (struct Neighbour)); 1124 n = GNUNET_malloc (sizeof (struct Neighbour));
1125 n->peer = *pid; 1125 n->peer = *pid;
1126 GNUNET_CRYPTO_aes_create_session_key (&n->encrypt_key); 1126 n->last_activity = GNUNET_TIME_absolute_get ();
1127 now = GNUNET_TIME_absolute_get ();
1128 n->encrypt_key_created = now;
1129 n->last_activity = now;
1130 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
1131 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; 1127 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
1132 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; 1128 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
1133 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX); 1129 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
@@ -1673,7 +1669,118 @@ GSC_SESSIONS_handle_client_request_info (void *cls, struct GNUNET_SERVER_Client
1673} 1669}
1674 1670
1675 1671
1672/**
1673 * Create a session, a key exchange was just completed.
1674 */
1675void
1676GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer)
1677{
1678 {
1679 struct GNUNET_MessageHeader *hdr;
1680
1681 hdr = compute_type_map_message ();
1682 send_type_map_to_neighbour (hdr, &n->peer.hashPubKey, n);
1683 GNUNET_free (hdr);
1684 }
1685 if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__)
1686 {
1687 n->bw_out_external_limit = t.inbound_bw_limit;
1688 n->bw_out =
1689 GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
1690 n->bw_out_internal_limit);
1691 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
1692 n->bw_out);
1693 GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out);
1694 }
1695#if DEBUG_CORE
1696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1697 "Confirmed key via `%s' message for peer `%4s'\n", "PONG",
1698 GNUNET_i2s (&n->peer));
1699#endif
1700
1701
1702 size =
1703 sizeof (struct ConnectNotifyMessage) +
1704 (n->ats_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1705 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1706 {
1707 GNUNET_break (0);
1708 /* recovery strategy: throw away performance data */
1709 GNUNET_array_grow (n->ats, n->ats_count, 0);
1710 size =
1711 sizeof (struct PeerStatusNotifyMessage) +
1712 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
1713 }
1714 cnm = (struct ConnectNotifyMessage *) buf;
1715 cnm->header.size = htons (size);
1716 cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
1717 cnm->ats_count = htonl (n->ats_count);
1718 cnm->peer = n->peer;
1719 mats = &cnm->ats;
1720 memcpy (mats, n->ats,
1721 n->ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
1722 mats[n->ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1723 mats[n->ats_count].value = htonl (0);
1724 send_to_all_clients (&cnm->header, GNUNET_NO,
1725 GNUNET_CORE_OPTION_SEND_CONNECT);
1726 process_encrypted_neighbour_queue (n);
1727 n->last_activity = GNUNET_TIME_absolute_get ();
1728
1729 if (n->status == PEER_STATE_KEY_CONFIRMED)
1730 {
1731 now = GNUNET_TIME_absolute_get ();
1732 n->last_activity = now;
1733 changed = GNUNET_YES;
1734 if (!up)
1735 {
1736 GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"),
1737 1, GNUNET_NO);
1738 n->time_established = now;
1739 }
1740 if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1741 GNUNET_SCHEDULER_cancel (n->keep_alive_task);
1742 n->keep_alive_task =
1743 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1744 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1745 2), &send_keep_alive, n);
1746 }
1747
1748
1749}
1750
1751
1752/**
1753 * Update information about a session.
1754 *
1755 * @param peer peer who's session should be updated
1756 * @param bw_out new outbound bandwidth limit for the peer
1757 * @param atsi performance information
1758 * @param atsi_count number of performance records supplied
1759 */
1760void
1761GSC_SESSIONS_update (const struct GNUNET_PeerIdentity *peer,
1762 struct GNUNET_BANDWIDTH_Value32NBO bw_out,
1763 const struct GNUNET_TRANSPORT_ATS_Information *atsi,
1764 uint32_t atsi_count)
1765{
1766 if (bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
1767 {
1768#if DEBUG_CORE_SET_QUOTA
1769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1770 "Received %u b/s as new inbound limit for peer `%4s'\n",
1771 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
1772 GNUNET_i2s (&n->peer));
1773#endif
1774 n->bw_out_external_limit = pt->inbound_bw_limit;
1775 n->bw_out =
1776 GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
1777 n->bw_out_internal_limit);
1778 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
1779 n->bw_out);
1780 GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out);
1781 }
1676 1782
1783}
1677 1784
1678 1785
1679/** 1786/**
diff --git a/src/core/gnunet-service-core_sessions.h b/src/core/gnunet-service-core_sessions.h
index fc5944cda..781398d44 100644
--- a/src/core/gnunet-service-core_sessions.h
+++ b/src/core/gnunet-service-core_sessions.h
@@ -147,6 +147,28 @@ GSC_SESSIONS_handle_client_request_info (void *cls, struct GNUNET_SERVER_Client
147 147
148 148
149/** 149/**
150 * Create a session, a key exchange was just completed.
151 */
152void
153GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer);
154
155/**
156 * Update information about a session.
157 *
158 * @param peer peer who's session should be updated
159 * @param bw_out new outbound bandwidth limit for the peer
160 * @param atsi performance information
161 * @param atsi_count number of performance records supplied
162 */
163void
164GSC_SESSIONS_update (const struct GNUNET_PeerIdentity *peer,
165 struct GNUNET_BANDWIDTH_Value32NBO bw_out,
166 const struct GNUNET_TRANSPORT_ATS_Information *atsi,
167 uint32_t atsi_count);
168
169
170
171/**
150 * Initialize sessions subsystem. 172 * Initialize sessions subsystem.
151 */ 173 */
152void 174void