From e6285bfc07cc2453dc3c6e532c191bcac30ff1f6 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 19 Aug 2020 01:29:45 -0400 Subject: [PATCH 01/70] also write tox_save in client mode (with -C) --- main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index ed2020e..6554aa4 100644 --- a/main.c +++ b/main.c @@ -1524,6 +1524,11 @@ int main(int argc, char *argv[]) do_bootstrap(tox); + if((!client_mode) || load_saved_toxid_in_client_mode) + { + write_save(tox); + } + if(client_mode) { uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; @@ -1550,8 +1555,6 @@ int main(int argc, char *argv[]) uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; char_t readable_dht_key[2 * TOX_PUBLIC_KEY_SIZE + 1]; - write_save(tox); - if(!use_shared_secret) { log_printf(L_WARNING, "Shared secret authentication is not used - skilled attackers may connect to your tuntox server"); From ee6e9376ab416283340d62c1f901bd1c04e2319e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 19 Aug 2020 01:47:34 -0400 Subject: [PATCH 02/70] Remove spurious debug output This produced a nonsensical warning in client mode. It is also redundant as there is this line: log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); --- main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/main.c b/main.c index 6554aa4..079a9c3 100644 --- a/main.c +++ b/main.c @@ -1316,7 +1316,6 @@ int main(int argc, char *argv[]) case 'i': /* Tox ID */ server_whitelist_mode = 1; - log_printf(L_DEBUG, "Server whitelist mode enabled"); allowed_toxid_obj = (allowed_toxid *)calloc(sizeof(allowed_toxid), 1); if(!allowed_toxid_obj) { From 15400c29ae57ed6d70fcd3999f8fb6f74bcbd2f1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 19 Aug 2020 01:50:57 -0400 Subject: [PATCH 03/70] Avoid code repetition The client and server blocks were nearly identical. Now they share code. Both client and server now call memset() on tox_printable_id. The distinct client message "Generated Tox ID: %s\n" was not preserved; both client and server will say "Using Tox ID: %s\n" which is more accurate (Tox ID might be persistent with -C). --- main.c | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/main.c b/main.c index 079a9c3..51043d5 100644 --- a/main.c +++ b/main.c @@ -1434,6 +1434,12 @@ int main(int argc, char *argv[]) min_log_level = L_INFO; } + if(client_mode && !remote_tox_id) + { + log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); + exit(1); + } + if(!client_mode && server_whitelist_mode) { log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); @@ -1528,28 +1534,6 @@ int main(int argc, char *argv[]) write_save(tox); } - if(client_mode) - { - uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; - char_t readable_dht_key[2 * TOX_PUBLIC_KEY_SIZE + 1]; - - tox_self_get_address(tox, tox_id); - id_to_string(tox_printable_id, tox_id); - tox_printable_id[TOX_ADDRESS_SIZE * 2] = '\0'; - log_printf(L_DEBUG, "Generated Tox ID: %s\n", tox_printable_id); - - tox_self_get_dht_id(tox, dht_key); - to_hex(readable_dht_key, dht_key, TOX_PUBLIC_KEY_SIZE); - log_printf(L_DEBUG, "DHT key: %s\n", readable_dht_key); - - if(!remote_tox_id) - { - log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); - exit(1); - } - do_client_loop(remote_tox_id); - } - else { uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; char_t readable_dht_key[2 * TOX_PUBLIC_KEY_SIZE + 1]; @@ -1569,9 +1553,16 @@ int main(int argc, char *argv[]) to_hex(readable_dht_key, dht_key, TOX_PUBLIC_KEY_SIZE); log_printf(L_DEBUG, "DHT key: %s\n", readable_dht_key); - tox_callback_friend_request(tox, accept_friend_request); - do_server_loop(); - clear_rules(); + if (client_mode) + { + do_client_loop(remote_tox_id); + } + else + { + tox_callback_friend_request(tox, accept_friend_request); + do_server_loop(); + clear_rules(); + } } return 0; From c72d70950d02fc2e4c709b672e89b25765aa0986 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 19 Aug 2020 02:36:22 -0400 Subject: [PATCH 04/70] gitignore build products --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 272c4eb..d98cdd6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ # tuntox related, not needed in repo tuntox +tuntox_nostatic +debian/debhelper-build-stamp +debian/files +debian/tuntox.substvars From de62d93767d02a6c4768936670b668eca5f3fafe Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 06:41:38 -0400 Subject: [PATCH 05/70] remove unused variable --- main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 51043d5..f9153c7 100644 --- a/main.c +++ b/main.c @@ -953,7 +953,6 @@ int do_server_loop() while(1) { - TOX_CONNECTION tmp_isconnected = 0; uint32_t tox_do_interval_ms; int select_rv = 0; sent_data = 0; @@ -969,10 +968,9 @@ int do_server_loop() gettimeofday(&tv_start, NULL); /* Check change in connection state */ - tmp_isconnected = connection_status; - if(tmp_isconnected != connected) + if(connection_status != connected) { - connected = tmp_isconnected; + connected = connection_status; if(connected) { log_printf(L_DEBUG, "Connected to Tox network\n"); From 5d1bce667f97244718bbeaff42bade637782c6ba Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 06:42:18 -0400 Subject: [PATCH 06/70] whitespace fixes --- client.c | 74 ++++++++++++++++----------------- main.c | 124 +++++++++++++++++++++++++++---------------------------- util.c | 12 +++--- 3 files changed, 105 insertions(+), 105 deletions(-) diff --git a/client.c b/client.c index 3073e5d..1e02286 100644 --- a/client.c +++ b/client.c @@ -310,12 +310,12 @@ int do_client_loop(uint8_t *tox_id_str) while(1) { - /* Let tox do its stuff */ - tox_iterate(tox, NULL); + /* Let tox do its stuff */ + tox_iterate(tox, NULL); switch(state) { - /* + /* * Send friend request */ case CLIENT_STATE_INITIAL: @@ -501,7 +501,7 @@ int do_client_loop(uint8_t *tox_id_str) tv.tv_sec = 0; tv.tv_usec = 20000; fds = client_master_fdset; - + /* Handle accepting new connections */ if(!client_pipe_mode && client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ @@ -628,39 +628,39 @@ int do_client_loop(uint8_t *tox_id_str) } } break; - case CLIENT_STATE_CONNECTION_LOST: - { - TOX_CONNECTION friend_connection_status; - friend_connection_status = tox_friend_get_connection_status(tox, friendnumber, &friend_query_error); - if(friend_query_error != TOX_ERR_FRIEND_QUERY_OK) - { - log_printf(L_DEBUG, "tox_friend_get_connection_status: error %u\n", friend_query_error); - } - else - { - if(friend_connection_status == TOX_CONNECTION_NONE) - { - /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1267 */ - TOX_ERR_FRIEND_DELETE tox_delete_error; - - log_printf(L_WARNING, "Lost connection to server, closing all tunnels and re-adding friend\n"); - client_close_all_connections(); - tox_friend_delete(tox, friendnumber, &tox_delete_error); - if(tox_delete_error) - { - log_printf(L_ERROR, "Error when deleting server from friend list: %d\n", tox_delete_error); - } - state = CLIENT_STATE_INITIAL; - } - else - { - state = CLIENT_STATE_FORWARDING; - } - } - } - break; - case 0xffffffff: - log_printf(L_ERROR, "You forgot a break statement\n"); + case CLIENT_STATE_CONNECTION_LOST: + { + TOX_CONNECTION friend_connection_status; + friend_connection_status = tox_friend_get_connection_status(tox, friendnumber, &friend_query_error); + if(friend_query_error != TOX_ERR_FRIEND_QUERY_OK) + { + log_printf(L_DEBUG, "tox_friend_get_connection_status: error %u\n", friend_query_error); + } + else + { + if(friend_connection_status == TOX_CONNECTION_NONE) + { + /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1267 */ + TOX_ERR_FRIEND_DELETE tox_delete_error; + + log_printf(L_WARNING, "Lost connection to server, closing all tunnels and re-adding friend\n"); + client_close_all_connections(); + tox_friend_delete(tox, friendnumber, &tox_delete_error); + if(tox_delete_error) + { + log_printf(L_ERROR, "Error when deleting server from friend list: %d\n", tox_delete_error); + } + state = CLIENT_STATE_INITIAL; + } + else + { + state = CLIENT_STATE_FORWARDING; + } + } + } + break; + case 0xffffffff: + log_printf(L_ERROR, "You forgot a break statement\n"); case CLIENT_STATE_SHUTDOWN: exit(0); break; diff --git a/main.c b/main.c index f9153c7..d3bd3a8 100644 --- a/main.c +++ b/main.c @@ -161,7 +161,7 @@ void tunnel_delete(tunnel *t) free(t); } -int tunnel_in_delete_queue(tunnel *t) +int tunnel_in_delete_queue(tunnel *t) { tunnel_list *element; @@ -232,7 +232,7 @@ void set_tox_username(Tox *tox) /* Get sockaddr, IPv4 or IPv6 */ void *get_in_addr(struct sockaddr *sa) { - if (sa->sa_family == AF_INET) + if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } @@ -254,7 +254,7 @@ int get_client_socket(char *hostname, int port) hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; - if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) + if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { /* Add a special case for "localhost" when name resolution is broken */ if(!strncmp("localhost", hostname, 256)) @@ -273,7 +273,7 @@ int get_client_socket(char *hostname, int port) } // loop through all the results and connect to the first we can - for(p = servinfo; p != NULL; p = p->ai_next) + for(p = servinfo; p != NULL; p = p->ai_next) { if (p->ai_family != AF_INET && p->ai_family != AF_INET6) continue; @@ -311,8 +311,8 @@ int get_client_socket(char *hostname, int port) /* Proto - our protocol handling */ -/* - * send_frame: (almost) zero-copy. Overwrites first PROTOCOL_BUFFER_OFFSET bytes of data +/* + * send_frame: (almost) zero-copy. Overwrites first PROTOCOL_BUFFER_OFFSET bytes of data * so actual data should start at position PROTOCOL_BUFFER_OFFSET */ int send_frame(protocol_frame *frame, uint8_t *data) @@ -414,7 +414,7 @@ int handle_ping_frame(protocol_frame *rcvd_frame) frame->friendnumber = rcvd_frame->friendnumber; frame->packet_type = PACKET_TYPE_PONG; frame->data_length = rcvd_frame->data_length; - + send_frame(frame, data); return 0; @@ -433,7 +433,7 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) log_printf(L_WARNING, "Got tunnel request frame from friend #%d when in client mode\n", rcvd_frame->friendnumber); return -1; } - + port = rcvd_frame->connid; hostname = calloc(1, rcvd_frame->data_length + 1); if(!hostname) @@ -446,14 +446,14 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) hostname[rcvd_frame->data_length] = '\0'; log_printf(L_INFO, "Got a request to forward data from %s:%d\n", hostname, port); - + // check rules if (rules_policy == VALIDATE && nrules > 0 ) { - + rule temp_rule, *found = NULL; temp_rule.host = hostname; temp_rule.port = port; - + LL_SEARCH(rules, found, &temp_rule, rule_cmp); if(!found) { @@ -532,7 +532,7 @@ int handle_client_tcp_frame(protocol_frame *rcvd_frame) int sent_bytes; sent_bytes = send( - tun->sockfd, + tun->sockfd, rcvd_frame->data + offset, rcvd_frame->data_length - offset, MSG_NOSIGNAL @@ -569,7 +569,7 @@ int handle_client_tcp_fin_frame(protocol_frame *rcvd_frame) log_printf(L_WARNING, "Friend #%d tried to close tunnel which belongs to #%d\n", rcvd_frame->friendnumber, tun->friendnumber); return -1; } - + log_printf(L_DEBUG2, "Deleting tunnel #%d (%p) in handle_client_tcp_fin_frame(), socket %d", rcvd_frame->connid, tun, tun->sockfd); tunnel_queue_delete(tun); @@ -614,7 +614,7 @@ int handle_frame(protocol_frame *frame) } break; default: - log_printf(L_DEBUG, "Got unknown packet type 0x%x from friend %d\n", + log_printf(L_DEBUG, "Got unknown packet type 0x%x from friend %d\n", frame->packet_type, frame->friendnumber ); @@ -623,7 +623,7 @@ int handle_frame(protocol_frame *frame) return 0; } -/* +/* * This is a callback which gets a packet from Tox core. * It checks for basic inconsistiencies and allocates the * protocol_frame structure. @@ -800,12 +800,12 @@ void load_rules() int valid_rules = 0; file = fopen(rules_file, "r"); - + if (file == NULL) { log_printf(L_WARNING, "Could not open rules file (%s)\n", rules_file); return; } - + while (fgets(line, sizeof(line), file)) { /* allow comments & white lines */ if (line[0]=='#'||line[0]=='\n') { @@ -834,10 +834,10 @@ void load_rules() } } fclose(file); - + /* save valid rules in global variable */ nrules = valid_rules; - + log_printf(L_INFO, "Loaded %d rules\n", nrules); if (nrules==0 && rules_policy != NONE){ log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); @@ -884,7 +884,7 @@ void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *m return; } } - + memset(tox_printable_id, '\0', sizeof(tox_printable_id)); id_to_string(tox_printable_id, public_key); @@ -927,7 +927,7 @@ void cleanup() tox_kill(tox); if(client_socket) { - close(client_socket); + close(client_socket); } log_close(); } @@ -1009,8 +1009,8 @@ int do_server_loop() log_printf(L_DEBUG, "Current tunnel: %p", tun); if(FD_ISSET(tun->sockfd, &fds)) { - int nbytes = recv(tun->sockfd, - tox_packet_buf+PROTOCOL_BUFFER_OFFSET, + int nbytes = recv(tun->sockfd, + tox_packet_buf+PROTOCOL_BUFFER_OFFSET, READ_BUFFER_SIZE, 0); /* Check if connection closed */ @@ -1039,7 +1039,7 @@ int do_server_loop() sent_data = 1; tunnel_queue_delete(tun); - + continue; } else @@ -1070,7 +1070,7 @@ int do_server_loop() gettimeofday(&tv_end, NULL); ms_start = 1000 * tv_start.tv_sec + tv_start.tv_usec/1000; ms_end = 1000 * tv_end.tv_sec + tv_end.tv_usec/1000; - + if(!sent_data && (ms_end - ms_start < tox_do_interval_ms)) { /*log_printf(L_DEBUG, "Sleeping for %d ms extra to prevent high CPU usage\n", (tox_do_interval_ms - (ms_end - ms_start)));*/ @@ -1089,7 +1089,7 @@ static void child_handler(int signum) } } -/* +/* * Daemonize the process if -D is set * Optionally drop privileges and create a lock file */ @@ -1099,17 +1099,17 @@ void do_daemonize() FILE *pidf = NULL; /* already a daemon */ - if (getppid() == 1) + if (getppid() == 1) { return; } /* Drop user if there is one, and we were run as root */ - if (daemon_username && (getuid() == 0 || geteuid() == 0)) + if (daemon_username && (getuid() == 0 || geteuid() == 0)) { struct passwd *pw = getpwnam(daemon_username); - if(pw) + if(pw) { log_printf(L_DEBUG, "Setuid to user %s", daemon_username); setuid(pw->pw_uid); @@ -1139,14 +1139,14 @@ void do_daemonize() /* Fork off the parent process */ pid = fork(); - if (pid < 0) + if (pid < 0) { log_printf(L_ERROR, "Unable to fork daemon, code=%d (%s)", errno, strerror(errno)); exit(1); } /* If we got a good PID, then we can exit the parent process. */ - if (pid > 0) + if (pid > 0) { /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or for two seconds to elapse (SIGALRM). pause() should not return. */ @@ -1175,7 +1175,7 @@ void do_daemonize() /* Create a new SID for the child process */ sid = setsid(); - if (sid < 0) + if (sid < 0) { log_printf(L_ERROR, "unable to create a new session, code %d (%s)", errno, strerror(errno)); @@ -1184,7 +1184,7 @@ void do_daemonize() /* Change the current working directory. This prevents the current directory from being locked; hence not being able to remove it. */ - if ((chdir("/")) < 0) + if ((chdir("/")) < 0) { log_printf(L_ERROR, "Unable to change directory to %s, code %d (%s)", "/", errno, strerror(errno) ); @@ -1197,10 +1197,10 @@ void do_daemonize() freopen( "/dev/null", "w", stderr); /* Create the pid file as the new user */ - if (pidfile && pidfile[0]) + if (pidfile && pidfile[0]) { pidf = fopen(pidfile, "w"); - if (!pidf) + if (!pidf) { log_printf(L_ERROR, "Unable to create PID file %s, code=%d (%s)", pidfile, errno, strerror(errno)); @@ -1212,7 +1212,7 @@ void do_daemonize() /* Tell the parent process that we are A-okay */ - kill( parent, SIGUSR1 ); + kill( parent, SIGUSR1 ); } void help() @@ -1239,8 +1239,8 @@ void help() fprintf(stderr, " mode\n"); fprintf(stderr, " -s - shared secret used for connection authentication (max\n"); fprintf(stderr, " %u characters)\n", TOX_MAX_FRIEND_REQUEST_LENGTH-1); - fprintf(stderr, " -t - set TCP relay port (0 disables TCP relaying)\n"); - fprintf(stderr, " -u : - set Tox UDP port range\n"); + fprintf(stderr, " -t - set TCP relay port (0 disables TCP relaying)\n"); + fprintf(stderr, " -u : - set Tox UDP port range\n"); fprintf(stderr, " -d - debug mode (use twice to display toxcore log too)\n"); fprintf(stderr, " -q - quiet mode\n"); fprintf(stderr, " -S - send output to syslog instead of stderr\n"); @@ -1260,11 +1260,11 @@ int main(int argc, char *argv[]) size_t save_size = 0; uint8_t *save_data = NULL; allowed_toxid *allowed_toxid_obj = NULL; - - srand(time(NULL)); - tcp_relay_port = 1024 + (rand() % 64511); - udp_start_port = 1024 + (rand() % 64500); - udp_end_port = udp_start_port + 10; + + srand(time(NULL)); + tcp_relay_port = 1024 + (rand() % 64511); + udp_start_port = 1024 + (rand() % 64500); + udp_end_port = udp_start_port + 10; log_init(); @@ -1334,7 +1334,7 @@ int main(int argc, char *argv[]) if(optarg[strlen(optarg) - 1] != '/') { int optarg_len = strlen(optarg); - + config_path[optarg_len] = '/'; config_path[optarg_len + 1] = '\0'; } @@ -1356,7 +1356,7 @@ int main(int argc, char *argv[]) { log_tox_trace = 1; } - if(min_log_level != L_DEBUG && min_log_level != L_DEBUG2) + if(min_log_level != L_DEBUG && min_log_level != L_DEBUG2) { min_log_level = L_DEBUG; } @@ -1442,7 +1442,7 @@ int main(int argc, char *argv[]) { log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); } - + if((!client_mode) && (rules_policy != NONE)) { load_rules(); @@ -1470,22 +1470,22 @@ int main(int argc, char *argv[]) /* Bootstrap tox */ tox_options_default(&tox_options); - if(min_log_level >= L_DEBUG2) - { - tox_options.log_callback = on_tox_log; - } - tox_options.udp_enabled = 1; - tox_options.local_discovery_enabled = 1; - tox_options.tcp_port = tcp_relay_port; - tox_options.start_port = udp_start_port; - tox_options.end_port = udp_end_port; - tox_options.hole_punching_enabled = 1; - - log_printf(L_INFO, "Using %d for TCP relay port and %d-%d for UDP", - tox_options.tcp_port, - tox_options.start_port, - tox_options.end_port - ); + if(min_log_level >= L_DEBUG2) + { + tox_options.log_callback = on_tox_log; + } + tox_options.udp_enabled = 1; + tox_options.local_discovery_enabled = 1; + tox_options.tcp_port = tcp_relay_port; + tox_options.start_port = udp_start_port; + tox_options.end_port = udp_end_port; + tox_options.hole_punching_enabled = 1; + + log_printf(L_INFO, "Using %d for TCP relay port and %d-%d for UDP", + tox_options.tcp_port, + tox_options.start_port, + tox_options.end_port + ); if((!client_mode) || load_saved_toxid_in_client_mode) { diff --git a/util.c b/util.c index 3e6a99c..01fbe65 100644 --- a/util.c +++ b/util.c @@ -92,12 +92,12 @@ int parse_local_port_forward(char *string, int *local_port, char **hostname, int /* First replace all @ with :, ':' is forbidden in some environments */ char *p = string; - while(*p) - { + while(*p) + { if(*p == '@') *p = ':'; p++; } - + lport = strtok(string, ":"); host = strtok(NULL, ":"); rport = strtok(NULL, ":"); @@ -123,12 +123,12 @@ int parse_pipe_port_forward(char *string, char **hostname, int *remote_port) /* First replace all @ with :, ':' is forbidden in some environments */ char *p = string; - while(*p) - { + while(*p) + { if(*p == '@') *p = ':'; p++; } - + host = strtok(string, ":"); rport = strtok(NULL, ":"); From d2345a8a2f28aed7722cbd76cc3f03543db90bbd Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 06:45:08 -0400 Subject: [PATCH 07/70] tokssh: persist client key if ~/.tuntox/persist/ exists --- scripts/tokssh | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/scripts/tokssh b/scripts/tokssh index eeddb21..8169bdd 100755 --- a/scripts/tokssh +++ b/scripts/tokssh @@ -23,9 +23,17 @@ examples: tokssh user@5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 -s TuNToXSeCreT files: - ~/.tuntox/hosts maps hostname to ToxID and optional secret. - format is - hostname ToxID secret(optional) + ~/.tuntox/persist/ + + If directory exists, then read & store a persistent secret key/TOXID within. + + ~/.tuntox/hosts + + Maps hostname to ToxID and optional secret. + + format is: + + hostname ToxID secret(optional) EOF } @@ -84,4 +92,10 @@ if [ -f ~/.tuntox/hosts ]; then done < ~/.tuntox/hosts fi -ssh -o ProxyCommand="tuntox -i $toxid -W 127.0.0.1:%p $secret" $args ${user}${hostname} +if [ -d ~/.tuntox/persist ]; then + persist='-C ~/.tuntox/persist' +else + persist= +fi + +ssh -o ProxyCommand="tuntox $persist -i $toxid -W 127.0.0.1:%p $secret" $args ${user}${hostname} From 930eda72be5ee1f3b61aa2ea6280eacd8fe01b36 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 07:02:25 -0400 Subject: [PATCH 08/70] improve parsing --- util.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/util.c b/util.c index 01fbe65..0084c19 100644 --- a/util.c +++ b/util.c @@ -90,17 +90,11 @@ int parse_local_port_forward(char *string, int *local_port, char **hostname, int char *host; char *rport; - /* First replace all @ with :, ':' is forbidden in some environments */ - char *p = string; - while(*p) - { - if(*p == '@') *p = ':'; - p++; - } + /* Alternative delimiter '@', as ':' is forbidden in some environments */ - lport = strtok(string, ":"); - host = strtok(NULL, ":"); - rport = strtok(NULL, ":"); + lport = strtok(string, ":@"); + host = strtok(NULL, ":@"); + rport = strtok(NULL, ":@"); if(!lport || !host || !rport) { @@ -121,16 +115,10 @@ int parse_pipe_port_forward(char *string, char **hostname, int *remote_port) char *host; char *rport; - /* First replace all @ with :, ':' is forbidden in some environments */ - char *p = string; - while(*p) - { - if(*p == '@') *p = ':'; - p++; - } + /* Alternative delimiter '@', as ':' is forbidden in some environments */ - host = strtok(string, ":"); - rport = strtok(NULL, ":"); + host = strtok(string, ":@"); + rport = strtok(NULL, ":@"); if(!host || !rport) { From 8b340e2ae7abf51f17c772a0cbb7c2ac38f2023e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 08:28:16 -0400 Subject: [PATCH 09/70] ping mode: quit after pong (per documentation) --- client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.c b/client.c index 1e02286..daefe54 100644 --- a/client.c +++ b/client.c @@ -37,7 +37,7 @@ int handle_pong_frame() if(ping_mode) { - state = CLIENT_STATE_SEND_PING; + state = CLIENT_STATE_SHUTDOWN; } return 0; } From 9217b34608eeb74b3273bc844b1eedf527c0d7d1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 08:43:42 -0400 Subject: [PATCH 10/70] remove unused variable --- client.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client.c b/client.c index daefe54..5ea3b4d 100644 --- a/client.c +++ b/client.c @@ -281,7 +281,6 @@ int do_client_loop(uint8_t *tox_id_str) uint32_t friendnumber = 0; TOX_CONNECTION last_friend_connection_status = TOX_CONNECTION_NONE; time_t last_friend_connection_status_received = 0; - time_t connection_lost_timestamp = 0; struct timeval tv; fd_set fds; static time_t invitation_sent_time = 0; @@ -618,7 +617,6 @@ int do_client_loop(uint8_t *tox_id_str) if(friend_connection_status == TOX_CONNECTION_NONE) { state = CLIENT_STATE_CONNECTION_LOST; - connection_lost_timestamp = time(NULL); } } From 6ce9e569d8afa86d80005775c0a86cce9c4847a7 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 08:47:27 -0400 Subject: [PATCH 11/70] avoid redundant comparison --- main.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/main.c b/main.c index d3bd3a8..117747b 100644 --- a/main.c +++ b/main.c @@ -985,17 +985,14 @@ int do_server_loop() /* Poll for data from our client connection */ select_rv = select(select_nfds, &fds, NULL, NULL, &tv); - if(select_rv == -1 || select_rv == 0) + if(select_rv == -1) { - if(select_rv == -1) - { - log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", - errno, strerror(errno)); - } - else - { - log_printf(L_DEBUG2, "Nothing to read..."); - } + log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", + errno, strerror(errno)); + } + else if (select_rv == 0) + { + log_printf(L_DEBUG2, "Nothing to read..."); } else { From ab4fa64b6353d9e30da9b8beeb5e52d4b2fbe5b6 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 09:38:40 -0400 Subject: [PATCH 12/70] use tox_callback_friend_connection_status instead of polling --- client.c | 50 ++++---------------------------------------------- main.c | 15 ++++++++++++++- main.h | 2 ++ 3 files changed, 20 insertions(+), 47 deletions(-) diff --git a/client.c b/client.c index 5ea3b4d..67d4fd3 100644 --- a/client.c +++ b/client.c @@ -279,13 +279,10 @@ int do_client_loop(uint8_t *tox_id_str) unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; unsigned char tox_id[TOX_ADDRESS_SIZE]; uint32_t friendnumber = 0; - TOX_CONNECTION last_friend_connection_status = TOX_CONNECTION_NONE; - time_t last_friend_connection_status_received = 0; struct timeval tv; fd_set fds; static time_t invitation_sent_time = 0; uint32_t invitations_sent = 0; - TOX_ERR_FRIEND_QUERY friend_query_error; TOX_ERR_FRIEND_CUSTOM_PACKET custom_packet_error; client_tunnel.sockfd = 0; @@ -371,17 +368,7 @@ int do_client_loop(uint8_t *tox_id_str) break; case CLIENT_STATE_SENTREQUEST: { - TOX_CONNECTION friend_connection_status; - friend_connection_status = tox_friend_get_connection_status(tox, friendnumber, &friend_query_error); - if(friend_query_error != TOX_ERR_FRIEND_QUERY_OK) { - log_printf(L_DEBUG, "tox_friend_get_connection_status: error %u", friend_query_error); - } - else - { - last_friend_connection_status_received = time(NULL); - last_friend_connection_status = friend_connection_status; - if(friend_connection_status != TOX_CONNECTION_NONE) { const char* status = readable_connection_status(friend_connection_status); @@ -390,7 +377,8 @@ int do_client_loop(uint8_t *tox_id_str) } else { - if(1 && (time(NULL) - invitation_sent_time > 45)) + const int INVITATION_SEND_INTERVAL = 90; + if (time(NULL) - invitation_sent_time > INVITATION_SEND_INTERVAL) { TOX_ERR_FRIEND_DELETE error = 0; @@ -597,44 +585,14 @@ int do_client_loop(uint8_t *tox_id_str) fds = client_master_fdset; /* Check friend connection status changes */ - /* TODO: learned about tox_friend_connection_status_cb after writing this... */ - /* TODO: also check friend status tox_callback_friend_status */ - if(time(NULL) - last_friend_connection_status_received > 15) + if(friend_connection_status == TOX_CONNECTION_NONE) { - TOX_CONNECTION friend_connection_status; - friend_connection_status = tox_friend_get_connection_status(tox, friendnumber, &friend_query_error); - if(friend_query_error != TOX_ERR_FRIEND_QUERY_OK) - { - log_printf(L_DEBUG, "tox_friend_get_connection_status: error %u\n", friend_query_error); - } - else - { - if(friend_connection_status != last_friend_connection_status) - { - const char* status = readable_connection_status(friend_connection_status); - log_printf(L_INFO, "Friend connection status changed to: %s (%d)\n", status, friend_connection_status); - - if(friend_connection_status == TOX_CONNECTION_NONE) - { - state = CLIENT_STATE_CONNECTION_LOST; - } - } - - last_friend_connection_status_received = time(NULL); - last_friend_connection_status = friend_connection_status; - } + state = CLIENT_STATE_CONNECTION_LOST; } } break; case CLIENT_STATE_CONNECTION_LOST: { - TOX_CONNECTION friend_connection_status; - friend_connection_status = tox_friend_get_connection_status(tox, friendnumber, &friend_query_error); - if(friend_query_error != TOX_ERR_FRIEND_QUERY_OK) - { - log_printf(L_DEBUG, "tox_friend_get_connection_status: error %u\n", friend_query_error); - } - else { if(friend_connection_status == TOX_CONNECTION_NONE) { diff --git a/main.c b/main.c index 117747b..f38784e 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ Tox *tox; int client_socket = 0; TOX_CONNECTION connection_status = TOX_CONNECTION_NONE; +TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; /** CONFIGURATION OPTIONS **/ /* Whether we're a client */ int client_mode = 0; @@ -908,7 +909,7 @@ void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *m return; } - log_printf(L_INFO, "Accepted friend request from %s as %d\n", tox_printable_id, friendnumber); + log_printf(L_INFO, "Accepted friend request from %s as #%d\n", tox_printable_id, friendnumber); } /* Callback for tox_callback_self_connection_status() */ @@ -920,6 +921,17 @@ void handle_connection_status_change(Tox *tox, TOX_CONNECTION p_connection_statu log_printf(L_INFO, "Connection status changed: %s", status); } +void handle_friend_connection_status(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, void *user_data) +{ + const char *status = NULL; + status = readable_connection_status(connection_status); + log_printf(L_INFO, "Friend #%d connection status changed: %s", friend_number, status); + if(client_mode) + { + friend_connection_status = connection_status; + } +} + void cleanup() { log_printf(L_DEBUG, "kthxbye\n"); @@ -1521,6 +1533,7 @@ int main(int argc, char *argv[]) set_tox_username(tox); tox_callback_self_connection_status(tox, handle_connection_status_change); + tox_callback_friend_connection_status(tox, handle_friend_connection_status); do_bootstrap(tox); diff --git a/main.h b/main.h index 17fb9b9..b998acc 100644 --- a/main.h +++ b/main.h @@ -112,6 +112,8 @@ extern char shared_secret[TOX_MAX_FRIEND_REQUEST_LENGTH]; extern int select_nfds; extern tunnel *by_id; +extern TOX_CONNECTION friend_connection_status; + void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t len, void *tmp); tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber); void tunnel_delete(tunnel *t); From 8569e6c00da8142c4f7f4b9e489608c69fb87f7b Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 17:03:32 -0400 Subject: [PATCH 13/70] two new make targets: install-debs and debs --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 808d57c..e01ffb9 100644 --- a/Makefile +++ b/Makefile @@ -48,4 +48,11 @@ install: tuntox_nostatic $(INSTALL_MKDIR) -d $(DESTDIR)$(bindir) cp tuntox_nostatic $(DESTDIR)$(bindir)/tuntox +debs = ../tuntox_0.0.9-1_amd64.deb ../tuntox-dbgsym_0.0.9-1_amd64.deb +.PHONY: install-debs debs +install-debs: $(debs) + $(shell [ "$$(id -u)" = 0 ] || echo sudo) dpkg -i $(debs) +$(debs) debs: + fakeroot ./debian/rules binary + .PHONY: all clean tuntox From 7712e552474de52fea79a3b7989b90004c4691c6 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 17:06:12 -0400 Subject: [PATCH 14/70] gitignore gitversion.h --- .gitignore | 1 + gitversion.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 gitversion.h diff --git a/.gitignore b/.gitignore index d98cdd6..08bcde6 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ tuntox_nostatic debian/debhelper-build-stamp debian/files debian/tuntox.substvars +gitversion.h diff --git a/gitversion.h b/gitversion.h deleted file mode 100644 index fdb8a74..0000000 --- a/gitversion.h +++ /dev/null @@ -1 +0,0 @@ -#define GITVERSION "0a8b0399cfac7873d350e4b2a90ec5203178922c" From ed93588e1476e5e75f7a18fd3eec56c5c3238a3c Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 17:25:51 -0400 Subject: [PATCH 15/70] add "-dirty" to gitversion.h when tree is dirty" --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e01ffb9..e6b0cef 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ bindir ?= $(prefix)/bin all: tuntox tuntox_nostatic gitversion.h: FORCE - @if [ -f .git/HEAD ] ; then echo " GEN $@"; echo "#define GITVERSION \"$(shell git rev-parse HEAD)\"" > $@; fi + @if [ -f .git/HEAD ] ; then echo " GEN $@"; echo "#define GITVERSION \"$(shell echo -n $$(git rev-parse HEAD) && (git diff --quiet || printf %s -dirty) )\"" > $@; fi FORCE: From a45445e4883c7eeff4f6063ab50c25a983bbec61 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 17:10:12 -0400 Subject: [PATCH 16/70] Implement logging of the remote friend IP address This relies on a patched c-toxcore. For that reason, it is disabled by an #ifdef. --- main.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/main.c b/main.c index f38784e..8915840 100644 --- a/main.c +++ b/main.c @@ -921,11 +921,28 @@ void handle_connection_status_change(Tox *tox, TOX_CONNECTION p_connection_statu log_printf(L_INFO, "Connection status changed: %s", status); } +#ifdef LOG_IP_ADDRESS +void log_friend_ip_address(Tox *tox, uint32_t friendnumber) +{ + IP_Port ip_port = tox_friend_get_connection_info(tox, friendnumber); + if (net_family_is_unspec(ip_port.ip.family)) return; + char ip_str[IP_NTOA_LEN]; + log_printf(L_INFO, "Friend #%d: IP: %s Port: %u\n", + friendnumber, + ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), + net_ntohs(ip_port.port)); +} +#endif + void handle_friend_connection_status(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, void *user_data) { const char *status = NULL; status = readable_connection_status(connection_status); log_printf(L_INFO, "Friend #%d connection status changed: %s", friend_number, status); +#ifdef LOG_IP_ADDRESS + if(connection_status == TOX_CONNECTION_UDP) + log_friend_ip_address(tox, friend_number); +#endif if(client_mode) { friend_connection_status = connection_status; From f70b248390060da885ba4da372393a0292a75e6a Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 20 Aug 2020 17:14:02 -0400 Subject: [PATCH 17/70] skip tox bootstrap --- main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 8915840..98b09b6 100644 --- a/main.c +++ b/main.c @@ -11,12 +11,14 @@ static struct Tox_Options tox_options; Tox *tox; int client_socket = 0; TOX_CONNECTION connection_status = TOX_CONNECTION_NONE; - TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; /** CONFIGURATION OPTIONS **/ /* Whether we're a client */ int client_mode = 0; +/* Don't bootstrap nodes */ +int skip_bootstrap = 1; + /* Just send a ping and exit */ int ping_mode = 0; @@ -1552,7 +1554,8 @@ int main(int argc, char *argv[]) tox_callback_self_connection_status(tox, handle_connection_status_change); tox_callback_friend_connection_status(tox, handle_friend_connection_status); - do_bootstrap(tox); + if (!skip_bootstrap) + do_bootstrap(tox); if((!client_mode) || load_saved_toxid_in_client_mode) { From f32dfb23412095f6bd19f96cc8e06fdf3cadc30e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 04:29:19 -0400 Subject: [PATCH 18/70] improve clarity --- main.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 98b09b6..7b267c0 100644 --- a/main.c +++ b/main.c @@ -1288,6 +1288,7 @@ int main(int argc, char *argv[]) size_t save_size = 0; uint8_t *save_data = NULL; allowed_toxid *allowed_toxid_obj = NULL; + int verbosity = 0; srand(time(NULL)); tcp_relay_port = 1024 + (rand() % 64511); @@ -1380,19 +1381,19 @@ int main(int argc, char *argv[]) strncpy(shared_secret, optarg, TOX_MAX_FRIEND_REQUEST_LENGTH-1); break; case 'd': - if(min_log_level == L_DEBUG2) - { - log_tox_trace = 1; - } - if(min_log_level != L_DEBUG && min_log_level != L_DEBUG2) - { - min_log_level = L_DEBUG; - } - else - { - min_log_level = L_DEBUG2; - } - + switch(++verbosity) + { + case 1: + min_log_level = L_DEBUG; + break; + case 2: + min_log_level = L_DEBUG2; + break; + case 3: + default: + min_log_level = L_DEBUG2; + log_tox_trace = 1; + } break; case 'q': min_log_level = L_ERROR; From bd9ff5dca38171597651693b56c3be272040330d Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 04:32:26 -0400 Subject: [PATCH 19/70] avoid unneeded conditionals --- main.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index 7b267c0..c94409d 100644 --- a/main.c +++ b/main.c @@ -451,8 +451,8 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) log_printf(L_INFO, "Got a request to forward data from %s:%d\n", hostname, port); // check rules - if (rules_policy == VALIDATE && nrules > 0 ) { - + if(rules_policy == VALIDATE && nrules > 0) + { rule temp_rule, *found = NULL; temp_rule.host = hostname; temp_rule.port = port; @@ -461,18 +461,14 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) if(!found) { log_printf(L_WARNING, "Rejected, request not in rules\n"); - if(hostname) - { - free(hostname); - } + free(hostname); return -1; } - } else if (rules_policy != NONE) { + } + else if (rules_policy != NONE) + { log_printf(L_WARNING, "Filter option active but no allowed host/port. All requests will be dropped.\n"); - if(hostname) - { - free(hostname); - } + free(hostname); return -1; } From de2f3dcbd8e5769c24e13cb2796bab006176e437 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 04:56:56 -0400 Subject: [PATCH 20/70] fix indentation --- main.c | 72 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/main.c b/main.c index c94409d..93bfe8f 100644 --- a/main.c +++ b/main.c @@ -1407,42 +1407,42 @@ int main(int argc, char *argv[]) case 'U': daemon_username = optarg; break; - case 't': - errno = 0; - tcp_relay_port = strtol(optarg, NULL, 10); - if(errno != 0 || tcp_relay_port < 0 || tcp_relay_port > 65535) - { - tcp_relay_port = 1024 + (rand() % 64511); - log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); - } - break; - case 'u': - { /* TODO make a function in util.h */ - char *sport; - char *eport; - - sport = strtok(optarg, ":"); - eport = strtok(NULL, ":"); - if(!sport || !eport) - { - log_printf(L_WARNING, "Ignored -u %s: wrong format"); - } - else - { - errno = 0; - udp_start_port = strtol(sport, NULL, 10); - udp_end_port = strtol(eport, NULL, 10); - if(errno != 0 || udp_start_port < 1 || udp_start_port > 65535 || \ - udp_end_port < 1 || udp_end_port > 65535) - { - log_printf(L_WARNING, "Ignored -u %s: ports need to be integers between 1 and 65535"); - udp_start_port = 1024 + (rand() % 64500); - udp_end_port = udp_start_port + 10; - } - - } - } - break; + case 't': + errno = 0; + tcp_relay_port = strtol(optarg, NULL, 10); + if(errno != 0 || tcp_relay_port < 0 || tcp_relay_port > 65535) + { + tcp_relay_port = 1024 + (rand() % 64511); + log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); + } + break; + case 'u': + { /* TODO make a function in util.h */ + char *sport; + char *eport; + + sport = strtok(optarg, ":"); + eport = strtok(NULL, ":"); + if(!sport || !eport) + { + log_printf(L_WARNING, "Ignored -u %s: wrong format"); + } + else + { + errno = 0; + udp_start_port = strtol(sport, NULL, 10); + udp_end_port = strtol(eport, NULL, 10); + if(errno != 0 || udp_start_port < 1 || udp_start_port > 65535 || \ + udp_end_port < 1 || udp_end_port > 65535) + { + log_printf(L_WARNING, "Ignored -u %s: ports need to be integers between 1 and 65535"); + udp_start_port = 1024 + (rand() % 64500); + udp_end_port = udp_start_port + 10; + } + + } + } + break; case '?': case 'h': default: From 1c8ef41b1b7c42bcfe5625f6996d02a0e3dae5d0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 08:01:08 -0400 Subject: [PATCH 21/70] Move rule check to separate function Renamed some variables. Improved clarity of conditional. --- main.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/main.c b/main.c index 93bfe8f..2a230e0 100644 --- a/main.c +++ b/main.c @@ -109,7 +109,7 @@ int allowed_toxid_cmp(allowed_toxid *a, allowed_toxid *b) } /* Comparison function for rule objects */ -int rule_cmp(rule *a, rule *b) +int rule_match(rule *a, rule *b) { //log_printf(L_INFO, "Comparison result: %d %d\n", strcmp(a->host, b->host), (a->port == b->port)); if ((strcmp(a->host, b->host)==0) && (a->port == b->port)) @@ -423,6 +423,34 @@ int handle_ping_frame(protocol_frame *rcvd_frame) return 0; } +bool check_requested_tunnel_against_rules(char *hostname, in_port_t port) +{ + switch(rules_policy) + { + case NONE: + return true; + case VALIDATE: + if(nrules > 0) + { + rule candidate, *found = NULL; + candidate.host = hostname; + candidate.port = port; + + LL_SEARCH(rules, found, &candidate, rule_match); + if(!found) + { + log_printf(L_WARNING, "Rejected, request not in rules\n"); + } + return found; + } + log_printf(L_WARNING, "Filter option active but no allowed host/port. All requests will be dropped.\n"); + return false; + default: + log_printf(L_WARNING, "BUG: invalid rules_policy (impossible!)\n"); + return false; + } +} + int handle_request_tunnel_frame(protocol_frame *rcvd_frame) { char *hostname = NULL; @@ -450,30 +478,12 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) log_printf(L_INFO, "Got a request to forward data from %s:%d\n", hostname, port); - // check rules - if(rules_policy == VALIDATE && nrules > 0) + if (!check_requested_tunnel_against_rules(hostname, port)) { - rule temp_rule, *found = NULL; - temp_rule.host = hostname; - temp_rule.port = port; - - LL_SEARCH(rules, found, &temp_rule, rule_cmp); - if(!found) - { - log_printf(L_WARNING, "Rejected, request not in rules\n"); - free(hostname); - return -1; - } - } - else if (rules_policy != NONE) - { - log_printf(L_WARNING, "Filter option active but no allowed host/port. All requests will be dropped.\n"); free(hostname); return -1; } - - tunnel_id = get_random_tunnel_id(); log_printf(L_DEBUG, "Tunnel ID: %d\n", tunnel_id); From 472f2f06be419bdf6bfbe794db9db0a53955fd85 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 08:03:58 -0400 Subject: [PATCH 22/70] Allow wildcards in rules The hostname "*" is treated as a wildcard. Port 0 is treated as a wildcard. Closes https://github.com/gjedeer/tuntox/issues/56 --- main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index 2a230e0..749f38b 100644 --- a/main.c +++ b/main.c @@ -108,14 +108,13 @@ int allowed_toxid_cmp(allowed_toxid *a, allowed_toxid *b) return memcmp(a->toxid, b->toxid, TOX_PUBLIC_KEY_SIZE); } -/* Comparison function for rule objects */ -int rule_match(rule *a, rule *b) +/* Match rule r against candidate host, port. Returns 0 for match. */ +int rule_match(rule *r, rule *candidate) { - //log_printf(L_INFO, "Comparison result: %d %d\n", strcmp(a->host, b->host), (a->port == b->port)); - if ((strcmp(a->host, b->host)==0) && (a->port == b->port)) - return 0; - else - return -1; + bool host_match = !strcmp(r->host, "*") || !strcmp(r->host, candidate->host); + bool port_match = r->port == 0 || r->port == candidate->port; + + return port_match && host_match ? 0 : -1; } void update_select_nfds(int fd) From 22fd38896ae61ba66a41d5f4d27f9e1096a7ca1e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 08:10:26 -0400 Subject: [PATCH 23/70] Change enum rules_policy to bool enforce_whitelist This reflects the fact that the rules constitute a whitelist. --- main.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/main.c b/main.c index 749f38b..c109deb 100644 --- a/main.c +++ b/main.c @@ -44,7 +44,7 @@ char config_path[500] = "/etc/tuntox/"; /* Limit hostname and port in server */ int nrules = 0; char rules_file[500] = "/etc/tuntox/rules"; -enum rules_policy_enum rules_policy = NONE; +bool enforce_whitelist = false; rule *rules = NULL; /* Ports and hostname for port forwarding */ @@ -424,30 +424,24 @@ int handle_ping_frame(protocol_frame *rcvd_frame) bool check_requested_tunnel_against_rules(char *hostname, in_port_t port) { - switch(rules_policy) - { - case NONE: - return true; - case VALIDATE: - if(nrules > 0) - { - rule candidate, *found = NULL; - candidate.host = hostname; - candidate.port = port; + if (!enforce_whitelist) return true; - LL_SEARCH(rules, found, &candidate, rule_match); - if(!found) - { - log_printf(L_WARNING, "Rejected, request not in rules\n"); - } - return found; - } - log_printf(L_WARNING, "Filter option active but no allowed host/port. All requests will be dropped.\n"); - return false; - default: - log_printf(L_WARNING, "BUG: invalid rules_policy (impossible!)\n"); + if (nrules <= 0) + { + log_printf(l_warning, "filter option active but no allowed host/port. all requests will be dropped.\n"); return false; } + + rule candidate, *found = NULL; + candidate.host = hostname; + candidate.port = port; + + LL_SEARCH(rules, found, &candidate, rule_match); + if(!found) + { + log_printf(L_WARNING, "Rejected, request not in rules\n"); + } + return found; } int handle_request_tunnel_frame(protocol_frame *rcvd_frame) @@ -847,7 +841,7 @@ void load_rules() nrules = valid_rules; log_printf(L_INFO, "Loaded %d rules\n", nrules); - if (nrules==0 && rules_policy != NONE){ + if (nrules==0 && enforce_whitelist){ log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); } } @@ -1376,7 +1370,7 @@ int main(int argc, char *argv[]) break; case 'f': strncpy(rules_file, optarg, sizeof(rules_file) - 1); - rules_policy = VALIDATE; + enforce_whitelist = true; log_printf(L_INFO, "Filter policy set to VALIDATE\n"); break; case 's': @@ -1477,7 +1471,7 @@ int main(int argc, char *argv[]) log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); } - if((!client_mode) && (rules_policy != NONE)) + if((!client_mode) && enforce_whitelist) { load_rules(); } From 127d2c239bb4c8d156154c5fb87e082ef22ed5a4 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 09:47:12 -0400 Subject: [PATCH 24/70] Implement wildcard rules The rules are reloaded as needed upon every connection. --- main.c | 163 ++++++++++++++++++++++++++++++--------------------------- util.c | 50 +++++++++++------- util.h | 4 +- 3 files changed, 118 insertions(+), 99 deletions(-) diff --git a/main.c b/main.c index c109deb..7e38022 100644 --- a/main.c +++ b/main.c @@ -42,10 +42,11 @@ long int udp_end_port = 0; char config_path[500] = "/etc/tuntox/"; /* Limit hostname and port in server */ -int nrules = 0; -char rules_file[500] = "/etc/tuntox/rules"; -bool enforce_whitelist = false; -rule *rules = NULL; +int tunnel_target_whitelist_size = 0; +char *tunnel_target_whitelist_file; +bool tunnel_target_whitelist_enforced = false; +rule *tunnel_target_whitelist_rules = NULL; +time_t tunnel_target_whitelist_mtime = 0; /* Ports and hostname for port forwarding */ int remote_port = 0; @@ -422,13 +423,16 @@ int handle_ping_frame(protocol_frame *rcvd_frame) return 0; } +void tunnel_target_whitelist_load(); bool check_requested_tunnel_against_rules(char *hostname, in_port_t port) { - if (!enforce_whitelist) return true; + if (!tunnel_target_whitelist_enforced) return true; - if (nrules <= 0) + tunnel_target_whitelist_load(); + + if (tunnel_target_whitelist_size <= 0) { - log_printf(l_warning, "filter option active but no allowed host/port. all requests will be dropped.\n"); + log_printf(L_WARNING, "Whitelist enforced, but no whitelisted entries. All requests will be dropped.\n"); return false; } @@ -436,11 +440,7 @@ bool check_requested_tunnel_against_rules(char *hostname, in_port_t port) candidate.host = hostname; candidate.port = port; - LL_SEARCH(rules, found, &candidate, rule_match); - if(!found) - { - log_printf(L_WARNING, "Rejected, request not in rules\n"); - } + LL_SEARCH(tunnel_target_whitelist_rules, found, &candidate, rule_match); return found; } @@ -473,6 +473,8 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) if (!check_requested_tunnel_against_rules(hostname, port)) { + log_printf(L_WARNING, "Rejected tunnel request from #%d to non-whitelisted target host:port (%s:%d)", + rcvd_frame->friendnumber, hostname, port); free(hostname); return -1; } @@ -791,71 +793,89 @@ static size_t load_save(uint8_t **out_data) } } +void tunnel_target_whitelist_clear(); /* Loads a list of allowed hostnames and ports from file. Format is hostname:port*/ -void load_rules() +void tunnel_target_whitelist_load() { char *ahost=NULL; int aport=0; - char line[100 + 1] = ""; + char line[1024]; FILE *file = NULL; rule *rule_obj = NULL; - int valid_rules = 0; - file = fopen(rules_file, "r"); - - if (file == NULL) { - log_printf(L_WARNING, "Could not open rules file (%s)\n", rules_file); - return; - } + if (!tunnel_target_whitelist_enforced) return; - while (fgets(line, sizeof(line), file)) { - /* allow comments & white lines */ - if (line[0]=='#'||line[0]=='\n') { - continue; + /* If we have existing rules, check to see if we need to continue. */ + if(tunnel_target_whitelist_rules) + { + struct stat buf; + if (stat(tunnel_target_whitelist_file, &buf) < 0) + { + /* File removed? Better clear the whitelist. */ + tunnel_target_whitelist_mtime = 0; + tunnel_target_whitelist_clear(); + return; } - if (parse_pipe_port_forward(line, &ahost, &aport) >= 0) { - if (aport > 0 && aport < 65535) { + if (buf.st_mtime == tunnel_target_whitelist_mtime) return; - rule_obj = (rule *)calloc(sizeof(rule), 1); - if(!rule_obj) - { - log_printf(L_ERROR, "Could not allocate memory for rule"); - exit(1); - } + tunnel_target_whitelist_mtime = buf.st_mtime; + tunnel_target_whitelist_clear(); + } - rule_obj->port = aport; - rule_obj->host = strdup(ahost); + file = fopen(tunnel_target_whitelist_file, "r"); - LL_APPEND(rules, rule_obj); - valid_rules++; - } else { - log_printf(L_WARNING, "Invalid port in line: %s\n", line); + if(file == NULL) { + log_printf(L_WARNING, "Could not open rules file (%s)\n", tunnel_target_whitelist_file); + return; + } + + while(fgets(line, sizeof(line), file)) + { + strtok(line, "#\n"); /* Chop line at first hash */ + char *orig_line = strdup(line); /* Not quite the original line; keeps + newline and comments out of logs */ + if(parse_pipe_port_forward(line, &ahost, &aport)) + { + rule_obj = (rule *)calloc(sizeof(rule), 1); + if(!rule_obj) + { + log_printf(L_ERROR, "Could not allocate memory for rule"); + exit(1); } - } else { - log_printf(L_WARNING, "Could not parse line: %s\n", line); + + rule_obj->port = aport; + rule_obj->host = strdup(ahost); + + LL_APPEND(tunnel_target_whitelist_rules, rule_obj); + tunnel_target_whitelist_size++; + } + else + { + log_printf(L_WARNING, "Could not parse line: %s\n", orig_line); } + free(orig_line); } fclose(file); - /* save valid rules in global variable */ - nrules = valid_rules; - - log_printf(L_INFO, "Loaded %d rules\n", nrules); - if (nrules==0 && enforce_whitelist){ + log_printf(L_INFO, "Loaded %d rules\n", tunnel_target_whitelist_size); + if (tunnel_target_whitelist_size == 0 && tunnel_target_whitelist_enforced){ log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); } } /* Clear rules loaded into memory */ -void clear_rules() +void tunnel_target_whitelist_clear() { rule * elt, *tmp; /* delete each elemen using the safe iterator */ - LL_FOREACH_SAFE(rules,elt,tmp) { - LL_DELETE(rules,elt); + LL_FOREACH_SAFE(tunnel_target_whitelist_rules,elt,tmp) { + LL_DELETE(tunnel_target_whitelist_rules,elt); free(elt->host); free(elt); } + free(tunnel_target_whitelist_rules); + tunnel_target_whitelist_rules = NULL; + tunnel_target_whitelist_size = 0; } void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) @@ -914,12 +934,17 @@ void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *m } /* Callback for tox_callback_self_connection_status() */ -void handle_connection_status_change(Tox *tox, TOX_CONNECTION p_connection_status, void *user_data) +void handle_connection_status_change(Tox *tox, TOX_CONNECTION new_connection_status, void *user_data) { - const char *status = NULL; - connection_status = p_connection_status; - status = readable_connection_status(connection_status); - log_printf(L_INFO, "Connection status changed: %s", status); + connection_status = new_connection_status; + if (connection_status) + { + log_printf(L_INFO, "Connected to Tox network: %s\n", readable_connection_status(connection_status)); + } + else + { + log_printf(L_INFO, "Disconnected from Tox network\n"); + } } #ifdef LOG_IP_ADDRESS @@ -971,7 +996,6 @@ int do_server_loop() unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; tunnel *tun = NULL; tunnel *tmp = NULL; - TOX_CONNECTION connected = 0; int sent_data = 0; tox_callback_friend_lossless_packet(tox, parse_lossless_packet); @@ -997,20 +1021,6 @@ int do_server_loop() log_printf(L_DEBUG2, "Iteration interval: %dms\n", tox_do_interval_ms); gettimeofday(&tv_start, NULL); - /* Check change in connection state */ - if(connection_status != connected) - { - connected = connection_status; - if(connected) - { - log_printf(L_DEBUG, "Connected to Tox network\n"); - } - else - { - log_printf(L_DEBUG, "Disconnected from Tox network\n"); - } - } - fds = master_server_fds; /* Poll for data from our client connection */ @@ -1304,7 +1314,7 @@ int main(int argc, char *argv[]) /* Local port forwarding */ client_mode = 1; client_local_port_mode = 1; - if(parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port) < 0) + if(!parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port)) { log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); exit(1); @@ -1319,7 +1329,7 @@ int main(int argc, char *argv[]) /* Pipe forwarding */ client_mode = 1; client_pipe_mode = 1; - if(parse_pipe_port_forward(optarg, &remote_host, &remote_port) < 0) + if(!parse_pipe_port_forward(optarg, &remote_host, &remote_port) || remote_port == 0) { log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); exit(1); @@ -1369,9 +1379,9 @@ int main(int argc, char *argv[]) load_saved_toxid_in_client_mode = 1; break; case 'f': - strncpy(rules_file, optarg, sizeof(rules_file) - 1); - enforce_whitelist = true; - log_printf(L_INFO, "Filter policy set to VALIDATE\n"); + tunnel_target_whitelist_file = strdup(optarg); + tunnel_target_whitelist_enforced = true; + log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n"); break; case 's': /* Shared secret */ @@ -1471,9 +1481,9 @@ int main(int argc, char *argv[]) log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); } - if((!client_mode) && enforce_whitelist) + if(!client_mode && tunnel_target_whitelist_enforced) { - load_rules(); + tunnel_target_whitelist_load(); } /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ @@ -1589,7 +1599,6 @@ int main(int argc, char *argv[]) { tox_callback_friend_request(tox, accept_friend_request); do_server_loop(); - clear_rules(); } } diff --git a/util.c b/util.c index 0084c19..03cf30f 100644 --- a/util.c +++ b/util.c @@ -83,52 +83,62 @@ int string_to_id(char_t *w, char_t *a) } /* Parse the -L parameter */ -/* 0 = success */ -int parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port) +/* true = success */ +bool parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port) { char *lport; - char *host; - char *rport; /* Alternative delimiter '@', as ':' is forbidden in some environments */ - lport = strtok(string, ":@"); - host = strtok(NULL, ":@"); - rport = strtok(NULL, ":@"); - if(!lport || !host || !rport) + if(!(*local_port = atoi(lport))) { - return -1; + return false; } - *local_port = atoi(lport); - *hostname = host; - *remote_port = atoi(rport); - - return 0; + if(parse_pipe_port_forward(lport + strlen(lport), hostname, remote_port)) + { + return *remote_port; + } + return false; } /* Parse the -W parameter */ -/* 0 = success */ -int parse_pipe_port_forward(char *string, char **hostname, int *remote_port) +/* true = success */ +bool parse_pipe_port_forward(char *string, char **hostname, int *remote_port) { char *host; char *rport; /* Alternative delimiter '@', as ':' is forbidden in some environments */ - host = strtok(string, ":@"); - rport = strtok(NULL, ":@"); + rport = strtok(NULL, ""); if(!host || !rport) { - return -1; + return false; } *hostname = host; *remote_port = atoi(rport); - return 0; + if(*remote_port > 0 && *remote_port < 65535) + { + /* This is tolerant of nonsense tokens after the port. */ + return true; + } + else + { + /* Port 0 is not allowed in the input. Only a literal '*' can produce a + * port 0 in the output, which will be treated as a wildcard if this is + * a rule. */ + if (rport[0] != '*') + { + return false; + } + /* Return an error if an extra token follows, but tolerate whitespace. */ + return !strtok(rport+1, "\n\t "); + } } void* file_raw(char *path, uint32_t *size) diff --git a/util.h b/util.h index 7dced6b..e97119b 100644 --- a/util.h +++ b/util.h @@ -13,7 +13,7 @@ void id_to_string(char_t *dest, const char_t *src); int string_to_id(char_t *w, char_t *a); void* file_raw(char *path, uint32_t *size); const char *readable_connection_status(TOX_CONNECTION status); -int parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port); -int parse_pipe_port_forward(char *string, char **hostname, int *remote_port); +bool parse_local_port_forward(char *string, int *local_port, char **hostname, int *remote_port); +bool parse_pipe_port_forward(char *string, char **hostname, int *remote_port); #endif From f2153aebaacc67e59311738f74f5b6f3b76347cf Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 12:47:29 -0400 Subject: [PATCH 25/70] represent program mode as a single enum --- client.c | 87 ++++++++++++++--------------- main.c | 163 +++++++++++++++++++++++++------------------------------ main.h | 20 ++++--- 3 files changed, 127 insertions(+), 143 deletions(-) diff --git a/client.c b/client.c index 67d4fd3..0ce1cb0 100644 --- a/client.c +++ b/client.c @@ -35,7 +35,7 @@ int handle_pong_frame() log_printf(L_INFO, "GOT PONG! Time = %.3fs\n", secs2-secs1); - if(ping_mode) + if(program_mode == Mode_Client_Ping) { state = CLIENT_STATE_SHUTDOWN; } @@ -116,12 +116,24 @@ int local_bind() return 0; } +bool tunnel_client_mode() +{ + switch (program_mode) { + case Mode_Client_Local_Port_Forward: + case Mode_Client_Pipe: + return true; + case Mode_Client_Ping: + default: + return false; + } +} + /* Bind the client.sockfd to a tunnel */ int handle_acktunnel_frame(protocol_frame *rcvd_frame) { tunnel *tun; - if(!client_mode) + if(!tunnel_client_mode()) { log_printf(L_WARNING, "Got ACK tunnel frame when not in client mode!?\n"); return -1; @@ -136,23 +148,12 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) /* Mark that we can accept() another connection */ client_tunnel.sockfd = -1; -// printf("New tunnel ID: %d\n", tun->connid); - - if(client_local_port_mode || client_pipe_mode) + update_select_nfds(tun->sockfd); + FD_SET(tun->sockfd, &client_master_fdset); + if(program_mode == Mode_Client_Local_Port_Forward) { - update_select_nfds(tun->sockfd); - FD_SET(tun->sockfd, &client_master_fdset); - if(client_local_port_mode) - { - log_printf(L_INFO, "Accepted a new connection on port %d\n", local_port); - } + log_printf(L_INFO, "Accepted a new connection on port %d\n", local_port); } - else - { - log_printf(L_ERROR, "This tunnel mode is not supported yet\n"); - exit(1); - } - return 0; } @@ -175,25 +176,18 @@ int handle_server_tcp_frame(protocol_frame *rcvd_frame) { int sent_bytes; - if(client_pipe_mode) - { - sent_bytes = write( - 1, /* STDOUT */ - rcvd_frame->data + offset, - rcvd_frame->data_length - offset - ); - } - else - { - sent_bytes = send( - tun->sockfd, - rcvd_frame->data + offset, - rcvd_frame->data_length - offset, - MSG_NOSIGNAL - ); + switch (program_mode) { + case Mode_Client_Pipe: + sent_bytes = write(1, rcvd_frame->data + offset, rcvd_frame->data_length - offset); + break; + case Mode_Client_Local_Port_Forward: + sent_bytes = send(tun->sockfd, rcvd_frame->data + offset, rcvd_frame->data_length - offset, MSG_NOSIGNAL); + break; + default: + log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); + return -1; } - if(sent_bytes < 0) { uint8_t data[PROTOCOL_BUFFER_OFFSET]; @@ -296,7 +290,7 @@ int do_client_loop(uint8_t *tox_id_str) exit(1); } - if(!ping_mode && !client_pipe_mode) + if(program_mode == Mode_Client_Local_Port_Forward) { local_bind(); signal(SIGPIPE, SIG_IGN); @@ -400,17 +394,19 @@ int do_client_loop(uint8_t *tox_id_str) break; } case CLIENT_STATE_REQUEST_ACCEPTED: - if(ping_mode) - { + switch (program_mode) { + case Mode_Client_Ping: state = CLIENT_STATE_SEND_PING; - } - else if(client_pipe_mode) - { + break; + case Mode_Client_Pipe: state = CLIENT_STATE_SETUP_PIPE; - } - else - { + break; + case Mode_Client_Local_Port_Forward: state = CLIENT_STATE_BIND_PORT; + break; + default: + log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); + exit(1); } break; case CLIENT_STATE_SEND_PING: @@ -490,8 +486,7 @@ int do_client_loop(uint8_t *tox_id_str) fds = client_master_fdset; /* Handle accepting new connections */ - if(!client_pipe_mode && - client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ + if(program_mode != Mode_Client_Ping && client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ { accept_fd = accept(bind_sockfd, NULL, NULL); if(accept_fd != -1) @@ -529,7 +524,7 @@ int do_client_loop(uint8_t *tox_id_str) if(FD_ISSET(tun->sockfd, &fds)) { int nbytes; - if(client_local_port_mode) + if(program_mode == Mode_Client_Local_Port_Forward) { nbytes = recv(tun->sockfd, tox_packet_buf + PROTOCOL_BUFFER_OFFSET, diff --git a/main.c b/main.c index 7e38022..8d00a62 100644 --- a/main.c +++ b/main.c @@ -3,6 +3,8 @@ #include "tox_bootstrap.h" #include "log.h" +#define LOG_IP_ADDRESS + #ifdef __MACH__ #include "mach.h" #endif @@ -14,19 +16,12 @@ TOX_CONNECTION connection_status = TOX_CONNECTION_NONE; TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; /** CONFIGURATION OPTIONS **/ /* Whether we're a client */ -int client_mode = 0; + /* Don't bootstrap nodes */ int skip_bootstrap = 1; -/* Just send a ping and exit */ -int ping_mode = 0; - -/* Open a local port and forward it */ -int client_local_port_mode = 0; - -/* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ -int client_pipe_mode = 0; +enum Mode program_mode = Mode_Unspecified; /* Remote Tox ID in client mode */ uint8_t *remote_tox_id = NULL; @@ -39,7 +34,7 @@ long int udp_start_port = 0; long int udp_end_port = 0; /* Directory with config and tox save */ -char config_path[500] = "/etc/tuntox/"; +char *config_path = "/etc/tuntox/"; /* Limit hostname and port in server */ int tunnel_target_whitelist_size = 0; @@ -68,7 +63,7 @@ char shared_secret[TOX_MAX_FRIEND_REQUEST_LENGTH]; int server_whitelist_mode = 0; allowed_toxid *allowed_toxids = NULL; -int load_saved_toxid_in_client_mode = 0; +bool config_path_modified = false; fd_set master_server_fds; @@ -452,9 +447,9 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) int sockfd = 0; uint16_t tunnel_id; - if(client_mode) + if(program_mode != Mode_Server) { - log_printf(L_WARNING, "Got tunnel request frame from friend #%d when in client mode\n", rcvd_frame->friendnumber); + log_printf(L_WARNING, "Got tunnel request frame from friend #%d but not in server mode\n", rcvd_frame->friendnumber); return -1; } @@ -592,15 +587,9 @@ int handle_frame(protocol_frame *frame) return handle_pong_frame(frame); break; case PACKET_TYPE_TCP: - if(client_mode) - { - return handle_server_tcp_frame(frame); - } - else - { - return handle_client_tcp_frame(frame); - } - break; + return program_mode != Mode_Server + ? handle_server_tcp_frame(frame) + : handle_client_tcp_frame(frame); case PACKET_TYPE_REQUESTTUNNEL: handle_request_tunnel_frame(frame); break; @@ -608,15 +597,9 @@ int handle_frame(protocol_frame *frame) handle_acktunnel_frame(frame); break; case PACKET_TYPE_TCP_FIN: - if(client_mode) - { - return handle_server_tcp_fin_frame(frame); - } - else - { - return handle_client_tcp_fin_frame(frame); - } - break; + return program_mode != Mode_Server + ? handle_server_tcp_fin_frame(frame) + : handle_client_tcp_fin_frame(frame); default: log_printf(L_DEBUG, "Got unknown packet type 0x%x from friend %d\n", frame->packet_type, @@ -672,14 +655,16 @@ void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, if(len < (size_t)frame->data_length + PROTOCOL_BUFFER_OFFSET) { - log_printf(L_WARNING, "Received frame too small (attempted buffer overflow?): %d bytes, excepted at least %d bytes\n", len, frame->data_length + PROTOCOL_BUFFER_OFFSET); + log_printf(L_WARNING, "Received frame too small (attempted buffer overflow?): %d bytes, excepted at least %d bytes\n", + len, frame->data_length + PROTOCOL_BUFFER_OFFSET); free(frame); return; } if(frame->data_length > (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)) { - log_printf(L_WARNING, "Declared data length too big (attempted buffer overflow?): %d bytes, excepted at most %d bytes\n", frame->data_length, (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)); + log_printf(L_WARNING, "Declared data length too big (attempted buffer overflow?): %d bytes, excepted at most %d bytes\n", + frame->data_length, (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET)); free(frame); return; } @@ -772,12 +757,13 @@ static size_t load_save(uint8_t **out_data) { void *data; uint32_t size; - uint8_t path_real[512], *p; + uint8_t path_real[PATH_MAX], *p; strncpy((char *)path_real, config_path, sizeof(path_real)); p = path_real + strlen((char *)path_real); - memcpy(p, "tox_save", sizeof("tox_save")); + char basename[] = "/tox_save"; + memcpy(p, "/tox_save", sizeof(basename)); data = file_raw((char *)path_real, &size); @@ -857,7 +843,7 @@ void tunnel_target_whitelist_load() } fclose(file); - log_printf(L_INFO, "Loaded %d rules\n", tunnel_target_whitelist_size); + log_printf(L_INFO, "Loaded %d rule%s\n", tunnel_target_whitelist_size, tunnel_target_whitelist_size == 1 ? "" : "s"); if (tunnel_target_whitelist_size == 0 && tunnel_target_whitelist_enforced){ log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); } @@ -969,7 +955,7 @@ void handle_friend_connection_status(Tox *tox, uint32_t friend_number, TOX_CONNE if(connection_status == TOX_CONNECTION_UDP) log_friend_ip_address(tox, friend_number); #endif - if(client_mode) + if(program_mode != Mode_Server) { friend_connection_status = connection_status; } @@ -1306,29 +1292,22 @@ int main(int argc, char *argv[]) log_init(); - while ((oc = getopt(argc, argv, "L:pi:C:s:f:W:dqhSF:DU:t:u:")) != -1) + while ((oc = getopt(argc, argv, "L:pi:C:s:f:W:vdqhSF:DU:t:u:")) != -1) { switch(oc) { case 'L': /* Local port forwarding */ - client_mode = 1; - client_local_port_mode = 1; + program_mode = Mode_Client_Local_Port_Forward; if(!parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port)) { log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); exit(1); } - if(min_log_level == L_UNSET) - { - min_log_level = L_INFO; - } - log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); break; case 'W': /* Pipe forwarding */ - client_mode = 1; - client_pipe_mode = 1; + program_mode = Mode_Client_Pipe; if(!parse_pipe_port_forward(optarg, &remote_host, &remote_port) || remote_port == 0) { log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); @@ -1338,12 +1317,10 @@ int main(int argc, char *argv[]) { min_log_level = L_ERROR; } - log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); break; case 'p': /* Ping */ - client_mode = 1; - ping_mode = 1; + program_mode = Mode_Client_Ping; if(min_log_level == L_UNSET) { min_log_level = L_INFO; @@ -1368,20 +1345,12 @@ int main(int argc, char *argv[]) break; case 'C': /* Config directory */ - strncpy(config_path, optarg, sizeof(config_path) - 1); - if(optarg[strlen(optarg) - 1] != '/') - { - int optarg_len = strlen(optarg); - - config_path[optarg_len] = '/'; - config_path[optarg_len + 1] = '\0'; - } - load_saved_toxid_in_client_mode = 1; + config_path = strdup(optarg); + config_path_modified = 1; break; case 'f': tunnel_target_whitelist_file = strdup(optarg); tunnel_target_whitelist_enforced = true; - log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n"); break; case 's': /* Shared secret */ @@ -1389,6 +1358,7 @@ int main(int argc, char *argv[]) memset(shared_secret, 0, TOX_MAX_FRIEND_REQUEST_LENGTH); strncpy(shared_secret, optarg, TOX_MAX_FRIEND_REQUEST_LENGTH-1); break; + case 'v': case 'd': switch(++verbosity) { @@ -1425,8 +1395,8 @@ int main(int argc, char *argv[]) tcp_relay_port = strtol(optarg, NULL, 10); if(errno != 0 || tcp_relay_port < 0 || tcp_relay_port > 65535) { - tcp_relay_port = 1024 + (rand() % 64511); - log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); + tcp_relay_port = 1024 + (rand() % 64511); + log_printf(L_WARNING, "Ignored -t %s: TCP port number needs to be a number between 0 and 65535."); } break; case 'u': @@ -1465,25 +1435,44 @@ int main(int argc, char *argv[]) } } - if(!client_mode && min_log_level == L_UNSET) - { - min_log_level = L_INFO; - } - - if(client_mode && !remote_tox_id) - { - log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); - exit(1); - } - - if(!client_mode && server_whitelist_mode) - { - log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); + switch (program_mode) { + case Mode_Client_Local_Port_Forward: + case Mode_Client_Pipe: + case Mode_Client_Ping: + if(!remote_tox_id) + { + log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); + exit(1); + } + break; + case Mode_Unspecified: + program_mode = Mode_Server; + case Mode_Server: + break; } - if(!client_mode && tunnel_target_whitelist_enforced) - { - tunnel_target_whitelist_load(); + switch (program_mode) { + case Mode_Client_Local_Port_Forward: + log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); + break; + case Mode_Client_Pipe: + log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); + break; + case Mode_Server: + if(min_log_level == L_UNSET) + { + min_log_level = L_INFO; + } + if(tunnel_target_whitelist_enforced) + { + log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n"); + tunnel_target_whitelist_load(); + } + if(server_whitelist_mode) + { + log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); + } + default:; } /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ @@ -1525,7 +1514,7 @@ int main(int argc, char *argv[]) tox_options.end_port ); - if((!client_mode) || load_saved_toxid_in_client_mode) + if(program_mode == Mode_Server || config_path_modified) { save_size = load_save(&save_data); if(save_data && save_size) @@ -1564,10 +1553,10 @@ int main(int argc, char *argv[]) tox_callback_self_connection_status(tox, handle_connection_status_change); tox_callback_friend_connection_status(tox, handle_friend_connection_status); - if (!skip_bootstrap) + if(!skip_bootstrap) do_bootstrap(tox); - if((!client_mode) || load_saved_toxid_in_client_mode) + if(program_mode == Mode_Server || config_path_modified) { write_save(tox); } @@ -1591,16 +1580,14 @@ int main(int argc, char *argv[]) to_hex(readable_dht_key, dht_key, TOX_PUBLIC_KEY_SIZE); log_printf(L_DEBUG, "DHT key: %s\n", readable_dht_key); - if (client_mode) + if (program_mode == Mode_Server) { - do_client_loop(remote_tox_id); + tox_callback_friend_request(tox, accept_friend_request); + return do_server_loop(); } else { - tox_callback_friend_request(tox, accept_friend_request); - do_server_loop(); + return do_client_loop(remote_tox_id); } } - - return 0; } diff --git a/main.h b/main.h index b998acc..602f8e4 100644 --- a/main.h +++ b/main.h @@ -80,26 +80,28 @@ typedef struct protocol_frame_t { } protocol_frame; /* Rules policy */ -enum rules_policy_enum { VALIDATE, NONE }; typedef struct rule { uint16_t port; char * host; struct rule *next; } rule; +enum Mode { + Mode_Unspecified, + Mode_Server, + Mode_Client_Local_Port_Forward, + Mode_Client_Pipe, + Mode_Client_Ping +}; + /**** GLOBAL VARIABLES ****/ extern Tox *tox; -/* Whether we're a client */ -extern int client_mode; -/* Just send a ping and exit */ -extern int ping_mode; + +/* Whether we're a server, client, etc. */ +extern enum Mode program_mode; /* TOX_CONNECTION global variable */ extern TOX_CONNECTION connection_status; /* Open a local port and forward it */ -extern int client_local_port_mode; -/* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ -extern int client_pipe_mode; -/* Remote Tox ID in client mode */ extern uint8_t *remote_tox_id; /* Ports and hostname for port forwarding */ extern int remote_port; From 43f3a5658f8d187a46fa2ecb9074982acce35728 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 14:58:37 -0400 Subject: [PATCH 26/70] cleaning up the client state machine --- client.c | 197 +++++++++++++++++++++---------------------------------- client.h | 2 +- log.h | 1 + 3 files changed, 78 insertions(+), 122 deletions(-) diff --git a/client.c b/client.c index 0ce1cb0..7082b21 100644 --- a/client.c +++ b/client.c @@ -9,6 +9,8 @@ #include "main.h" #include "client.h" +const bool attempt_reconnect = true; + /* The state machine */ int state = CLIENT_STATE_INITIAL; @@ -296,8 +298,6 @@ int do_client_loop(uint8_t *tox_id_str) signal(SIGPIPE, SIG_IGN); } - log_printf(L_INFO, "Connecting to Tox...\n"); - while(1) { /* Let tox do its stuff */ @@ -309,16 +309,9 @@ int do_client_loop(uint8_t *tox_id_str) * Send friend request */ case CLIENT_STATE_INITIAL: - if(connection_status != TOX_CONNECTION_NONE) - { - state = CLIENT_STATE_CONNECTED; - } - break; - case CLIENT_STATE_CONNECTED: { uint8_t* data = (uint8_t *)"Hi, fellow tuntox instance!"; uint16_t length = sizeof(data); - /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1168 */ TOX_ERR_FRIEND_ADD add_error; if(use_shared_secret) @@ -329,13 +322,13 @@ int do_client_loop(uint8_t *tox_id_str) log_printf(L_DEBUG, "Sent shared secret of length %u\n", length); } - if(invitations_sent == 0) + if(invitations_sent > 0) { - log_printf(L_INFO, "Connected. Sending friend request.\n"); + log_printf(L_INFO, "Sending friend request #%d.", invitations_sent); } else { - log_printf(L_INFO, "Sending another friend request.\n"); + log_printf(L_INFO, "Sending friend request."); } friendnumber = tox_friend_add( @@ -356,123 +349,84 @@ int do_client_loop(uint8_t *tox_id_str) invitation_sent_time = time(NULL); invitations_sent++; - state = CLIENT_STATE_SENTREQUEST; - log_printf(L_INFO, "Waiting for friend to accept us...\n"); + state = CLIENT_STATE_REQUEST_SENT; + log_printf(L_INFO, "Waiting for server to accept friend request...\n"); } break; - case CLIENT_STATE_SENTREQUEST: + case CLIENT_STATE_REQUEST_SENT: + if(friend_connection_status != TOX_CONNECTION_NONE) { + const char* status = readable_connection_status(friend_connection_status); + log_printf(L_INFO, "Friend request accepted (%s)!\n", status); + state = CLIENT_STATE_REQUEST_ACCEPTED; + } + else + { + const int INVITATION_SEND_INTERVAL = 90; + if (time(NULL) - invitation_sent_time > INVITATION_SEND_INTERVAL) { - if(friend_connection_status != TOX_CONNECTION_NONE) + TOX_ERR_FRIEND_DELETE error = 0; + + log_printf(L_INFO, "Friend request timed out. Sending another..."); + tox_friend_delete(tox, friendnumber, &error); + if(error != TOX_ERR_FRIEND_DELETE_OK) { - const char* status = readable_connection_status(friend_connection_status); - log_printf(L_INFO, "Friend request accepted (%s)!\n", status); - state = CLIENT_STATE_REQUEST_ACCEPTED; + log_printf(L_ERROR, "Error %u deleting friend before reconnection\n", error); + exit(-1); } - else - { - const int INVITATION_SEND_INTERVAL = 90; - if (time(NULL) - invitation_sent_time > INVITATION_SEND_INTERVAL) - { - TOX_ERR_FRIEND_DELETE error = 0; - - log_printf(L_INFO, "Sending another friend request..."); - tox_friend_delete( - tox, - friendnumber, - &error); - if(error != TOX_ERR_FRIEND_DELETE_OK) - { - log_printf(L_ERROR, "Error %u deleting friend before reconnection\n", error); - exit(-1); - } - state = CLIENT_STATE_CONNECTED; - } - } + state = CLIENT_STATE_INITIAL; } - break; } + break; case CLIENT_STATE_REQUEST_ACCEPTED: switch (program_mode) { case Mode_Client_Ping: - state = CLIENT_STATE_SEND_PING; + /* Send the ping packet */ + { + uint8_t data[] = { + 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05, + 0x48, 0x65, 0x6c, 0x6c, 0x6f + }; + clock_gettime(CLOCK_MONOTONIC, &ping_sent_time); + tox_friend_send_lossless_packet(tox, friendnumber, data, sizeof(data), &custom_packet_error); + } + if(custom_packet_error == TOX_ERR_FRIEND_CUSTOM_PACKET_OK) + { + state = CLIENT_STATE_PING_SENT; + } + else + { + log_printf(L_WARNING, "When sending ping packet: %u", custom_packet_error); + } break; case Mode_Client_Pipe: - state = CLIENT_STATE_SETUP_PIPE; + send_tunnel_request_packet(remote_host, remote_port, friendnumber); + state = CLIENT_STATE_FORWARDING; break; case Mode_Client_Local_Port_Forward: - state = CLIENT_STATE_BIND_PORT; + if(bind_sockfd < 0) + { + log_printf(L_ERROR, "Shutting down - could not bind to listening port\n"); + exit(1); + } + state = CLIENT_STATE_FORWARDING; break; default: log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); exit(1); } break; - case CLIENT_STATE_SEND_PING: - /* Send the ping packet */ - { - uint8_t data[] = { - 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05, - 0x48, 0x65, 0x6c, 0x6c, 0x6f - }; - - clock_gettime(CLOCK_MONOTONIC, &ping_sent_time); - tox_friend_send_lossless_packet( - tox, - friendnumber, - data, - sizeof(data), - &custom_packet_error - ); - } - if(custom_packet_error == TOX_ERR_FRIEND_CUSTOM_PACKET_OK) - { - state = CLIENT_STATE_PING_SENT; - } - else - { - log_printf(L_WARNING, "When sending ping packet: %u", custom_packet_error); - } - break; case CLIENT_STATE_PING_SENT: /* Just sit there and wait for pong */ break; - - case CLIENT_STATE_BIND_PORT: - if(bind_sockfd < 0) - { - log_printf(L_ERROR, "Shutting down - could not bind to listening port\n"); - state = CLIENT_STATE_SHUTDOWN; - } - else - { - state = CLIENT_STATE_FORWARDING; - } - break; - case CLIENT_STATE_SETUP_PIPE: - send_tunnel_request_packet( - remote_host, - remote_port, - friendnumber - ); - state = CLIENT_STATE_FORWARDING; - break; case CLIENT_STATE_REQUEST_TUNNEL: - send_tunnel_request_packet( - remote_host, - remote_port, - friendnumber - ); + send_tunnel_request_packet(remote_host, remote_port, friendnumber); state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; break; case CLIENT_STATE_WAIT_FOR_ACKTUNNEL: - client_tunnel.sockfd = 0; - send_tunnel_request_packet( - remote_host, - remote_port, - friendnumber - ); + /* client_tunnel.sockfd = 0; */ + /* send_tunnel_request_packet(remote_host, remote_port, friendnumber); */ break; case CLIENT_STATE_FORWARDING: { @@ -514,7 +468,7 @@ int do_client_loop(uint8_t *tox_id_str) } else { - log_printf(L_DEBUG2, "Nothing to read..."); + log_printf(L_DEBUG3, "Nothing to read..."); } } else @@ -587,31 +541,32 @@ int do_client_loop(uint8_t *tox_id_str) } break; case CLIENT_STATE_CONNECTION_LOST: + /* Trying to reconnect here does not seem like a good idea. */ + if(!attempt_reconnect) { - { - if(friend_connection_status == TOX_CONNECTION_NONE) - { - /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1267 */ - TOX_ERR_FRIEND_DELETE tox_delete_error; + log_printf(L_DEBUG, "Exiting on CLIENT_STATE_CONNECTION_LOST"); + exit(1); + } - log_printf(L_WARNING, "Lost connection to server, closing all tunnels and re-adding friend\n"); - client_close_all_connections(); - tox_friend_delete(tox, friendnumber, &tox_delete_error); - if(tox_delete_error) - { - log_printf(L_ERROR, "Error when deleting server from friend list: %d\n", tox_delete_error); - } - state = CLIENT_STATE_INITIAL; - } - else - { - state = CLIENT_STATE_FORWARDING; - } + if(friend_connection_status == TOX_CONNECTION_NONE) + { + /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1267 */ + TOX_ERR_FRIEND_DELETE tox_delete_error; + + log_printf(L_WARNING, "Lost connection to server, closing all tunnels and re-adding friend\n"); + client_close_all_connections(); + tox_friend_delete(tox, friendnumber, &tox_delete_error); + if(tox_delete_error) + { + log_printf(L_ERROR, "Error when deleting server from friend list: %d\n", tox_delete_error); } + state = CLIENT_STATE_INITIAL; + } + else + { + state = CLIENT_STATE_FORWARDING; } break; - case 0xffffffff: - log_printf(L_ERROR, "You forgot a break statement\n"); case CLIENT_STATE_SHUTDOWN: exit(0); break; diff --git a/client.h b/client.h index be68f25..028e112 100644 --- a/client.h +++ b/client.h @@ -1,7 +1,7 @@ #include "main.h" #define CLIENT_STATE_INITIAL 1 -#define CLIENT_STATE_SENTREQUEST 2 +#define CLIENT_STATE_REQUEST_SENT 2 #define CLIENT_STATE_REQUEST_ACCEPTED 3 #define CLIENT_STATE_PING_SENT 4 #define CLIENT_STATE_CONNECTED 5 diff --git a/log.h b/log.h index bcd4c9b..ee25a14 100644 --- a/log.h +++ b/log.h @@ -6,6 +6,7 @@ #define L_INFO 6 #define L_DEBUG 7 #define L_DEBUG2 8 +#define L_DEBUG3 9 #define L_UNSET 0x29a From 8ee3c22920f77a9dc36780c31018310203784d3c Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 16:25:08 -0400 Subject: [PATCH 27/70] WIP --- main.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/main.c b/main.c index 8d00a62..e90518e 100644 --- a/main.c +++ b/main.c @@ -651,7 +651,7 @@ void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, frame->data_length = INT16_AT(data, 6); frame->data = (uint8_t *)(data + PROTOCOL_BUFFER_OFFSET); frame->friendnumber = friendnumber; - log_printf(L_DEBUG, "Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber); + log_printf(L_DEBUG2, "Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber); if(len < (size_t)frame->data_length + PROTOCOL_BUFFER_OFFSET) { @@ -1004,7 +1004,7 @@ int do_server_loop() tox_do_interval_ms = tox_iteration_interval(tox); tv.tv_usec = (tox_do_interval_ms % 1000) * 1000; tv.tv_sec = tox_do_interval_ms / 1000; - log_printf(L_DEBUG2, "Iteration interval: %dms\n", tox_do_interval_ms); + log_printf(L_DEBUG3, "Iteration interval: %dms\n", tox_do_interval_ms); gettimeofday(&tv_start, NULL); fds = master_server_fds; @@ -1018,7 +1018,7 @@ int do_server_loop() } else if (select_rv == 0) { - log_printf(L_DEBUG2, "Nothing to read..."); + log_printf(L_DEBUG3, "Nothing to read..."); } else { @@ -1026,10 +1026,10 @@ int do_server_loop() tmp = NULL; tun = NULL; - log_printf(L_DEBUG, "Starting tunnel iteration..."); + log_printf(L_DEBUG2, "Starting tunnel iteration..."); HASH_ITER(hh, by_id, tun, tmp) { - log_printf(L_DEBUG, "Current tunnel: %p", tun); + log_printf(L_DEBUG2, "Current tunnel: %p", tun); if(FD_ISSET(tun->sockfd, &fds)) { int nbytes = recv(tun->sockfd, @@ -1080,7 +1080,7 @@ int do_server_loop() } } } - log_printf(L_DEBUG, "Tunnel iteration done"); + log_printf(L_DEBUG2, "Tunnel iteration done"); LL_FOREACH_SAFE(tunnels_to_delete, tunnel_list_entry, list_tmp) { @@ -1313,18 +1313,10 @@ int main(int argc, char *argv[]) log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); exit(1); } - if(min_log_level == L_UNSET) - { - min_log_level = L_ERROR; - } break; case 'p': /* Ping */ program_mode = Mode_Client_Ping; - if(min_log_level == L_UNSET) - { - min_log_level = L_INFO; - } break; case 'i': /* Tox ID */ @@ -1369,9 +1361,13 @@ int main(int argc, char *argv[]) min_log_level = L_DEBUG2; break; case 3: - default: min_log_level = L_DEBUG2; log_tox_trace = 1; + break; + case 4: + default: + min_log_level = L_DEBUG3; + log_tox_trace = 1; } break; case 'q': @@ -1456,8 +1452,18 @@ int main(int argc, char *argv[]) log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); break; case Mode_Client_Pipe: + if(min_log_level == L_UNSET) + { + min_log_level = L_ERROR; + } log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); break; + case Mode_Client_Ping: + if(min_log_level == L_UNSET) + { + min_log_level = L_INFO; + } + break; case Mode_Server: if(min_log_level == L_UNSET) { @@ -1472,7 +1478,9 @@ int main(int argc, char *argv[]) { log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); } - default:; + break; + case Mode_Unspecified: + exit(1); } /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ From b9470442a3199a58b1665350ec0d285ca169167c Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 16:45:25 -0400 Subject: [PATCH 28/70] It's broken. --- client.c | 115 +++++++++++++++++++------------------------------------ 1 file changed, 39 insertions(+), 76 deletions(-) diff --git a/client.c b/client.c index 7082b21..2879f40 100644 --- a/client.c +++ b/client.c @@ -39,7 +39,8 @@ int handle_pong_frame() if(program_mode == Mode_Client_Ping) { - state = CLIENT_STATE_SHUTDOWN; + log_printf(L_INFO, "Ping mode successful. Exiting."); + exit(0); } return 0; } @@ -324,7 +325,7 @@ int do_client_loop(uint8_t *tox_id_str) if(invitations_sent > 0) { - log_printf(L_INFO, "Sending friend request #%d.", invitations_sent); + log_printf(L_INFO, "Sending friend request #%d.", invitations_sent+1); } else { @@ -358,7 +359,40 @@ int do_client_loop(uint8_t *tox_id_str) { const char* status = readable_connection_status(friend_connection_status); log_printf(L_INFO, "Friend request accepted (%s)!\n", status); - state = CLIENT_STATE_REQUEST_ACCEPTED; + + switch (program_mode) { + case Mode_Client_Ping: + /* Send the ping packet */ + { + uint8_t data[] = { + 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05, + 0x48, 0x65, 0x6c, 0x6c, 0x6f + }; + clock_gettime(CLOCK_MONOTONIC, &ping_sent_time); + tox_friend_send_lossless_packet(tox, friendnumber, data, sizeof(data), &custom_packet_error); + } + if(custom_packet_error != TOX_ERR_FRIEND_CUSTOM_PACKET_OK) + { + log_printf(L_WARNING, "When sending ping packet: %u", custom_packet_error); + exit(1); + } + state = CLIENT_STATE_PING_SENT; + break; + case Mode_Client_Local_Port_Forward: + if(bind_sockfd < 0) + { + log_printf(L_ERROR, "Shutting down - could not bind to listening port\n"); + exit(1); + } + /* fall through... */ + case Mode_Client_Pipe: + send_tunnel_request_packet(remote_host, remote_port, friendnumber); + state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; + break; + default: + log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); + exit(1); + } } else { @@ -379,51 +413,9 @@ int do_client_loop(uint8_t *tox_id_str) } } break; - case CLIENT_STATE_REQUEST_ACCEPTED: - switch (program_mode) { - case Mode_Client_Ping: - /* Send the ping packet */ - { - uint8_t data[] = { - 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05, - 0x48, 0x65, 0x6c, 0x6c, 0x6f - }; - clock_gettime(CLOCK_MONOTONIC, &ping_sent_time); - tox_friend_send_lossless_packet(tox, friendnumber, data, sizeof(data), &custom_packet_error); - } - if(custom_packet_error == TOX_ERR_FRIEND_CUSTOM_PACKET_OK) - { - state = CLIENT_STATE_PING_SENT; - } - else - { - log_printf(L_WARNING, "When sending ping packet: %u", custom_packet_error); - } - break; - case Mode_Client_Pipe: - send_tunnel_request_packet(remote_host, remote_port, friendnumber); - state = CLIENT_STATE_FORWARDING; - break; - case Mode_Client_Local_Port_Forward: - if(bind_sockfd < 0) - { - log_printf(L_ERROR, "Shutting down - could not bind to listening port\n"); - exit(1); - } - state = CLIENT_STATE_FORWARDING; - break; - default: - log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); - exit(1); - } - break; case CLIENT_STATE_PING_SENT: /* Just sit there and wait for pong */ break; - case CLIENT_STATE_REQUEST_TUNNEL: - send_tunnel_request_packet(remote_host, remote_port, friendnumber); - state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; - break; case CLIENT_STATE_WAIT_FOR_ACKTUNNEL: /* client_tunnel.sockfd = 0; */ /* send_tunnel_request_packet(remote_host, remote_port, friendnumber); */ @@ -536,39 +528,10 @@ int do_client_loop(uint8_t *tox_id_str) /* Check friend connection status changes */ if(friend_connection_status == TOX_CONNECTION_NONE) { - state = CLIENT_STATE_CONNECTION_LOST; - } - } - break; - case CLIENT_STATE_CONNECTION_LOST: - /* Trying to reconnect here does not seem like a good idea. */ - if(!attempt_reconnect) - { - log_printf(L_DEBUG, "Exiting on CLIENT_STATE_CONNECTION_LOST"); - exit(1); - } - - if(friend_connection_status == TOX_CONNECTION_NONE) - { - /* https://github.com/TokTok/c-toxcore/blob/acb6b2d8543c8f2ea0c2e60dc046767cf5cc0de8/toxcore/tox.h#L1267 */ - TOX_ERR_FRIEND_DELETE tox_delete_error; - - log_printf(L_WARNING, "Lost connection to server, closing all tunnels and re-adding friend\n"); - client_close_all_connections(); - tox_friend_delete(tox, friendnumber, &tox_delete_error); - if(tox_delete_error) - { - log_printf(L_ERROR, "Error when deleting server from friend list: %d\n", tox_delete_error); + log_printf(L_ERROR, "Lost connection to server. Exiting."); + exit(1); } - state = CLIENT_STATE_INITIAL; } - else - { - state = CLIENT_STATE_FORWARDING; - } - break; - case CLIENT_STATE_SHUTDOWN: - exit(0); break; } From 0a9ce77c015d5aba4e22ac39aa17f00dcb65bdaf Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 17:25:48 -0400 Subject: [PATCH 29/70] It's fixed! --- client.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client.c b/client.c index 2879f40..5493d84 100644 --- a/client.c +++ b/client.c @@ -384,10 +384,11 @@ int do_client_loop(uint8_t *tox_id_str) log_printf(L_ERROR, "Shutting down - could not bind to listening port\n"); exit(1); } + client_tunnel.sockfd = 0; /* fall through... */ case Mode_Client_Pipe: send_tunnel_request_packet(remote_host, remote_port, friendnumber); - state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; + state = CLIENT_STATE_FORWARDING; break; default: log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); @@ -416,10 +417,6 @@ int do_client_loop(uint8_t *tox_id_str) case CLIENT_STATE_PING_SENT: /* Just sit there and wait for pong */ break; - case CLIENT_STATE_WAIT_FOR_ACKTUNNEL: - /* client_tunnel.sockfd = 0; */ - /* send_tunnel_request_packet(remote_host, remote_port, friendnumber); */ - break; case CLIENT_STATE_FORWARDING: { int accept_fd = 0; From 893fab60956bf982e0dfd8fcbd80d384dd8deee3 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 17:33:28 -0400 Subject: [PATCH 30/70] whitespace --- client.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/client.c b/client.c index 5493d84..687bdcf 100644 --- a/client.c +++ b/client.c @@ -142,11 +142,7 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) return -1; } - tun = tunnel_create( - client_tunnel.sockfd, - rcvd_frame->connid, - rcvd_frame->friendnumber - ); + tun = tunnel_create(client_tunnel.sockfd, rcvd_frame->connid, rcvd_frame->friendnumber); /* Mark that we can accept() another connection */ client_tunnel.sockfd = -1; @@ -438,11 +434,7 @@ int do_client_loop(uint8_t *tox_id_str) /* Open a new tunnel for this FD */ client_tunnel.sockfd = accept_fd; - send_tunnel_request_packet( - remote_host, - remote_port, - friendnumber - ); + send_tunnel_request_packet(remote_host, remote_port, friendnumber); } } From 475d51fc1a006503f0a0096c86d29e1253555967 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 17:52:51 -0400 Subject: [PATCH 31/70] set CONNECTED state in callback --- client.c | 30 ++++++++++++++++++++---------- client.h | 24 ++++++++++-------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/client.c b/client.c index 687bdcf..4a82bbc 100644 --- a/client.c +++ b/client.c @@ -12,7 +12,7 @@ const bool attempt_reconnect = true; /* The state machine */ -int state = CLIENT_STATE_INITIAL; +int state = CLIENT_STATE_AWAIT_FRIENDSHIP; /* Used in ping mode */ struct timespec ping_sent_time; @@ -143,6 +143,10 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) } tun = tunnel_create(client_tunnel.sockfd, rcvd_frame->connid, rcvd_frame->friendnumber); + if (!tun) + { + exit(1); + } /* Mark that we can accept() another connection */ client_tunnel.sockfd = -1; @@ -153,6 +157,11 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) { log_printf(L_INFO, "Accepted a new connection on port %d\n", local_port); } + if(state != CLIENT_STATE_AWAIT_TUNNEL) + { + log_printf(L_WARNING, "Got ACK tunnel frame when state is %d", state); + } + state = CLIENT_STATE_CONNECTED; return 0; } @@ -305,7 +314,7 @@ int do_client_loop(uint8_t *tox_id_str) /* * Send friend request */ - case CLIENT_STATE_INITIAL: + case CLIENT_STATE_AWAIT_FRIENDSHIP: { uint8_t* data = (uint8_t *)"Hi, fellow tuntox instance!"; uint16_t length = sizeof(data); @@ -346,11 +355,11 @@ int do_client_loop(uint8_t *tox_id_str) invitation_sent_time = time(NULL); invitations_sent++; - state = CLIENT_STATE_REQUEST_SENT; + state = CLIENT_STATE_AWAIT_FRIEND_CONNECTED; log_printf(L_INFO, "Waiting for server to accept friend request...\n"); } break; - case CLIENT_STATE_REQUEST_SENT: + case CLIENT_STATE_AWAIT_FRIEND_CONNECTED: if(friend_connection_status != TOX_CONNECTION_NONE) { const char* status = readable_connection_status(friend_connection_status); @@ -372,7 +381,7 @@ int do_client_loop(uint8_t *tox_id_str) log_printf(L_WARNING, "When sending ping packet: %u", custom_packet_error); exit(1); } - state = CLIENT_STATE_PING_SENT; + state = CLIENT_STATE_AWAIT_PONG; break; case Mode_Client_Local_Port_Forward: if(bind_sockfd < 0) @@ -384,7 +393,7 @@ int do_client_loop(uint8_t *tox_id_str) /* fall through... */ case Mode_Client_Pipe: send_tunnel_request_packet(remote_host, remote_port, friendnumber); - state = CLIENT_STATE_FORWARDING; + state = CLIENT_STATE_AWAIT_TUNNEL; break; default: log_printf(L_ERROR, "BUG: Impossible client mode at %s:%s", __FILE__, __LINE__); @@ -406,14 +415,15 @@ int do_client_loop(uint8_t *tox_id_str) exit(-1); } - state = CLIENT_STATE_INITIAL; + state = CLIENT_STATE_AWAIT_FRIENDSHIP; } } break; - case CLIENT_STATE_PING_SENT: - /* Just sit there and wait for pong */ + case CLIENT_STATE_AWAIT_TUNNEL: + break; + case CLIENT_STATE_AWAIT_PONG: break; - case CLIENT_STATE_FORWARDING: + case CLIENT_STATE_CONNECTED: { int accept_fd = 0; int select_rv = 0; diff --git a/client.h b/client.h index 028e112..d83bb2a 100644 --- a/client.h +++ b/client.h @@ -1,19 +1,15 @@ #include "main.h" -#define CLIENT_STATE_INITIAL 1 -#define CLIENT_STATE_REQUEST_SENT 2 -#define CLIENT_STATE_REQUEST_ACCEPTED 3 -#define CLIENT_STATE_PING_SENT 4 -#define CLIENT_STATE_CONNECTED 5 -#define CLIENT_STATE_PONG_RECEIVED 6 -#define CLIENT_STATE_SEND_PING 7 -#define CLIENT_STATE_REQUEST_TUNNEL 8 -#define CLIENT_STATE_WAIT_FOR_ACKTUNNEL 9 -#define CLIENT_STATE_FORWARDING 10 -#define CLIENT_STATE_SHUTDOWN 11 -#define CLIENT_STATE_BIND_PORT 12 -#define CLIENT_STATE_SETUP_PIPE 13 -#define CLIENT_STATE_CONNECTION_LOST 14 +enum CLIENT_STATE { + CLIENT_STATE_AWAIT_FRIENDSHIP, + CLIENT_STATE_AWAIT_FRIEND_CONNECTED, + CLIENT_STATE_AWAIT_PONG, + CLIENT_STATE_AWAIT_TUNNEL, + CLIENT_STATE_SEND_PING, + CLIENT_STATE_REQUEST_TUNNEL, + CLIENT_STATE_WAIT_FOR_ACKTUNNEL, + CLIENT_STATE_CONNECTED +}; int handle_pong_frame(); int handle_acktunnel_frame(protocol_frame *rcvd_frame); From 2a7edb9cda824338c4f7dcb00b264f37e3a6928c Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 17:56:34 -0400 Subject: [PATCH 32/70] remove unused states --- client.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/client.h b/client.h index d83bb2a..c951044 100644 --- a/client.h +++ b/client.h @@ -5,9 +5,6 @@ enum CLIENT_STATE { CLIENT_STATE_AWAIT_FRIEND_CONNECTED, CLIENT_STATE_AWAIT_PONG, CLIENT_STATE_AWAIT_TUNNEL, - CLIENT_STATE_SEND_PING, - CLIENT_STATE_REQUEST_TUNNEL, - CLIENT_STATE_WAIT_FOR_ACKTUNNEL, CLIENT_STATE_CONNECTED }; From 4dbabac9eccd43445808c583777ba853b1ad1155 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 18:16:29 -0400 Subject: [PATCH 33/70] split large function in two, changing nothing --- client.c | 228 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 115 insertions(+), 113 deletions(-) diff --git a/client.c b/client.c index 4a82bbc..154c1c5 100644 --- a/client.c +++ b/client.c @@ -79,8 +79,7 @@ int local_bind() setsockopt_status = setsockopt(bind_sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if(setsockopt_status < 0) { - log_printf(L_ERROR, "Could not set socket options: %s\n", - strerror(errno)); + log_printf(L_ERROR, "Could not set socket options: %s\n", strerror(errno)); freeaddrinfo(res); exit(1); } @@ -228,7 +227,7 @@ int handle_server_tcp_frame(protocol_frame *rcvd_frame) } /* Delete tunnel and clear client-side fdset */ -void client_close_tunnel(tunnel *tun) +void client_close_tunnel(tunnel *tun) { if(tun->sockfd) { @@ -275,14 +274,123 @@ void client_close_all_connections() } } +void client_connected_loop_iteration(uint32_t friendnumber) +{ + static unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; + static fd_set fds; + static struct timeval tv; + + int accept_fd = 0; + int select_rv = 0; + tunnel *tmp = NULL; + tunnel *tun = NULL; + + tv.tv_sec = 0; + tv.tv_usec = 20000; + fds = client_master_fdset; + + /* Handle accepting new connections */ + if(program_mode != Mode_Client_Ping && client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ + { + accept_fd = accept(bind_sockfd, NULL, NULL); + if(accept_fd != -1) + { + log_printf(L_INFO, "Accepting a new connection - requesting tunnel...\n"); + + /* Open a new tunnel for this FD */ + client_tunnel.sockfd = accept_fd; + send_tunnel_request_packet(remote_host, remote_port, friendnumber); + } + } + + /* Handle reading from sockets */ + select_rv = select(select_nfds, &fds, NULL, NULL, &tv); + if(select_rv == -1 || select_rv == 0) + { + if(select_rv == -1) + { + log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", errno, strerror(errno)); + } + else + { + log_printf(L_DEBUG3, "Nothing to read..."); + } + } + else + { + HASH_ITER(hh, by_id, tun, tmp) + { + if(FD_ISSET(tun->sockfd, &fds)) + { + int nbytes; + if(program_mode == Mode_Client_Local_Port_Forward) + { + nbytes = recv(tun->sockfd, + tox_packet_buf + PROTOCOL_BUFFER_OFFSET, + READ_BUFFER_SIZE, 0); + } + else + { + nbytes = read(tun->sockfd, + tox_packet_buf + PROTOCOL_BUFFER_OFFSET, + READ_BUFFER_SIZE + ); + } + + /* Check if connection closed */ + if(nbytes == 0) + { + uint8_t data[PROTOCOL_BUFFER_OFFSET]; + protocol_frame frame_st, *frame; + + log_printf(L_INFO, "Connection closed\n"); + + frame = &frame_st; + memset(frame, 0, sizeof(protocol_frame)); + frame->friendnumber = tun->friendnumber; + frame->packet_type = PACKET_TYPE_TCP_FIN; + frame->connid = tun->connid; + frame->data_length = 0; + send_frame(frame, data); + if(tun->sockfd) + { + FD_CLR(tun->sockfd, &client_master_fdset); + } + tunnel_delete(tun); + } + else + { + protocol_frame frame_st, *frame; + + frame = &frame_st; + memset(frame, 0, sizeof(protocol_frame)); + frame->friendnumber = tun->friendnumber; + frame->packet_type = PACKET_TYPE_TCP; + frame->connid = tun->connid; + frame->data_length = nbytes; + send_frame(frame, tox_packet_buf); + +// printf("Wrote %d bytes from sock %d to tunnel %d\n", nbytes, tun->sockfd, tun->connid); + } + } + } + } + + fds = client_master_fdset; + + /* Check friend connection status changes */ + if(friend_connection_status == TOX_CONNECTION_NONE) + { + log_printf(L_ERROR, "Lost connection to server. Exiting."); + exit(1); + } +} + /* Main loop for the client */ int do_client_loop(uint8_t *tox_id_str) { - unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; unsigned char tox_id[TOX_ADDRESS_SIZE]; uint32_t friendnumber = 0; - struct timeval tv; - fd_set fds; static time_t invitation_sent_time = 0; uint32_t invitations_sent = 0; TOX_ERR_FRIEND_CUSTOM_PACKET custom_packet_error; @@ -424,113 +532,7 @@ int do_client_loop(uint8_t *tox_id_str) case CLIENT_STATE_AWAIT_PONG: break; case CLIENT_STATE_CONNECTED: - { - int accept_fd = 0; - int select_rv = 0; - tunnel *tmp = NULL; - tunnel *tun = NULL; - - tv.tv_sec = 0; - tv.tv_usec = 20000; - fds = client_master_fdset; - - /* Handle accepting new connections */ - if(program_mode != Mode_Client_Ping && client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ - { - accept_fd = accept(bind_sockfd, NULL, NULL); - if(accept_fd != -1) - { - log_printf(L_INFO, "Accepting a new connection - requesting tunnel...\n"); - - /* Open a new tunnel for this FD */ - client_tunnel.sockfd = accept_fd; - send_tunnel_request_packet(remote_host, remote_port, friendnumber); - } - } - - /* Handle reading from sockets */ - select_rv = select(select_nfds, &fds, NULL, NULL, &tv); - if(select_rv == -1 || select_rv == 0) - { - if(select_rv == -1) - { - log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", - errno, strerror(errno)); - } - else - { - log_printf(L_DEBUG3, "Nothing to read..."); - } - } - else - { - HASH_ITER(hh, by_id, tun, tmp) - { - if(FD_ISSET(tun->sockfd, &fds)) - { - int nbytes; - if(program_mode == Mode_Client_Local_Port_Forward) - { - nbytes = recv(tun->sockfd, - tox_packet_buf + PROTOCOL_BUFFER_OFFSET, - READ_BUFFER_SIZE, 0); - } - else - { - nbytes = read(tun->sockfd, - tox_packet_buf + PROTOCOL_BUFFER_OFFSET, - READ_BUFFER_SIZE - ); - } - - /* Check if connection closed */ - if(nbytes == 0) - { - uint8_t data[PROTOCOL_BUFFER_OFFSET]; - protocol_frame frame_st, *frame; - - log_printf(L_INFO, "Connection closed\n"); - - frame = &frame_st; - memset(frame, 0, sizeof(protocol_frame)); - frame->friendnumber = tun->friendnumber; - frame->packet_type = PACKET_TYPE_TCP_FIN; - frame->connid = tun->connid; - frame->data_length = 0; - send_frame(frame, data); - if(tun->sockfd) - { - FD_CLR(tun->sockfd, &client_master_fdset); - } - tunnel_delete(tun); - } - else - { - protocol_frame frame_st, *frame; - - frame = &frame_st; - memset(frame, 0, sizeof(protocol_frame)); - frame->friendnumber = tun->friendnumber; - frame->packet_type = PACKET_TYPE_TCP; - frame->connid = tun->connid; - frame->data_length = nbytes; - send_frame(frame, tox_packet_buf); - - // printf("Wrote %d bytes from sock %d to tunnel %d\n", nbytes, tun->sockfd, tun->connid); - } - } - } - } - - fds = client_master_fdset; - - /* Check friend connection status changes */ - if(friend_connection_status == TOX_CONNECTION_NONE) - { - log_printf(L_ERROR, "Lost connection to server. Exiting."); - exit(1); - } - } + client_connected_loop_iteration(friendnumber); break; } From 1c0e0737b49b8f58fd5bd9d1797e842ff973de6e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 18:21:02 -0400 Subject: [PATCH 34/70] do not need to check program_mode here --- client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client.c b/client.c index 154c1c5..1359e31 100644 --- a/client.c +++ b/client.c @@ -290,8 +290,9 @@ void client_connected_loop_iteration(uint32_t friendnumber) fds = client_master_fdset; /* Handle accepting new connections */ - if(program_mode != Mode_Client_Ping && client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ + if(client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ { + log_printf(L_DEBUG, "calling accept(%d)", bind_sockfd); accept_fd = accept(bind_sockfd, NULL, NULL); if(accept_fd != -1) { From 7c03915273d53bee5f25a8816181c4e82b6f7f23 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 21 Aug 2020 21:41:11 -0400 Subject: [PATCH 35/70] factorize usleep()-related code in main.c --- log.c | 6 ++++++ log.h | 2 ++ main.c | 63 +++++++++++++++++++++++++++++++++------------------------- main.h | 7 +++++++ 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/log.c b/log.c index 3124434..36472db 100644 --- a/log.c +++ b/log.c @@ -41,6 +41,12 @@ char *log_printable_level(int level) return "DEBUG"; case L_DEBUG2: return "DEBUG2"; + case L_DEBUG3: + return "DEBUG3"; + case L_DEBUG4: + return "DEBUG4"; + case L_DEBUG5: + return "DEBUG5"; } return "UNKNOWN"; } diff --git a/log.h b/log.h index ee25a14..a05af64 100644 --- a/log.h +++ b/log.h @@ -7,6 +7,8 @@ #define L_DEBUG 7 #define L_DEBUG2 8 #define L_DEBUG3 9 +#define L_DEBUG4 10 +#define L_DEBUG5 11 #define L_UNSET 0x29a diff --git a/main.c b/main.c index e90518e..84561b8 100644 --- a/main.c +++ b/main.c @@ -973,44 +973,58 @@ void cleanup() log_close(); } +struct tox_timer init_tox_timer(Tox *tox) +{ + struct tox_timer t; + t.tox_iteration_interval_ms = tox_iteration_interval(tox); + log_printf(L_DEBUG5, "Iteration interval: %dms\n", t.tox_iteration_interval_ms); + + gettimeofday(&t.tv_start, NULL); + + t.tv.tv_usec = (t.tox_iteration_interval_ms % 1000) * 1000; + t.tv.tv_sec = t.tox_iteration_interval_ms / 1000; + return t; +} + +void run_tox_timer(Tox *tox, struct tox_timer t) +{ + struct timeval tv_end; + gettimeofday(&tv_end, NULL); + unsigned long long ms_elapsed = tv_end.tv_sec + tv_end.tv_usec/1000 - t.tv_start.tv_sec - t.tv_start.tv_usec/1000; + + if(ms_elapsed < t.tox_iteration_interval_ms) + { + log_printf(L_DEBUG5, "Sleeping for %d ms extra to prevent high CPU usage\n", t.tox_iteration_interval_ms - ms_elapsed); + usleep((t.tox_iteration_interval_ms - ms_elapsed) * 1000); + } +} int do_server_loop() { - struct timeval tv, tv_start, tv_end; - unsigned long long ms_start, ms_end; fd_set fds; unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; tunnel *tun = NULL; tunnel *tmp = NULL; - int sent_data = 0; tox_callback_friend_lossless_packet(tox, parse_lossless_packet); - tv.tv_sec = 0; - tv.tv_usec = 20000; - FD_ZERO(&master_server_fds); while(1) { - uint32_t tox_do_interval_ms; + bool tox_timer_do_sleep = false; int select_rv = 0; - sent_data = 0; /* Let tox do its stuff */ tox_iterate(tox, NULL); /* Get the desired sleep time, used in select() later */ - tox_do_interval_ms = tox_iteration_interval(tox); - tv.tv_usec = (tox_do_interval_ms % 1000) * 1000; - tv.tv_sec = tox_do_interval_ms / 1000; - log_printf(L_DEBUG3, "Iteration interval: %dms\n", tox_do_interval_ms); - gettimeofday(&tv_start, NULL); + struct tox_timer t = init_tox_timer(tox); fds = master_server_fds; /* Poll for data from our client connection */ - select_rv = select(select_nfds, &fds, NULL, NULL, &tv); + select_rv = select(select_nfds, &fds, NULL, NULL, &t.tv); if(select_rv == -1) { log_printf(L_DEBUG, "Reading from local socket failed: code=%d (%s)\n", @@ -1018,7 +1032,7 @@ int do_server_loop() } else if (select_rv == 0) { - log_printf(L_DEBUG3, "Nothing to read..."); + log_printf(L_DEBUG5, "Nothing to read..."); } else { @@ -1032,6 +1046,7 @@ int do_server_loop() log_printf(L_DEBUG2, "Current tunnel: %p", tun); if(FD_ISSET(tun->sockfd, &fds)) { + tox_timer_do_sleep = true; int nbytes = recv(tun->sockfd, tox_packet_buf+PROTOCOL_BUFFER_OFFSET, READ_BUFFER_SIZE, 0); @@ -1059,8 +1074,6 @@ int do_server_loop() frame->connid = tun->connid; frame->data_length = 0; send_frame(frame, data); - sent_data = 1; - tunnel_queue_delete(tun); continue; @@ -1090,14 +1103,9 @@ int do_server_loop() } } - gettimeofday(&tv_end, NULL); - ms_start = 1000 * tv_start.tv_sec + tv_start.tv_usec/1000; - ms_end = 1000 * tv_end.tv_sec + tv_end.tv_usec/1000; - - if(!sent_data && (ms_end - ms_start < tox_do_interval_ms)) + if(tox_timer_do_sleep) { - /*log_printf(L_DEBUG, "Sleeping for %d ms extra to prevent high CPU usage\n", (tox_do_interval_ms - (ms_end - ms_start)));*/ - usleep((tox_do_interval_ms - (ms_end - ms_start)) * 1000); + run_tox_timer(tox, t); } } } @@ -1361,13 +1369,14 @@ int main(int argc, char *argv[]) min_log_level = L_DEBUG2; break; case 3: - min_log_level = L_DEBUG2; + min_log_level = L_DEBUG3; log_tox_trace = 1; break; case 4: + min_log_level = L_DEBUG4; + case 5: default: - min_log_level = L_DEBUG3; - log_tox_trace = 1; + min_log_level = L_DEBUG5; } break; case 'q': diff --git a/main.h b/main.h index 602f8e4..8411cc6 100644 --- a/main.h +++ b/main.h @@ -94,6 +94,13 @@ enum Mode { Mode_Client_Ping }; +struct tox_timer { + uint32_t tox_iteration_interval_ms; + struct timeval tv, tv_start; +}; +struct tox_timer init_tox_timer(Tox *tox); +void run_tox_timer(Tox *tox, struct tox_timer t); + /**** GLOBAL VARIABLES ****/ extern Tox *tox; From 3b65c8c3489910d1813d6bb9a8803536add9e921 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 22 Aug 2020 09:18:42 -0400 Subject: [PATCH 36/70] change log levels --- client.c | 2 +- main.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client.c b/client.c index 1359e31..5d8e2af 100644 --- a/client.c +++ b/client.c @@ -314,7 +314,7 @@ void client_connected_loop_iteration(uint32_t friendnumber) } else { - log_printf(L_DEBUG3, "Nothing to read..."); + log_printf(L_DEBUG4, "Nothing to read..."); } } else diff --git a/main.c b/main.c index 84561b8..670a311 100644 --- a/main.c +++ b/main.c @@ -651,7 +651,7 @@ void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, frame->data_length = INT16_AT(data, 6); frame->data = (uint8_t *)(data + PROTOCOL_BUFFER_OFFSET); frame->friendnumber = friendnumber; - log_printf(L_DEBUG2, "Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber); + log_printf(L_DEBUG4, "Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber); if(len < (size_t)frame->data_length + PROTOCOL_BUFFER_OFFSET) { @@ -1040,10 +1040,10 @@ int do_server_loop() tmp = NULL; tun = NULL; - log_printf(L_DEBUG2, "Starting tunnel iteration..."); + log_printf(L_DEBUG3, "Starting tunnel iteration..."); HASH_ITER(hh, by_id, tun, tmp) { - log_printf(L_DEBUG2, "Current tunnel: %p", tun); + log_printf(L_DEBUG3, "Current tunnel: %p", tun); if(FD_ISSET(tun->sockfd, &fds)) { tox_timer_do_sleep = true; @@ -1093,7 +1093,7 @@ int do_server_loop() } } } - log_printf(L_DEBUG2, "Tunnel iteration done"); + log_printf(L_DEBUG3, "Tunnel iteration done"); LL_FOREACH_SAFE(tunnels_to_delete, tunnel_list_entry, list_tmp) { From afdfa84369451c54e485acb8aea76b4acb7258b0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 22 Aug 2020 09:18:56 -0400 Subject: [PATCH 37/70] fixup! factorize usleep()-related code in main.c --- main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/main.c b/main.c index 670a311..45b1d8b 100644 --- a/main.c +++ b/main.c @@ -1089,7 +1089,6 @@ int do_server_loop() frame->connid = tun->connid; frame->data_length = nbytes; send_frame(frame, tox_packet_buf); - sent_data = 1; } } } From 34867d178d3173e679d54c129e2681a1f9d774f1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 22 Aug 2020 09:23:44 -0400 Subject: [PATCH 38/70] error handling/reporting --- client.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/client.c b/client.c index 5d8e2af..a9493f0 100644 --- a/client.c +++ b/client.c @@ -140,10 +140,16 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) log_printf(L_WARNING, "Got ACK tunnel frame when not in client mode!?\n"); return -1; } + if(state != CLIENT_STATE_AWAIT_TUNNEL) + { + log_printf(L_WARNING, "Got ACK tunnel frame in unexpected state (%d); ignoring", state); + return -1; + } tun = tunnel_create(client_tunnel.sockfd, rcvd_frame->connid, rcvd_frame->friendnumber); if (!tun) { + log_printf(L_ERROR, "Got server ACK but failed to create new tunnel"); exit(1); } @@ -152,14 +158,6 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) update_select_nfds(tun->sockfd); FD_SET(tun->sockfd, &client_master_fdset); - if(program_mode == Mode_Client_Local_Port_Forward) - { - log_printf(L_INFO, "Accepted a new connection on port %d\n", local_port); - } - if(state != CLIENT_STATE_AWAIT_TUNNEL) - { - log_printf(L_WARNING, "Got ACK tunnel frame when state is %d", state); - } state = CLIENT_STATE_CONNECTED; return 0; } From 38f74d3530ff3d5724493114f430c3b2a851b82d Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 22 Aug 2020 09:25:08 -0400 Subject: [PATCH 39/70] fixup! change log levels --- client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.c b/client.c index a9493f0..54f8c8a 100644 --- a/client.c +++ b/client.c @@ -290,8 +290,8 @@ void client_connected_loop_iteration(uint32_t friendnumber) /* Handle accepting new connections */ if(client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ { - log_printf(L_DEBUG, "calling accept(%d)", bind_sockfd); accept_fd = accept(bind_sockfd, NULL, NULL); + log_printf(L_DEBUG4, "calling accept(%d)", bind_sockfd); if(accept_fd != -1) { log_printf(L_INFO, "Accepting a new connection - requesting tunnel...\n"); From 7b8fea71623849972b9aa61c9264a7d2bc6e76bf Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 22 Aug 2020 09:27:43 -0400 Subject: [PATCH 40/70] use tox_timer for sleep on client --- client.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client.c b/client.c index 54f8c8a..d0353b1 100644 --- a/client.c +++ b/client.c @@ -272,19 +272,16 @@ void client_close_all_connections() } } -void client_connected_loop_iteration(uint32_t friendnumber) +void client_connected_loop_iteration(uint32_t friendnumber, struct tox_timer *t) { static unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; static fd_set fds; - static struct timeval tv; int accept_fd = 0; int select_rv = 0; tunnel *tmp = NULL; tunnel *tun = NULL; - tv.tv_sec = 0; - tv.tv_usec = 20000; fds = client_master_fdset; /* Handle accepting new connections */ @@ -303,7 +300,7 @@ void client_connected_loop_iteration(uint32_t friendnumber) } /* Handle reading from sockets */ - select_rv = select(select_nfds, &fds, NULL, NULL, &tv); + select_rv = select(select_nfds, &fds, NULL, NULL, &(t->tv)); if(select_rv == -1 || select_rv == 0) { if(select_rv == -1) @@ -415,6 +412,7 @@ int do_client_loop(uint8_t *tox_id_str) { /* Let tox do its stuff */ tox_iterate(tox, NULL); + struct tox_timer t = init_tox_timer(tox); switch(state) { @@ -531,11 +529,11 @@ int do_client_loop(uint8_t *tox_id_str) case CLIENT_STATE_AWAIT_PONG: break; case CLIENT_STATE_CONNECTED: - client_connected_loop_iteration(friendnumber); + client_connected_loop_iteration(friendnumber, &t); break; } - usleep(tox_iteration_interval(tox) * 1000); + run_tox_timer(tox, t); } } From 17c8cbf9c0c2e86ce91a9570d5f6a66fd5d366c3 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 23 Aug 2020 22:07:28 -0400 Subject: [PATCH 41/70] logging improvements --- client.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/client.c b/client.c index d0353b1..1561590 100644 --- a/client.c +++ b/client.c @@ -118,38 +118,30 @@ int local_bind() return 0; } -bool tunnel_client_mode() -{ - switch (program_mode) { - case Mode_Client_Local_Port_Forward: - case Mode_Client_Pipe: - return true; - case Mode_Client_Ping: - default: - return false; - } -} - /* Bind the client.sockfd to a tunnel */ int handle_acktunnel_frame(protocol_frame *rcvd_frame) { tunnel *tun; - if(!tunnel_client_mode()) - { - log_printf(L_WARNING, "Got ACK tunnel frame when not in client mode!?\n"); + switch (program_mode) { + case Mode_Client_Local_Port_Forward: + case Mode_Client_Pipe: + break; + default: + log_printf(L_WARNING, "Got ACKTUNNEL frame in unexpected mode (%d); ignoring", program_mode); return -1; } + if(state != CLIENT_STATE_AWAIT_TUNNEL) { - log_printf(L_WARNING, "Got ACK tunnel frame in unexpected state (%d); ignoring", state); + log_printf(L_WARNING, "Got ACKTUNNEL frame in unexpected state (%d); ignoring", state); return -1; } tun = tunnel_create(client_tunnel.sockfd, rcvd_frame->connid, rcvd_frame->friendnumber); if (!tun) { - log_printf(L_ERROR, "Got server ACK but failed to create new tunnel"); + log_printf(L_ERROR, "Got ACKTUNNEL frame but tunnel_create() failed to create new tunnel object"); exit(1); } From 702b610636012b8f9247c3bbc1d39cd8bddde7b2 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 23 Aug 2020 23:39:06 -0400 Subject: [PATCH 42/70] tighter variable scope --- client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client.c b/client.c index 1561590..61d1fec 100644 --- a/client.c +++ b/client.c @@ -269,7 +269,6 @@ void client_connected_loop_iteration(uint32_t friendnumber, struct tox_timer *t) static unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; static fd_set fds; - int accept_fd = 0; int select_rv = 0; tunnel *tmp = NULL; tunnel *tun = NULL; @@ -279,8 +278,8 @@ void client_connected_loop_iteration(uint32_t friendnumber, struct tox_timer *t) /* Handle accepting new connections */ if(client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ { - accept_fd = accept(bind_sockfd, NULL, NULL); log_printf(L_DEBUG4, "calling accept(%d)", bind_sockfd); + int accept_fd = accept(bind_sockfd, NULL, NULL); if(accept_fd != -1) { log_printf(L_INFO, "Accepting a new connection - requesting tunnel...\n"); From e1d746ec1a5c4239359c81ee24c9427bb9bfedd0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 28 Aug 2020 16:55:17 -0400 Subject: [PATCH 43/70] steve --- main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.c b/main.c index 45b1d8b..3d11f8c 100644 --- a/main.c +++ b/main.c @@ -3,7 +3,6 @@ #include "tox_bootstrap.h" #include "log.h" -#define LOG_IP_ADDRESS #ifdef __MACH__ #include "mach.h" @@ -19,7 +18,7 @@ TOX_CONNECTION friend_connection_status = TOX_CONNECTION_NONE; /* Don't bootstrap nodes */ -int skip_bootstrap = 1; +int skip_bootstrap = 0; enum Mode program_mode = Mode_Unspecified; From 99a05205c58752126abe648f230988c221687d27 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 29 Aug 2020 14:06:21 -0400 Subject: [PATCH 44/70] Fix public key conflict The public keys of different toxid ssh servers were stored in known_hosts under the name 'localhost'. The key is stored under the toxid instead. --- scripts/tokssh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tokssh b/scripts/tokssh index 8169bdd..22a5f0b 100755 --- a/scripts/tokssh +++ b/scripts/tokssh @@ -71,12 +71,12 @@ then # last argument is user@toxid user="${arruserhost[0]}@" toxid=${arruserhost[1]} - hostname=localhost + hostname=$toxid else # last argument is just toxid user="" toxid=$userhost - hostname=localhost + hostname=$toxid fi #search toxid in ~/.tuntox/hosts and map it to toxid From 5961303fc6e8f87e61a7abb1b4c14d24e7e30758 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 29 Aug 2020 14:19:37 -0400 Subject: [PATCH 45/70] install tokssh --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index e6b0cef..0fe0bb0 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,7 @@ clean: install: tuntox_nostatic $(INSTALL_MKDIR) -d $(DESTDIR)$(bindir) cp tuntox_nostatic $(DESTDIR)$(bindir)/tuntox + install scripts/tokssh $(DESTDIR)$(bindir)/ debs = ../tuntox_0.0.9-1_amd64.deb ../tuntox-dbgsym_0.0.9-1_amd64.deb .PHONY: install-debs debs From f32da4ead891548cd23ec0dd6408ef3125b4e9e3 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 24 Feb 2021 18:19:42 -0500 Subject: [PATCH 46/70] debian package will include service file; install target will enable service --- Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0fe0bb0..94a7956 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ INSTALL_MKDIR = $(INSTALL) -d -m 755 prefix ?= /usr bindir ?= $(prefix)/bin +etcdir ?= /etc # Targets all: tuntox tuntox_nostatic @@ -45,15 +46,22 @@ clean: rm -f *.o tuntox cscope.out gitversion.h tox_bootstrap.h install: tuntox_nostatic - $(INSTALL_MKDIR) -d $(DESTDIR)$(bindir) - cp tuntox_nostatic $(DESTDIR)$(bindir)/tuntox - install scripts/tokssh $(DESTDIR)$(bindir)/ + install -d -m755 $(DESTDIR)$(bindir) $(DESTDIR)$(etcdir) + install -d -m700 $(DESTDIR)$(etcdir)/tuntox + install -D -T tuntox_nostatic $(DESTDIR)$(bindir)/tuntox + install -D scripts/tokssh -t $(DESTDIR)$(bindir)/ + install -m0644 -D -t $(DESTDIR)$(etcdir)/systemd/system scripts/tuntox.service +ifeq ($(SKIP_SYSTEMCTL),) + systemctl daemon-reload + systemctl restart tuntox + systemctl status tuntox +endif debs = ../tuntox_0.0.9-1_amd64.deb ../tuntox-dbgsym_0.0.9-1_amd64.deb .PHONY: install-debs debs install-debs: $(debs) $(shell [ "$$(id -u)" = 0 ] || echo sudo) dpkg -i $(debs) $(debs) debs: - fakeroot ./debian/rules binary + fakeroot -- sh -c 'SKIP_SYSTEMCTL=y ./debian/rules binary' .PHONY: all clean tuntox From 88f3bbb8fe301815ac2115b7edf2fbbc61390c6b Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 15:42:59 -0400 Subject: [PATCH 47/70] hard-code dependencies instead of using wildcard --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 94a7956..08bd883 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -SOURCES = $(wildcard *.c) +SOURCES = client.c gitversion.c log.c mach.c main.c util.c +OBJECTS=$(SOURCES:.c=.o) +INCLUDES = client.h gitversion.h log.h mach.h main.h tox_bootstrap.h utarray.h uthash.h util.h utlist.h utstring.h DEPS=toxcore CC=gcc CFLAGS=-g -Wall #-std=c99 @@ -7,8 +9,6 @@ LDFLAGS=-g -pthread -lm -static -lrt LDFLAGS += $(shell pkg-config --static --libs $(DEPS)) DSO_LDFLAGS=-g -pthread -lm -lrt DSO_LDFLAGS += $(shell pkg-config --libs $(DEPS)) -OBJECTS=$(SOURCES:.c=.o) -INCLUDES = $(wildcard *.h) PYTHON = /usr/bin/env python3 INSTALL = install -C INSTALL_MKDIR = $(INSTALL) -d -m 755 From 41e73ea8220a6bf6a0d8a39b452733a2afadae27 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 15:43:16 -0400 Subject: [PATCH 48/70] fix whitespace --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 08bd883..f14f7da 100644 --- a/Makefile +++ b/Makefile @@ -25,18 +25,18 @@ gitversion.h: FORCE FORCE: -tox_bootstrap.h: - $(PYTHON) generate_tox_bootstrap.py +tox_bootstrap.h: + $(PYTHON) generate_tox_bootstrap.py %.o: %.c $(INCLUDES) gitversion.h tox_bootstrap.h @echo " CC $@" @$(CC) -c $(CFLAGS) $< -o $@ tuntox: $(OBJECTS) $(INCLUDES) - $(CC) -o $@ $(OBJECTS) -lpthread $(LDFLAGS) + $(CC) -o $@ $(OBJECTS) -lpthread $(LDFLAGS) tuntox_nostatic: $(OBJECTS) $(INCLUDES) - $(CC) -o $@ $(OBJECTS) -lpthread $(DSO_LDFLAGS) + $(CC) -o $@ $(OBJECTS) -lpthread $(DSO_LDFLAGS) cscope.out: @echo " GEN $@" From 4f0d0347d2b27689f91dda9723c48f6d37f4a05e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 15:44:10 -0400 Subject: [PATCH 49/70] fix gitversion.h to rebuild only when changed --- Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f14f7da..7555f2f 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,14 @@ etcdir ?= /etc # Targets all: tuntox tuntox_nostatic -gitversion.h: FORCE - @if [ -f .git/HEAD ] ; then echo " GEN $@"; echo "#define GITVERSION \"$(shell echo -n $$(git rev-parse HEAD) && (git diff --quiet || printf %s -dirty) )\"" > $@; fi +gitversion != printf %s $$(git rev-parse HEAD) && (git diff --quiet || printf %s -dirty) +gitversion_on_disk != read _ _ v < gitversion.h; echo $$v +ifneq ("$(gitversion)", $(gitversion_on_disk)) +.PHONY: gitversion.h +endif + +gitversion.h: + echo '#define GITVERSION "$(gitversion)"' > $@ FORCE: From d965141cc88f05127e70e79f7613170224edab5e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 16:18:19 -0400 Subject: [PATCH 50/70] cleanup whitespace --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 7555f2f..9fba668 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ SOURCES = client.c gitversion.c log.c mach.c main.c util.c -OBJECTS=$(SOURCES:.c=.o) +OBJECTS = $(SOURCES:.c=.o) INCLUDES = client.h gitversion.h log.h mach.h main.h tox_bootstrap.h utarray.h uthash.h util.h utlist.h utstring.h -DEPS=toxcore -CC=gcc -CFLAGS=-g -Wall #-std=c99 +DEPS = toxcore +CC = gcc +CFLAGS = -g -Wall #-std=c99 CFLAGS += $(shell pkg-config --cflags $(DEPS)) -LDFLAGS=-g -pthread -lm -static -lrt +LDFLAGS = -g -pthread -lm -static -lrt LDFLAGS += $(shell pkg-config --static --libs $(DEPS)) -DSO_LDFLAGS=-g -pthread -lm -lrt +DSO_LDFLAGS = -g -pthread -lm -lrt DSO_LDFLAGS += $(shell pkg-config --libs $(DEPS)) PYTHON = /usr/bin/env python3 INSTALL = install -C From ba7ed80ea14479f154eb2818c99879be13c9f076 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 16:20:21 -0400 Subject: [PATCH 51/70] fixup! fix gitversion.h to rebuild only when changed --- Makefile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 9fba668..eda232a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,9 @@ SOURCES = client.c gitversion.c log.c mach.c main.c util.c OBJECTS = $(SOURCES:.c=.o) +EXECUTABLES = tuntox tuntox_nostatic +DEB_VERSION = 0.0.9-1 +DEB_ARCH = amd64 +DEBS = ../tuntox_$(DEB_VERSION)_$(DEB_ARCH).deb ../tuntox-dbgsym_$(DEB_VERSION)_$(DEB_ARCH).deb INCLUDES = client.h gitversion.h log.h mach.h main.h tox_bootstrap.h utarray.h uthash.h util.h utlist.h utstring.h DEPS = toxcore CC = gcc @@ -18,10 +22,11 @@ bindir ?= $(prefix)/bin etcdir ?= /etc # Targets -all: tuntox tuntox_nostatic +.PHONY: all clean +all: $(EXECUTABLES) gitversion != printf %s $$(git rev-parse HEAD) && (git diff --quiet || printf %s -dirty) -gitversion_on_disk != read _ _ v < gitversion.h; echo $$v +gitversion_on_disk != 2>/dev/null read _ _ v < gitversion.h && echo $$v || true ifneq ("$(gitversion)", $(gitversion_on_disk)) .PHONY: gitversion.h endif @@ -29,8 +34,6 @@ endif gitversion.h: echo '#define GITVERSION "$(gitversion)"' > $@ -FORCE: - tox_bootstrap.h: $(PYTHON) generate_tox_bootstrap.py @@ -49,7 +52,7 @@ cscope.out: @cscope -bv ./*.[ch] &> /dev/null clean: - rm -f *.o tuntox cscope.out gitversion.h tox_bootstrap.h + rm -f $(OBJECTS) $(EXECUTABLES) cscope.out gitversion.h tox_bootstrap.h install: tuntox_nostatic install -d -m755 $(DESTDIR)$(bindir) $(DESTDIR)$(etcdir) @@ -63,11 +66,8 @@ ifeq ($(SKIP_SYSTEMCTL),) systemctl status tuntox endif -debs = ../tuntox_0.0.9-1_amd64.deb ../tuntox-dbgsym_0.0.9-1_amd64.deb .PHONY: install-debs debs -install-debs: $(debs) - $(shell [ "$$(id -u)" = 0 ] || echo sudo) dpkg -i $(debs) -$(debs) debs: +install-debs: $(DEBS) + $(shell [ "$$(id -u)" = 0 ] || echo sudo) dpkg -i $(DEBS) +$(DEBS) debs: fakeroot -- sh -c 'SKIP_SYSTEMCTL=y ./debian/rules binary' - -.PHONY: all clean tuntox From e3e7db9e862d6d63b9cebf756d76875e3d9729b0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 16:36:08 -0400 Subject: [PATCH 52/70] enable warnings ROFL, warnings were disabled. also enabled -O2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index eda232a..b758288 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ DEBS = ../tuntox_$(DEB_VERSION)_$(DEB_ARCH).deb ../tuntox-dbgsym_$(DEB_VERSION)_ INCLUDES = client.h gitversion.h log.h mach.h main.h tox_bootstrap.h utarray.h uthash.h util.h utlist.h utstring.h DEPS = toxcore CC = gcc -CFLAGS = -g -Wall #-std=c99 +CFLAGS = -g -W -Wall -O2 -fcompare-debug-second CFLAGS += $(shell pkg-config --cflags $(DEPS)) LDFLAGS = -g -pthread -lm -static -lrt LDFLAGS += $(shell pkg-config --static --libs $(DEPS)) From dc362fa7e098cc48bd2a48542c2f1a9bcbfcb11e Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 16:36:50 -0400 Subject: [PATCH 53/70] silence warnings --- uthash.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/uthash.h b/uthash.h index 7205c67..d6b54e9 100644 --- a/uthash.h +++ b/uthash.h @@ -449,15 +449,25 @@ do { hashv += keylen; \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ + [[fallthrough]]; \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ + [[fallthrough]]; \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ + [[fallthrough]]; \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ + [[fallthrough]]; \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ + [[fallthrough]]; \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ + [[fallthrough]]; \ case 5: _hj_j += _hj_key[4]; \ + [[fallthrough]]; \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ + [[fallthrough]]; \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ + [[fallthrough]]; \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ + [[fallthrough]]; \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ From 0108aeec741a8f7cc86dd42955eacdf5312c63ef Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:34:06 -0400 Subject: [PATCH 54/70] Makefile fixes --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index b758288..1942852 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,9 @@ PYTHON = /usr/bin/env python3 INSTALL = install -C INSTALL_MKDIR = $(INSTALL) -d -m 755 -prefix ?= /usr -bindir ?= $(prefix)/bin -etcdir ?= /etc +prefix = /usr +bindir = $(prefix)/bin +etcdir = /etc # Targets .PHONY: all clean @@ -52,7 +52,7 @@ cscope.out: @cscope -bv ./*.[ch] &> /dev/null clean: - rm -f $(OBJECTS) $(EXECUTABLES) cscope.out gitversion.h tox_bootstrap.h + rm -f $(OBJECTS) $(EXECUTABLES) cscope.out gitversion.h install: tuntox_nostatic install -d -m755 $(DESTDIR)$(bindir) $(DESTDIR)$(etcdir) From 38987813e2e4a8a1c05e418cc44cacb439ce0354 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:34:45 -0400 Subject: [PATCH 55/70] silence unused variable warnings --- log.c | 1 + main.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/log.c b/log.c index 36472db..cc7f9a4 100644 --- a/log.c +++ b/log.c @@ -151,6 +151,7 @@ static const char *tox_log_level_name(TOX_LOG_LEVEL level) void on_tox_log(Tox *tox, TOX_LOG_LEVEL level, const char *path, uint32_t line, const char *func, const char *message, void *user_data) { + tox = tox; uint32_t index = user_data ? *(uint32_t *)user_data : 0; const char *file = strrchr(path, '/'); diff --git a/main.c b/main.c index 3d11f8c..feee4a1 100644 --- a/main.c +++ b/main.c @@ -616,6 +616,8 @@ int handle_frame(protocol_frame *frame) */ void parse_lossless_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t len, void *tmp) { + tox = tox; + tmp = tmp; protocol_frame *frame = NULL; if(len < PROTOCOL_BUFFER_OFFSET) @@ -865,6 +867,7 @@ void tunnel_target_whitelist_clear() void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) { + userdata = userdata; unsigned char tox_printable_id[TOX_ADDRESS_SIZE * 2 + 1]; uint32_t friendnumber; TOX_ERR_FRIEND_ADD friend_add_error; @@ -921,6 +924,9 @@ void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *m /* Callback for tox_callback_self_connection_status() */ void handle_connection_status_change(Tox *tox, TOX_CONNECTION new_connection_status, void *user_data) { + tox = tox; + user_data = user_data; + connection_status = new_connection_status; if (connection_status) { @@ -947,6 +953,8 @@ void log_friend_ip_address(Tox *tox, uint32_t friendnumber) void handle_friend_connection_status(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status, void *user_data) { + tox = tox; + user_data = user_data; const char *status = NULL; status = readable_connection_status(connection_status); log_printf(L_INFO, "Friend #%d connection status changed: %s", friend_number, status); @@ -987,6 +995,7 @@ struct tox_timer init_tox_timer(Tox *tox) void run_tox_timer(Tox *tox, struct tox_timer t) { + tox = tox; struct timeval tv_end; gettimeofday(&tv_end, NULL); unsigned long long ms_elapsed = tv_end.tv_sec + tv_end.tv_usec/1000 - t.tv_start.tv_sec - t.tv_start.tv_usec/1000; From 6d71058e25c94d44339110dbbf93c8d4895ba91b Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:35:09 -0400 Subject: [PATCH 56/70] whitespace --- log.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/log.c b/log.c index cc7f9a4..1be6ffa 100644 --- a/log.c +++ b/log.c @@ -155,10 +155,10 @@ void on_tox_log(Tox *tox, TOX_LOG_LEVEL level, const char *path, uint32_t line, uint32_t index = user_data ? *(uint32_t *)user_data : 0; const char *file = strrchr(path, '/'); - if(level == TOX_LOG_LEVEL_TRACE && !log_tox_trace) - { - return; - } + if(level == TOX_LOG_LEVEL_TRACE && !log_tox_trace) + { + return; + } file = file ? file + 1 : path; log_printf(L_DEBUG2, "[#%d] %s %s:%d\t%s:\t%s\n", index, tox_log_level_name(level), file, line, func, message); From 3347bab22f85c0666c9da17b0328c59844fa9d43 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:36:35 -0400 Subject: [PATCH 57/70] enabling warnings found this real bug the bug didn't matter --- main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main.c b/main.c index feee4a1..f490c82 100644 --- a/main.c +++ b/main.c @@ -1381,6 +1381,7 @@ int main(int argc, char *argv[]) break; case 4: min_log_level = L_DEBUG4; + break; case 5: default: min_log_level = L_DEBUG5; From 19043546f68da0ba42463723b2a2d6e562db5619 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:36:53 -0400 Subject: [PATCH 58/70] clarify string manipulation code doing it eliminated some warnings --- main.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index f490c82..c316c32 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,7 @@ long int udp_start_port = 0; long int udp_end_port = 0; /* Directory with config and tox save */ -char *config_path = "/etc/tuntox/"; +char *config_path = "/etc/tuntox"; /* Limit hostname and port in server */ int tunnel_target_whitelist_size = 0; @@ -705,38 +705,42 @@ int send_tunnel_request_packet(char *remote_host, int remote_port, int friend_nu /* End proto */ +void path_append(char *target, char *prefix, char *suffix) +{ + size_t prefix_len = strlen(prefix); + size_t suffix_len = strlen(suffix); + if (prefix_len + suffix_len + 1 > PATH_MAX) return; + memcpy(target, prefix, prefix_len); + memcpy(target + prefix_len, suffix, suffix_len); + *(target + prefix_len + suffix_len) = 0; +} + /* Save tox identity to a file */ static void write_save(Tox *tox) { void *data; uint32_t size; - uint8_t path_tmp[512], path_real[512], *p; + char path_tmp[PATH_MAX], path_real[PATH_MAX]; FILE *file; size = tox_get_savedata_size(tox); data = malloc(size); tox_get_savedata(tox, data); - strncpy((char *)path_real, config_path, sizeof(path_real)); - - p = path_real + strlen((char *)path_real); - memcpy(p, "tox_save", sizeof("tox_save")); + path_append(path_real, config_path, "/tox_save"); + path_append(path_tmp, path_real, ".tmp"); - unsigned int path_len = (p - path_real) + sizeof("tox_save"); - memcpy(path_tmp, path_real, path_len); - memcpy(path_tmp + (path_len - 1), ".tmp", sizeof(".tmp")); - - file = fopen((char*)path_tmp, "wb"); - if(file) { + file = fopen(path_tmp, "wb"); + if (file) { fwrite(data, size, 1, file); fflush(file); fclose(file); - if (rename((char*)path_tmp, (char*)path_real) != 0) { + if (rename(path_tmp, path_real) != 0) { log_printf(L_WARNING, "Failed to rename file. %s to %s deleting and trying again\n", path_tmp, path_real); - if(remove((const char *)path_real) < 0) { + if (remove(path_real) < 0) { log_printf(L_WARNING, "Failed to remove old save file %s\n", path_real); } - if (rename((char*)path_tmp, (char*)path_real) != 0) { + if (rename(path_tmp, path_real) != 0) { log_printf(L_WARNING, "Saving Failed\n"); } else { log_printf(L_DEBUG, "Saved data\n"); @@ -758,15 +762,10 @@ static size_t load_save(uint8_t **out_data) { void *data; uint32_t size; - uint8_t path_real[PATH_MAX], *p; - - strncpy((char *)path_real, config_path, sizeof(path_real)); - - p = path_real + strlen((char *)path_real); - char basename[] = "/tox_save"; - memcpy(p, "/tox_save", sizeof(basename)); + char f[PATH_MAX]; - data = file_raw((char *)path_real, &size); + path_append(f, config_path, "/tox_save"); + data = file_raw(f, &size); if(data) { From 90085bacc47ea92cbec6622f9678fc3233e7536f Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 17:44:44 -0400 Subject: [PATCH 59/70] "make install" will use sudo --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 1942852..3fcaea9 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,10 @@ cscope.out: clean: rm -f $(OBJECTS) $(EXECUTABLES) cscope.out gitversion.h +ifneq ($(shell id -u),0) +install: + sudo MAKEFLAGS=$(MAKEFLAGS) -- $(MAKE) install +else install: tuntox_nostatic install -d -m755 $(DESTDIR)$(bindir) $(DESTDIR)$(etcdir) install -d -m700 $(DESTDIR)$(etcdir)/tuntox @@ -65,6 +69,7 @@ ifeq ($(SKIP_SYSTEMCTL),) systemctl restart tuntox systemctl status tuntox endif +endif .PHONY: install-debs debs install-debs: $(DEBS) From 447ad0521b439ffdb30831b4c158af708b242fa0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 18:50:24 -0400 Subject: [PATCH 60/70] Makefile: output consistency --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3fcaea9..60ec88b 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,8 @@ ifneq ("$(gitversion)", $(gitversion_on_disk)) endif gitversion.h: - echo '#define GITVERSION "$(gitversion)"' > $@ + @echo " GEN $@" + @echo '#define GITVERSION "$(gitversion)"' > $@ tox_bootstrap.h: $(PYTHON) generate_tox_bootstrap.py From eb4d601667665c3b757a917f7c9ad0f2c233fe07 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 7 Oct 2021 19:17:57 -0400 Subject: [PATCH 61/70] tokssh can safely accept new ssh keys, since the tox ID is self-authenticating --- scripts/tokssh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/tokssh b/scripts/tokssh index 22a5f0b..904efd4 100755 --- a/scripts/tokssh +++ b/scripts/tokssh @@ -98,4 +98,10 @@ else persist= fi -ssh -o ProxyCommand="tuntox $persist -i $toxid -W 127.0.0.1:%p $secret" $args ${user}${hostname} +ssh \ + -o ProxyCommand="tuntox $persist -i $toxid -W localhost:%p $secret" \ + -o StrictHostKeyChecking=accept-new \ + -o CanonicalizeHostname=no \ + -o UpdateHostKeys=yes \ + $args \ + ${user}${hostname} From 07f88c96a6fd5c66c1883c7170e665d18c38861c Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 8 Oct 2021 01:50:28 -0400 Subject: [PATCH 62/70] new command toxish --- Makefile | 3 +- scripts/toxish | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100755 scripts/toxish diff --git a/Makefile b/Makefile index 60ec88b..f08e26e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ SOURCES = client.c gitversion.c log.c mach.c main.c util.c OBJECTS = $(SOURCES:.c=.o) +SCRIPTS = scripts/tokssh scripts/toxish EXECUTABLES = tuntox tuntox_nostatic DEB_VERSION = 0.0.9-1 DEB_ARCH = amd64 @@ -63,7 +64,7 @@ install: tuntox_nostatic install -d -m755 $(DESTDIR)$(bindir) $(DESTDIR)$(etcdir) install -d -m700 $(DESTDIR)$(etcdir)/tuntox install -D -T tuntox_nostatic $(DESTDIR)$(bindir)/tuntox - install -D scripts/tokssh -t $(DESTDIR)$(bindir)/ + install -D -t $(DESTDIR)$(bindir) $(SCRIPTS) install -m0644 -D -t $(DESTDIR)$(etcdir)/systemd/system scripts/tuntox.service ifeq ($(SKIP_SYSTEMCTL),) systemctl daemon-reload diff --git a/scripts/toxish b/scripts/toxish new file mode 100755 index 0000000..9f62b53 --- /dev/null +++ b/scripts/toxish @@ -0,0 +1,132 @@ +#!/bin/bash +set -e +function help +{ + PROGNAME=${0##*/} + cat < +Usage: $PROGNAME connect + + +For example, first do this: + + $PROGNAME add billy 4BC18209278C9B2AA1BF9B9B27E671FC47D3DE3B15D175A63CC2C6E01B532A4CAE3D4BE083C8 + +Then you can connect to billy's SSH server through Tox with this command: + + ssh billy + + + +It will use Tox for connectivity but provide all the features of ssh (such as +git, rsync, tunneling with -w, etc). + + + +It is also possible to use this command: + + $PROGNAME connect + $PROGNAME connect billy 4BC18209278C9B2AA1BF9B9B27E671FC47D3DE3B15D175A63CC2C6E01B532A4CAE3D4BE083C8 + +...which will first add the entry, if necessary, and then connect by running the +command 'ssh billy'. + + +EOF +} + +function main +{ + if [ $# = 0 ] + then + help + exit + fi + case "$1" in + add) + shift + tokssh_add "$@" + ;; + connect) + shift + exists_ok + tokssh_add "$@" + exec ssh "$name" + ;; + *) + help + exit 1 + ;; + esac + exit +} + + +function ssh_config_fragment +{ + cat <&2 + exit 1 + fi + mkdir -p ~/.ssh/config.d + mkdir -p ~/.tuntox/persist + grep -q '^Include config\.d/\*' ~/.ssh/config || sed -i -e '1i Include config.d/*' ~/.ssh/config + if grep -q "^Host $name" ~/.ssh/config + then + if [ "$exists_ok" ] + then + return + else + echo "$0: Error: name exists in your .ssh/config. Refused to edit. name=$name" >&2 + exit 1 + fi + fi + out=~/.ssh/config.d/$name + if [ -e "$out" ] + then + if [ "$exists_ok" ] + then + return + else + echo "$0: Error: file exists. Refused to edit. file=$out" >&2 + exit 1 + fi + else + ssh_config_fragment > "$out" + fi +} + +main "$@" From 8b9302b36494393c942aea268b4e22e530ffe6e6 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 8 Oct 2021 02:23:59 -0400 Subject: [PATCH 63/70] always rebuild debs for install-debs --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f08e26e..c4d4f97 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ endif endif .PHONY: install-debs debs -install-debs: $(DEBS) +install-debs: debs $(shell [ "$$(id -u)" = 0 ] || echo sudo) dpkg -i $(DEBS) $(DEBS) debs: fakeroot -- sh -c 'SKIP_SYSTEMCTL=y ./debian/rules binary' From e247b29913de26abef93de2133bf920bbfcd04f1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 10 Oct 2021 06:42:58 -0400 Subject: [PATCH 64/70] try to fix the fallthrough warning --- uthash.h | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/uthash.h b/uthash.h index d6b54e9..02f6e0a 100644 --- a/uthash.h +++ b/uthash.h @@ -423,6 +423,15 @@ do { c -= a; c -= b; c ^= ( b >> 15 ); \ } while (0) +#if defined __has_cpp_attribute + #if __has_cpp_attribute(fallthrough) + #define fallthrough ([[fallthrough]];) + #endif +#endif +#ifndef fallthrough +#define fallthrough /* FALL-THRU */ +#endif + #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ @@ -449,25 +458,25 @@ do { hashv += keylen; \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - [[fallthrough]]; \ + fallthrough \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - [[fallthrough]]; \ + fallthrough \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - [[fallthrough]]; \ + fallthrough \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - [[fallthrough]]; \ + fallthrough \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - [[fallthrough]]; \ + fallthrough \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - [[fallthrough]]; \ + fallthrough \ case 5: _hj_j += _hj_key[4]; \ - [[fallthrough]]; \ + fallthrough \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - [[fallthrough]]; \ + fallthrough \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - [[fallthrough]]; \ + fallthrough \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - [[fallthrough]]; \ + fallthrough \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ From 6b71f5dd26283ff95d6bbd19797d3d15dd7215f3 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 10 Oct 2021 06:45:20 -0400 Subject: [PATCH 65/70] tokssh: major improvements --- scripts/tokssh | 127 ++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 71 deletions(-) diff --git a/scripts/tokssh b/scripts/tokssh index 904efd4..844bad6 100755 --- a/scripts/tokssh +++ b/scripts/tokssh @@ -2,95 +2,72 @@ set -e function help { cat < Usage: - tokssh [ssh options] [user@]address [-s secret] + TUNTOX_DESTINATION=[user@]
tokssh where - ssh options: options to pass to ssh process - user: login on remote host - address: either a ToxID or a hostname. ~/.tuntox/hosts is read to map - hostname to ToxID. hostname MUST resolve to 127.0.0.1 + ssh options: options to pass to ssh process + user: login username on remote host (you could also use "-l user") + address: a ToxID - -s optional secret to use to connect to tuntox server + To specify a tuntox secret (password), set the environment variable + TUNTOX_SECRET. + + Specifying passwords on the command line is insecure, since the arguments of + programs are considered public data. + + For that reason, you can also specify the remote address and username with + the environment variable TUNTOX_DESTINATION. This hides your desintation + from other users on the system. In this case, all options will be passed to + SSH. examples: + + TUNTOX_SECRET=sOmEPassWOrd tokssh 5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 tokssh user@5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 tokssh 5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 - tokssh -p 2222 -o ForwardAgent=yes user@5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 - tokssh user@5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 -s TuNToXSeCreT + tokssh -p 2222 -o ForwardAgent=yes -l user 5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 + TUNTOX_DESTINATION=5A40C3443ABD6E1DDEE682E83F84A4D556C24C22D2230DCC141A4723C123473C171A4D9C4054 tokssh -p 2222 files: ~/.tuntox/persist/ If directory exists, then read & store a persistent secret key/TOXID within. - ~/.tuntox/hosts - - Maps hostname to ToxID and optional secret. - - format is: - - hostname ToxID secret(optional) EOF } -strargs="'$*'" -if [ -z "${strargs##*-h*}" ] || [ -z "${strargs##*--help*}" ] ;then - help - exit -fi - -array=( $@ ) -len=${#array[@]} - -if [ $len -lt 1 ]; then - help - exit -fi - - -# look for secret and remvove it from args -if [ $len -gt 2 ] && [ "${array[$len-2]}" == "-s" ] -then - secret="${array[@]:$len-2:$len-1}" - len=$[len-2] -fi - -userhost=${array[$len-1]} -args=${array[@]:0:$len-1} - -# check for user@id -arruserhost=(${userhost//@/ }) -arruserhostlen=${#arruserhost[@]} - -if [ $arruserhostlen -gt 1 ] +if [ "$TUNTOX_DESTINATION" ] then - # last argument is user@toxid - user="${arruserhost[0]}@" - toxid=${arruserhost[1]} - hostname=$toxid -else - # last argument is just toxid - user="" - toxid=$userhost - hostname=$toxid + set -- "$@" "$TUNTOX_DESTINATION" + unset TUNTOX_DESTINATION fi -#search toxid in ~/.tuntox/hosts and map it to toxid -if [ -f ~/.tuntox/hosts ]; then - while read c_hostname c_toxid c_secret; do - if [ "${c_hostname:0:1}" != "#" ] && [ "$c_hostname" == "$toxid" ]; then - toxid="$c_toxid" - if [ "$secret" == "" ]; then - secret="-s $c_secret" - fi - break - fi - done < ~/.tuntox/hosts -fi +while [ $# -gt 0 ] +do + case "$1" in + -h|--help) + help + exit ;; + *) + if [ $# -eq 1 ] + then + break + else + ssh_options += "$1" + fi ;; + esac + shift +done +[ $# = 1 ] || { help; exit 1; } if [ -d ~/.tuntox/persist ]; then persist='-C ~/.tuntox/persist' @@ -98,10 +75,18 @@ else persist= fi +# Explicitly set the default values for CanonicalizeHostname and UpdateHostKeys, +# just to be safe. + +# We use StrictHostKeyChecking=accept because Tox validates the Tox identity and +# the Tox key is the identity. We have already performed initial public key +# exchange. + ssh \ - -o ProxyCommand="tuntox $persist -i $toxid -W localhost:%p $secret" \ - -o StrictHostKeyChecking=accept-new \ + -o ProxyCommand="tuntox $persist -i $toxid -W localhost:%p '$TUNTOX_SECRET'" \ + -o StrictHostKeyChecking=accept \ -o CanonicalizeHostname=no \ -o UpdateHostKeys=yes \ - $args \ - ${user}${hostname} + "${ssh_options[@]}" \ + -- \ + "$1" From 4f56fa7ba8e6f632b48c6085a76cd93da21574a0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 10 Oct 2021 06:53:55 -0400 Subject: [PATCH 66/70] toxish: fixes --- scripts/toxish | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/toxish b/scripts/toxish index 9f62b53..a59671a 100755 --- a/scripts/toxish +++ b/scripts/toxish @@ -51,7 +51,7 @@ function main ;; connect) shift - exists_ok + exists_ok=y tokssh_add "$@" exec ssh "$name" ;; @@ -88,18 +88,13 @@ function tokssh_add then help exit 1 - fi - if [ ${#2} = 76 ] - then - name=$1 - toxid=$2 - elif [ ${#1} = 76 ] + elif [ ${#2} != 76 ] then - name=$2 - toxid=$1 - else echo "$0: Error: Invalid ToxID: $2" >&2 exit 1 + else + name=$1 + toxid=$2 fi mkdir -p ~/.ssh/config.d mkdir -p ~/.tuntox/persist From 630f77b50285ab70659d3256135bf8bf6a7e1965 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Thu, 24 Feb 2022 19:43:48 -0500 Subject: [PATCH 67/70] Revert "try to fix the fallthrough warning" This reverts commit e247b29913de26abef93de2133bf920bbfcd04f1. --- uthash.h | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/uthash.h b/uthash.h index 02f6e0a..d6b54e9 100644 --- a/uthash.h +++ b/uthash.h @@ -423,15 +423,6 @@ do { c -= a; c -= b; c ^= ( b >> 15 ); \ } while (0) -#if defined __has_cpp_attribute - #if __has_cpp_attribute(fallthrough) - #define fallthrough ([[fallthrough]];) - #endif -#endif -#ifndef fallthrough -#define fallthrough /* FALL-THRU */ -#endif - #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ @@ -458,25 +449,25 @@ do { hashv += keylen; \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - fallthrough \ + [[fallthrough]]; \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - fallthrough \ + [[fallthrough]]; \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - fallthrough \ + [[fallthrough]]; \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - fallthrough \ + [[fallthrough]]; \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - fallthrough \ + [[fallthrough]]; \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - fallthrough \ + [[fallthrough]]; \ case 5: _hj_j += _hj_key[4]; \ - fallthrough \ + [[fallthrough]]; \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - fallthrough \ + [[fallthrough]]; \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - fallthrough \ + [[fallthrough]]; \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - fallthrough \ + [[fallthrough]]; \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ From c65d4eaa126b6e5b63091cc622ebfbc15e605149 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Tue, 1 Mar 2022 20:42:14 -0500 Subject: [PATCH 68/70] fix tokssh --- scripts/tokssh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/tokssh b/scripts/tokssh index 844bad6..1e13eca 100755 --- a/scripts/tokssh +++ b/scripts/tokssh @@ -51,6 +51,7 @@ then unset TUNTOX_DESTINATION fi +ssh_options=() while [ $# -gt 0 ] do case "$1" in @@ -83,8 +84,8 @@ fi # exchange. ssh \ - -o ProxyCommand="tuntox $persist -i $toxid -W localhost:%p '$TUNTOX_SECRET'" \ - -o StrictHostKeyChecking=accept \ + -o ProxyCommand="tuntox $persist -i %h -W localhost:%p '$TUNTOX_SECRET'" \ + -o StrictHostKeyChecking=accept-new \ -o CanonicalizeHostname=no \ -o UpdateHostKeys=yes \ "${ssh_options[@]}" \ From fe05915a8b7cb7c0496118dd3ca10bddb891c15a Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Tue, 1 Mar 2022 20:42:21 -0500 Subject: [PATCH 69/70] gitignore *.deb --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 08bcde6..91d07b3 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ debian/debhelper-build-stamp debian/files debian/tuntox.substvars gitversion.h +*.deb From e7010e7c2c4edf6fac17656487d9b23e31f6d2bc Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sun, 9 Oct 2022 16:43:33 -0400 Subject: [PATCH 70/70] toxish: files in ~/.ssh/config.d/ must end in .conf --- scripts/toxish | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/toxish b/scripts/toxish index a59671a..d55e8fd 100755 --- a/scripts/toxish +++ b/scripts/toxish @@ -67,15 +67,15 @@ function main function ssh_config_fragment { cat <