diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 124 |
1 files changed, 123 insertions, 1 deletions
@@ -31,6 +31,12 @@ char *remote_tox_id = NULL; | |||
31 | /* Directory with config and tox save */ | 31 | /* Directory with config and tox save */ |
32 | char config_path[500] = "/etc/tuntox/"; | 32 | char config_path[500] = "/etc/tuntox/"; |
33 | 33 | ||
34 | /* Limit hostname and port in server */ | ||
35 | int nrules = 0; | ||
36 | char rules_file[500] = "/etc/tuntox/rules"; | ||
37 | enum rules_policy_enum rules_policy = NONE; | ||
38 | rule *rules = NULL; | ||
39 | |||
34 | /* Ports and hostname for port forwarding */ | 40 | /* Ports and hostname for port forwarding */ |
35 | int remote_port = 0; | 41 | int remote_port = 0; |
36 | char *remote_host = NULL; | 42 | char *remote_host = NULL; |
@@ -88,6 +94,16 @@ int allowed_toxid_cmp(allowed_toxid *a, allowed_toxid *b) | |||
88 | return memcmp(a->toxid, b->toxid, TOX_PUBLIC_KEY_SIZE); | 94 | return memcmp(a->toxid, b->toxid, TOX_PUBLIC_KEY_SIZE); |
89 | } | 95 | } |
90 | 96 | ||
97 | /* Comparison function for rule objects */ | ||
98 | int rule_cmp(rule *a, rule *b) | ||
99 | { | ||
100 | //log_printf(L_INFO, "Comparison result: %d %d\n", strcmp(a->host, b->host), (a->port == b->port)); | ||
101 | if ((strcmp(a->host, b->host)==0) && (a->port == b->port)) | ||
102 | return 0; | ||
103 | else | ||
104 | return -1; | ||
105 | } | ||
106 | |||
91 | void update_select_nfds(int fd) | 107 | void update_select_nfds(int fd) |
92 | { | 108 | { |
93 | /* TODO maybe replace with a scan every time to make select() more efficient in the long run? */ | 109 | /* TODO maybe replace with a scan every time to make select() more efficient in the long run? */ |
@@ -389,6 +405,26 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) | |||
389 | hostname[rcvd_frame->data_length] = '\0'; | 405 | hostname[rcvd_frame->data_length] = '\0'; |
390 | 406 | ||
391 | log_printf(L_INFO, "Got a request to forward data from %s:%d\n", hostname, port); | 407 | log_printf(L_INFO, "Got a request to forward data from %s:%d\n", hostname, port); |
408 | |||
409 | // check rules | ||
410 | if (rules_policy == VALIDATE && nrules > 0 ) { | ||
411 | |||
412 | rule rtmp, *found = NULL; | ||
413 | rtmp.host = hostname; | ||
414 | rtmp.port = port; | ||
415 | |||
416 | LL_SEARCH(rules, found, &rtmp, rule_cmp); | ||
417 | if(!found) | ||
418 | { | ||
419 | log_printf(L_WARNING, "Rejected, request not in rules\n"); | ||
420 | return -1; | ||
421 | } | ||
422 | } else if (rules_policy != NONE) { | ||
423 | log_printf(L_WARNING, "Filter option active but no allowed host/port. All requests will be dropped.\n"); | ||
424 | return -1; | ||
425 | } | ||
426 | |||
427 | |||
392 | 428 | ||
393 | tunnel_id = get_random_tunnel_id(); | 429 | tunnel_id = get_random_tunnel_id(); |
394 | log_printf(L_DEBUG, "Tunnel ID: %d\n", tunnel_id); | 430 | log_printf(L_DEBUG, "Tunnel ID: %d\n", tunnel_id); |
@@ -707,6 +743,80 @@ static size_t load_save(uint8_t **out_data) | |||
707 | } | 743 | } |
708 | } | 744 | } |
709 | 745 | ||
746 | /* Loads a list of allowed hostnames and ports from file. Format is hostname:port*/ | ||
747 | void load_rules() | ||
748 | { | ||
749 | char * ahost=NULL; | ||
750 | int aport=0; | ||
751 | char line[100 + 1] = ""; | ||
752 | FILE *file = NULL; | ||
753 | rule *rule_obj = NULL; | ||
754 | int valid_rules = 0; | ||
755 | |||
756 | file = fopen(rules_file, "r"); | ||
757 | |||
758 | if (file == NULL) { | ||
759 | log_printf(L_WARNING, "Could not open rules file (%s)\n", rules_file); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | while (fgets(line, sizeof(line), file)) { | ||
764 | if(line) | ||
765 | { | ||
766 | /* allow comments & white lines */ | ||
767 | if (line[0]=='#'||line[0]=='\n') { | ||
768 | continue; | ||
769 | } | ||
770 | if (parse_pipe_port_forward(line, &ahost, &aport) >= 0) { | ||
771 | if (aport > 0 && aport < 65535) { | ||
772 | |||
773 | rule_obj = (rule *)calloc(sizeof(rule), 1); | ||
774 | if(!rule_obj) | ||
775 | { | ||
776 | log_printf(L_ERROR, "Could not allocate memory for rule"); | ||
777 | exit(1); | ||
778 | } | ||
779 | |||
780 | rule_obj->port = aport; | ||
781 | rule_obj->host = strdup(ahost); | ||
782 | |||
783 | LL_APPEND(rules, rule_obj); | ||
784 | valid_rules++; | ||
785 | } else { | ||
786 | log_printf(L_WARNING, "Invalid port in line: %s\n", line); | ||
787 | } | ||
788 | } else { | ||
789 | log_printf(L_WARNING, "Could not parse line: %s\n", line); | ||
790 | } | ||
791 | } else { | ||
792 | /* reached end of file*/ | ||
793 | break; | ||
794 | } | ||
795 | } | ||
796 | fclose(file); | ||
797 | |||
798 | /* save valid rules in global variable */ | ||
799 | nrules = valid_rules; | ||
800 | |||
801 | log_printf(L_INFO, "Loaded %d rules\n", nrules); | ||
802 | if (nrules==0 && rules_policy != NONE){ | ||
803 | log_printf(L_WARNING, "No rules loaded! NO CONNECTIONS WILL BE ALLOWED!\n"); | ||
804 | } | ||
805 | } | ||
806 | |||
807 | /* Clear rules loaded into memory */ | ||
808 | void clear_rules() | ||
809 | { | ||
810 | int i; | ||
811 | rule * elt, *tmp; | ||
812 | /* delete each elemen using the safe iterator */ | ||
813 | LL_FOREACH_SAFE(rules,elt,tmp) { | ||
814 | LL_DELETE(rules,elt); | ||
815 | free(elt->host); | ||
816 | free(elt); | ||
817 | } | ||
818 | } | ||
819 | |||
710 | void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) | 820 | void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) |
711 | { | 821 | { |
712 | unsigned char tox_printable_id[TOX_ADDRESS_SIZE * 2 + 1]; | 822 | unsigned char tox_printable_id[TOX_ADDRESS_SIZE * 2 + 1]; |
@@ -1060,6 +1170,7 @@ void help() | |||
1060 | fprintf(stderr, "-p - ping the server from -i and exit\n"); | 1170 | fprintf(stderr, "-p - ping the server from -i and exit\n"); |
1061 | fprintf(stderr, "-C <dir> - save private key in <dir> instead of /etc/tuntox in server mode\n"); | 1171 | fprintf(stderr, "-C <dir> - save private key in <dir> instead of /etc/tuntox in server mode\n"); |
1062 | fprintf(stderr, "-s <secret> - shared secret used for connection authentication (max %u characters)\n", TOX_MAX_FRIEND_REQUEST_LENGTH-1); | 1172 | fprintf(stderr, "-s <secret> - shared secret used for connection authentication (max %u characters)\n", TOX_MAX_FRIEND_REQUEST_LENGTH-1); |
1173 | fprintf(stderr, "-f <file> - only allow connections to hostname/port combinations contained in <file>. Rules must by entered one per line with the <hostname>:<port> format\n"); | ||
1063 | fprintf(stderr, "-d - debug mode\n"); | 1174 | fprintf(stderr, "-d - debug mode\n"); |
1064 | fprintf(stderr, "-q - quiet mode\n"); | 1175 | fprintf(stderr, "-q - quiet mode\n"); |
1065 | fprintf(stderr, "-S - send output to syslog instead of stderr\n"); | 1176 | fprintf(stderr, "-S - send output to syslog instead of stderr\n"); |
@@ -1081,7 +1192,7 @@ int main(int argc, char *argv[]) | |||
1081 | 1192 | ||
1082 | log_init(); | 1193 | log_init(); |
1083 | 1194 | ||
1084 | while ((oc = getopt(argc, argv, "L:pi:C:s:P:dqhSF:DU:")) != -1) | 1195 | while ((oc = getopt(argc, argv, "L:pi:C:s:f:P:dqhSF:DU:")) != -1) |
1085 | { | 1196 | { |
1086 | switch(oc) | 1197 | switch(oc) |
1087 | { | 1198 | { |
@@ -1154,6 +1265,11 @@ int main(int argc, char *argv[]) | |||
1154 | } | 1265 | } |
1155 | load_saved_toxid_in_client_mode = 1; | 1266 | load_saved_toxid_in_client_mode = 1; |
1156 | break; | 1267 | break; |
1268 | case 'f': | ||
1269 | strncpy(rules_file, optarg, sizeof(rules_file) - 1); | ||
1270 | rules_policy = VALIDATE; | ||
1271 | log_printf(L_INFO, "Filter policy set to VALIDATE\n"); | ||
1272 | break; | ||
1157 | case 's': | 1273 | case 's': |
1158 | /* Shared secret */ | 1274 | /* Shared secret */ |
1159 | use_shared_secret = 1; | 1275 | use_shared_secret = 1; |
@@ -1197,6 +1313,11 @@ int main(int argc, char *argv[]) | |||
1197 | { | 1313 | { |
1198 | log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); | 1314 | log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); |
1199 | } | 1315 | } |
1316 | |||
1317 | if((!client_mode) && (rules_policy != NONE)) | ||
1318 | { | ||
1319 | load_rules(); | ||
1320 | } | ||
1200 | 1321 | ||
1201 | if(daemonize) | 1322 | if(daemonize) |
1202 | { | 1323 | { |
@@ -1281,6 +1402,7 @@ int main(int argc, char *argv[]) | |||
1281 | 1402 | ||
1282 | tox_callback_friend_request(tox, accept_friend_request, NULL); | 1403 | tox_callback_friend_request(tox, accept_friend_request, NULL); |
1283 | do_server_loop(); | 1404 | do_server_loop(); |
1405 | clear_rules(); | ||
1284 | } | 1406 | } |
1285 | 1407 | ||
1286 | return 0; | 1408 | return 0; |