2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/gnunet-communicator-tcp.c
23 * @brief Transport plugin using TCP.
24 * @author Christian Grothoff
27 * - lots of basic adaptations (see FIXMEs)
28 * - better message queue management
29 * - actually encrypt, hmac, decrypt
34 #include "gnunet_util_lib.h"
35 #include "gnunet_protocols.h"
36 #include "gnunet_constants.h"
37 #include "gnunet_nt_lib.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet_transport_communication_service.h"
42 * How many messages do we keep at most in the queue to the
43 * transport service before we start to drop (default,
44 * can be changed via the configuration file).
45 * Should be _below_ the level of the communicator API, as
46 * otherwise we may read messages just to have them dropped
47 * by the communicator API.
49 #define DEFAULT_MAX_QUEUE_LENGTH 8
52 * Address prefix used by the communicator.
54 #define COMMUNICATOR_ADDRESS_PREFIX "tcp"
57 * Configuration section used by the communicator.
59 #define COMMUNICATOR_CONFIG_SECTION "communicator-tcp"
61 GNUNET_NETWORK_STRUCT_BEGIN
64 * TCP initial bytes on the wire (in either direction), used to
65 * establish a shared secret.
70 * First bytes: ephemeral key for KX.
72 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
78 * Signature we use to verify that the ephemeral key was really chosen by
79 * the specified sender.
81 struct TcpHandshakeSignature
84 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
86 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
89 * Identity of the inititor of the TCP connection (TCP client).
91 struct GNUNET_PeerIdentity sender;
94 * Presumed identity of the target of the TCP connection (TCP server)
96 struct GNUNET_PeerIdentity receiver;
99 * Ephemeral key used by the @e sender.
101 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
104 * Monotonic time of @e sender, to possibly help detect replay attacks
105 * (if receiver persists times by sender).
107 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
112 * Encrypted continuation of TCP initial handshake.
114 struct TCPConfirmation
119 struct GNUNET_PeerIdentity sender;
122 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
124 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
127 * Monotonic time of @e sender, to possibly help detect replay attacks
128 * (if receiver persists times by sender).
130 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
136 * TCP message box. Always sent encrypted!
142 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.
144 struct GNUNET_MessageHeader header;
147 * HMAC for the following encrypted message. Yes, we MUST use
148 * mac-then-encrypt here, as we want to hide the message sizes on
149 * the wire (zero plaintext design!). Using CTR mode padding oracle
150 * attacks do not apply. Besides, due to the use of ephemeral keys
151 * (hopefully with effective replay protection from monotonic time!)
152 * the attacker is limited in using the oracle.
154 struct GNUNET_ShortHashCode hmac;
156 /* followed by as may bytes of payload as indicated in @e header */
162 * TCP rekey message box. Always sent encrypted! Data after
163 * this message will use the new key.
169 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
171 struct GNUNET_MessageHeader header;
174 * HMAC for the following encrypted message. Yes, we MUST use
175 * mac-then-encrypt here, as we want to hide the message sizes on
176 * the wire (zero plaintext design!). Using CTR mode padding oracle
177 * attacks do not apply. Besides, due to the use of ephemeral keys
178 * (hopefully with effective replay protection from monotonic time!)
179 * the attacker is limited in using the oracle.
181 struct GNUNET_ShortHashCode hmac;
186 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
189 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
191 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
194 * Monotonic time of @e sender, to possibly help detect replay attacks
195 * (if receiver persists times by sender).
197 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
203 * TCP finish. Sender asks for the connection to be closed.
204 * Needed/useful in case we drop RST/FIN packets on the GNUnet
205 * port due to the possibility of malicious RST/FIN injection.
211 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
213 struct GNUNET_MessageHeader header;
216 * HMAC for the following encrypted message. Yes, we MUST use
217 * mac-then-encrypt here, as we want to hide the message sizes on
218 * the wire (zero plaintext design!). Using CTR mode padding oracle
219 * attacks do not apply. Besides, due to the use of ephemeral keys
220 * (hopefully with effective replay protection from monotonic time!)
221 * the attacker is limited in using the oracle.
223 struct GNUNET_ShortHashCode hmac;
228 GNUNET_NETWORK_STRUCT_END
232 * Handle for a queue.
238 * To whom are we talking to.
240 struct GNUNET_PeerIdentity target;
243 * socket that we transmit all data with on this queue
245 struct GNUNET_NETWORK_Handle *sock;
248 * cipher for decryption of incoming data.
250 gcry_cipher_hd_t in_cipher;
253 * cipher for encryption of outgoing data.
255 gcry_cipher_hd_t out_cipher;
258 * Shared secret for HMAC verification on incoming data.
260 struct GNUNET_HashCode in_hmac;
263 * Shared secret for HMAC generation on outgoing data.
265 struct GNUNET_HashCode out_hmac;
268 * ID of read task for this connection.
270 struct GNUNET_SCHEDULER_Task *read_task;
273 * ID of write task for this connection.
275 struct GNUNET_SCHEDULER_Task *write_task;
278 * Address of the other peer.
280 struct sockaddr *address;
283 * How many more bytes may we sent with the current @e out_cipher
284 * before we should rekey?
286 uint64_t rekey_left_bytes;
289 * Until what time may we sent with the current @e out_cipher
290 * before we should rekey?
292 struct GNUNET_TIME_Absolute rekey_time;
295 * Length of the address.
297 socklen_t address_len;
300 * Message currently scheduled for transmission, non-NULL if and only
301 * if this queue is in the #queue_head DLL.
303 const struct GNUNET_MessageHeader *msg;
306 * Message queue we are providing for the #ch.
308 struct GNUNET_MQ_Handle *mq;
311 * handle for this queue with the #ch.
313 struct GNUNET_TRANSPORT_QueueHandle *qh;
316 * Number of bytes we currently have in our write queue.
318 unsigned long long bytes_in_queue;
321 * Timeout for this queue.
323 struct GNUNET_TIME_Absolute timeout;
326 * Which network type does this queue use?
328 enum GNUNET_NetworkType nt;
336 static struct GNUNET_SCHEDULER_Task *listen_task;
339 * Number of messages we currently have in our queues towards the transport service.
341 static unsigned long long delivering_messages;
344 * Maximum queue length before we stop reading towards the transport service.
346 static unsigned long long max_queue_length;
349 * For logging statistics.
351 static struct GNUNET_STATISTICS_Handle *stats;
356 static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
359 * Queues (map from peer identity to `struct Queue`)
361 static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
366 static struct GNUNET_NETWORK_Handle *listen_sock;
369 * Handle to the operation that publishes our address.
371 static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
375 * We have been notified that our listen socket has something to
376 * read. Do the read and reschedule this function to be called again
377 * once more is available.
382 listen_cb (void *cls);
386 * Functions with this signature are called whenever we need
387 * to close a queue due to a disconnect or failure to
388 * establish a connection.
390 * @param queue queue to close down
393 queue_destroy (struct Queue *queue)
395 struct GNUNET_MQ_Handle *mq;
397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
398 "Disconnecting queue for peer `%s'\n",
399 GNUNET_i2s (&queue->target));
400 if (NULL != (mq = queue->mq))
403 GNUNET_MQ_destroy (mq);
405 GNUNET_assert (GNUNET_YES ==
406 GNUNET_CONTAINER_multipeermap_remove (queue_map,
409 GNUNET_STATISTICS_set (stats,
410 "# UNIX queues active",
411 GNUNET_CONTAINER_multipeermap_size (queue_map),
413 if (NULL != queue->read_task)
415 GNUNET_SCHEDULER_cancel (queue->read_task);
416 queue->read_task = NULL;
418 if (NULL != queue->write_task)
420 GNUNET_SCHEDULER_cancel (queue->write_task);
421 queue->write_task = NULL;
423 GNUNET_NETWORK_socket_close (queue->sock);
424 gcry_cipher_close (queue->in_cipher);
425 gcry_cipher_close (queue->out_cipher);
426 GNUNET_free (queue->address);
428 if (NULL == listen_task)
429 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
438 * Queue read task. If we hit the timeout, disconnect it
440 * @param cls the `struct Queue *` to disconnect
443 queue_read (void *cls)
445 struct Queue *queue = cls;
446 struct GNUNET_TIME_Relative left;
448 queue->read_task = NULL;
449 /* CHECK IF READ-ready, then perform read! */
451 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
452 if (0 != left.rel_value_us)
454 /* not actually our turn yet, but let's at least update
455 the monitor, it may think we're about to die ... */
457 = GNUNET_SCHEDULER_add_read_net (left,
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Queue %p was idle for %s, disconnecting\n",
466 GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
468 // FIXME: try to send 'finish' message first!?
469 queue_destroy (queue);
474 * Increment queue timeout due to activity. We do not immediately
475 * notify the monitor here as that might generate excessive
478 * @param queue queue for which the timeout should be rescheduled
481 reschedule_queue_timeout (struct Queue *queue)
483 GNUNET_assert (NULL != queue->read_task);
485 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
490 * Convert TCP bind specification to a `struct sockaddr *`
492 * @param bindto bind specification to convert
493 * @param[out] sock_len set to the length of the address
494 * @return converted bindto specification
496 static struct sockaddr *
497 tcp_address_to_sockaddr (const char *bindto,
503 /* FIXME: parse, allocate, return! */
509 * We have been notified that our socket is ready to write.
510 * Then reschedule this function to be called again once more is available.
512 * @param cls a `struct Queue`
515 queue_write (void *cls)
517 struct Queue *queue = cls;
518 const struct GNUNET_MessageHeader *msg = queue->msg;
519 size_t msg_size = ntohs (msg->size);
521 queue->write_task = NULL;
522 /* FIXME: send 'msg' */
523 /* FIXME: check if we have more messages pending */
525 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
533 * Signature of functions implementing the sending functionality of a
536 * @param mq the message queue
537 * @param msg the message to send
538 * @param impl_state our `struct Queue`
541 mq_send (struct GNUNET_MQ_Handle *mq,
542 const struct GNUNET_MessageHeader *msg,
545 struct Queue *queue = impl_state;
547 GNUNET_assert (mq == queue->mq);
548 GNUNET_assert (NULL == queue->msg);
550 GNUNET_assert (NULL != queue->sock);
551 if (NULL == queue->write_task)
553 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
561 * Signature of functions implementing the destruction of a message
562 * queue. Implementations must not free @a mq, but should take care
565 * @param mq the message queue to destroy
566 * @param impl_state our `struct Queue`
569 mq_destroy (struct GNUNET_MQ_Handle *mq,
572 struct Queue *queue = impl_state;
577 queue_destroy (queue);
583 * Implementation function that cancels the currently sent message.
585 * @param mq message queue
586 * @param impl_state our `struct Queue`
589 mq_cancel (struct GNUNET_MQ_Handle *mq,
592 struct Queue *queue = impl_state;
594 GNUNET_assert (NULL != queue->msg);
596 GNUNET_assert (NULL != queue->write_task);
599 GNUNET_SCHEDULER_cancel (queue->write_task);
600 queue->write_task = NULL;
606 * Generic error handler, called with the appropriate
607 * error code and the same closure specified at the creation of
609 * Not every message queue implementation supports an error handler.
611 * @param cls our `struct Queue`
612 * @param error error code
616 enum GNUNET_MQ_Error error)
618 struct Queue *queue = cls;
620 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
621 "TCP MQ error in queue to %s: %d\n",
622 GNUNET_i2s (&queue->target),
624 queue_destroy (queue);
629 * Creates a new outbound queue the transport service will use to send
630 * data to another peer.
632 * @param peer the target peer
633 * @param cs inbound or outbound queue
634 * @param in the address
635 * @param in_len number of bytes in @a in
636 * @return the queue or NULL of max connections exceeded
638 static struct Queue *
639 setup_queue (struct GNUNET_NETWORK_Handle *sock,
640 enum GNUNET_TRANSPORT_ConnectionStatus cs,
641 const struct sockaddr *in,
646 queue = GNUNET_new (struct Queue);
647 // queue->target = *target; // FIXME: handle case that we don't know the target yet!
648 queue->address = GNUNET_memdup (in,
650 queue->address_len = in_len;
652 queue->nt = 0; // FIXME: determine NT!
653 (void) GNUNET_CONTAINER_multipeermap_put (queue_map,
656 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
657 GNUNET_STATISTICS_set (stats,
659 GNUNET_CONTAINER_multipeermap_size (queue_map),
662 = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
664 = GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
669 = GNUNET_MQ_queue_for_callbacks (&mq_send,
679 switch (queue->address->sa_family)
682 GNUNET_asprintf (&foreign_addr,
684 COMMUNICATOR_ADDRESS_PREFIX,
689 GNUNET_asprintf (&foreign_addr,
691 COMMUNICATOR_ADDRESS_PREFIX,
699 = GNUNET_TRANSPORT_communicator_mq_add (ch,
706 GNUNET_free (foreign_addr);
713 * We have been notified that our listen socket has something to
714 * read. Do the read and reschedule this function to be called again
715 * once more is available.
720 listen_cb (void *cls);
724 * We have been notified that our listen socket has something to
725 * read. Do the read and reschedule this function to be called again
726 * once more is available.
731 listen_cb (void *cls)
733 char buf[65536] GNUNET_ALIGN;
735 struct sockaddr_storage in;
739 struct GNUNET_NETWORK_Handle *sock;
742 GNUNET_assert (NULL != listen_sock);
743 addrlen = sizeof (in);
747 sock = GNUNET_NETWORK_socket_accept (listen_sock,
748 (struct sockaddr *) &in,
750 if ( (NULL == sock) &&
751 ( (EMFILE == errno) ||
752 (ENFILE == errno) ) )
753 return; /* system limit reached, wait until connection goes down */
754 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
758 if ( (NULL == sock) &&
759 ( (EAGAIN == errno) ||
760 (ENOBUFS == errno) ) )
764 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
768 queue = setup_queue (sock,
769 GNUNET_TRANSPORT_CS_INBOUND,
770 (struct sockaddr *) &in,
774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
775 _("Maximum number of TCP connections exceeded, dropping incoming connection\n"));
782 * Function called by the transport service to initialize a
783 * message queue given address information about another peer.
784 * If and when the communication channel is established, the
785 * communicator must call #GNUNET_TRANSPORT_communicator_mq_add()
786 * to notify the service that the channel is now up. It is
787 * the responsibility of the communicator to manage sane
788 * retries and timeouts for any @a peer/@a address combination
789 * provided by the transport service. Timeouts and retries
790 * do not need to be signalled to the transport service.
793 * @param peer identity of the other peer
794 * @param address where to send the message, human-readable
795 * communicator-specific format, 0-terminated, UTF-8
796 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
800 const struct GNUNET_PeerIdentity *peer,
808 if (0 != strncmp (address,
809 COMMUNICATOR_ADDRESS_PREFIX "-",
810 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
813 return GNUNET_SYSERR;
815 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
816 in = tcp_address_to_sockaddr (path,
819 queue = setup_queue (peer,
820 GNUNET_TRANSPORT_CS_OUTBOUND,
827 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
828 "Failed to setup queue to %s at `%s'\n",
838 * Iterator over all message queues to clean up.
841 * @param target unused
842 * @param value the queue to destroy
843 * @return #GNUNET_OK to continue to iterate
846 get_queue_delete_it (void *cls,
847 const struct GNUNET_PeerIdentity *target,
850 struct Queue *queue = value;
854 queue_destroy (queue);
860 * Shutdown the UNIX communicator.
862 * @param cls NULL (always)
865 do_shutdown (void *cls)
867 if (NULL != listen_task)
869 GNUNET_SCHEDULER_cancel (listen_task);
872 if (NULL != listen_sock)
874 GNUNET_break (GNUNET_OK ==
875 GNUNET_NETWORK_socket_close (listen_sock));
878 GNUNET_CONTAINER_multipeermap_iterate (queue_map,
879 &get_queue_delete_it,
881 GNUNET_CONTAINER_multipeermap_destroy (queue_map);
884 GNUNET_TRANSPORT_communicator_address_remove (ai);
889 GNUNET_TRANSPORT_communicator_disconnect (ch);
894 GNUNET_STATISTICS_destroy (stats,
902 * Function called when the transport service has received an
903 * acknowledgement for this communicator (!) via a different return
906 * Not applicable for UNIX.
909 * @param sender which peer sent the notification
913 enc_notify_cb (void *cls,
914 const struct GNUNET_PeerIdentity *sender,
915 const struct GNUNET_MessageHeader *msg)
925 * Setup communicator and launch network interactions.
927 * @param cls NULL (always)
928 * @param args remaining command-line arguments
929 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
930 * @param cfg configuration
936 const struct GNUNET_CONFIGURATION_Handle *cfg)
945 GNUNET_CONFIGURATION_get_value_filename (cfg,
946 COMMUNICATOR_CONFIG_SECTION,
950 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
951 COMMUNICATOR_CONFIG_SECTION,
956 GNUNET_CONFIGURATION_get_value_number (cfg,
957 COMMUNICATOR_CONFIG_SECTION,
960 max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
962 in = tcp_address_to_sockaddr (bindto,
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 "Failed to setup TCP socket address with path `%s'\n",
969 GNUNET_free (bindto);
972 listen_sock = GNUNET_NETWORK_socket_create (in->sa_family,
975 if (NULL == listen_sock)
977 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
980 GNUNET_free (bindto);
984 GNUNET_NETWORK_socket_bind (listen_sock,
988 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
991 GNUNET_NETWORK_socket_close (listen_sock);
994 GNUNET_free (bindto);
998 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1001 stats = GNUNET_STATISTICS_create ("C-TCP",
1003 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1005 listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1009 queue_map = GNUNET_CONTAINER_multipeermap_create (10,
1011 ch = GNUNET_TRANSPORT_communicator_connect (cfg,
1012 COMMUNICATOR_CONFIG_SECTION,
1013 COMMUNICATOR_ADDRESS_PREFIX,
1014 GNUNET_TRANSPORT_CC_RELIABLE,
1022 GNUNET_SCHEDULER_shutdown ();
1023 GNUNET_free (bindto);
1026 // FIXME: bindto is wrong here, we MUST get our external
1027 // IP address and really look at 'in' here as we might
1028 // be bound to loopback or some other specific IP address!
1029 GNUNET_asprintf (&my_addr,
1031 COMMUNICATOR_ADDRESS_PREFIX,
1033 GNUNET_free (bindto);
1034 // FIXME: based on our bindto, we might not be able to tell the
1035 // network type yet! What to do here!?
1036 ai = GNUNET_TRANSPORT_communicator_address_add (ch,
1038 GNUNET_NT_LOOPBACK, // FIXME: wrong NT!
1039 GNUNET_TIME_UNIT_FOREVER_REL);
1040 GNUNET_free (my_addr);
1045 * The main function for the UNIX communicator.
1047 * @param argc number of arguments from the command line
1048 * @param argv command line arguments
1049 * @return 0 ok, 1 on error
1055 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1056 GNUNET_GETOPT_OPTION_END
1061 GNUNET_STRINGS_get_utf8_args (argc, argv,
1067 GNUNET_PROGRAM_run (argc, argv,
1068 "gnunet-communicator-tcp",
1069 _("GNUnet TCP communicator"),
1073 GNUNET_free ((void*) argv);
1078 #if defined(LINUX) && defined(__GLIBC__)
1082 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1084 void __attribute__ ((constructor))
1085 GNUNET_ARM_memory_init ()
1087 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1088 mallopt (M_TOP_PAD, 1 * 1024);
1093 /* end of gnunet-communicator-tcp.c */