summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c163
1 files changed, 86 insertions, 77 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;
42char config_path[500] = "/etc/tuntox/"; 42char config_path[500] = "/etc/tuntox/";
43 43
44/* Limit hostname and port in server */ 44/* Limit hostname and port in server */
45int nrules = 0; 45int tunnel_target_whitelist_size = 0;
46char rules_file[500] = "/etc/tuntox/rules"; 46char *tunnel_target_whitelist_file;
47bool enforce_whitelist = false; 47bool tunnel_target_whitelist_enforced = false;
48rule *rules = NULL; 48rule *tunnel_target_whitelist_rules = NULL;
49time_t tunnel_target_whitelist_mtime = 0;
49 50
50/* Ports and hostname for port forwarding */ 51/* Ports and hostname for port forwarding */
51int remote_port = 0; 52int remote_port = 0;
@@ -422,13 +423,16 @@ int handle_ping_frame(protocol_frame *rcvd_frame)
422 return 0; 423 return 0;
423} 424}
424 425
426void tunnel_target_whitelist_load();
425bool check_requested_tunnel_against_rules(char *hostname, in_port_t port) 427bool check_requested_tunnel_against_rules(char *hostname, in_port_t port)
426{ 428{
427 if (!enforce_whitelist) return true; 429 if (!tunnel_target_whitelist_enforced) return true;
428 430
429 if (nrules <= 0) 431 tunnel_target_whitelist_load();
432
433 if (tunnel_target_whitelist_size <= 0)
430 { 434 {
431 log_printf(l_warning, "filter option active but no allowed host/port. all requests will be dropped.\n"); 435 log_printf(L_WARNING, "Whitelist enforced, but no whitelisted entries. All requests will be dropped.\n");
432 return false; 436 return false;
433 } 437 }
434 438
@@ -436,11 +440,7 @@ bool check_requested_tunnel_against_rules(char *hostname, in_port_t port)
436 candidate.host = hostname; 440 candidate.host = hostname;
437 candidate.port = port; 441 candidate.port = port;
438 442
439 LL_SEARCH(rules, found, &candidate, rule_match); 443 LL_SEARCH(tunnel_target_whitelist_rules, found, &candidate, rule_match);
440 if(!found)
441 {
442 log_printf(L_WARNING, "Rejected, request not in rules\n");
443 }
444 return found; 444 return found;
445} 445}
446 446
@@ -473,6 +473,8 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame)
473 473
474 if (!check_requested_tunnel_against_rules(hostname, port)) 474 if (!check_requested_tunnel_against_rules(hostname, port))
475 { 475 {
476 log_printf(L_WARNING, "Rejected tunnel request from #%d to non-whitelisted target host:port (%s:%d)",
477 rcvd_frame->friendnumber, hostname, port);
476 free(hostname); 478 free(hostname);
477 return -1; 479 return -1;
478 } 480 }
@@ -791,71 +793,89 @@ static size_t load_save(uint8_t **out_data)
791 } 793 }
792} 794}
793 795
796void tunnel_target_whitelist_clear();
794/* Loads a list of allowed hostnames and ports from file. Format is hostname:port*/ 797/* Loads a list of allowed hostnames and ports from file. Format is hostname:port*/
795void load_rules() 798void tunnel_target_whitelist_load()
796{ 799{
797 char *ahost=NULL; 800 char *ahost=NULL;
798 int aport=0; 801 int aport=0;
799 char line[100 + 1] = ""; 802 char line[1024];
800 FILE *file = NULL; 803 FILE *file = NULL;
801 rule *rule_obj = NULL; 804 rule *rule_obj = NULL;
802 int valid_rules = 0;
803 805
804 file = fopen(rules_file, "r"); 806 if (!tunnel_target_whitelist_enforced) return;
805
806 if (file == NULL) {
807 log_printf(L_WARNING, "Could not open rules file (%s)\n", rules_file);
808 return;
809 }
810 807
811 while (fgets(line, sizeof(line), file)) { 808 /* If we have existing rules, check to see if we need to continue. */
812 /* allow comments & white lines */ 809 if(tunnel_target_whitelist_rules)
813 if (line[0]=='#'||line[0]=='\n') { 810 {
814 continue; 811 struct stat buf;
812 if (stat(tunnel_target_whitelist_file, &buf) < 0)
813 {
814 /* File removed? Better clear the whitelist. */
815 tunnel_target_whitelist_mtime = 0;
816 tunnel_target_whitelist_clear();
817 return;
815 } 818 }
816 if (parse_pipe_port_forward(line, &ahost, &aport) >= 0) { 819 if (buf.st_mtime == tunnel_target_whitelist_mtime) return;
817 if (aport > 0 && aport < 65535) {
818 820
819 rule_obj = (rule *)calloc(sizeof(rule), 1); 821 tunnel_target_whitelist_mtime = buf.st_mtime;
820 if(!rule_obj) 822 tunnel_target_whitelist_clear();
821 { 823 }
822 log_printf(L_ERROR, "Could not allocate memory for rule");
823 exit(1);
824 }
825 824
826 rule_obj->port = aport; 825 file = fopen(tunnel_target_whitelist_file, "r");
827 rule_obj->host = strdup(ahost);
828 826
829 LL_APPEND(rules, rule_obj); 827 if(file == NULL) {
830 valid_rules++; 828 log_printf(L_WARNING, "Could not open rules file (%s)\n", tunnel_target_whitelist_file);
831 } else { 829 return;
832 log_printf(L_WARNING, "Invalid port in line: %s\n", line); 830 }
831
832 while(fgets(line, sizeof(line), file))
833 {
834 strtok(line, "#\n"); /* Chop line at first hash */
835 char *orig_line = strdup(line); /* Not quite the original line; keeps
836 newline and comments out of logs */
837 if(parse_pipe_port_forward(line, &ahost, &aport))
838 {
839 rule_obj = (rule *)calloc(sizeof(rule), 1);
840 if(!rule_obj)
841 {
842 log_printf(L_ERROR, "Could not allocate memory for rule");
843 exit(1);
833 } 844 }
834 } else { 845
835 log_printf(L_WARNING, "Could not parse line: %s\n", line); 846 rule_obj->port = aport;
847 rule_obj->host = strdup(ahost);
848
849 LL_APPEND(tunnel_target_whitelist_rules, rule_obj);
850 tunnel_target_whitelist_size++;
851 }
852 else
853 {
854 log_printf(L_WARNING, "Could not parse line: %s\n", orig_line);
836 } 855 }
856 free(orig_line);
837 } 857 }
838 fclose(file); 858 fclose(file);
839 859
840 /* save valid rules in global variable */ 860 log_printf(L_INFO, "Loaded %d rules\n", tunnel_target_whitelist_size);
841 nrules = valid_rules; 861 if (tunnel_target_whitelist_size == 0 && tunnel_target_whitelist_enforced){
842
843 log_printf(L_INFO, "Loaded %d rules\n", nrules);
844 if (nrules==0 && enforce_whitelist){
845 log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); 862 log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n");
846 } 863 }
847} 864}
848 865
849/* Clear rules loaded into memory */ 866/* Clear rules loaded into memory */
850void clear_rules() 867void tunnel_target_whitelist_clear()
851{ 868{
852 rule * elt, *tmp; 869 rule * elt, *tmp;
853 /* delete each elemen using the safe iterator */ 870 /* delete each elemen using the safe iterator */
854 LL_FOREACH_SAFE(rules,elt,tmp) { 871 LL_FOREACH_SAFE(tunnel_target_whitelist_rules,elt,tmp) {
855 LL_DELETE(rules,elt); 872 LL_DELETE(tunnel_target_whitelist_rules,elt);
856 free(elt->host); 873 free(elt->host);
857 free(elt); 874 free(elt);
858 } 875 }
876 free(tunnel_target_whitelist_rules);
877 tunnel_target_whitelist_rules = NULL;
878 tunnel_target_whitelist_size = 0;
859} 879}
860 880
861void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) 881void 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
914} 934}
915 935
916/* Callback for tox_callback_self_connection_status() */ 936/* Callback for tox_callback_self_connection_status() */
917void handle_connection_status_change(Tox *tox, TOX_CONNECTION p_connection_status, void *user_data) 937void handle_connection_status_change(Tox *tox, TOX_CONNECTION new_connection_status, void *user_data)
918{ 938{
919 const char *status = NULL; 939 connection_status = new_connection_status;
920 connection_status = p_connection_status; 940 if (connection_status)
921 status = readable_connection_status(connection_status); 941 {
922 log_printf(L_INFO, "Connection status changed: %s", status); 942 log_printf(L_INFO, "Connected to Tox network: %s\n", readable_connection_status(connection_status));
943 }
944 else
945 {
946 log_printf(L_INFO, "Disconnected from Tox network\n");
947 }
923} 948}
924 949
925#ifdef LOG_IP_ADDRESS 950#ifdef LOG_IP_ADDRESS
@@ -971,7 +996,6 @@ int do_server_loop()
971 unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; 996 unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE];
972 tunnel *tun = NULL; 997 tunnel *tun = NULL;
973 tunnel *tmp = NULL; 998 tunnel *tmp = NULL;
974 TOX_CONNECTION connected = 0;
975 int sent_data = 0; 999 int sent_data = 0;
976 1000
977 tox_callback_friend_lossless_packet(tox, parse_lossless_packet); 1001 tox_callback_friend_lossless_packet(tox, parse_lossless_packet);
@@ -997,20 +1021,6 @@ int do_server_loop()
997 log_printf(L_DEBUG2, "Iteration interval: %dms\n", tox_do_interval_ms); 1021 log_printf(L_DEBUG2, "Iteration interval: %dms\n", tox_do_interval_ms);
998 gettimeofday(&tv_start, NULL); 1022 gettimeofday(&tv_start, NULL);
999 1023
1000 /* Check change in connection state */
1001 if(connection_status != connected)
1002 {
1003 connected = connection_status;
1004 if(connected)
1005 {
1006 log_printf(L_DEBUG, "Connected to Tox network\n");
1007 }
1008 else
1009 {
1010 log_printf(L_DEBUG, "Disconnected from Tox network\n");
1011 }
1012 }
1013
1014 fds = master_server_fds; 1024 fds = master_server_fds;
1015 1025
1016 /* Poll for data from our client connection */ 1026 /* Poll for data from our client connection */
@@ -1304,7 +1314,7 @@ int main(int argc, char *argv[])
1304 /* Local port forwarding */ 1314 /* Local port forwarding */
1305 client_mode = 1; 1315 client_mode = 1;
1306 client_local_port_mode = 1; 1316 client_local_port_mode = 1;
1307 if(parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port) < 0) 1317 if(!parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port))
1308 { 1318 {
1309 log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); 1319 log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n");
1310 exit(1); 1320 exit(1);
@@ -1319,7 +1329,7 @@ int main(int argc, char *argv[])
1319 /* Pipe forwarding */ 1329 /* Pipe forwarding */
1320 client_mode = 1; 1330 client_mode = 1;
1321 client_pipe_mode = 1; 1331 client_pipe_mode = 1;
1322 if(parse_pipe_port_forward(optarg, &remote_host, &remote_port) < 0) 1332 if(!parse_pipe_port_forward(optarg, &remote_host, &remote_port) || remote_port == 0)
1323 { 1333 {
1324 log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n"); 1334 log_printf(L_ERROR, "Invalid value for -W option - use something like -W 127.0.0.1:22\n");
1325 exit(1); 1335 exit(1);
@@ -1369,9 +1379,9 @@ int main(int argc, char *argv[])
1369 load_saved_toxid_in_client_mode = 1; 1379 load_saved_toxid_in_client_mode = 1;
1370 break; 1380 break;
1371 case 'f': 1381 case 'f':
1372 strncpy(rules_file, optarg, sizeof(rules_file) - 1); 1382 tunnel_target_whitelist_file = strdup(optarg);
1373 enforce_whitelist = true; 1383 tunnel_target_whitelist_enforced = true;
1374 log_printf(L_INFO, "Filter policy set to VALIDATE\n"); 1384 log_printf(L_INFO, "Whitelist enforced on outgoing connections: only matched hosts/ports will be allowed.\n");
1375 break; 1385 break;
1376 case 's': 1386 case 's':
1377 /* Shared secret */ 1387 /* Shared secret */
@@ -1471,9 +1481,9 @@ int main(int argc, char *argv[])
1471 log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); 1481 log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect");
1472 } 1482 }
1473 1483
1474 if((!client_mode) && enforce_whitelist) 1484 if(!client_mode && tunnel_target_whitelist_enforced)
1475 { 1485 {
1476 load_rules(); 1486 tunnel_target_whitelist_load();
1477 } 1487 }
1478 1488
1479 /* If shared secret has not been provided via -s, read from TUNTOX_SHARED_SECRET env variable */ 1489 /* 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[])
1589 { 1599 {
1590 tox_callback_friend_request(tox, accept_friend_request); 1600 tox_callback_friend_request(tox, accept_friend_request);
1591 do_server_loop(); 1601 do_server_loop();
1592 clear_rules();
1593 } 1602 }
1594 } 1603 }
1595 1604