aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-communicator-tcp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-01-28 05:50:12 +0100
committerChristian Grothoff <christian@grothoff.org>2019-01-28 05:50:12 +0100
commit64483767341fc741ea68249335ac1914c5a6cf1c (patch)
treef74cf6c12efc8b8bc718880fc3ff61b820acf84d /src/transport/gnunet-communicator-tcp.c
parent1c9f269ea5cadb20bb5f7fc209274ba5d6af4749 (diff)
downloadgnunet-64483767341fc741ea68249335ac1914c5a6cf1c.tar.gz
gnunet-64483767341fc741ea68249335ac1914c5a6cf1c.zip
more work on TCP communicator
Diffstat (limited to 'src/transport/gnunet-communicator-tcp.c')
-rw-r--r--src/transport/gnunet-communicator-tcp.c583
1 files changed, 521 insertions, 62 deletions
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index 6e3faa44a..5a397c296 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018 GNUnet e.V. 3 Copyright (C) 2010-2014, 2018, 2019 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -33,6 +33,7 @@
33#include "platform.h" 33#include "platform.h"
34#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
35#include "gnunet_protocols.h" 35#include "gnunet_protocols.h"
36#include "gnunet_signatures.h"
36#include "gnunet_constants.h" 37#include "gnunet_constants.h"
37#include "gnunet_nt_lib.h" 38#include "gnunet_nt_lib.h"
38#include "gnunet_statistics_service.h" 39#include "gnunet_statistics_service.h"
@@ -49,6 +50,23 @@
49#define DEFAULT_MAX_QUEUE_LENGTH 8 50#define DEFAULT_MAX_QUEUE_LENGTH 8
50 51
51/** 52/**
53 * Size of our IO buffers for ciphertext data. Must be at
54 * least UINT_MAX + sizeof (struct TCPBox).
55 */
56#define BUF_SIZE (2 * 64 * 1024 + sizeof (struct TCPBox))
57
58/**
59 * How often do we rekey based on time (at least)
60 */
61#define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
62
63/**
64 * How often do we rekey based on number of bytes transmitted?
65 * (additionally randomized).
66 */
67#define REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
68
69/**
52 * Address prefix used by the communicator. 70 * Address prefix used by the communicator.
53 */ 71 */
54#define COMMUNICATOR_ADDRESS_PREFIX "tcp" 72#define COMMUNICATOR_ADDRESS_PREFIX "tcp"
@@ -60,19 +78,6 @@
60 78
61GNUNET_NETWORK_STRUCT_BEGIN 79GNUNET_NETWORK_STRUCT_BEGIN
62 80
63/**
64 * TCP initial bytes on the wire (in either direction), used to
65 * establish a shared secret.
66 */
67struct TCPHandshake
68{
69 /**
70 * First bytes: ephemeral key for KX.
71 */
72 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
73
74};
75
76 81
77/** 82/**
78 * Signature we use to verify that the ephemeral key was really chosen by 83 * Signature we use to verify that the ephemeral key was really chosen by
@@ -139,7 +144,10 @@ struct TCPBox
139{ 144{
140 145
141 /** 146 /**
142 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX. 147 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX. Warning: the
148 * header size EXCLUDES the size of the `struct TCPBox`. We usually
149 * never do this, but here the payload may truly be 64k *after* the
150 * TCPBox (as we have no MTU)!!
143 */ 151 */
144 struct GNUNET_MessageHeader header; 152 struct GNUNET_MessageHeader header;
145 153
@@ -153,7 +161,8 @@ struct TCPBox
153 */ 161 */
154 struct GNUNET_ShortHashCode hmac; 162 struct GNUNET_ShortHashCode hmac;
155 163
156 /* followed by as may bytes of payload as indicated in @e header */ 164 /* followed by as may bytes of payload as indicated in @e header,
165 excluding the TCPBox itself! */
157 166
158}; 167};
159 168
@@ -186,7 +195,7 @@ struct TCPRekey
186 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral; 195 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
187 196
188 /** 197 /**
189 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE 198 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY
190 */ 199 */
191 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 200 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
192 201
@@ -260,11 +269,17 @@ struct Queue
260 struct GNUNET_HashCode in_hmac; 269 struct GNUNET_HashCode in_hmac;
261 270
262 /** 271 /**
263 * Shared secret for HMAC generation on outgoing data. 272 * Shared secret for HMAC generation on outgoing data, ratcheted after
273 * each operation.
264 */ 274 */
265 struct GNUNET_HashCode out_hmac; 275 struct GNUNET_HashCode out_hmac;
266 276
267 /** 277 /**
278 * Our ephemeral key. Stored here temporarily during rekeying / key generation.
279 */
280 struct GNUNET_CRYPTO_EcdhePrivateKey ephemeral;
281
282 /**
268 * ID of read task for this connection. 283 * ID of read task for this connection.
269 */ 284 */
270 struct GNUNET_SCHEDULER_Task *read_task; 285 struct GNUNET_SCHEDULER_Task *read_task;
@@ -297,12 +312,6 @@ struct Queue
297 socklen_t address_len; 312 socklen_t address_len;
298 313
299 /** 314 /**
300 * Message currently scheduled for transmission, non-NULL if and only
301 * if this queue is in the #queue_head DLL.
302 */
303 const struct GNUNET_MessageHeader *msg;
304
305 /**
306 * Message queue we are providing for the #ch. 315 * Message queue we are providing for the #ch.
307 */ 316 */
308 struct GNUNET_MQ_Handle *mq; 317 struct GNUNET_MQ_Handle *mq;
@@ -318,6 +327,50 @@ struct Queue
318 unsigned long long bytes_in_queue; 327 unsigned long long bytes_in_queue;
319 328
320 /** 329 /**
330 * Buffer for reading ciphertext from network into.
331 */
332 char cread_buf[BUF_SIZE];
333
334 /**
335 * buffer for writing ciphertext to network.
336 */
337 char cwrite_buf[BUF_SIZE];
338
339 /**
340 * Plaintext buffer for decrypted plaintext.
341 */
342 char pread_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
343
344 /**
345 * Plaintext buffer for messages to be encrypted.
346 */
347 char pwrite_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
348
349 /**
350 * At which offset in the ciphertext read buffer should we
351 * append more ciphertext for transmission next?
352 */
353 size_t cread_off;
354
355 /**
356 * At which offset in the ciphertext write buffer should we
357 * append more ciphertext from reading next?
358 */
359 size_t cwrite_off;
360
361 /**
362 * At which offset in the plaintext input buffer should we
363 * append more plaintext from decryption next?
364 */
365 size_t pread_off;
366
367 /**
368 * At which offset in the plaintext output buffer should we
369 * append more plaintext for encryption next?
370 */
371 size_t pwrite_off;
372
373 /**
321 * Timeout for this queue. 374 * Timeout for this queue.
322 */ 375 */
323 struct GNUNET_TIME_Absolute timeout; 376 struct GNUNET_TIME_Absolute timeout;
@@ -326,7 +379,23 @@ struct Queue
326 * Which network type does this queue use? 379 * Which network type does this queue use?
327 */ 380 */
328 enum GNUNET_NetworkType nt; 381 enum GNUNET_NetworkType nt;
382
383 /**
384 * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call?
385 */
386 int mq_awaits_continue;
329 387
388 /**
389 * Did we enqueue a finish message and are closing down the queue?
390 */
391 int finishing;
392
393 /**
394 * #GNUNET_YES after #inject_key() placed the rekey message into the
395 * plaintext buffer. Once the plaintext buffer is drained, this
396 * means we must switch to the new key material.
397 */
398 int rekey_state;
330}; 399};
331 400
332 401
@@ -370,6 +439,21 @@ static struct GNUNET_NETWORK_Handle *listen_sock;
370 */ 439 */
371static struct GNUNET_TRANSPORT_AddressIdentifier *ai; 440static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
372 441
442/**
443 * Our public key.
444 */
445static struct GNUNET_PeerIdentity my_identity;
446
447/**
448 * Our private key.
449 */
450static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
451
452/**
453 * Our configuration.
454 */
455static const struct GNUNET_CONFIGURATION_Handle *cfg;
456
373 457
374/** 458/**
375 * We have been notified that our listen socket has something to 459 * We have been notified that our listen socket has something to
@@ -407,7 +491,7 @@ queue_destroy (struct Queue *queue)
407 &queue->target, 491 &queue->target,
408 queue)); 492 queue));
409 GNUNET_STATISTICS_set (stats, 493 GNUNET_STATISTICS_set (stats,
410 "# UNIX queues active", 494 "# queues active",
411 GNUNET_CONTAINER_multipeermap_size (queue_map), 495 GNUNET_CONTAINER_multipeermap_size (queue_map),
412 GNUNET_NO); 496 GNUNET_NO);
413 if (NULL != queue->read_task) 497 if (NULL != queue->read_task)
@@ -435,6 +519,52 @@ queue_destroy (struct Queue *queue)
435 519
436 520
437/** 521/**
522 * Compute @a mac over @a buf, and ratched the @a hmac_secret.
523 *
524 * @param[in,out] hmac_secret secret for HMAC calculation
525 * @param buf buffer to MAC
526 * @param buf_size number of bytes in @a buf
527 * @param smac[out] where to write the HMAC
528 */
529static void
530hmac (struct GNUNET_HashCode *hmac_secret,
531 const void *buf,
532 size_t buf_size,
533 struct GNUNET_ShortHashCode *smac)
534{
535 struct GNUNET_HashCode mac;
536
537 GNUNET_CRYPTO_hmac_raw (hmac_secret,
538 sizeof (struct GNUNET_HashCode),
539 buf,
540 buf_size,
541 &mac);
542 /* truncate to `struct GNUNET_ShortHashCode` */
543 memcpy (smac,
544 &mac,
545 sizeof (struct GNUNET_ShortHashCode));
546 /* ratchet hmac key */
547 GNUNET_CRYPTO_hash (hmac_secret,
548 sizeof (struct GNUNET_HashCode),
549 hmac_secret);
550}
551
552
553/**
554 * Append a 'finish' message to the outgoing transmission. Once the
555 * finish has been transmitted, destroy the queue.
556 *
557 * @param queue queue to shut down nicely
558 */
559static void
560queue_finish (struct Queue *queue)
561{
562 // FIXME: try to send 'finish' message first!?
563 queue_destroy (queue);
564}
565
566
567/**
438 * Queue read task. If we hit the timeout, disconnect it 568 * Queue read task. If we hit the timeout, disconnect it
439 * 569 *
440 * @param cls the `struct Queue *` to disconnect 570 * @param cls the `struct Queue *` to disconnect
@@ -444,12 +574,32 @@ queue_read (void *cls)
444{ 574{
445 struct Queue *queue = cls; 575 struct Queue *queue = cls;
446 struct GNUNET_TIME_Relative left; 576 struct GNUNET_TIME_Relative left;
577 ssize_t rcvd;
447 578
448 queue->read_task = NULL; 579 queue->read_task = NULL;
449 /* CHECK IF READ-ready, then perform read! */ 580 /* FIXME: perform read! */
581 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
582 &queue->cread_buf[queue->cread_off],
583 BUF_SIZE - queue->cread_off);
584 if (-1 == rcvd)
585 {
586 // FIXME: error handling...
587 }
588 if (0 != rcvd)
589 /* update queue timeout */
590 queue->cread_off += rcvd;
591 if (queue->pread_off < sizeof (queue->pread_buf))
592 {
593 /* FIXME: decrypt */
450 594
595 /* FIXME: check plaintext for complete messages, if complete, hand to CORE */
596 /* FIXME: CORE flow control: suspend doing more until CORE has ACKed */
597 }
598
599 if (BUF_SIZE == queue->cread_off)
600 return; /* buffer full, suspend reading */
451 left = GNUNET_TIME_absolute_get_remaining (queue->timeout); 601 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
452 if (0 != left.rel_value_us) 602 if (0 != left.rel_value_us)
453 { 603 {
454 /* not actually our turn yet, but let's at least update 604 /* not actually our turn yet, but let's at least update
455 the monitor, it may think we're about to die ... */ 605 the monitor, it may think we're about to die ... */
@@ -458,6 +608,7 @@ queue_read (void *cls)
458 queue->sock, 608 queue->sock,
459 &queue_read, 609 &queue_read,
460 queue); 610 queue);
611
461 return; 612 return;
462 } 613 }
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -465,8 +616,7 @@ queue_read (void *cls)
465 queue, 616 queue,
466 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 617 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
467 GNUNET_YES)); 618 GNUNET_YES));
468 // FIXME: try to send 'finish' message first!? 619 queue_finish (queue);
469 queue_destroy (queue);
470} 620}
471 621
472 622
@@ -506,6 +656,175 @@ tcp_address_to_sockaddr (const char *bindto,
506 656
507 657
508/** 658/**
659 * Setup @a cipher based on shared secret @a dh and decrypting
660 * peer @a pid.
661 *
662 * @param dh shared secret
663 * @param pid decrypting peer's identity
664 * @param cipher[out] cipher to initialize
665 * @param hmac_key[out] HMAC key to initialize
666 */
667static void
668setup_cipher (const struct GNUNET_HashCode *dh,
669 const struct GNUNET_PeerIdentity *pid,
670 gcry_cipher_hd_t *cipher,
671 struct GNUNET_HashCode *hmac_key)
672{
673 char key[256/8];
674 char ctr[128/8];
675
676 gcry_cipher_open (cipher,
677 GCRY_CIPHER_AES256 /* low level: go for speed */,
678 GCRY_CIPHER_MODE_CTR,
679 0 /* flags */);
680 GNUNET_assert (GNUNET_YES ==
681 GNUNET_CRYPTO_kdf (key,
682 sizeof (key),
683 "TCP-key",
684 strlen ("TCP-key"),
685 dh,
686 sizeof (*dh),
687 pid,
688 sizeof (*pid),
689 NULL, 0));
690 gcry_cipher_setkey (*cipher,
691 key,
692 sizeof (key));
693 GNUNET_assert (GNUNET_YES ==
694 GNUNET_CRYPTO_kdf (ctr,
695 sizeof (ctr),
696 "TCP-ctr",
697 strlen ("TCP-ctr"),
698 dh,
699 sizeof (*dh),
700 pid,
701 sizeof (*pid),
702 NULL, 0));
703 gcry_cipher_setctr (*cipher,
704 ctr,
705 sizeof (ctr));
706 GNUNET_assert (GNUNET_YES ==
707 GNUNET_CRYPTO_kdf (hmac_key,
708 sizeof (struct GNUNET_HashCode),
709 "TCP-hmac",
710 strlen ("TCP-hmac"),
711 dh,
712 sizeof (*dh),
713 pid,
714 sizeof (*pid),
715 NULL, 0));
716}
717
718
719/**
720 * Setup cipher of @a queue for decryption.
721 *
722 * @param ephemeral ephemeral key we received from the other peer
723 * @param queue[in,out] queue to initialize decryption cipher for
724 */
725static void
726setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
727 struct Queue *queue)
728{
729 struct GNUNET_HashCode dh;
730
731 GNUNET_CRYPTO_eddsa_ecdh (my_private_key,
732 ephemeral,
733 &dh);
734 setup_cipher (&dh,
735 &my_identity,
736 &queue->in_cipher,
737 &queue->in_hmac);
738}
739
740
741/**
742 * Setup cipher for outgoing data stream based on target and
743 * our ephemeral private key.
744 *
745 * @param queue queue to setup outgoing (encryption) cipher for
746 */
747static void
748setup_out_cipher (struct Queue *queue)
749{
750 struct GNUNET_HashCode dh;
751
752 GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral,
753 &queue->target.public_key,
754 &dh);
755 /* we don't need the private key anymore, drop it! */
756 memset (&queue->ephemeral,
757 0,
758 sizeof (queue->ephemeral));
759 setup_cipher (&dh,
760 &queue->target,
761 &queue->out_cipher,
762 &queue->out_hmac);
763
764 queue->rekey_time = GNUNET_TIME_relative_to_absolute (REKEY_TIME_INTERVAL);
765 queue->rekey_left_bytes = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
766 REKEY_MAX_BYTES);
767}
768
769
770/**
771 * Inject a `struct TCPRekey` message into the queue's plaintext
772 * buffer.
773 *
774 * @param queue queue to perform rekeying on
775 */
776static void
777inject_rekey (struct Queue *queue)
778{
779 struct TCPRekey rekey;
780 struct TcpHandshakeSignature thp;
781
782 GNUNET_assert (0 == queue->pwrite_off);
783 memset (&rekey,
784 0,
785 sizeof (rekey));
786 GNUNET_assert (GNUNET_OK ==
787 GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral));
788 rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
789 rekey.header.size = ntohs (sizeof (rekey));
790 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
791 &rekey.ephemeral);
792 rekey.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
793 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
794 thp.purpose.size = htonl (sizeof (thp));
795 thp.sender = my_identity;
796 thp.receiver = queue->target;
797 thp.ephemeral = rekey.ephemeral;
798 thp.monotonic_time = rekey.monotonic_time;
799 GNUNET_assert (GNUNET_OK ==
800 GNUNET_CRYPTO_eddsa_sign (my_private_key,
801 &thp.purpose,
802 &rekey.sender_sig));
803 hmac (&queue->out_hmac,
804 &rekey,
805 sizeof (rekey),
806 &rekey.hmac);
807 memcpy (queue->pwrite_buf,
808 &rekey,
809 sizeof (rekey));
810 queue->rekey_state = GNUNET_YES;
811}
812
813
814/**
815 * We encrypted the rekey message, now update actually swap the key
816 * material and update the key freshness parameters of @a queue.
817 */
818static void
819switch_key (struct Queue *queue)
820{
821 queue->rekey_state = GNUNET_NO;
822 gcry_cipher_close (queue->out_cipher);
823 setup_out_cipher (queue);
824}
825
826
827/**
509 * We have been notified that our socket is ready to write. 828 * We have been notified that our socket is ready to write.
510 * Then reschedule this function to be called again once more is available. 829 * Then reschedule this function to be called again once more is available.
511 * 830 *
@@ -515,17 +834,68 @@ static void
515queue_write (void *cls) 834queue_write (void *cls)
516{ 835{
517 struct Queue *queue = cls; 836 struct Queue *queue = cls;
518 const struct GNUNET_MessageHeader *msg = queue->msg; 837 ssize_t sent;
519 size_t msg_size = ntohs (msg->size);
520 838
521 queue->write_task = NULL; 839 queue->write_task = NULL;
522 /* FIXME: send 'msg' */ 840 sent = GNUNET_NETWORK_socket_send (queue->sock,
523 /* FIXME: check if we have more messages pending */ 841 queue->cwrite_buf,
524 queue->write_task 842 queue->cwrite_off);
525 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 843 if ( (-1 == sent) &&
526 queue->sock, 844 (EAGAIN != errno) &&
527 &queue_write, 845 (EINTR != errno) )
528 queue); 846 {
847 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
848 "send");
849 queue_destroy (queue);
850 return;
851 }
852 if (sent > 0)
853 {
854 size_t usent = (size_t) sent;
855
856 memmove (queue->cwrite_buf,
857 &queue->cwrite_buf[sent],
858 queue->cwrite_off - sent);
859 /* FIXME: update queue timeout */
860 }
861 /* can we encrypt more? (always encrypt full messages, needed
862 such that #mq_cancel() can work!) */
863 if (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE)
864 {
865 GNUNET_assert (0 ==
866 gcry_cipher_encrypt (queue->out_cipher,
867 &queue->cwrite_buf[queue->cwrite_off],
868 queue->pwrite_off,
869 queue->pwrite_buf,
870 queue->pwrite_off));
871 if (queue->rekey_left_bytes > queue->pwrite_off)
872 queue->rekey_left_bytes -= queue->pwrite_off;
873 else
874 queue->rekey_left_bytes = 0;
875 queue->cwrite_off += queue->pwrite_off;
876 queue->pwrite_off = 0;
877 }
878 if ( (GNUNET_YES == queue->rekey_state) &&
879 (0 == queue->pwrite_off) )
880 switch_key (queue);
881 if ( (0 == queue->pwrite_off) &&
882 ( (0 == queue->rekey_left_bytes) ||
883 (0 == GNUNET_TIME_absolute_get_remaining (queue->rekey_time).rel_value_us) ) )
884 inject_rekey (queue);
885 if ( (0 == queue->pwrite_off) &&
886 (! queue->finishing) &&
887 (queue->mq_awaits_continue) )
888 {
889 queue->mq_awaits_continue = GNUNET_NO;
890 GNUNET_MQ_impl_send_continue (queue->mq);
891 }
892 /* do we care to write more? */
893 if (0 < queue->cwrite_off)
894 queue->write_task
895 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
896 queue->sock,
897 &queue_write,
898 queue);
529} 899}
530 900
531 901
@@ -543,10 +913,25 @@ mq_send (struct GNUNET_MQ_Handle *mq,
543 void *impl_state) 913 void *impl_state)
544{ 914{
545 struct Queue *queue = impl_state; 915 struct Queue *queue = impl_state;
916 uint16_t msize = ntohs (msg->size);
917 struct TCPBox box;
546 918
547 GNUNET_assert (mq == queue->mq); 919 GNUNET_assert (mq == queue->mq);
548 GNUNET_assert (NULL == queue->msg); 920 GNUNET_assert (0 == queue->pread_off);
549 queue->msg = msg; 921 box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
922 box.header.size = htons (msize);
923 hmac (&queue->out_hmac,
924 msg,
925 msize,
926 &box.hmac);
927 memcpy (&queue->pread_buf[queue->pread_off],
928 &box,
929 sizeof (box));
930 queue->pread_off += sizeof (box);
931 memcpy (&queue->pread_buf[queue->pread_off],
932 msg,
933 msize);
934 queue->pread_off += msize;
550 GNUNET_assert (NULL != queue->sock); 935 GNUNET_assert (NULL != queue->sock);
551 if (NULL == queue->write_task) 936 if (NULL == queue->write_task)
552 queue->write_task = 937 queue->write_task =
@@ -574,7 +959,7 @@ mq_destroy (struct GNUNET_MQ_Handle *mq,
574 if (mq == queue->mq) 959 if (mq == queue->mq)
575 { 960 {
576 queue->mq = NULL; 961 queue->mq = NULL;
577 queue_destroy (queue); 962 queue_finish (queue);
578 } 963 }
579} 964}
580 965
@@ -591,14 +976,8 @@ mq_cancel (struct GNUNET_MQ_Handle *mq,
591{ 976{
592 struct Queue *queue = impl_state; 977 struct Queue *queue = impl_state;
593 978
594 GNUNET_assert (NULL != queue->msg); 979 GNUNET_assert (0 != queue->pwrite_off);
595 queue->msg = NULL; 980 queue->pwrite_off = 0;
596 GNUNET_assert (NULL != queue->write_task);
597 if (1) // FIXME?
598 {
599 GNUNET_SCHEDULER_cancel (queue->write_task);
600 queue->write_task = NULL;
601 }
602} 981}
603 982
604 983
@@ -618,10 +997,10 @@ mq_error (void *cls,
618 struct Queue *queue = cls; 997 struct Queue *queue = cls;
619 998
620 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
621 "TCP MQ error in queue to %s: %d\n", 1000 "MQ error in queue to %s: %d\n",
622 GNUNET_i2s (&queue->target), 1001 GNUNET_i2s (&queue->target),
623 (int) error); 1002 (int) error);
624 queue_destroy (queue); 1003 queue_finish (queue);
625} 1004}
626 1005
627 1006
@@ -629,7 +1008,8 @@ mq_error (void *cls,
629 * Creates a new outbound queue the transport service will use to send 1008 * Creates a new outbound queue the transport service will use to send
630 * data to another peer. 1009 * data to another peer.
631 * 1010 *
632 * @param peer the target peer 1011 * @param sock the queue's socket
1012 * @param target the target peer
633 * @param cs inbound or outbound queue 1013 * @param cs inbound or outbound queue
634 * @param in the address 1014 * @param in the address
635 * @param in_len number of bytes in @a in 1015 * @param in_len number of bytes in @a in
@@ -637,6 +1017,7 @@ mq_error (void *cls,
637 */ 1017 */
638static struct Queue * 1018static struct Queue *
639setup_queue (struct GNUNET_NETWORK_Handle *sock, 1019setup_queue (struct GNUNET_NETWORK_Handle *sock,
1020 const struct GNUNET_PeerIdentity *target,
640 enum GNUNET_TRANSPORT_ConnectionStatus cs, 1021 enum GNUNET_TRANSPORT_ConnectionStatus cs,
641 const struct sockaddr *in, 1022 const struct sockaddr *in,
642 socklen_t in_len) 1023 socklen_t in_len)
@@ -644,7 +1025,7 @@ setup_queue (struct GNUNET_NETWORK_Handle *sock,
644 struct Queue *queue; 1025 struct Queue *queue;
645 1026
646 queue = GNUNET_new (struct Queue); 1027 queue = GNUNET_new (struct Queue);
647 // queue->target = *target; // FIXME: handle case that we don't know the target yet! 1028 queue->target = *target;
648 queue->address = GNUNET_memdup (in, 1029 queue->address = GNUNET_memdup (in,
649 in_len); 1030 in_len);
650 queue->address_len = in_len; 1031 queue->address_len = in_len;
@@ -730,12 +1111,9 @@ listen_cb (void *cls);
730static void 1111static void
731listen_cb (void *cls) 1112listen_cb (void *cls)
732{ 1113{
733 char buf[65536] GNUNET_ALIGN;
734 struct Queue *queue; 1114 struct Queue *queue;
735 struct sockaddr_storage in; 1115 struct sockaddr_storage in;
736 socklen_t addrlen; 1116 socklen_t addrlen;
737 ssize_t ret;
738 uint16_t msize;
739 struct GNUNET_NETWORK_Handle *sock; 1117 struct GNUNET_NETWORK_Handle *sock;
740 1118
741 listen_task = NULL; 1119 listen_task = NULL;
@@ -765,6 +1143,9 @@ listen_cb (void *cls)
765 "accept"); 1143 "accept");
766 return; 1144 return;
767 } 1145 }
1146#if 0
1147 // FIXME: setup proto-queue first here, until we have received the starting
1148 // messages!
768 queue = setup_queue (sock, 1149 queue = setup_queue (sock,
769 GNUNET_TRANSPORT_CS_INBOUND, 1150 GNUNET_TRANSPORT_CS_INBOUND,
770 (struct sockaddr *) &in, 1151 (struct sockaddr *) &in,
@@ -775,6 +1156,7 @@ listen_cb (void *cls)
775 _("Maximum number of TCP connections exceeded, dropping incoming connection\n")); 1156 _("Maximum number of TCP connections exceeded, dropping incoming connection\n"));
776 return; 1157 return;
777 } 1158 }
1159#endif
778} 1160}
779 1161
780 1162
@@ -804,6 +1186,10 @@ mq_init (void *cls,
804 const char *path; 1186 const char *path;
805 struct sockaddr *in; 1187 struct sockaddr *in;
806 socklen_t in_len; 1188 socklen_t in_len;
1189 struct GNUNET_NETWORK_Handle *sock;
1190 struct GNUNET_CRYPTO_EcdhePublicKey epub;
1191 struct TcpHandshakeSignature ths;
1192 struct TCPConfirmation tc;
807 1193
808 if (0 != strncmp (address, 1194 if (0 != strncmp (address,
809 COMMUNICATOR_ADDRESS_PREFIX "-", 1195 COMMUNICATOR_ADDRESS_PREFIX "-",
@@ -815,12 +1201,37 @@ mq_init (void *cls,
815 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; 1201 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
816 in = tcp_address_to_sockaddr (path, 1202 in = tcp_address_to_sockaddr (path,
817 &in_len); 1203 &in_len);
818#if FIXME 1204
819 queue = setup_queue (peer, 1205 sock = GNUNET_NETWORK_socket_create (in->sa_family,
1206 SOCK_STREAM,
1207 IPPROTO_TCP);
1208 if (NULL == sock)
1209 {
1210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1211 "socket(%d) failed: %s",
1212 in->sa_family,
1213 STRERROR (errno));
1214 GNUNET_free (in);
1215 return GNUNET_SYSERR;
1216 }
1217 if (GNUNET_OK !=
1218 GNUNET_NETWORK_socket_connect (sock,
1219 in,
1220 in_len))
1221 {
1222 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1223 "connect to `%s' failed: %s",
1224 address,
1225 STRERROR (errno));
1226 GNUNET_NETWORK_socket_close (sock);
1227 GNUNET_free (in);
1228 return GNUNET_SYSERR;
1229 }
1230 queue = setup_queue (sock,
1231 peer,
820 GNUNET_TRANSPORT_CS_OUTBOUND, 1232 GNUNET_TRANSPORT_CS_OUTBOUND,
821 in, 1233 in,
822 in_len); 1234 in_len);
823#endif
824 GNUNET_free (in); 1235 GNUNET_free (in);
825 if (NULL == queue) 1236 if (NULL == queue)
826 { 1237 {
@@ -828,8 +1239,39 @@ mq_init (void *cls,
828 "Failed to setup queue to %s at `%s'\n", 1239 "Failed to setup queue to %s at `%s'\n",
829 GNUNET_i2s (peer), 1240 GNUNET_i2s (peer),
830 path); 1241 path);
1242 GNUNET_NETWORK_socket_close (sock);
831 return GNUNET_NO; 1243 return GNUNET_NO;
832 } 1244 }
1245 GNUNET_assert (GNUNET_OK ==
1246 GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral));
1247 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
1248 &epub);
1249 setup_out_cipher (queue);
1250 memcpy (queue->cwrite_buf,
1251 &epub,
1252 sizeof (epub));
1253 queue->cwrite_off = sizeof (epub);
1254 /* compute 'tc' and append in encrypted format to cwrite_buf */
1255 tc.sender = my_identity;
1256 tc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1257 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE);
1258 ths.purpose.size = htonl (sizeof (ths));
1259 ths.sender = my_identity;
1260 ths.receiver = queue->target;
1261 ths.ephemeral = epub;
1262 ths.monotonic_time = tc.monotonic_time;
1263 GNUNET_assert (GNUNET_OK ==
1264 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1265 &ths.purpose,
1266 &tc.sender_sig));
1267 GNUNET_assert (0 ==
1268 gcry_cipher_encrypt (queue->out_cipher,
1269 &queue->cwrite_buf[queue->cwrite_off],
1270 sizeof (tc),
1271 &tc,
1272 sizeof (tc)));
1273 queue->cwrite_off += sizeof (tc);
1274
833 return GNUNET_OK; 1275 return GNUNET_OK;
834} 1276}
835 1277
@@ -895,6 +1337,11 @@ do_shutdown (void *cls)
895 GNUNET_NO); 1337 GNUNET_NO);
896 stats = NULL; 1338 stats = NULL;
897 } 1339 }
1340 if (NULL != my_private_key)
1341 {
1342 GNUNET_free (my_private_key);
1343 my_private_key = NULL;
1344 }
898} 1345}
899 1346
900 1347
@@ -903,7 +1350,7 @@ do_shutdown (void *cls)
903 * acknowledgement for this communicator (!) via a different return 1350 * acknowledgement for this communicator (!) via a different return
904 * path. 1351 * path.
905 * 1352 *
906 * Not applicable for UNIX. 1353 * Not applicable for TCP.
907 * 1354 *
908 * @param cls closure 1355 * @param cls closure
909 * @param sender which peer sent the notification 1356 * @param sender which peer sent the notification
@@ -927,13 +1374,13 @@ enc_notify_cb (void *cls,
927 * @param cls NULL (always) 1374 * @param cls NULL (always)
928 * @param args remaining command-line arguments 1375 * @param args remaining command-line arguments
929 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 1376 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
930 * @param cfg configuration 1377 * @param c configuration
931 */ 1378 */
932static void 1379static void
933run (void *cls, 1380run (void *cls,
934 char *const *args, 1381 char *const *args,
935 const char *cfgfile, 1382 const char *cfgfile,
936 const struct GNUNET_CONFIGURATION_Handle *cfg) 1383 const struct GNUNET_CONFIGURATION_Handle *c)
937{ 1384{
938 char *bindto; 1385 char *bindto;
939 struct sockaddr *in; 1386 struct sockaddr *in;
@@ -941,6 +1388,7 @@ run (void *cls,
941 char *my_addr; 1388 char *my_addr;
942 (void) cls; 1389 (void) cls;
943 1390
1391 cfg = c;
944 if (GNUNET_OK != 1392 if (GNUNET_OK !=
945 GNUNET_CONFIGURATION_get_value_filename (cfg, 1393 GNUNET_CONFIGURATION_get_value_filename (cfg,
946 COMMUNICATOR_CONFIG_SECTION, 1394 COMMUNICATOR_CONFIG_SECTION,
@@ -1002,6 +1450,17 @@ run (void *cls,
1002 cfg); 1450 cfg);
1003 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 1451 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1004 NULL); 1452 NULL);
1453 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1454 if (NULL == my_private_key)
1455 {
1456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1457 _("Transport service is lacking key configuration settings. Exiting.\n"));
1458 GNUNET_SCHEDULER_shutdown ();
1459 return;
1460 }
1461 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1462 &my_identity.public_key);
1463
1005 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 1464 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1006 listen_sock, 1465 listen_sock,
1007 &listen_cb, 1466 &listen_cb,