From 1adde65db245ec1fca752cfee4c198badf40fb5f Mon Sep 17 00:00:00 2001 From: Jakub SÅ‚awiÅ„ski Date: Tue, 15 Mar 2005 01:22:55 +0100 Subject: v0.6 - Fixed: default password incompatibilities from config file - Added: "client's id" option - Lightly Modified: verbose mode - Added: temporary listen ports - Fixed: bug in printing "client's id" - Added: 'dateformat' option to set format of the date in the logs - Modified: command line option and config file behaviour - Added: logging to a socket - Fixed: parsing config file - Fixed: major bug in packet buffering - Added: several clients-users in one realm - Modified: default hostname used by afserver - Modified: server listening behaviour (for clients) - Fixed: bug in checking options values - Modified: verbose mode - Modified: client initial connection to server - Added: connection time / uptime statistics - Added: first version of remote administration (statistics only) - Fixed: major bug in remove_client routine - Added: 'raclients' option - Added: use of automake/autoconf - Added: creating ~/.apf directory - Modified: the way of creating/managing keys/certificates - Added: 'dnslookups' option - Modified: usage functions - Fixed: no handling of missing 'listen' option after 'newrealm' in config file - Added: 'quit' command in remote administration mode - Modified: logging error messages during initialization - Modified: 'newrealm' changed to 'realm' in config file - Added: realm names - Modified: connection time / uptime - Added: client names / unique numbers - Added: user unique numbers - Fixed: segmentation fault after 'quit' command --- ChangeLog | 90 +++ Changelog | 54 -- Makefile | 50 -- Makefile.am | 4 + NEWS | 2 + README | 255 +++++-- activefor.h | 96 --- afclient.c | 905 ------------------------ afserver.c | 1134 ------------------------------ buflist.c | 70 -- buflist.h | 35 - config | 42 -- configure.ac | 82 +++ doc/afclient.1 | 246 +++++++ doc/afserver.1 | 175 +++++ doc/afserver.conf.5 | 126 ++++ doc/afserver_example.conf | 57 ++ doc/en/README | 479 +++++++++++++ doc/fr/fr_README | 488 +++++++++++++ doc/ru/ru_README | 294 ++++++++ docs/en/README | 308 -------- docs/fr/fr_README | 102 --- docs/ru/ru_README | 294 -------- exmodule.c | 81 --- file.c | 203 ------ file.h | 72 -- modules.c | 63 -- modules.h | 37 - modules/Makefile.am | 3 + modules/exmodule.c | 82 +++ network.c | 364 ---------- network.h | 54 -- src/Makefile.am | 7 + src/activefor.h | 162 +++++ src/afclient.c | 1000 ++++++++++++++++++++++++++ src/afclient.h | 50 ++ src/afserver.c | 1720 +++++++++++++++++++++++++++++++++++++++++++++ src/afserver.h | 51 ++ src/buflist.c | 70 ++ src/buflist.h | 35 + src/clientnames.c | 129 ++++ src/clientnames.h | 35 + src/file.c | 373 ++++++++++ src/file.h | 37 + src/first_run.c | 156 ++++ src/first_run.h | 29 + src/inet_ntop.c | 227 ++++++ src/inet_ntop.h | 36 + src/make_ssl_handshake.c | 103 +++ src/make_ssl_handshake.h | 31 + src/modules.c | 69 ++ src/modules.h | 43 ++ src/network.c | 484 +++++++++++++ src/network.h | 54 ++ src/realmnames.c | 62 ++ src/realmnames.h | 30 + src/remoteadmin.c | 503 +++++++++++++ src/remoteadmin.h | 49 ++ src/server_check.c | 61 ++ src/server_check.h | 28 + src/server_eval.c | 44 ++ src/server_eval.h | 31 + src/server_find.c | 56 ++ src/server_find.h | 31 + src/server_remove.c | 84 +++ src/server_remove.h | 30 + src/server_set.c | 34 + src/server_set.h | 27 + src/stats.c | 127 ++++ src/stats.h | 36 + src/usernames.c | 41 ++ src/usernames.h | 30 + stats.c | 98 --- stats.h | 31 - 74 files changed, 8546 insertions(+), 4135 deletions(-) create mode 100644 ChangeLog delete mode 100644 Changelog delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100644 NEWS delete mode 100644 activefor.h delete mode 100644 afclient.c delete mode 100644 afserver.c delete mode 100644 buflist.c delete mode 100644 buflist.h delete mode 100644 config create mode 100644 configure.ac create mode 100644 doc/afclient.1 create mode 100644 doc/afserver.1 create mode 100644 doc/afserver.conf.5 create mode 100644 doc/afserver_example.conf create mode 100644 doc/en/README create mode 100644 doc/fr/fr_README create mode 100644 doc/ru/ru_README delete mode 100644 docs/en/README delete mode 100644 docs/fr/fr_README delete mode 100644 docs/ru/ru_README delete mode 100644 exmodule.c delete mode 100644 file.c delete mode 100644 file.h delete mode 100644 modules.c delete mode 100644 modules.h create mode 100644 modules/Makefile.am create mode 100644 modules/exmodule.c delete mode 100644 network.c delete mode 100644 network.h create mode 100644 src/Makefile.am create mode 100644 src/activefor.h create mode 100644 src/afclient.c create mode 100644 src/afclient.h create mode 100644 src/afserver.c create mode 100644 src/afserver.h create mode 100644 src/buflist.c create mode 100644 src/buflist.h create mode 100644 src/clientnames.c create mode 100644 src/clientnames.h create mode 100644 src/file.c create mode 100644 src/file.h create mode 100644 src/first_run.c create mode 100644 src/first_run.h create mode 100644 src/inet_ntop.c create mode 100644 src/inet_ntop.h create mode 100644 src/make_ssl_handshake.c create mode 100644 src/make_ssl_handshake.h create mode 100644 src/modules.c create mode 100644 src/modules.h create mode 100644 src/network.c create mode 100644 src/network.h create mode 100644 src/realmnames.c create mode 100644 src/realmnames.h create mode 100644 src/remoteadmin.c create mode 100644 src/remoteadmin.h create mode 100644 src/server_check.c create mode 100644 src/server_check.h create mode 100644 src/server_eval.c create mode 100644 src/server_eval.h create mode 100644 src/server_find.c create mode 100644 src/server_find.h create mode 100644 src/server_remove.c create mode 100644 src/server_remove.h create mode 100644 src/server_set.c create mode 100644 src/server_set.h create mode 100644 src/stats.c create mode 100644 src/stats.h create mode 100644 src/usernames.c create mode 100644 src/usernames.h delete mode 100644 stats.c delete mode 100644 stats.h diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..6617f4e --- /dev/null +++ b/ChangeLog @@ -0,0 +1,90 @@ +11.03.2005 (v0.6): + - Fixed: default password incompatibilities from config file + - Added: "client's id" option + - Lightly Modified: verbose mode + - Added: temporary listen ports + - Fixed: bug in printing "client's id" + - Added: 'dateformat' option to set format of the date in the logs + - Modified: command line option and config file behaviour + - Added: logging to a socket + - Fixed: parsing config file + - Fixed: major bug in packet buffering + - Added: several clients-users in one realm + - Modified: default hostname used by afserver + - Modified: server listening behaviour (for clients) + - Fixed: bug in checking options values + - Modified: verbose mode + - Modified: client initial connection to server + - Added: connection time / uptime statistics + - Added: first version of remote administration (statistics only) + - Fixed: major bug in remove_client routine + - Added: 'raclients' option + - Added: use of automake/autoconf + - Added: creating ~/.apf directory + - Modified: the way of creating/managing keys/certificates + - Added: 'dnslookups' option + - Modified: usage functions + - Fixed: no handling of missing 'listen' option after 'newrealm' in config file + - Added: 'quit' command in remote administration mode + - Modified: logging error messages during initialization + - Modified: 'newrealm' changed to 'realm' in config file + - Added: realm names + - Modified: connection time / uptime + - Added: client names / unique numbers + - Added: user unique numbers + - Fixed: segmentation fault after 'quit' command + +19.11.2004 (udp_patch): + - Lightly Modified: verbose in client's udp reverse mode + - Fixed: major bug in udp protocol forwarding + +11.10.2004 (v0.5.5): + - Added: rsa key generation by afclient + - Modified: afclient is now generating keys by default + - Fixed: major bug in packet buffering + - Added: 'timeout', 'clients' and 'usrpcli' options + - Fixed: parsing 'users' option + - Modified: module management routines + - Added: module support for service's packet filtering + - Fixed: few minor bugs in closing connection routines + - Added: possibility to use several clients per realm + - Modified: there is no need for 'users', 'timeout', 'clients', + 'proto', 'usrpcli' and 'climode' options in config + file when default values are acceptable + +26.05.2004 (v0.5.4): + - Fixed: default password incompatibilities + - Modified: server listening behaviour + - Added: module support for client's packet filtering + - Modified: client behaviour after unsuccessful connection + - Fixed: printing ipv6 addresses + - Added: IP protocol family strict choice: 'ipv4' and 'ipv6' + - Added: flow control / packet buffering + - Fixed: signal handling + - Fixed: client freeze in udp reverse mode with zlib enabled + +09.01.2004 (v0.5.3): + - Added: client password identification (weak) + - Added: sigint interception and server closing + - Modified: communication between server and client + - Added: 'nossl' and 'nozlib' modes + - Added: zlib support + - Lightly Modified: verbose mode + - Modified/Added: help screen and long options support + +06.12.2003 (v0.5.2): + - Added: types of realm + - Added: logging to a file + - Fixed: major bug in communication between server and client + - Fixed: deformed packets in udp protocol forwarding + +04.12.2003 (v0.5.1): + - Fixed: some data transfer problems + - Added: udp protocol tunneling/forwarding + - Fixed: bug in parsing the config file + - Improved: making connection between server and client + - Lightly modified: verbose mode (added double v mode) + +23.11.2003 (v0.5): + - This is the first release + - There are no known major bugs diff --git a/Changelog b/Changelog deleted file mode 100644 index d6c8e6b..0000000 --- a/Changelog +++ /dev/null @@ -1,54 +0,0 @@ -19.11.2004 (udp_patch): - - Lightly Modified: verbose in client's udp reverse mode - - Fixed: major bug in udp protocol forwarding - -11.10.2004 (v0.5.5): - - Added: rsa key generation by afclient - - Modified: afclient is now generating keys by default - - Fixed: major bug in packet buffering - - Added: 'timeout', 'clients' and 'usrpcli' options - - Fixed: parsing 'users' option - - Modified: module management routines - - Added: module support for service's packet filtering - - Fixed: few minor bugs in closing connection routines - - Added: possibility to use several clients per realm - - Modified: there is no need for 'users', 'timeout', 'clients', - 'proto', 'usrpcli' and 'climode' options in config - file when default values are acceptable - -26.05.2004 (v0.5.4): - - Fixed: default password incompatibilities - - Modified: server listening behaviour - - Added: module support for client's packet filtering - - Modified: client behaviour after unsuccessful connection - - Fixed: printing ipv6 addresses - - Added: IP protocol family strict choice: 'ipv4' and 'ipv6' - - Added: flow control / packet buffering - - Fixed: signal handling - - Fixed: client freeze in udp reverse mode with zlib enabled - -09.01.2004 (v0.5.3): - - Added: client password identification (weak) - - Added: sigint interception and server closing - - Modified: communication between server and client - - Added: 'nossl' and 'nozlib' modes - - Added: zlib support - - Lightly Modified: verbose mode - - Modified/Added: help screen and long options support - -06.12.2003 (v0.5.2): - - Added: types of realm - - Added: logging to a file - - Fixed: major bug in communication between server and client - - Fixed: deformed packets in udp protocol forwarding - -04.12.2003 (v0.5.1): - - Fixed: some data transfer problems - - Added: udp protocol tunneling/forwarding - - Fixed: bug in parsing the config file - - Improved: making connection between server and client - - Lightly modified: verbose mode (added double v mode) - -23.11.2003 (v0.5): - - This is the first release - - There are no known major bugs diff --git a/Makefile b/Makefile deleted file mode 100644 index 09c9034..0000000 --- a/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -CC=gcc -CFLAGS=-pedantic -Wall -O2 -programs=afserver afclient -security=server.rsa cacert.pem -serdepends=afserver.c network.o file.o stats.o buflist.o -clidepends=afclient.c network.o stats.o buflist.o modules.o - -all: compi $(programs) ok1 secure - -afserver: $(serdepends) - $(CC) $(CFLAGS) -lssl -lz $(serdepends) -o afserver - -afclient: $(clidepends) - $(CC) $(CFLAGS) -rdynamic -lssl -lz -ldl $(clidepends) -o afclient - -%.o: %.c %.h - $(CC) $(CFLAGS) -c $*.c - -exmodule: exmodule.c - $(CC) -fPIC $(CFLAGS) -c $@.c - $(CC) $(CFLAGS) -shared -o $@ $@.o - -secure: crea $(security) ok2 - -server.rsa: - @openssl genrsa -rand Makefile -out server.rsa 2048 - -client.rsa: - @openssl genrsa -rand server.rsa -out client.rsa 2048 - -cacert.pem: - @echo -e "\n Generating certificate...\n" - @echo -e "pl\nWar-Maz\nOlsztyn\nSHEG\nUtils productions\njeremian\njeremian@poczta.fm" | openssl req -new -x509 -key server.rsa -out cacert.pem -days 1095 > /dev/null 2>&1 - -compi: - @echo -e "\nCompiling program...\n" - -crea: - @echo -e "\nCreating necessary files...\n" - -ok1: - @echo " OK!" - -ok2: - @echo " OK!" - -.PHONY: clean - -clean: - rm -rf a.out *~ *.o $(programs) $(security) exmodule diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..a918d53 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = src +DIST_SUBDIRS = src +man_MANS = doc/afclient.1 doc/afserver.1 doc/afserver.conf.5 +EXTRA_DIST = doc modules config diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..8d8e11c --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ +18.02.2005: + * source tree has been reorganized for automake/autoconf diff --git a/README b/README index 8901699..0e49c3e 100644 --- a/README +++ b/README @@ -1,11 +1,11 @@ -AF - Active Port Forwarder v0.5.5 - README -Copyright (C) 2003,2004 jeremian - -=================== +AF - Active Port Forwarder 0.6 - README +Copyright (C) 2003,2004,2005 jeremian - +================================================================= ================================================================================ GRAY-WORLD.NET / Active Port Forwarder -========================== +====================================== The Active Port Forwarder program is part of the Gray-World.net projects. @@ -29,10 +29,12 @@ INTRO 2. USAGE 2.1 afserver 2.2 afclient -3. EXAMPLES - 3.1 tcp mode - 3.2 reverse udp mode -4. BUGS/PROBLEMS +3. REMOTE ADMINISTRATION +4. MODULES +5. EXAMPLES + 5.1 tcp mode + 5.2 reverse udp mode +6. BUGS/PROBLEMS NOTES @@ -71,8 +73,10 @@ Multiple clients allow to create more sophisticated tunneling scheme. 1. Download the compressed sources from http://www.gray-world.net/pr_af.shtml 2. Unpack them with tar zxvf -3. Type "make". -4. If something goes wrong - mail the author or post a message on +3. Type "./configure" +4. Type "make" +5. Type "make install" while logged as root +6. If something goes wrong - mail the author or post a message on http://gray-world.net/board/ 1.2 Required libs @@ -86,9 +90,7 @@ Multiple clients allow to create more sophisticated tunneling scheme. 1. Linux: Gentoo, Slackware, Mandrake - built without any problems -2. Freebsd: - 4.4, 4.9 - have to use patch from project homepage -3. Windows: +2. Windows: win32 - cygwin version is available on the project homepage ================================================================================ @@ -100,53 +102,75 @@ Multiple clients allow to create more sophisticated tunneling scheme. 2.1 afserver ------------ - Options: + Basic options: + -n, --hostname - it's used when creating listening sockets - (default: name returned by hostname function) + (default: '') -l, --listenport - listening port number - users connect to it (default: 50127) -m, --manageport - manage port number - second part of the active port forwarder connects to it (default: 50126) + -h, --help - prints this help + + Authorization: + + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -c, --cerfile - the name of the file with certificate + (default: cacert.pem) + -k, --keyfile - the name of the file with RSA key (default: server.rsa) + -f, --cfgfile - the name of the file with the configuration for the + active forwarder (server) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + -t, --timeout - the timeout value for the client's connection (default: 5) -u, --users - the amount of users allowed to use this server (default: 5) -C, --clients - the number of allowed clients to use this server (default: 1) + -r, --realm - set the realm name (default: none) + -R, --raclients - the number of allowed clients in remote administration + mode to use this server (default: 1) -U, --usrpcli - the number of allowed users per client (default: $users) - -M, --climode - strategy used for connecting users with clients (default: 1) + -M, --climode - strategy used for connecting users with clients + (default: 1) Available strategies: 1. fill first client before go to next - -c, --cerfile - the name of the file with certificate - (default: cacert.pem) - -k, --keyfile - the name of the file with RSA key (default: server.rsa) - -f, --cfgfile - the name of the file with the configuration for the - active forwarder (server) - -p, --proto - type of server (tcp|udp) - for which protocol it will be - operating (default: tcp) + -p, --proto - type of server (tcp|udp) - for which protocol it will + be operating (default: tcp) + -b, --baseport - listenports are temporary and differ for each client + --nossl - ssl is not used for transferring data (but it's still + used to establish a connection) (default: ssl is used) + --nozlib - zlib is not used for compressing data (default: + zlib is used) + --dnslookups - try to obtain dns names of the computers rather than + their numeric IP + + Logging: + -O, --heavylog - logging everything to a logfile -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) - --nossl - ssl is not used for transfering data (but it's still - used to establish a connection) (default: ssl is used) - --nozlib - zlib is not used for compressing data (default: - zlib is used) - --pass - set the password used for client identification - (default: no password) + IP family: -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only - -h, --help - prints this help - 2.2 afclient ------------ - Options: - -h, --help - prints this help + Basic options: + -n, --servername - where the second part of the active port forwarder is running (required) -m, --manageport - manage port number - server must be @@ -155,30 +179,174 @@ Multiple clients allow to create more sophisticated tunneling scheme. destination of the packets (default: the name returned by hostname function) -p, --portnum - the port we are forwarding connection to (required) - -k, --keyfile - the name of the file with RSA key (default: (none)) + -h, --help - prints this help + + Authorization: + + -i, --id - send the id string to afserver + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -k, --keyfile - the name of the file with RSA key (default: client.rsa) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + + Modes: + -u, --udpmode - udp mode - client will use udp protocol to communicate with the hostname -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded from hostname:portnum (-p) to the server name:portnum (-m) + -r, --remoteadmin - remote administration mode. (using '-p #port' will + force afclient to use port rather then stdin-stdout) + + Logging: + -O, --heavylog - logging everything to a logfile -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) - --pass - set the password used for client identification - (default: no password) + + IP family: + -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only + + Modules: + -l, --load - load a module for user's packets filtering -L, --Load - load a module for service's packets filtering ================================================================================ +======================== +3. REMOTE ADMINISTRATION +======================== + +Afclient can be started in remote administration mode by '-r, --remoteadmin' +option. Required option: '-n, --servername NAME'. + +After successful authorization stdin/stdout is used to communicate with user. +All the commands parsing is done by afserver. + +Currently available commands are: + + help + display help + + lcmd + lists available commands + + info + prints info about server + + rshow + display realms + + cshow X + display clients in X realm + + ushow X + display users in X realm + + quit + quit connection + +Afclient with '-p, --portnum PORT' option listens for connection from user at +NAME:PORT. NAME is set by '-d, --hostname' option or hostname() function, when +the option is missing. + +When user quits (close the connection or send 'quit' command), afclient exits. + +================================================================================ + +========== +4. MODULES +========== + +Afclient can use external modules for user's packets filtering ('-l, --load') +and service's packets filtering ('-L, --Load'). Module file has to declare three +functions: + +char* info(void); + + info() return values: + - info about module + + Example: + + char* + info(void) + { + return "Module tester v0.1"; + } + +int allow(char* host, char* port); + + allow() return values: + 0 - allow to connect + !0 - drop the connection + + Example: + + int + allow(char* host, char* port) + { + return 0; /* allow to connect */ + } + +int filter(char* host, unsigned char* message, int* length); + + filter() return values: + 0 - allow to transfer + 1 - drop the packet + 2 - drop the connection + 3 - release the module + 4 - drop the packet and release the module + 5 - drop the connection and release the module + + Example: + + int + filter(char* host, unsigned char* message, int* length) + { + int i; + for (i = 1; i < *length; ++i) { + if (message[i-1] == 'M') { + if (message[i] == '1') { + return 1; /* ignored */ + } + if (message[i] == '2') { + return 2; /* dropped */ + } + if (message[i] == '3') { + return 3; /* release */ + } + if (message[i] == '4') { + return 4; /* ignored + release */ + } + if (message[i] == '5') { + return 5; /* dropped + release */ + } + } + } + return 0; /* allow to transfer */ + } + +Modules have to be compiled with '-fPIC -shared' options. + +================================================================================ + =========== -3. EXAMPLES +5. EXAMPLES =========== - 3.1 tcp mode + 5.1 tcp mode ------------ local network |FireWall| Internet @@ -227,7 +395,7 @@ on our computer and we are behind a masquerade or a firewall: 6) We can now enter with a web-browser to: :50127 and we will enter to our computer in the fact. - 3.2 reverse udp mode + 5.2 reverse udp mode -------------------- local network |FireWall| Internet @@ -266,7 +434,7 @@ server on our computer (udp port 27960 on our machine): ================================================================================ ================ -4. BUGS/PROBLEMS +6. BUGS/PROBLEMS ================ There are no known/open bugs at the moment. @@ -297,12 +465,15 @@ THANKS Thanks to Ilia Perevezentsev who read and corrected the README file. + Thanks to Marco Solari for a lot of +requests, suggestions and ideas. + And thanks for using this software! LICENSE ------- Active Port Forwarder is distributed under the terms of the GNU General - Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. + Public License v2.0 and is copyright (C) 2003,2004,2005 jeremian . See the file COPYING for details. diff --git a/activefor.h b/activefor.h deleted file mode 100644 index 29244c7..0000000 --- a/activefor.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_ACTIVEFOR_H -#define _JS_ACTIVEFOR_H - -#include "network.h" -#include "buflist.h" - -#define AF_S_CONCLOSED 1 -#define AF_S_CONOPEN 2 -#define AF_S_MESSAGE 3 -#define AF_S_CLOSING 4 -#define AF_S_LOGIN 8 -#define AF_S_DONT_SEND 9 -#define AF_S_CAN_SEND 10 -#define AF_S_CANT_OPEN 12 - -#define S_STATE_CLEAR 0 -#define S_STATE_CLOSING 5 -#define S_STATE_OPENING 6 -#define S_STATE_OPEN 7 -#define S_STATE_STOPPED 11 - -#define AF_VER(info) info" v0.5.5 (+udp_patch)" - -#define TYPE_TCP 1 -#define TYPE_UDP 3 -#define TYPE_SSL 4 -#define TYPE_ZLIB 8 -#define TYPE_IPV4 16 -#define TYPE_IPV6 32 -#define TYPE_COMP 0x4000 - -#define TYPE_SET_ZERO(type) (type=0) -#define TYPE_IS_SET(type) (type&1) -#define TYPE_IS_UDP(type) TYPE_IS_SET(type)&&(type&2) -#define TYPE_IS_TCP(type) TYPE_IS_SET(type)&&(!(type&2)) -#define TYPE_SET_UDP(type) (type|=TYPE_UDP) -#define TYPE_SET_TCP(type) (type|=TYPE_TCP) -#define TYPE_SET_SSL(type) (type|=TYPE_SSL) -#define TYPE_UNSET_SSL(type) (type&=(~TYPE_SSL)) -#define TYPE_IS_SSL(type) (type&TYPE_SSL) -#define TYPE_SET_ZLIB(type) (type|=TYPE_ZLIB) -#define TYPE_UNSET_ZLIB(type) (type&=(~TYPE_ZLIB)) -#define TYPE_IS_ZLIB(type) (type&TYPE_ZLIB) - -#define TYPE_SET_IPV4(type) (type|=TYPE_IPV4) -#define TYPE_UNSET_IPV4(type) (type&=(~TYPE_IPV4)) -#define TYPE_IS_IPV4(type) (type&TYPE_IPV4) -#define TYPE_SET_IPV6(type) (type|=TYPE_IPV6) -#define TYPE_UNSET_IPV6(type) (type&=(~TYPE_IPV6)) -#define TYPE_IS_IPV6(type) (type&TYPE_IPV6) -#define TYPE_SET_UNSPEC(type) (type&=(~(TYPE_IPV4|TYPE_IPV6))) -#define TYPE_IS_UNSPEC(type) (!(type&(TYPE_IPV4|TYPE_IPV6))) - -#define TYPE_SET_COMP(type) (type|=TYPE_COMP) -#define TYPE_IS_COMP(type) (type&TYPE_COMP) - -typedef struct { - char state; - int connfd; - char namebuf[128]; - char portbuf[7]; - int whatcli; - blnodeT* head; -} ConnectuserT; - -typedef struct { - char ready; - clifd cliconn; - struct timeval tv; - int* users; - int usercon; - int usernum; -} ConnectclientT; - -#endif - diff --git a/afclient.c b/afclient.c deleted file mode 100644 index 710cd8f..0000000 --- a/afclient.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "activefor.h" -#include "network.h" -#include "stats.h" -#include "modules.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static void usage(char* info); -static void sig_int(int); -static void callback(int, int, void*); - -static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"udpmode", 0, 0, 'u'}, - {"reverseudp", 0, 0, 'U'}, - {"servername", 1, 0, 'n'}, - {"manageport", 1, 0, 'm'}, - {"hostname", 1, 0, 'd'}, - {"portnum", 1, 0, 'p'}, - {"verbose", 0, 0, 'v'}, - {"keyfile", 1, 0, 'k'}, - {"heavylog", 1, 0, 'O'}, - {"lightlog", 1, 0, 'o'}, - {"pass", 1, 0, 301}, - {"ipv4", 0, 0, '4'}, - {"ipv6", 0, 0, '6'}, - {"load", 1, 0, 'l'}, - {"Load", 1, 0, 'L'}, - {0, 0, 0, 0} -}; - -int -main(int argc, char **argv) -{ - int i, n, numofcon, length, buflength, notsent, temp2; - ConnectuserT* contable = NULL; - clifd master; - unsigned char buff[9000]; - char hostname[100]; - struct timeval tv; - int maxfdp1, usernum, usercon, merror; - socklen_t len, addrlen; - struct sockaddr* cliaddr; - fd_set rset, allset, wset, tmpset; - char verbose = 0; - char logging = 0; - char* name = NULL; - char* manage = NULL; - char* desnam = NULL; - char* despor = NULL; - char* keys = NULL; - char* logfname = NULL; - char ipfam = 0; - unsigned char pass[4] = {1, 2, 3, 4}; - char udp = 0; - char reverse = 0; - char type = 0; - struct sigaction act; - moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL}; - - SSL_METHOD* method; - SSL_CTX* ctx; - RSA* rsa; - - sigfillset(&(act.sa_mask)); - act.sa_flags = 0; - - act.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &act, NULL); - act.sa_handler = sig_int; - sigaction(SIGINT, &act, NULL); - - while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:L:", long_options, 0)) != -1) { - switch (n) { - case 'h': { - usage(AF_VER("Active port forwarder (client)")); - break; - } - case 'n': { - name = optarg; - break; - } - case 'm': { - manage = optarg; - break; - } - case 'd': { - desnam = optarg; - break; - } - case 'p': { - despor = optarg; - break; - } - case 'v': { - ++verbose; - break; - } - case 'u': { - udp = 1; - break; - } - case 'U': { - reverse = 1; - break; - } - case 'k': { - keys = optarg; - break; - } - case 'O': { - logfname = optarg; - logging = 3; - break; - } - case 'o': { - logfname = optarg; - logging = 1; - break; - } - case 301: { - n = strlen(optarg); - memset(pass, 0, 4); - for (i = 0; i < n; ++i) { - pass[i%4] += optarg[i]; - } - break; - } - case '4': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 4; - } - break; - } - case '6': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 6; - } - break; - } - case 'l': { - module.name = optarg; - break; - } - case 'L': { - secmodule.name = optarg; - break; - } - case '?': { - usage(""); - break; - } - } - } - - if (optind < argc) { - usage("Unrecognized non-option elements"); - } - - if (name == NULL) { - usage("Name of the server is required"); - } - if (manage == NULL) { - manage = "50126"; - if (reverse) - usage("Port on the server is required in reverse mode"); - } - if (desnam == NULL) { - gethostname(hostname, 100); - desnam = hostname; - } - if (despor == NULL) { - usage("Destination port number is required"); - } - - if (loadmodule(&module)) { - printf("Loading a module %s failed!\n", module.name); - exit(1); - } - if (loadmodule(&secmodule)) { - printf("Loading a module %s failed!\n", secmodule.name); - exit(1); - } - - TYPE_SET_SSL(type); - TYPE_SET_ZLIB(type); - - if (ipfam == -1) { - printf("Conflicting types of ip protocol family... exiting\n"); - exit(1); - } - else if (ipfam == 4) { - TYPE_SET_IPV4(type); - } - else if (ipfam == 6) { - TYPE_SET_IPV6(type); - } - - ipfam = 0x01; - if (TYPE_IS_IPV4(type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(type)) { - ipfam |= 0x04; - } - if (ip_connect(&(master.commfd), name, manage, ipfam)) { - printf("tcp_connect_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage); - exit(1); - } - - if (!reverse) { - SSL_library_init(); - method = SSLv3_client_method(); - ctx = SSL_CTX_new(method); - if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { - printf("Setting cipher list failed... exiting\n"); - exit(1); - } - if (keys == NULL) { - gettimeofday(&tv, 0); - srand(tv.tv_sec); - if (verbose) - printf("Generating RSA key...\n"); - if (verbose>1) { - rsa = RSA_generate_key(2048, 65537, callback, NULL); - printf("\n"); - } - else { - rsa = RSA_generate_key(2048, 65537, NULL, NULL); - } - if (verbose) { - if (RSA_check_key(rsa)==1) { - printf(" OK!\n"); - } - else { - printf(" FAILED\n"); - } - } - } - else { - if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) { - printf("Setting rsa key failed (%s)... exiting\n", keys); - exit(1); - } - } - master.ssl = SSL_new(ctx); - if (SSL_set_fd(master.ssl, master.commfd) != 1) { - printf("Problem with initializing ssl... exiting\n"); - exit(1); - } - if (verbose>1) - printf("Trying SSL_connect\n"); - if ((n = SSL_connect(master.ssl)) == 1) { - if (verbose) { - printf("SSL_connect successfull\n"); - } - } - else { - printf("SSL_connect has failed (%d)... exiting\n", n); - exit(1); - } - - buff[0] = AF_S_LOGIN; - buff[1] = pass[0]; - buff[2] = pass[1]; - buff[3] = pass[2]; - buff[4] = pass[3]; - send_message(type, master, buff, 5); - buff[0] = 0; - get_message(type, master, buff, -5); - - if ( buff[0] == 0 ) { - printf("Wrong password\n"); - exit(1); - } - if ( buff[0] != AF_S_LOGIN ) { - printf("Incompatible server type or server full\n"); - exit(1); - } - - type = buff[3]; - usernum = buff[1]; - usernum = usernum << 8; - usernum += buff[2]; - } /* !reverse */ - else { - usernum = 1; - master.ssl = NULL; - } - - contable = calloc( usernum, sizeof(ConnectuserT)); - if (contable == NULL) { - printf("Calloc error - unable to succesfully communicate with server\n"); - exit(1); - } - - len = 4; - if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) { - printf("Can't get socket send buffer size - exiting...\n"); - exit(1); - } - - if (loginit(verbose, logging, logfname)) { - printf("Can't open file to log to... exiting\n"); - exit(1); - } - - if (!verbose) - daemon(0, 0); - - FD_ZERO(&allset); - FD_ZERO(&wset); - - FD_SET(master.commfd, &allset); - maxfdp1 = master.commfd + 1; - - /* UDP REVERSE MODE */ - - if (reverse) { - ipfam = 0; - if (TYPE_IS_IPV4(type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(type)) { - ipfam |= 0x04; - } - if (ip_listen(&(contable[0].connfd), desnam, despor, &addrlen, ipfam)) { - printf("udp_listen_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor); - exit(1); - } - cliaddr = malloc(addrlen); - maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1; - FD_SET(contable[0].connfd, &allset); - aflog(1, "CLIENT STARTED mode: udp reverse"); - for ( ; ; ) { - len = 4; - if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { - if (temp2 != buflength) { - buflength = temp2; - aflog(2, "Send buffer size changed..."); - } - } - len = addrlen; - rset = allset; - aflog(3, ">select"); - select(maxfdp1, &rset, NULL, NULL, NULL); - aflog(3, " >>after select..."); - - if (FD_ISSET(contable[0].connfd, &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/ - n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len); -#ifdef SIOCOUTQ - if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { - aflog(0, "ioctl error -> exiting..."); - exit(1); - } - if (buflength <= notsent + n + 5) { /* when we can't do this */ - aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); -#else - if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { - aflog(0, "ioctl error -> exiting..."); - exit(1); - } - if (notsent <= n + 5) { /* when we can't do this */ - aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength); -#endif - } - else { - if (n > 0) { - aflog(2, "Sending %d bytes to service (w:%d/%d) (FROM:%s)", n, -#ifdef SIOCOUTQ - notsent -#else - buflength - notsent -#endif - , buflength, sock_ntop(cliaddr, len, NULL, NULL)); - buff[0] = AF_S_MESSAGE; - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; - buff[4] = n; - writen(master.commfd, buff, n + 5); - } - } - } /* - FD_ISSET CONTABLE[0].CONNFD RSET */ - if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ - n = readn(master.commfd, buff, 5); - if (n == 5) { - if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) { - aflog(0, "Incompatible server type (not udp?) or data corruption -> exiting..."); - exit(1); - } - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - n = readn(master.commfd, buff, length); - } - else { - n = 0; - } - if (n == 0) { /* server quits -> we do the same... */ - aflog(0, "premature quit of the server -> exiting..."); - exit(1); - } - aflog(2, "Sending %d bytes to user (TO:%s)", n, sock_ntop(cliaddr, addrlen, NULL, NULL)); - sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen); - } /* - FD_ISSET MASTER.COMMFD RSET */ - } - exit(0); /* we shouldn't get here */ - } - - /* NORMAL MODE */ - - aflog(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp"); - aflog(1, "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(type))?"yes":"no", - (TYPE_IS_ZLIB(type))?"yes":"no", (TYPE_IS_TCP(type))?"tcp":"udp"); - aflog(2, "CIPHER: %s VER: %s", SSL_get_cipher_name(master.ssl), SSL_get_cipher_version(master.ssl)); - if (ismloaded(&module)) { - aflog(1, "LOADED MODULE: %s INFO: %s", module.name, module.info()); - } - if (ismloaded(&secmodule)) { - aflog(1, "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); - } - - for ( ; ; ) { - rset = allset; - tmpset = wset; - aflog(3, ">select"); - select(maxfdp1, &rset, &tmpset, NULL, NULL); - aflog(3, " >>after select..."); - - for (i = 0; i < usernum; ++i) { - if ((contable[i].state == S_STATE_OPEN)||(contable[i].state == S_STATE_STOPPED)) { - if (FD_ISSET(contable[i].connfd, &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */ - aflog(3, " user[%d]: FD_ISSET", i); - n = read(contable[i].connfd, &buff[5], 8091); - if (n == -1) { - aflog(0, " error (%d): while reading from service", n); - n = 0; - } -#ifdef SIOCOUTQ - if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { - aflog(0, "ioctl error -> exiting..."); - exit(1); - } - if (udp) { - len = 4; - if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { - if (temp2 != buflength) { - buflength = temp2; - aflog(2, "Send buffer size changed..."); - } - } - if (buflength <= notsent + n + 5) { /* when we can't send this */ - aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, notsent, buflength); -#else - if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { - aflog(0, "ioctl error -> exiting..."); - exit(1); - } - if (udp) { - len = 4; - if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { - if (temp2 != buflength) { - buflength = temp2; - aflog(2, "Send buffer size changed..."); - } - } - if (notsent <= n + 5) { /* when we can't send this */ - aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", - i, n+5, buflength, buflength-notsent, buflength); -#endif - continue; /* drop this packet */ - } - } - if (n) { - if (ismloaded(&secmodule)) { - switch ((temp2 = secmodule.filter(contable[i].namebuf, &buff[5], &n))) { - case 1: case 4: { - aflog(3, " user[%d] (by ser): PACKET IGNORED BY MODULE", i); - if (temp2 == 4) { - aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); - releasemodule(&secmodule); - } - continue; - break; - } - case 2: case 5: { - aflog(2, " user[%d] (by ser): DROPPED BY MODULE", i); - close(contable[i].connfd); - FD_CLR(contable[i].connfd, &allset); - FD_CLR(contable[i].connfd, &wset); - contable[i].state = S_STATE_CLOSING; - freebuflist(&contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); - if (temp2 == 5) { - aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); - releasemodule(&secmodule); - } - continue; - break; - } - case 3: { - aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); - releasemodule(&secmodule); - break; - } - } - } - buff[0] = AF_S_MESSAGE; /* sending message */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - aflog(2, " user[%d]: TO msglen: %d [%d/%d]", i, n, -#ifdef SIOCOUTQ - notsent -#else - buflength - notsent -#endif - , buflength); - send_message(type, master, buff, n+5); - } - else if (!udp) { - aflog(2, " user[%d]: CLOSING", i); - close(contable[i].connfd); - FD_CLR(contable[i].connfd, &allset); - FD_CLR(contable[i].connfd, &wset); - contable[i].state = S_STATE_CLOSING; - freebuflist(&contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); - } - } /* - FD_ISSET CONTABLE[i].CONNFD RSET */ - } - } - for (i = 0; i < usernum; ++i) { - if (contable[i].state == S_STATE_STOPPED) { - if (FD_ISSET(contable[i].connfd, &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */ - aflog(3, " user[%d]: FD_ISSET - WRITE", i); - n = contable[i].head->msglen - contable[i].head->actptr; - temp2 = write(contable[i].connfd, &(contable[i].head->buff[contable[i].head->actptr]), n); - if ((temp2 > 0) && (temp2 != n)) { - contable[i].head->actptr+=temp2; - } - else if ((temp2 == -1) && (errno == EAGAIN)) { - aflog(3, " user[%d]: Couldn't write?", i); - } - else if (temp2 == -1) { - close(contable[i].connfd); - FD_CLR(contable[i].connfd, &allset); - FD_CLR(contable[i].connfd, &wset); - contable[i].state = S_STATE_CLOSING; - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); - } - else { - deleteblnode(&contable[i].head); - if (contable[i].head == NULL) { - contable[i].state = S_STATE_OPEN; - FD_CLR(contable[i].connfd, &wset); - buff[0] = AF_S_CAN_SEND; /* stopping transfer */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - aflog(3, " FROM user[%d]: BUFFERING MESSAGE ENDED", i); - send_message(type, master, buff, 5); - } - } - } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */ - } - } - if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ - aflog(3, " masterfd: FD_ISSET"); - n = get_message(type, master, buff, 5); - if (n != 5) { - aflog(2, " FATAL ERROR! (%d)", n); - if (n == -1) { - if (TYPE_IS_SSL(type)) { - merror = SSL_get_error(master.ssl, n); - switch (merror) { - case SSL_ERROR_NONE : { - aflog(2, "FE: none"); - break; - } - case SSL_ERROR_ZERO_RETURN : { - aflog(2, "FE: zero"); - break; - } - case SSL_ERROR_WANT_READ : { - aflog(2, "FE: w_read"); - break; - } - case SSL_ERROR_WANT_WRITE : { - aflog(2, "FE: w_write"); - break; - } - case SSL_ERROR_WANT_CONNECT : { - aflog(2, "FE: w_connect"); - break; - } - case SSL_ERROR_WANT_X509_LOOKUP : { - aflog(2, "FE: w_x509_lookup"); - break; - } - case SSL_ERROR_SYSCALL : { - aflog(2, "FE: syscall"); - break; - } - case SSL_ERROR_SSL : { - SSL_load_error_strings(); - aflog(2, "FE: ssl:%s", - ERR_error_string(ERR_get_error(), (char*) buff)); - break; - } - } - continue; /* what happened? */ - } - } - if (n != 0) - exit(1); - } - if (n == 0) { /* server quits -> we do the same... */ - aflog(0, " SERVER: premature quit -> exiting..."); - exit(1); - } - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - switch (buff[0]) { - case AF_S_CONCLOSED : { - if ((numofcon>=0) && (numofcon<=usernum)) { - usercon--; - if (contable[numofcon].state == S_STATE_CLOSING) { - contable[numofcon].state = S_STATE_CLEAR; - aflog(2, " user[%d]: CLOSED", numofcon); - } - else if ((contable[numofcon].state==S_STATE_OPEN) || (contable[numofcon].state==S_STATE_STOPPED)){ - aflog(2, " user[%d]: CLOSED", numofcon); - close(contable[numofcon].connfd); - FD_CLR(contable[numofcon].connfd, &allset); - FD_CLR(contable[numofcon].connfd, &wset); - contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - } - } - break; - } - case AF_S_CONOPEN : { - if ((numofcon>=0) && (numofcon<=usernum)) { - usercon++; - if (contable[numofcon].state == S_STATE_CLEAR) { - n = get_message(type, master, buff, length); - memcpy(contable[numofcon].namebuf, buff, 128); - memcpy(contable[numofcon].portbuf,&buff[128],7); - aflog(2, " user[%d]: OPENING", numofcon); - aflog(1, "user[%d]: IP:%s PORT:%s", numofcon, - contable[numofcon].namebuf, contable[numofcon].portbuf); - if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) { - aflog(2, " IT'S NOT ALLOWED - DROPPING", numofcon); - buff[0] = AF_S_CANT_OPEN; /* not opening connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - usercon--; - continue; - } - if (udp) { - ipfam = 0; - } - else { - ipfam = 0x01; - } - if (TYPE_IS_IPV4(type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(type)) { - ipfam |= 0x04; - } - if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) { - aflog(2, " CAN'T OPEN - DROPPING", numofcon); - buff[0] = AF_S_CANT_OPEN; /* not opening connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - usercon--; - continue; - } - temp2 = fcntl(contable[numofcon].connfd, F_GETFL, 0); - fcntl(contable[numofcon].connfd, F_SETFL, temp2 | O_NONBLOCK); - FD_SET(contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1); - buff[0] = AF_S_CONOPEN; /* opening connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - contable[numofcon].state = S_STATE_OPEN; - } - } - break; - } - case AF_S_MESSAGE : { - aflog(2, " user[%d]: FROM msglen: %d", numofcon, length); - n = get_message(type, master, buff, length); - if ((numofcon>=0) && (numofcon<=usernum)) { - if (contable[numofcon].state == S_STATE_OPEN) { - if (ismloaded(&module)) { - switch ((temp2 = module.filter(contable[numofcon].namebuf, buff, &n))) { - case 1: case 4:{ - aflog(3, " user[%d]: PACKET IGNORED BY MODULE", numofcon); - if (temp2 == 4) { - aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); - releasemodule(&module); - } - continue; - break; - } - case 2: case 5:{ - aflog(2, " user[%d]: DROPPED BY MODULE", numofcon); - close(contable[numofcon].connfd); - FD_CLR(contable[numofcon].connfd, &allset); - FD_CLR(contable[numofcon].connfd, &wset); - contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - if (temp2 == 5) { - aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); - releasemodule(&module); - } - continue; - break; - } - case 3: { - aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); - releasemodule(&module); - break; - } - } - } - aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n); - temp2 = write(contable[numofcon].connfd, buff, n); - if ((temp2 > 0) && (temp2 != n)) { - insertblnode(&(contable[numofcon].head), temp2, n, buff); - contable[numofcon].state = S_STATE_STOPPED; - FD_SET(contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); - send_message(type, master, buff, 5); - } - else if ((temp2 == -1) && (errno == EAGAIN)) { - insertblnode(&(contable[numofcon].head), 0, n, buff); - contable[numofcon].state = S_STATE_STOPPED; - FD_SET(contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); - send_message(type, master, buff, 5); - } - else if (temp2 == -1) { - close(contable[numofcon].connfd); - FD_CLR(contable[numofcon].connfd, &allset); - FD_CLR(contable[numofcon].connfd, &wset); - contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - } - } - else if (contable[numofcon].state == S_STATE_STOPPED) { - aflog(3, " FROM user[%d]: BUFFERING MESSAGE", numofcon); - insertblnode(&(contable[numofcon].head), 0, n, buff); - } - } - break; - } - case AF_S_CLOSING : { /* server shut down -> exiting... */ - aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); - exit(1); - break; - } - case AF_S_DONT_SEND: { - FD_CLR(contable[numofcon].connfd, &allset); - break; - } - case AF_S_CAN_SEND: { - FD_SET(contable[numofcon].connfd, &allset); - break; - } - default : { /* unrecognized type of message -> exiting... */ - aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); - exit(1); - break; - } - } - } /* - FD_ISSET MASTER.COMMFD RSET */ - } -} - -static void -usage(char* info) -{ - printf("\n%s\n\n", info); - printf(" Options:\n"); - printf(" -h, --help - prints this help\n"); - printf(" -n, --servername - where the second part of the active\n"); - printf(" port forwarder is running (required)\n"); - printf(" -m, --manageport - manage port number - server must be\n"); - printf(" listening on it (default: 50126)\n"); - printf(" -d, --hostname - the name of this host/remote host - the final\n"); - printf(" destination of the packets (default: the name\n"); - printf(" returned by hostname function)\n"); - printf(" -p, --portnum - the port we are forwarding connection to (required)\n"); - printf(" -k, --keyfile - the name of the file with RSA key (default: (none))\n"); - printf(" -u, --udpmode - udp mode - client will use udp protocol to\n"); - printf(" communicate with the hostname\n"); - printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n"); - printf(" from hostname:portnum (-p) to the server name:portnum\n"); - printf(" (-m)\n"); - printf(" -O, --heavylog - logging everything to a logfile\n"); - printf(" -o, --lightlog - logging some data to a logfile\n"); - printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); - printf(" (use several times for greater effect)\n"); - printf(" --pass - set the password used for client identification\n"); - printf(" (default: no password)\n"); - printf(" -4, --ipv4 - use ipv4 only\n"); - printf(" -6, --ipv6 - use ipv6 only\n"); - printf(" -l, --load - load a module for user's packets filtering\n"); - printf(" -L, --Load - load a module for service's packets filtering\n\n"); - - exit(0); -} - -static void -sig_int(int signo) -{ - aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg()); - exit(0); -} - -void -callback(int i, int j, void* k) -{ - if (k == NULL) { - printf("%d", i); - fflush(stdout); - } -} diff --git a/afserver.c b/afserver.c deleted file mode 100644 index a8ca773..0000000 --- a/afserver.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "activefor.h" -#include "network.h" -#include "file.h" -#include "stats.h" - -#include -#include -#include -#include -#include -#include - -static void usage(char* info); -static void sig_int(int); -static void remove_client(RealmT*, int, fd_set*, fd_set*, int*); -static int find_client(RealmT*, char); -static int eval_numofcon(RealmT*, int, int); -static int eval_usernum(ConnectclientT*, int); -static int find_usernum(ConnectclientT*, int); -static void check_value(int*, char*, char*); - -static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"hostname", 1, 0, 'n'}, - {"listenport", 1, 0, 'l'}, - {"manageport", 1, 0, 'm'}, - {"timeout", 1, 0, 't'}, - {"verbose", 0, 0, 'v'}, - {"users", 1, 0, 'u'}, - {"clients", 1, 0, 'C'}, - {"usrpcli", 1, 0, 'U'}, - {"climode", 1, 0, 'M'}, - {"cerfile", 1, 0, 'c'}, - {"keyfile", 1, 0, 'k'}, - {"cfgfile", 1, 0, 'f'}, - {"proto", 1, 0, 'p'}, - {"lightlog", 1, 0, 'o'}, - {"heavylog", 1, 0, 'O'}, - {"nossl", 0, 0, 301}, - {"nozlib", 0, 0, 302}, - {"pass", 1, 0, 303}, - {"ipv4", 0, 0, '4'}, - {"ipv6", 0, 0, '6'}, - {0, 0, 0, 0} -}; - -static ConfigurationT config; - -int -main(int argc, char **argv) -{ - int i, j=0, k, n, flags, sent; - socklen_t len; - unsigned char buff[9000]; - char hostname[100]; - int maxfdp1; - fd_set rset, allset, wset, tmpset; - int manconnecting, numofcon, length; - char* name = NULL; - char* listen = NULL; - char* manage = NULL; - char* amount = NULL; - char* clients = NULL; - char* usrpcli = NULL; - char* clim = NULL; - char* filenam = NULL; - char* type = NULL; - char* timeout = NULL; - unsigned char pass[4] = {1, 2, 3, 4}; - char verbose = 0; - char mode = 0; - char ipfam = 0; - RealmT* pointer = NULL; - struct sigaction act; - - SSL_METHOD* method; - SSL_CTX* ctx; - - sigfillset(&(act.sa_mask)); - act.sa_flags = 0; - - act.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &act, NULL); - act.sa_handler = sig_int; - sigaction(SIGINT, &act, NULL); - - TYPE_SET_SSL(mode); - TYPE_SET_ZLIB(mode); - - config.certif = NULL; - config.keys = NULL; - config.size = 0; - config.realmtable = NULL; - config.logging = 0; - config.logfnam = NULL; - - while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:", long_options, 0)) != -1) { - switch (n) { - case 'h': { - usage(AF_VER("Active port forwarder (server)")); - break; - } - case 'n': { - name = optarg; - break; - } - case 'l': { - listen = optarg; - break; - } - case 'm': { - manage = optarg; - break; - } - case 't': { - timeout = optarg; - break; - } - case 'v': { - ++verbose; - break; - } - case 'u': { - amount = optarg; - break; - } - case 'C': { - clients = optarg; - break; - } - case 'U': { - usrpcli = optarg; - break; - } - case 'M': { - clim = optarg; - break; - } - case 'c': { - config.certif = optarg; - break; - } - case 'k': { - config.keys = optarg; - break; - } - case 'p': { - type = optarg; - break; - } - case 'f': { - filenam = optarg; - break; - } - case 'O': { - config.logfnam = optarg; - config.logging = 3; - break; - } - case 'o': { - config.logfnam = optarg; - config.logging = 1; - break; - } - case 301: { - TYPE_UNSET_SSL(mode); - break; - } - case 302: { - TYPE_UNSET_ZLIB(mode); - break; - } - case 303: { - n = strlen(optarg); - memset(pass, 0, 4); - for (i = 0; i < n; ++i) { - pass[i%4] += optarg[i]; - } - break; - } - case '4': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 4; - } - break; - } - case '6': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 6; - } - break; - } - case '?': { - usage(""); - break; - } - } - } - - if (optind < argc) { - usage("Unrecognized non-option elements"); - } - - if (filenam != NULL) { - config = parsefile(filenam, &n); - if (n) { - printf("parsing failed! line:%d\n", n); - exit(1); - } - else { - if (verbose) { - printf("cfg file OK! (readed realms: %d)\n", config.size); - } - } - } - else { - if (name == NULL) { - gethostname(hostname, 100); - name = hostname; - } - if (listen == NULL) { - listen = "50127"; - } - if (manage == NULL) { - manage = "50126"; - } - if (timeout == NULL) { - timeout = "5"; - } - if (amount == NULL) { - amount = "5"; - } - if (clients == NULL) { - clients = "1"; - } - if (usrpcli == NULL) { - usrpcli = amount; - } - if (clim == NULL) { - clim = "1"; - } - if (config.certif == NULL) { - config.certif = "cacert.pem"; - } - if (config.keys == NULL) { - config.keys = "server.rsa"; - } - if (type == NULL) { - type = "tcp"; - } - config.size = 1; - config.realmtable = calloc(config.size, sizeof(RealmT)); - config.realmtable[0].hostname = name; - config.realmtable[0].lisportnum = listen; - config.realmtable[0].manportnum = manage; - config.realmtable[0].users = amount; - config.realmtable[0].clients = clients; - config.realmtable[0].timeout = timeout; - config.realmtable[0].usrpcli = usrpcli; - config.realmtable[0].clim = clim; - memcpy(config.realmtable[0].pass, pass, 4); - if (strcmp(type, "tcp") == 0) { - TYPE_SET_TCP(config.realmtable[0].type); - } - else if (strcmp(type, "udp") == 0) { - TYPE_SET_UDP(config.realmtable[0].type); - } - else { - TYPE_SET_ZERO(config.realmtable[0].type); - } - if (ipfam == -1) { - printf("Conflicting types of ip protocol family... exiting\n"); - exit(1); - } - else if (ipfam == 4) { - TYPE_SET_IPV4(config.realmtable[0].type); - } - else if (ipfam == 6) { - TYPE_SET_IPV6(config.realmtable[0].type); - } - config.realmtable[0].type |= mode; - } - - maxfdp1 = manconnecting = 0; - - SSL_library_init(); - method = SSLv3_server_method(); - ctx = SSL_CTX_new(method); - if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { - printf("Setting ciphers list failed... exiting\n"); - exit(1); - } - if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) { - printf("Setting rsa key failed (%s)... exiting\n", config.keys); - exit(1); - } - if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) { - printf("Setting certificate failed (%s)... exiting\n", config.certif); - exit(1); - } - - if (config.size == 0) { - printf("Working without sense is really without sense...\n"); - exit(1); - } - - FD_ZERO(&allset); - FD_ZERO(&wset); - - for (i = 0; i < config.size; ++i) { - if ((config.realmtable[i].hostname == NULL) || - (config.realmtable[i].lisportnum == NULL) || - (config.realmtable[i].manportnum == NULL)) { - printf("Missing some of the configurable variables...\n"); - printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\n", - i, config.realmtable[i].hostname, - config.realmtable[i].lisportnum, - config.realmtable[i].manportnum); - exit(1); - } - /* checking type of the realm */ - if (!TYPE_IS_SET(config.realmtable[i].type)) { - TYPE_SET_TCP(config.realmtable[i].type); - } - /* checking users amount */ - if (config.realmtable[i].users == NULL) { - config.realmtable[i].users = "5"; - } - check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount"); - /* checking clients amount */ - if (config.realmtable[i].clients == NULL) { - config.realmtable[i].clients = "1"; - } - check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount"); - /* checking usrpcli value */ - if (config.realmtable[i].usrpcli == NULL) { - config.realmtable[i].usrpcli = config.realmtable[i].users; - } - check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value"); - /* checking timeout value */ - if (config.realmtable[i].timeout == NULL) { - config.realmtable[i].timeout = "5"; - } - check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value"); - /* checking climode value */ - if (config.realmtable[i].clim == NULL) { - config.realmtable[i].clim = "1"; - } - check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value"); - /* allocating memory*/ - config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT)); - if (config.realmtable[i].contable == NULL) { - printf("Calloc error - try define smaller amount of users\n"); - exit(1); - } - config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT)); - if (config.realmtable[i].clitable == NULL) { - printf("Calloc error - try define smaller amount of clients\n"); - exit(1); - } - ipfam = 0x01; - if (TYPE_IS_IPV4(config.realmtable[i].type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(config.realmtable[i].type)) { - ipfam |= 0x04; - } - if (ip_listen(&(config.realmtable[i].listenfd), config.realmtable[i].hostname, - config.realmtable[i].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) { - printf("tcp_listen_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", - config.realmtable[i].hostname, config.realmtable[i].lisportnum); - exit(1); - } - if (ip_listen(&(config.realmtable[i].managefd), config.realmtable[i].hostname, - config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), ipfam)) { - printf("tcp_listen_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", - config.realmtable[i].hostname, config.realmtable[i].manportnum); - exit(1); - } - config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); - - for (j=0; j (config.realmtable[i].managefd+1)) ? maxfdp1 : (config.realmtable[i].managefd+1); - maxfdp1 = (maxfdp1 > (config.realmtable[i].listenfd+1)) ? maxfdp1 : (config.realmtable[i].listenfd+1); - config.realmtable[i].usercon = 0; - config.realmtable[i].clicon = 0; - for (j=0; jselect, maxfdp1: %d", maxfdp1); - if (manconnecting) { - /* find out, in what realm client is trying to connect */ - for (k = 0; k < config.size; ++k) { - for (j=0; j < config.realmtable[k].clinum; ++j) { - if ((config.realmtable[k].clitable[j].ready == 1) || (config.realmtable[k].clitable[j].ready == 2)) { - i = k; - k = config.size; - break; /* so i points to first good realm and j to good client */ - } - } - } - if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].clitable[j].tv))) == 0) { - close (config.realmtable[i].clitable[j].cliconn.commfd); - FD_CLR(config.realmtable[i].clitable[j].cliconn.commfd, &allset); - FD_SET(config.realmtable[i].managefd, &allset); - SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl); - config.realmtable[i].clitable[j].ready = 0; - manconnecting--; - config.realmtable[i].clicon--; - aflog(1, " realm[%d]: client[%d]: SSL_accept failed (timeout)", i, j); - } - } - else { - select(maxfdp1, &rset, &tmpset, NULL, NULL); - } - aflog(3, " >>after select..."); - - for (j = 0; j < config.size; ++j) { - pointer = (&(config.realmtable[j])); - for (i = 0; i usernum; ++i) { - if ((pointer->contable[i].state == S_STATE_OPEN) || (pointer->contable[i].state == S_STATE_STOPPED)) - if (FD_ISSET(pointer->contable[i].connfd, &rset)) { - k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); - aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET", j, pointer->contable[i].whatcli, k); - if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ - n = read(pointer->contable[i].connfd, &buff[5], 8091); - if (n == -1) { - aflog(3, " realm[%d]: client[%d]: user[%d]: READ ERROR (%d)", j, - pointer->contable[i].whatcli, k, errno); - n = 0; - } - if (n) { - aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, - pointer->contable[i].whatcli, k, n); - if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { - aflog(2, " WARNING: got packet similiar to udp"); - } - buff[0] = AF_S_MESSAGE; /* sending message */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5); - } - else { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, - pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - else { /* when forwarding udp packets */ - n = readn(pointer->contable[i].connfd, buff, 5 ); - if (n != 5) { - n = 0; - } - if (n) { - if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { - aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, - pointer->contable[i].whatcli, k, n); - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, - buff, n+5); - } - } - else { - n = 0; - } - } - - if (n == 0) { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED (udp mode)", j, - pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, - pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - - } - } - } - /* ------------------------------------ */ - for (i = 0; i usernum; ++i) { - if (pointer->contable[i].state == S_STATE_STOPPED) - if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { - k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); - aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET - WRITE", j, pointer->contable[i].whatcli, - k); - n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr; - sent = write(pointer->contable[i].connfd, - &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n); - if ((sent > 0) && (sent != n)) { - pointer->contable[i].head->actptr+=sent; - } - else if ((sent == -1) && (errno == EAGAIN)) { - } - else if (sent == -1) { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - else { - deleteblnode(&pointer->contable[i].head); - if (pointer->contable[i].head == NULL) { - pointer->contable[i].state = S_STATE_OPEN; - FD_CLR(pointer->contable[i].connfd, &wset); - buff[0] = AF_S_CAN_SEND; /* stopping transfer */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - aflog(3, " realm[%d]: client[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j, - pointer->contable[i].whatcli, k); - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - } - } - /* ------------------------------------ */ - if (FD_ISSET(pointer->listenfd, &rset)) { - len = pointer->addrlen; - sent = accept(pointer->listenfd, pointer->cliaddr, &len); - flags = fcntl(sent, F_GETFL, 0); - fcntl(sent, F_SETFL, flags | O_NONBLOCK); - aflog(3, " realm[%d]: listenfd: FD_ISSET", j); - k = find_client(pointer, pointer->climode); - if (pointer->clitable[k].ready == 3) { - if (pointer->usercon == pointer->usernum) { - close(sent); - aflog(3, " realm[%d]: user limit EXCEEDED", j); - } - else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) { - close(sent); - aflog(3, " realm[%d]: client[%d]: usrpcli limit EXCEEDED", j, k); - } - else { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state == S_STATE_CLEAR) { - aflog(2, " realm[%d]: client[%d]: new user: CONNECTING", j, k); - pointer->contable[i].connfd = sent; - pointer->contable[i].state = S_STATE_OPENING; - pointer->contable[i].whatcli = k; - pointer->usercon++; - pointer->clitable[k].usercon++; - aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len, - pointer->contable[i].namebuf, pointer->contable[i].portbuf)); - memcpy(&buff[5], pointer->contable[i].namebuf, 128); - memcpy(&buff[133], pointer->contable[i].portbuf, 7); - n = 135; - i = find_usernum(&(pointer->clitable[k]), i); - buff[0] = AF_S_CONOPEN; /* opening connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); - break; - } - } - } - } - else { - close(sent); - aflog(3, " realm[%d]: client[%d] is NOT CONNECTED", j, k); - } - } - /* ------------------------------------ */ - for (k = 0; k < pointer->clinum; ++k) - if (pointer->clitable[k].ready != 0) /* Command file descriptor */ - if (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset)) { - if (pointer->clitable[k].ready == 1) { - if (SSL_set_fd(pointer->clitable[k].cliconn.ssl, pointer->clitable[k].cliconn.commfd) != 1) { - aflog(0, "Problem with initializing ssl... exiting"); - exit(1); - } - aflog(2, " realm[%d]: new client: SSL_accept", j); - if ((n = SSL_accept(pointer->clitable[k].cliconn.ssl)) != 1) { - flags = SSL_get_error(pointer->clitable[k].cliconn.ssl, n); - switch (flags) { - case SSL_ERROR_NONE : { - aflog(2, " SSL_accept has failed(%d)...none", n); - break; - } - case SSL_ERROR_ZERO_RETURN : { - aflog(2, " SSL_accept has failed(%d)...zero", n); - break; - } - case SSL_ERROR_WANT_READ : { - aflog(2, " SSL_accept has failed(%d)...w_read", n); - break; - } - case SSL_ERROR_WANT_WRITE : { - aflog(2, " SSL_accept has failed(%d)...w_write", n); - break; - } - case SSL_ERROR_WANT_CONNECT : { - aflog(2, " SSL_accept has failed(%d)...w_connect", n); - break; - } - case SSL_ERROR_WANT_X509_LOOKUP : { - aflog(2, " SSL_accept has failed(%d)...w_x509_lookup", n); - break; - } - case SSL_ERROR_SYSCALL : { - aflog(2, " SSL_accept has failed(%d)...syscall", n); - break; - } - case SSL_ERROR_SSL : { - SSL_load_error_strings(); - aflog(2, " SSL_accept has failed(%d)...ssl:%s", - n, ERR_error_string(ERR_get_error(), (char*) buff)); - break; - } - } - if (flags == SSL_ERROR_WANT_READ) - continue; - close (pointer->clitable[k].cliconn.commfd); - FD_CLR(pointer->clitable[k].cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - SSL_clear(pointer->clitable[k].cliconn.ssl); - pointer->clitable[k].ready = 0; - manconnecting--; - pointer->clicon--; - aflog(1, " realm[%d]: new client[%d]: DENIED by SSL_accept", j, k); - } - else { - aflog(1, " realm[%d]: new client[%d]: ACCEPTED by SSL_accept", j, k); - pointer->clitable[k].ready = 2; - } - continue; /* in the case this is not our client */ - } - aflog(3, " realm[%d]: client[%d]: commfd: FD_ISSET", j, k); - if (pointer->clitable[k].ready == 2) { - n = get_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, -5); - } - else { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5); - } - if (n == -1) { - if (errno == EAGAIN) { - aflog(4, " realm[%d]: client[%d]: commfd: EAGAIN", j, k); - continue; - } - else { - aflog(4, " realm[%d]: client[%d]: commfd: ERROR: %d", j, k, errno); - n = 0; - } - } - else if (n != 5) { - n = 0; - } - if (n==0) { - remove_client(pointer, k, &allset, &wset, &manconnecting); - aflog(1, " realm[%d]: client[%d]: commfd: CLOSED", j, k); - continue; - } - - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - - switch (buff[0]) { - case AF_S_CONCLOSED : { - n = numofcon; - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - pointer->usercon--; - pointer->clitable[k].usercon--; - pointer->clitable[k].users[n] = -1; - if (pointer->contable[numofcon].state == S_STATE_CLOSING) { - pointer->contable[numofcon].state = S_STATE_CLEAR; - } - else if ((pointer->contable[numofcon].state == S_STATE_OPEN) || - (pointer->contable[numofcon].state == S_STATE_STOPPED)) { - aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CONOPEN : { - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon); - FD_SET(pointer->contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? - maxfdp1 : (pointer->contable[numofcon].connfd+1); - pointer->contable[numofcon].state = S_STATE_OPEN; - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CANT_OPEN : { - n = numofcon; - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: DROPPED", j, numofcon); - pointer->usercon--; - pointer->clitable[k].usercon--; - pointer->clitable[k].users[n] = -1; - close(pointer->contable[numofcon].connfd); - pointer->contable[numofcon].state = S_STATE_CLEAR; - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_MESSAGE : { - if ((pointer->clitable[k].ready) != 3) { - remove_client(pointer, k, &allset, &wset, &manconnecting); - break; - } - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - n = get_message(pointer->type, pointer->clitable[k].cliconn, &buff[5], length); - } - else { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); - } - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum))) { - if (pointer->contable[numofcon].state == S_STATE_OPEN) { - aflog(2, " realm[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - sent = write(pointer->contable[numofcon].connfd, buff, n+5); - if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED (write-udp)", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { /* tcp */ - sent = write(pointer->contable[numofcon].connfd, buff, n); - if ((sent > 0) && (sent != n)) { - insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, - sent, n); - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - else if ((sent == -1) && (errno == EAGAIN)) { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, - sent, n); - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - else if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED (write-tcp)", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - } - else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE (%d)", j, numofcon, n); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); - } - else { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - } - } - } - break; - } - case AF_S_LOGIN : { - if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && - (length==(pointer->pass[2]*256+pointer->pass[3]))) { - pointer->clitable[k].ready = 3; - aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j); - buff[0] = AF_S_LOGIN; /* sending message */ - buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */ - buff[2] = pointer->clitable[k].usernum; /* low bits of user number */ - buff[3] = pointer->type; /* type of connection */ - send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5); - manconnecting--; - } - else { - aflog(1, " realm[%d]: Wrong password - CLOSING", j); - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_DONT_SEND: { - FD_CLR(pointer->contable[numofcon].connfd, &allset); - break; - } - case AF_S_CAN_SEND: { - FD_SET(pointer->contable[numofcon].connfd, &allset); - break; - } - default : { - aflog(1, " realm[%d]: Unrecognized message - CLOSING", j); - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - } - } - if (FD_ISSET(pointer->managefd, &rset)) { - aflog(3, " realm[%d]: managefd: FD_ISSET", j); - len = pointer->addrlen; - for (k = 0; k < pointer->clinum; ++k) - if (!(pointer->clitable[k].ready)) { - aflog(2, " realm[%d]: new client[%d]: CONNECTING", j, k); - pointer->clitable[k].cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len); - flags = fcntl(pointer->clitable[k].cliconn.commfd, F_GETFL, 0); - fcntl(pointer->clitable[k].cliconn.commfd, F_SETFL, flags | O_NONBLOCK); - aflog(1, " realm[%d]: Client[%d] IP:%s", j, k, sock_ntop(pointer->cliaddr, len, NULL, NULL)); - FD_SET(pointer->clitable[k].cliconn.commfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ? - maxfdp1 : (pointer->clitable[k].cliconn.commfd+1); - pointer->clicon++; - if (pointer->clicon == pointer->clinum) - FD_CLR(pointer->managefd, &allset); - pointer->clitable[k].tv.tv_sec = pointer->tmout; - manconnecting++; - pointer->clitable[k].ready = 1; - break; - } - } - } /* realms loop */ - } -} - -static void -usage(char* info) -{ - printf("\n%s\n\n", info); - printf(" Options:\n"); - printf(" -n, --hostname - it's used when creating listening sockets\n"); - printf(" (default: name returned by hostname function)\n"); - printf(" -l, --listenport - listening port number - users connect\n"); - printf(" to it (default: 50127)\n"); - printf(" -m, --manageport - manage port number - second part of the active\n"); - printf(" port forwarder connects to it (default: 50126)\n"); - printf(" -t, --timeout - the timeout value for the client's connection\n"); - printf(" (default: 5)\n"); - printf(" -u, --users - the amount of users allowed to use this server\n"); - printf(" (default: 5)\n"); - printf(" -C, --clients - the number of allowed clients to use this server\n"); - printf(" (default: 1)\n"); - printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n"); - printf(" -M, --climode - strategy used for connecting users with clients (default: 1)\n"); - printf(" Available strategies:\n"); - printf(" 1. fill first client before go to next\n\n"); - printf(" -c, --cerfile - the name of the file with certificate\n"); - printf(" (default: cacert.pem)\n"); - printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n"); - printf(" -f, --cfgfile - the name of the file with the configuration for the\n"); - printf(" active forwarder (server)\n"); - printf(" -p, --proto - type of server (tcp|udp) - for which protocol it will be\n"); - printf(" operating (default: tcp)\n"); - printf(" -O, --heavylog - logging everything to a logfile\n"); - printf(" -o, --lightlog - logging some data to a logfile\n"); - printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); - printf(" (use several times for greater effect)\n\n"); - printf(" --nossl - ssl is not used for transfering data (but it's still\n"); - printf(" used to establish a connection) (default: ssl is used)\n"); - printf(" --nozlib - zlib is not used for compressing data (default:\n"); - printf(" zlib is used)\n"); - printf(" --pass - set the password used for client identification\n"); - printf(" (default: no password)\n\n"); - printf(" -4, --ipv4 - use ipv4 only\n"); - printf(" -6, --ipv6 - use ipv6 only\n\n"); - printf(" -h, --help - prints this help\n\n"); - exit(0); -} - -static void -sig_int(int signo) -{ - int i, j; - unsigned char buff[5]; - for (j = 0; j < config.size; ++j) { - buff[0] = AF_S_CLOSING; /* closing */ - for (i = 0; i < config.realmtable[j].clinum; ++i) { - if (config.realmtable[j].clitable[i].ready == 3) { - send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5); - } - } - } - aflog(1, "SERVER CLOSED cg: %ld bytes", getcg()); - exit(0); -} - -static void -remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) -{ - int i; - if (ptr->clitable[client].ready == 3) { - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->contable[i].whatcli == client) { - if (ptr->contable[i].state != S_STATE_CLEAR) { - ptr->contable[i].state = S_STATE_CLEAR; - FD_CLR(ptr->contable[i].connfd, set); - FD_CLR(ptr->contable[i].connfd, wset); - close(ptr->contable[i].connfd); - ptr->usercon--; - } - } - } - } - ptr->clitable[client].usercon = 0; - close(ptr->clitable[client].cliconn.commfd); - FD_CLR(ptr->clitable[client].cliconn.commfd, set); - FD_SET(ptr->managefd, set); - if (ptr->clitable[client].ready == 2) - (*con)--; - SSL_clear(ptr->clitable[client].cliconn.ssl); - ptr->clitable[client].ready = 0; - ptr->clicon--; -} - -static int -find_client(RealmT* ptr, char mode) -{ - int i; - switch(mode) { - case 1: { /* fill first client before go to next */ - for (i = 0; i < ptr->clinum; ++i) { - if (ptr->clitable[i].ready == 3) { - if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) { - return i; - } - } - } - break; - } - default: { - return 0; - } - } - return 0; -} - -static int -eval_numofcon(RealmT* ptr, int client, int numofcon) -{ - if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) { - numofcon = ptr->clitable[client].users[numofcon]; - } - else { - numofcon = -1; - } - return numofcon; -} - -static int -eval_usernum(ConnectclientT* ptr, int usernum) -{ - int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == usernum) - return i; - } - return -1; -} - -static int -find_usernum(ConnectclientT* ptr, int usernum) -{ - int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == -1) { - ptr->users[i] = usernum; - return i; - } - } - return -1; -} - -static void -check_value(int* where, char* what, char* info) -{ - char* znak; - if ((( (*where) = strtol(what, &znak, 10)) == LONG_MAX) || ((*where) == LONG_MIN)) { - printf("%s: %s\n", info, what); - exit(1); - } - if (((*what) == '\0') || (*znak != '\0')) { - printf("%s: %s\n", info, what); - exit(1); - } - if ((*where) <= 0) { - printf("%s: %d\n", info, *where); - exit(1); - } -} diff --git a/buflist.c b/buflist.c deleted file mode 100644 index d25a0ea..0000000 --- a/buflist.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include - -#include "buflist.h" - -int -insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff) -{ - blnodeT* newnode, *lastnode; - lastnode = newnode = *headRef; - while (newnode) { - lastnode = newnode; - newnode = newnode->next; - } - newnode = calloc(1, sizeof(blnodeT)); - newnode->next = NULL; - newnode->actptr = 0; - newnode->msglen = msglen - actptr; - newnode->buff = calloc(1, newnode->msglen); - if (newnode->buff == NULL) - return 1; - strncpy(newnode->buff, buff+actptr, newnode->msglen); - if (lastnode) - lastnode->next = newnode; - else - *headRef = newnode; - return 0; -} - -int -deleteblnode(blnodeT** headRef) -{ - blnodeT* node = *headRef; - if (*headRef == NULL) - return 1; - *headRef = node->next; - if (node->buff != NULL) - free(node->buff); - free(node); - return 0; -} - -int -freebuflist(blnodeT** headRef) -{ - while (*headRef) { - deleteblnode(headRef); - } - return 0; -} diff --git a/buflist.h b/buflist.h deleted file mode 100644 index c4baeae..0000000 --- a/buflist.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_BUFLIST_H -#define _JS_BUFLIST_H - -typedef struct blnode { - int actptr; - int msglen; - unsigned char* buff; - struct blnode* next; -} blnodeT; - -int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff); -int deleteblnode(blnodeT** headRef); -int freebuflist(blnodeT** headRef); - -#endif diff --git a/config b/config deleted file mode 100644 index 8d82f1d..0000000 --- a/config +++ /dev/null @@ -1,42 +0,0 @@ -# This is an example configuration file for active forwarder -# Firstly, we have to declare our files with key and certificate - -certificate cacert.pem - -# Please note, that we can place only blank characters between words - -key server.rsa - -# when we want to log some information, we specify file for lightlog -# when we want to log everything - we do this by using heavylog option - -# type name of file - -lightlog logfile -#heavylog logfile - - -# And it's time for create forwarding targets (named realms here) - -#newrealm indicates a new set of commands to a server -newrealm - -#options values - -hostname #this is a name of the server (it's using it for choosing interface) -listen 50127 #portnumber on which server is listening for users -manage 50126 #portnumber on which server is listening for afclient -#users 5 #amount of users we are allowing to connect (>0) (default: 5) -#timeout 5 #timeout value for the client's connection (>0) (default: 5) -#clients 1 #number of allowed clients for this realm (>0) (default: 1) -#usrpcli $users #allowed users per client for this realm (>0) (default: $users) -#climode 1 #strategy used for connecting users with clients (1) (default: 1) -#proto tcp #type of the realm (which protocol it will forward (tcp|udp) (default: tcp) -#pass mypassword #this is a password used for client identification - -# and now the second realm - -newrealm -hostname -listen 50125 -manage 50124 diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6c5c7b8 --- /dev/null +++ b/configure.ac @@ -0,0 +1,82 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([Active port forwarder], [0.6], [jeremian@poczta.fm], [apf]) +AM_INIT_AUTOMAKE([apf], [0.6]) +AC_COPYRIGHT([ +Copyright (C) 2003,2004,2005 jeremian - +=================== + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +========================== + + The Active Port Forwarder program is part of the Gray-World.net projects. + + Our Gray-World Team presents on the http://gray-world.net website the projects + and publications we are working on which are related to the NACS (Network + Access Control System) bypassing research field and to the computer and + network security topics. + +================================================================================ +]) +AC_CONFIG_SRCDIR([src/afserver.c]) +AM_CONFIG_HEADER([config.h]) +AC_CONFIG_FILES([Makefile + modules/Makefile + src/Makefile]) + +CFLAGS="-pedantic -Wall -O2" + +# Checks for programs. +AC_PROG_CC +AC_PROG_GCC_TRADITIONAL +AC_CHECK_PROGS(HAVE_OPENSSL, [openssl]) + +# Checks for libraries. +AC_CHECK_LIB([ssl], [SSL_library_init], [], + [ + AC_ERROR("lib ssl not found!") + ]) +AC_CHECK_LIB([z], [compress], [], + [ + AC_ERROR("zlib not found!") + ]) +AC_CHECK_LIB([dl], [dlopen], + [ + LINKED_LDLIB="-ldl" + USE_RDYNAMIC="-rdynamic" + AC_DEFINE(HAVE_LIBDL, 1, [Define to 1 if you have the `dl' library (-ldl).]) + ], + [ + LINKED_LDLIB="" + USE_RDYNAMIC="" + ]) +AC_SUBST(LINKED_LDLIB) +AC_SUBST(USE_RDYNAMIC) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/ioctl.h sys/socket.h sys/time.h unistd.h sys/types.h pwd.h linux/sockios.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_HEADER_TIME +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_FUNC_SELECT_ARGTYPES +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([bzero gethostname gettimeofday memset select socket strtol getaddrinfo]) +AC_CHECK_FUNCS([SSL_library_init SSL_get_cipher_name SSL_get_cipher_version ERR_error_string ERR_get_error SSL_CTX_new SSL_CTX_set_cipher_list SSL_CTX_use_RSAPrivateKey_file SSL_CTX_use_certificate_file SSL_new SSL_clear SSL_write SSL_read SSL_accept SSL_set_fd SSL_connect SSL_load_error_strings SSL_get_error]) +AC_CHECK_FUNCS([compress uncompress]) +AC_CHECK_FUNCS([dlopen dlsym dlclose]) +AC_CHECK_FUNCS([getpwnam]) +AC_CHECK_FUNCS([inet_ntop getnameinfo]) + +AC_OUTPUT diff --git a/doc/afclient.1 b/doc/afclient.1 new file mode 100644 index 0000000..5cdd770 --- /dev/null +++ b/doc/afclient.1 @@ -0,0 +1,246 @@ +.TH afclient 1 "apf 0.6" Jeremian +.SH NAME +afclient \- active port forwarder client +.SH SYNOPSIS +.B afclient [ +.I options +.B ] -n +.I servername +.B -p +.I portnum +.SH DESCRIPTION +.B Afclient +is a port forwarding program designed to be efficient and easy to use. It connects to +.B afserver +to listenport (default listenport is 50126) and after a successful authorization +.B afclient +redirects all the data to the specified destination host:port. +.SH "EXAMPLES" +.B afclient -n servername -p 22 + program connects to servername:50126 and redirects data to local port 22 (becomes a daemon) + +.B afclient -n servername -p 22 -v + the same as above, but verbose mode is enabled (program won't enter daemon mode) + +.B afclient -n servername -r + program connects to servername:50126 in remote administration mode +.SH OPTIONS +.I "Basic options" + +.B -n, --servername NAME + name of the host, where +.I afserver +is running (required) + +.B -m, --manageport PORT + manage port number - server must be listening on it (default: 50126) + +.B -d, --hostname NAME + the name of this host/remote host - the final destination of the packets (default: the name returned by hostname function) + +.B -p, --portnum PORT + the port we are forwarding connection to (required) + +.B -h, --help + prints help screen + +.I Authorization + +.B -i, --id STRING + sends the id string to afserver + +.B --pass PASSWORD + set the password used for client identification (default: no password) + +.I Configuration + +.B -k, --keyfile FILE + the name of the file with RSA key (default: client.rsa) + +.B -D, --dateformat FORMAT + format of the date printed in logs (see 'man strftime' for details) (default: %d.%m.%Y %H:%M:%S) + +.I Modes + +.B -u, --udpmode + udp mode - client will use udp protocol to communicate with the hostname:portnum (-p) + +.B -U, --reverseudp + reverse udp forwarding. Udp packets will be forwarded from hostname:portnum (-p) to the server name:portnum (-m) + +.B -r, --remoteadmin + remote administration mode. (using '-p PORT' will force afclient to use port rather then stdin-stdout) + +.I Logging + +.B -O, --heavylog + logging everything to a logfile + +.B -o, --lightlog + logging some data to a logfile + +.B -S, --heavysocklog + logging everything to a localport + +.B -s, --lightsocklog + logging some data to a localport + +.B -v, --verbose + to be verbose - program won't enter the daemon mode (use several times for greater effect) + +.I "IP family" + +.B -4, --ipv4 + use ipv4 only + +.B -6, --ipv6 + use ipv6 only + +.I Modules + +.B -l, --load + load a module for user's packets filtering + +.B -L, --Load + load a module for service's packets filtering + +.SH "REMOTE ADMINISTRATION" + +Remote administration mode is enabled by +.B '-r, --remoteadmin' +option. Required options: +.B '-n, --servername NAME' + +After successful authorization stdin/stdout are used to communicate with user. All the commands parsing is done by +.BR afserver . +Commands guaranteed to be available: + +.B help + display help + +.B lcmd + lists available commands + +.B quit + quit connection + +For list of all available commands take a look at +.BR afserver (1). + +When +.B '-p, --portnum PORT' +is used, +.B afclient +listens for connection from user at NAME:PORT. NAME is set by +.B '-d, --hostname' +option or hostname() function, when the option is missing. + +When user quits (close the connection or send +.B 'quit' +command), +.B afclient +exits. + +.SH MODULES + +.B Afclient +can use external modules for user's packets filtering +.RB ( "'-l, --load'" ) +and service's packets filtering +.RB ( "'-L, --Load'" ). +Module file has to declare three functions: + +.BI "char* info(" void ); + + info() return values: + - info about module + + Example: + + char* + info(void) + { + return "Module tester v0.1"; + } + +.BI "int allow(char* " host ", char* " port ); + + allow() return values: + 0 - allow to connect + !0 - drop the connection + + Example: + + int + allow(char* host, char* port) + { + return 0; /* allow to connect */ + } + +.BI "int filter(char* " host ", unsigned char* " message ", int* " length ); + + filter() return values: + 0 - allow to transfer + 1 - drop the packet + 2 - drop the connection + 3 - release the module + 4 - drop the packet and release the module + 5 - drop the connection and release the module + + Example: + + int + filter(char* host, unsigned char* message, int* length) + { + int i; + for (i = 1; i < *length; ++i) { + if (message[i-1] == 'M') { + if (message[i] == '1') { + return 1; /* ignored */ + } + if (message[i] == '2') { + return 2; /* dropped */ + } + if (message[i] == '3') { + return 3; /* release */ + } + if (message[i] == '4') { + return 4; /* ignored + release */ + } + if (message[i] == '5') { + return 5; /* dropped + release */ + } + } + } + return 0; /* allow to transfer */ + } + +Modules have to be compiled with +.B -fPIC -shared +options. + +.SH "SEE ALSO" + +.BR afserver (1), +.BR afserver.conf (5) + +.SH BUGS + +.B Afclient +is still under development. There are no known open bugs at the moment. + +.SH "REPORTING BUGS" + +Please report bugs to + +.SH AUTHOR + +Jeremian + +.SH CONTRIBUTIONS + +Alex Dyatlov , Simon , Ilia Perevezentsev and Marco Solari + +.SH LICENSE + +Active Port Forwarder is distributed under the terms of the GNU General Public License v2.0 and is copyright (C) 2003,2004,2005 jeremian . See the file COPYING for details. diff --git a/doc/afserver.1 b/doc/afserver.1 new file mode 100644 index 0000000..0a39c2c --- /dev/null +++ b/doc/afserver.1 @@ -0,0 +1,175 @@ +.TH afserver 1 "apf 0.6" Jeremian +.SH NAME +afserver \- active port forwarder server +.SH SYNOPSIS +.B afserver [ +.I options +.B ] +.SH DESCRIPTION +.B Afserver +is a port forwarding program designed to be efficient and easy to use. It listens for incoming +.B afclient +connections at listenport (default listenport is 50126). After successful client authorization, +.B afserver +listens for incoming user connections. When a new user connection is opened, all the data is redirected to previously connected +.B afclient, +which redirects it to the specified destination host:port. +.SH EXAMPLES +.B afserver + program starts with default options (become a daemon) + +.B afserver -v + verbose mode is enabled (program won't enter daemon mode) + +.B afserver -n localhost -l 5435 -m 6375 + program will listen on localhost:5435 for users and on localhost:6375 for clients +.SH OPTIONS +.I "Basic options" + +.B -n, --hostname NAME + used when creating listening sockets (default: '') + +.B -l, --listenport PORT + listening port number - users connect to it (default: 50127) + +.B -m, --manageport PORT + manage port number - +.I afclient +connects to it (default: 50126) + +.B -h, --help + prints help screen + +.I Authorization + +.B --pass PASSWORD + password used for client identification (default: no password) + +.I Configuration + +.B -c, --cerfile FILE + the name of the file with certificate (default: cacert.pem) + +.B -k, --keyfile FILE + the name of the file with RSA key (default: server.rsa) + +.B -f, --cfgfile FILE + the name of the file with the configuration for the +.I afserver + +.B -D, --dateformat FORMAT + format of the date printed in logs (see 'man strftime' for details) (default: %d.%m.%Y %H:%M:%S) + +.B -t, --timeout N + the timeout value for the client's connection (default: 5) + +.B -u, --users N + the amount of users allowed to use this server (default: 5) + +.B -C, --clients N + the number of allowed clients to use this server (default: 1) + +.B -r, --realm + set the realm name (default: none) + +.B -R, --raclients N + the number of allowed clients in remote administration mode to use this server (default: 1) + +.B -U, --usrpcli N + the number of allowed users per client (default: $users) + +.B -M, --climode N + strategy used to connect users with clients (default: 1) + Available strategies: + 1. fill first client before go to next + +.B -p, --proto TYPE + type of server (tcp|udp) - what protocol it will be operating for (default: tcp) + +.B -b, --baseport + listenports are temporary and differ for each client + +.B --nossl + ssl is not used to transfer data (but it's still used to establish a connection) (default: ssl is used) + +.B --nozlib + zlib is not used to compress data (default: zlib is used) + +.B --dnslookups + try to obtain dns names of the computers rather than their numeric IP + +.I Logging + +.B -O, --heavylog + logging everything to a logfile + +.B -o, --lightlog + logging some data to a logfile + +.B -S, --heavysocklog + logging everything to a localport + +.B -s, --lightsocklog + logging some data to a localport + +.B -v, --verbose + to be verbose - program won't enter the daemon mode (use several times for greater effect) + +.I "IP family" + +.B -4, --ipv4 + use ipv4 only + +.B -6, --ipv6 + use ipv6 only + +.SH "REMOTE ADMINISTRATION" + +Currently available commands are: + +.B help + display help + +.B lcmd + lists available commands + +.B info + prints info about server + +.B rshow + display realms + +.B cshow X + display clients in X realm + +.B ushow X + display users in X realm + +.B quit + quit connection + +.SH "SEE ALSO" + +.BR afclient (1), +.BR afserver.conf (5) + +.SH BUGS + +.B Afserver +is still under development. There are no known open bugs at the moment. + +.SH "REPORTING BUGS" + +Please report bugs to + +.SH AUTHOR + +Jeremian + +.SH CONTRIBUTIONS + +Alex Dyatlov , Simon , Ilia Perevezentsev and Marco Solari + +.SH LICENSE + +Active Port Forwarder is distributed under the terms of the GNU General Public License v2.0 and is copyright (C) 2003,2004,2005 jeremian . See the file COPYING for details. diff --git a/doc/afserver.conf.5 b/doc/afserver.conf.5 new file mode 100644 index 0000000..b15bf2d --- /dev/null +++ b/doc/afserver.conf.5 @@ -0,0 +1,126 @@ +.TH afserver.conf 5 "apf 0.6" Jeremian +.SH NAME +afserver.conf \- Configuration File for afserver +.SH INTRODUCTION +.B Afserver +supports several mechanisms to supply configuration and run-time parameters: command line options, +.B afserver.conf +and hard-coded defaults. When the same information is supplied in more than one way, the highest precedence mechanism is used. When configuration file is used (option: +.IR "-f FILE") +command line options like +.IR --hostname , +.IR --listenport , +.I --manageport +and +.I --pass +are ignored. Options from configuration file are taken before values from command line. When something is not declared, hard-coded values are used. + +.SH DESCRIPTION +.B Afserver +uses configuration file, which name is supplied by the +.I -f FILE +option. The +.B afserver.conf +file is composed of two sections which have to be in fixed order. In first section global values like certificates, keys and logging options are set. The second section starts with first +.B newrealm +command and includes options describing specific realms. There may be several +.B newrealm +commands. + +.SH "GLOBAL OPTIONS" + +.B certificate FILE + the name of the file with certificate (default: cacert.pem) + +.B key FILE + the name of the file with RSA key (default: server.rsa) + +.B lightlog FILE + logging some data to a logfile + +.B heavylog FILE + logging everything to a logfile + +.B heavysocklog PORT + logging everything to a localport + +.B lightsocklog PORT + logging some data to a localport + +.B dateformat FORMAT + format of the date printed in logs (see 'man strftime' for details) (default: %d.%m.%Y %H:%M:%S). Format string is trimmed. In order to include white characters into format string, use dots to mark beginning and end of the text. If the dot is first or last character, it's removed. Only one character from the beginning and one from the end can be removed. + +.SH "REALM OPTIONS" + +.B realm [NAME] + starts configuration of the next realm. Name of the realm can be specified using this option. + +.B hostname NAME + used when creating listening sockets (default: '') + +.B listen PORT + listening port number - users connect to it (required at least one) + +.B manage PORT + manage port number - afclient connects to it (required at least one) + +.B pass PASSWORD + password used for client identification (default: no password) + +.B users N + the amount of users allowed to use this server (default: 5) + +.B timeout N + the timeout value for the client's connection (default: 5) + +.B clients N + the number of allowed clients to use this server (default: 1) + +.B raclients N + the number of allowed clients in remote administration mode to use this server (default: 1) + +.B usrpcli N + the number of allowed users per client (default: $users) + +.B climode N + strategy used to connect users with clients (default: 1) + Available strategies: + 1. fill first client before go to next + +.B proto TYPE + type of server (tcp|udp) - what protocol it will be operating for (default: tcp) + +.B nossl + ssl is not used to transfer data (but it's still used to establish a connection) (default: ssl is used) + +.B nozlib + zlib is not used to compress data (default: zlib is used) + +.B baseport + listenports are temporary and differ for each client + +.B dnslookups + try to obtain dns names of the computers rather than their numeric IP + +.B ipv4 + use ipv4 only + +.B ipv6 + use ipv6 only + +.SH "SEE ALSO" + +.BR afclient (1), +.BR afserver (1) + +.SH AUTHOR + +Jeremian + +.SH CONTRIBUTIONS + +Alex Dyatlov , Simon , Ilia Perevezentsev and Marco Solari + +.SH LICENSE + +Active Port Forwarder is distributed under the terms of the GNU General Public License v2.0 and is copyright (C) 2003,2004,2005 jeremian . See the file COPYING for details. diff --git a/doc/afserver_example.conf b/doc/afserver_example.conf new file mode 100644 index 0000000..2046b03 --- /dev/null +++ b/doc/afserver_example.conf @@ -0,0 +1,57 @@ +# This is an example configuration file for active port forwarder +# Firstly, we have to declare our files with key and certificate + +certificate cacert.pem + +# Please note, that we can place only blank characters between words + +key server.rsa + +# when we want to log some information, we specify file for lightlog +# when we want to log everything - we do this by using heavylog option + +# type name of file + +lightlog logfile +#heavylog logfile + +# we we could also want to use sockets instead of files + +# type port (on localhost) + +#lightsocklog 12345 +#heavysocklog 12345 + +#dateformat %d.%m.%Y %H:%M:%S + +# And it's time to create forwarding targets (named realms here) + +#realm indicates a new set of commands to a server +#realmname is optional +realm my realm + +#options values + +#hostname #this is the name of the server (used to choose interface) +listen 50127 #portnumber on which server is listening for users +manage 50126 #portnumber on which server is listening for afclient +#users 5 #amount of users we are allowing to connect (>0) (default: 5) +#timeout 5 #timeout value for the client's connection (>0) (default: 5) +#clients 1 #number of allowed clients for this realm (>0) (default: 1) +#usrpcli $users #allowed users per client for this realm (>0) (default: $users) +#climode 1 #strategy used for connecting users with clients (1) (default: 1) +#proto tcp #type of the realm (which protocol it will forward (tcp|udp) (default: tcp) +#pass mypassword #this is a password used for client identification +#raclients 1 #number of allowed clients in remote administration mode (>0) (default: 1) +#nossl #don't use ssl for data transfer +#nozlib #don't use zlib +#baseport #listenports are temporary and differ for each client +#dnslookups #try to obtain dns names of the computers +#ipv4 #use ipv4 only +#ipv6 #use ipv6 only + +# and now the second realm + +realm +listen 50125 +manage 50124 diff --git a/doc/en/README b/doc/en/README new file mode 100644 index 0000000..0e49c3e --- /dev/null +++ b/doc/en/README @@ -0,0 +1,479 @@ +AF - Active Port Forwarder 0.6 - README +Copyright (C) 2003,2004,2005 jeremian - +================================================================= + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +====================================== + + The Active Port Forwarder program is part of the Gray-World.net projects. + + Our Gray-World Team presents on the http://gray-world.net website the projects + and publications we are working on which are related to the NACS (Network + Access Control System) bypassing research field and to the computer and + network security topics. + +================================================================================ + +======= +SUMMARY +======= + +INTRO + +1. INSTALLATION + 1.1 Instructions + 1.2 Required libs + 1.3 Tested platforms +2. USAGE + 2.1 afserver + 2.2 afclient +3. REMOTE ADMINISTRATION +4. MODULES +5. EXAMPLES + 5.1 tcp mode + 5.2 reverse udp mode +6. BUGS/PROBLEMS + +NOTES + +THANKS + +================================================================================ + +===== +INTRO +===== + +Active port forwarder is a software tool for secure port forwarding. +It uses ssl to increase security of communication between a server and a client. +Originally, it was developed to forward data point to point. However, the need +for bypassing firewalls in order to connect to internally located computers +influenced the further development of the project. + +AF is dedicated for people, who don't have an external ip number and want to +make some services available across the net. + +Moreover, zlib is used to compress the transferred data. + +Using one, permanent data/control channel with flow control / packet buffering +provides good performance and reasonably small latency. + +Multiple clients allow to create more sophisticated tunneling scheme. + +================================================================================ + +=============== +1. INSTALLATION +=============== + + 1.1 Instructions + ---------------- + +1. Download the compressed sources from http://www.gray-world.net/pr_af.shtml +2. Unpack them with tar zxvf +3. Type "./configure" +4. Type "make" +5. Type "make install" while logged as root +6. If something goes wrong - mail the author or post a message on + http://gray-world.net/board/ + + 1.2 Required libs + ----------------- + +1. openssl - http://www.openssl.org/ +2. zlib - http://www.gzip.org/zlib/ + + 1.3 Tested platforms + -------------------- + +1. Linux: + Gentoo, Slackware, Mandrake - built without any problems +2. Windows: + win32 - cygwin version is available on the project homepage + +================================================================================ + +======== +2. USAGE +======== + + 2.1 afserver + ------------ + + Basic options: + + -n, --hostname - it's used when creating listening sockets + (default: '') + -l, --listenport - listening port number - users connect + to it (default: 50127) + -m, --manageport - manage port number - second part of the active + port forwarder connects to it (default: 50126) + -h, --help - prints this help + + Authorization: + + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -c, --cerfile - the name of the file with certificate + (default: cacert.pem) + -k, --keyfile - the name of the file with RSA key (default: server.rsa) + -f, --cfgfile - the name of the file with the configuration for the + active forwarder (server) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + + -t, --timeout - the timeout value for the client's connection + (default: 5) + -u, --users - the amount of users allowed to use this server + (default: 5) + -C, --clients - the number of allowed clients to use this server + (default: 1) + -r, --realm - set the realm name (default: none) + -R, --raclients - the number of allowed clients in remote administration + mode to use this server (default: 1) + -U, --usrpcli - the number of allowed users per client (default: $users) + -M, --climode - strategy used for connecting users with clients + (default: 1) + Available strategies: + 1. fill first client before go to next + + -p, --proto - type of server (tcp|udp) - for which protocol it will + be operating (default: tcp) + -b, --baseport - listenports are temporary and differ for each client + --nossl - ssl is not used for transferring data (but it's still + used to establish a connection) (default: ssl is used) + --nozlib - zlib is not used for compressing data (default: + zlib is used) + --dnslookups - try to obtain dns names of the computers rather than + their numeric IP + + Logging: + + -O, --heavylog - logging everything to a logfile + -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport + -v, --verbose - to be verbose - program won't enter the daemon mode + (use several times for greater effect) + + IP family: + + -4, --ipv4 - use ipv4 only + -6, --ipv6 - use ipv6 only + + 2.2 afclient + ------------ + + Basic options: + + -n, --servername - where the second part of the active + port forwarder is running (required) + -m, --manageport - manage port number - server must be + listening on it (default: 50126) + -d, --hostname - the name of this host/remote host - the final + destination of the packets (default: the name + returned by hostname function) + -p, --portnum - the port we are forwarding connection to (required) + -h, --help - prints this help + + Authorization: + + -i, --id - send the id string to afserver + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -k, --keyfile - the name of the file with RSA key (default: client.rsa) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + + Modes: + + -u, --udpmode - udp mode - client will use udp protocol to + communicate with the hostname + -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded + from hostname:portnum (-p) to the server name:portnum + (-m) + -r, --remoteadmin - remote administration mode. (using '-p #port' will + force afclient to use port rather then stdin-stdout) + + Logging: + + -O, --heavylog - logging everything to a logfile + -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport + -v, --verbose - to be verbose - program won't enter the daemon mode + (use several times for greater effect) + + IP family: + + -4, --ipv4 - use ipv4 only + -6, --ipv6 - use ipv6 only + + Modules: + + -l, --load - load a module for user's packets filtering + -L, --Load - load a module for service's packets filtering + +================================================================================ + +======================== +3. REMOTE ADMINISTRATION +======================== + +Afclient can be started in remote administration mode by '-r, --remoteadmin' +option. Required option: '-n, --servername NAME'. + +After successful authorization stdin/stdout is used to communicate with user. +All the commands parsing is done by afserver. + +Currently available commands are: + + help + display help + + lcmd + lists available commands + + info + prints info about server + + rshow + display realms + + cshow X + display clients in X realm + + ushow X + display users in X realm + + quit + quit connection + +Afclient with '-p, --portnum PORT' option listens for connection from user at +NAME:PORT. NAME is set by '-d, --hostname' option or hostname() function, when +the option is missing. + +When user quits (close the connection or send 'quit' command), afclient exits. + +================================================================================ + +========== +4. MODULES +========== + +Afclient can use external modules for user's packets filtering ('-l, --load') +and service's packets filtering ('-L, --Load'). Module file has to declare three +functions: + +char* info(void); + + info() return values: + - info about module + + Example: + + char* + info(void) + { + return "Module tester v0.1"; + } + +int allow(char* host, char* port); + + allow() return values: + 0 - allow to connect + !0 - drop the connection + + Example: + + int + allow(char* host, char* port) + { + return 0; /* allow to connect */ + } + +int filter(char* host, unsigned char* message, int* length); + + filter() return values: + 0 - allow to transfer + 1 - drop the packet + 2 - drop the connection + 3 - release the module + 4 - drop the packet and release the module + 5 - drop the connection and release the module + + Example: + + int + filter(char* host, unsigned char* message, int* length) + { + int i; + for (i = 1; i < *length; ++i) { + if (message[i-1] == 'M') { + if (message[i] == '1') { + return 1; /* ignored */ + } + if (message[i] == '2') { + return 2; /* dropped */ + } + if (message[i] == '3') { + return 3; /* release */ + } + if (message[i] == '4') { + return 4; /* ignored + release */ + } + if (message[i] == '5') { + return 5; /* dropped + release */ + } + } + } + return 0; /* allow to transfer */ + } + +Modules have to be compiled with '-fPIC -shared' options. + +================================================================================ + +=========== +5. EXAMPLES +=========== + + 5.1 tcp mode + ------------ + + local network |FireWall| Internet + || + || User 1 + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | \(tcp) + /(tcp) || (tcp)| User 2 + / || \ + Http server || User 3 + || + + +The use of it is extremely simple. Let's suppose we want to create a http server +on our computer and we are behind a masquerade or a firewall: + +1) We have to find some machine on the net with an external ip and a shell + account. + +2) Use "make" to compile everything on that machine. (you can freely remove the + afclient and client.rsa files) + +3) You can edit the config file or just type from the console (to use the config + type -f ) : + $ ./afserver + This will work, if you want to use default values: + - hostname will be taken from hostname function (it would be ideally, if + there is appropriate registration in /etc/hosts) + - server will be listening for users on port 50127 + - server will be listening for client on port 50126 + - server will be for maximum 5 users + - server will forward tcp packets + - there will be no logging and no verbose messages + - there will be no password identification + - ip protocol family will be unspecified + +4) We use "make" on our machine (we can delete everything apart from afclient + and client.rsa) + +5) We are typing from the console: + $ ./afclient -n -p 80 + Where is a string like : 'bastion.univ.gda.pl' or + '153.19.7.200' + +6) We can now enter with a web-browser to: :50127 and we + will enter to our computer in the fact. + + 5.2 reverse udp mode + -------------------- + + local network |FireWall| Internet + || (udp) + || User 1-------AF Client + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | + /(udp) || (tcp)| + / || / + Game server || AF Client-------User 2 + || (udp) + + +Let's see how to use af to forward udp packets. Suppose we want to create a game +server on our computer (udp port 27960 on our machine): + +1) - 4) is the same like in example 1. (but we add option: -p udp) + +5) We are typing from the console: + $ ./afclient -u -n -p 27960 + Where is a name (or ip) of a host where our server is + running. + +6) Connecting to our game is more complicated. The user must use afclient to do + this. He has to specify the server he is connecting to and the port, which + his program will be listening on: + $ ./afclient -U -d -p -n \ + -m + Where is the name of the user machine (who wants to connect to our + game). is the port he will be connecting to. + is the name of the host where our server is running. is the + port on which the server is listening for users. In order to connect to our + game, the user has to connect to :. + +================================================================================ + +================ +6. BUGS/PROBLEMS +================ + +There are no known/open bugs at the moment. + +================================================================================ + +===== +NOTES +===== + +Active port forwarder is still under development, so please sent any comments, +bugs notices and suggestions about it to + +If you have some problems or want to share your opinions with others, feel free +to post a message at http://gray-world.net/board/ + +================================================================================ + +====== +THANKS +====== + + Big thanks to the GW Team: + + to Alex + and Simon for testing AF and a lot of advices. + + Thanks to Ilia Perevezentsev who read and corrected the +README file. + + Thanks to Marco Solari for a lot of +requests, suggestions and ideas. + + And thanks for using this software! + +LICENSE +------- + + Active Port Forwarder is distributed under the terms of the GNU General + Public License v2.0 and is copyright (C) 2003,2004,2005 jeremian . See the file COPYING for details. + diff --git a/doc/fr/fr_README b/doc/fr/fr_README new file mode 100644 index 0000000..1366291 --- /dev/null +++ b/doc/fr/fr_README @@ -0,0 +1,488 @@ +AF - Active Port Forwarder 0.6 - README +Copyright (C) 2003,2004,2005 jeremian - +================================================================= + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +====================================== + + Le programme Active Port Forwarder est partie intégrante des projets + Gray-World.net. + + Notre équipe présente sur le site http://gray-world.net les projets et + publications sur lesquels nous travaillons. Ces projets et publications sont + relatifs au contournement des systèmes de contrôle d'accès réseau (NACS + bypassing) ainsi qu'à la sécurité des systèmes et réseaux. + +================================================================================ + +======== +SOMMAIRE +======== + +INTRO + +1. INSTALLATION + 1.1 Instructions + 1.2 Librairies requises + 1.3 Plate-formes testées +2. USAGE + 2.1 afserver + 2.2 afclient +3. ADMINISTRATION DISTANTE +4. MODULES +5. EXEMPLES + 5.1 tcp mode + 5.2 reverse udp mode +6. BUGS/PROBLEMES + +NOTES + +THANKS + +================================================================================ + +===== +INTRO +===== + +Active port forwarder est un programme permettant de réaliser du forwarding de +port sécurisé. Il utilise le protocole SSL pour augmenter le niveau de sécurité +des communications entre serveur et client. Son développement initial comme +outil de communication point à point a été influencé de façon à permettre le +contournement de firewalls et les communications à destination d'équipements +localisés sur le réseau interne. + +Af est destiné aux personnes sans adresse IP publique externe qui désirent +offrir des services accessibles depuis le net. + +La librairie Zlib est de plus employée pour compresser les données transférées. + +L'utilisation d'un canal contrôle/données permanent avec une gestion de flux et +une mise en cache des paquets fournit de bonnes performances et un temps de +latence raisonnablement court. + +L'emploi de clients multiples permet la création de schémas de tunneling plus +sophistiqués. + +================================================================================ + +=============== +1. INSTALLATION +=============== + + 1.1 Instructions + ---------------- + +1. Télécharger les sources compressées depuis www.gray-world.net/pr_af.shtml +2. Décompresser avec tar zxvf +3. Entrer "./configure" +4. Entrer "make" +5. Entrer "make install" sous l'identité root +6. Si un problème survient - envoyez un mail à l'auteur ou postez un message + sur http://gray-world.net/board/ + + 1.2 Librairies requises + ----------------------- + +1. openssl - http://www.openssl.org/ +2. zlib - http://www.gzip.org/zlib/ + + 1.3 Plate-formes testées + ------------------------ + +1. Linux: + Gentoo, Slackware, Mandrake - Compilation sans problème +2. Windows: + win32 - Version cygwin disponible sur la page du projet + +================================================================================ + +======== +2. USAGE +======== + + 2.1 afserver + ------------ + + Basic options: + + -n, --hostname - it's used when creating listening sockets + (default: '') + -l, --listenport - listening port number - users connect + to it (default: 50127) + -m, --manageport - manage port number - second part of the active + port forwarder connects to it (default: 50126) + -h, --help - prints this help + + Authorization: + + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -c, --cerfile - the name of the file with certificate + (default: cacert.pem) + -k, --keyfile - the name of the file with RSA key (default: server.rsa) + -f, --cfgfile - the name of the file with the configuration for the + active forwarder (server) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + + -t, --timeout - the timeout value for the client's connection + (default: 5) + -u, --users - the amount of users allowed to use this server + (default: 5) + -C, --clients - the number of allowed clients to use this server + (default: 1) + -r, --realm - set the realm name (default: none) + -R, --raclients - the number of allowed clients in remote administration + mode to use this server (default: 1) + -U, --usrpcli - the number of allowed users per client (default: $users) + -M, --climode - strategy used for connecting users with clients + (default: 1) + Available strategies: + 1. fill first client before go to next + + -p, --proto - type of server (tcp|udp) - for which protocol it will + be operating (default: tcp) + -b, --baseport - listenports are temporary and differ for each client + --nossl - ssl is not used for transferring data (but it's still + used to establish a connection) (default: ssl is used) + --nozlib - zlib is not used for compressing data (default: + zlib is used) + --dnslookups - try to obtain dns names of the computers rather than + their numeric IP + + Logging: + + -O, --heavylog - logging everything to a logfile + -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport + -v, --verbose - to be verbose - program won't enter the daemon mode + (use several times for greater effect) + + IP family: + + -4, --ipv4 - use ipv4 only + -6, --ipv6 - use ipv6 only + + 2.2 afclient + ------------ + + Basic options: + + -n, --servername - where the second part of the active + port forwarder is running (required) + -m, --manageport - manage port number - server must be + listening on it (default: 50126) + -d, --hostname - the name of this host/remote host - the final + destination of the packets (default: the name + returned by hostname function) + -p, --portnum - the port we are forwarding connection to (required) + -h, --help - prints this help + + Authorization: + + -i, --id - send the id string to afserver + --pass - set the password used for client identification + (default: no password) + + Configuration: + + -k, --keyfile - the name of the file with RSA key (default: client.rsa) + -D, --dateformat - format of the date printed in logs (see 'man strftime' + for details) (default: %d.%m.%Y %H:%M:%S) + + Modes: + + -u, --udpmode - udp mode - client will use udp protocol to + communicate with the hostname + -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded + from hostname:portnum (-p) to the server name:portnum + (-m) + -r, --remoteadmin - remote administration mode. (using '-p #port' will + force afclient to use port rather then stdin-stdout) + + Logging: + + -O, --heavylog - logging everything to a logfile + -o, --lightlog - logging some data to a logfile + -S, --heavysocklog - logging everything to a localport + -s, --lightsocklog - logging some data to a localport + -v, --verbose - to be verbose - program won't enter the daemon mode + (use several times for greater effect) + + IP family: + + -4, --ipv4 - use ipv4 only + -6, --ipv6 - use ipv6 only + + Modules: + + -l, --load - load a module for user's packets filtering + -L, --Load - load a module for service's packets filtering + +================================================================================ + +========================== +3. ADMINISTRATION DISTANTE +========================== + +Afclient peut être démarré en mode d'administration distante avec l'option '-r, +--remoteadmin'. L'option requise est: '-n, --servername NAME'. + +Après autorisation, les flux stdin/stdout sont utilisés pour communiquer avec +l'utilisateur. La prise en compte des commandes est effectuée par afserver. + +Les commandes disponibles sont: + + help + display help + + lcmd + lists available commands + + info + prints info about server + + rshow + display realms + + cshow X + display clients in X realm + + ushow X + display users in X realm + + quit + quit connection + +Afclient se positionne en écoute sur NAME:PORT avec '-p, --portnum PORT'. NAME +est positionné avec l'option '-d, --hostname' ou par la fonction hostname() si +l'argument n'est pas fourni. + +Quand l'utilisateur quitte (termine la connexion ou envoie la commande 'quit'), +afclient se termine. + +================================================================================ + +========== +4. MODULES +========== + +Afclient peut utiliser des modules externes pour le filtrage des paquets ('-l, + --load') utilisateurs et pour le filtrage des paquets service ('-L, --Load'). +Le fichier contenant les modules doit déclarer trois fonctions : + +char* info(void); + + info() return values: + - info about module + + Example: + + char* + info(void) + { + return "Module tester v0.1"; + } + +int allow(char* host, char* port); + + allow() return values: + 0 - allow to connect + !0 - drop the connection + + Example: + + int + allow(char* host, char* port) + { + return 0; /* allow to connect */ + } + +int filter(char* host, unsigned char* message, int* length); + + filter() return values: + 0 - allow to transfer + 1 - drop the packet + 2 - drop the connection + 3 - release the module + 4 - drop the packet and release the module + 5 - drop the connection and release the module + + Example: + + int + filter(char* host, unsigned char* message, int* length) + { + int i; + for (i = 1; i < *length; ++i) { + if (message[i-1] == 'M') { + if (message[i] == '1') { + return 1; /* ignored */ + } + if (message[i] == '2') { + return 2; /* dropped */ + } + if (message[i] == '3') { + return 3; /* release */ + } + if (message[i] == '4') { + return 4; /* ignored + release */ + } + if (message[i] == '5') { + return 5; /* dropped + release */ + } + } + } + return 0; /* allow to transfer */ + } + +Les modules doivent être compilés avec les options '-fPIC -shared'. + +================================================================================ + +=========== +5. EXEMPLES +=========== + + 5.1 tcp mode + ------------ + + local network |FireWall| Internet + || + || User 1 + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | \(tcp) + /(tcp) || (tcp)| User 2 + / || \ + Http server || User 3 + || + + +L'utilisation de Af est extrèmement simple. Supposons que nous voulons mettre en +place un serveur http sur notre station et que nous sommes masqueradés ou placé +derrière un firewall: + +1) Nous devons tout d'abord trouver une station sur internet avec une IP +publique et un shell. + +2) Utilisez ensuite make pour compiler Af sur cette machine. (Vous pouvez par la +suite supprimer les fichiers afclient et client.rsa) + +3) Editez le fichier de configuration ou entrez sur la console: (pour utiliser +la configuration, entrez type -f ) + $ ./afserver + Si vous voulez utiliser les valeurs par défaut: + - Le nom d'hôte sera pris en compte par la fonction hostname (Il serait idéal + qu'il soit référencé dans le fichier /etc/hosts) + - Le serveur sera en écoute pour les utilisateurs sur le port 50127 + - Le serveur sera en écoute pour le client sur le port 50126 + - Le serveur sera limité à 5 utilisateurs + - Le serveur retransmettra les paquets tcp + - Aucun log ou message verbeux ne sera activé + +4) Nous utilisons make sur notre propre station (Nous pouvons ensuite supprimer +tous les fichiers sauf afclient et client.rsa) + +5) Nous entrons sur la console: + $ ./afclient -n -p 80 + Où est une chaîne du type : 'bastion.univ.gda.pl' ou + '153.19.7.200' + +6) Nous pouvons ensuite utiliser notre navigateur web avec : + :50127 et nous atteindrons notre propre station. + + 5.2 reverse udp mode + -------------------- + + local network |FireWall| Internet + || (udp) + || User 1-------AF Client + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | + /(udp) || (tcp)| + / || / + Game server || AF Client-------User 2 + || (udp) + + +Regardons comment nous pouvons utiliser af pour forwarder des paquets udp. +Supposez que nous voulons mettre en place un serveur de jeu sur notre station +(port udp 27960 sur notre station): + +1) - 4) sont les mêmes que pour l'exemple 1. + +5) Nous entrons sur la console: + $ ./afclient -u -n -p 27960 + Où est un nom (ou une ip) d'un hôte sur lequel notre + serveur tourne. + +6) Nous connecter à notre jeu est un peu plus compliqué. L'utilisateur doit se + servir de afclient pour cela. + Il doit spécifier le serveur auquel il veut se connecter et le port sur + lequel son programme sera en écoute: + $ ./afclient -U -d -p -n -m\ + + Où est le nom de la station utilisateur (qui veut se connecter à + notre jeu). est le port auquel il se connectera. est le nom de l'hôte sur lequel notre serveur tourne. + est le port sur lequel notre serveur est en écoute pour les utilisateurs. + Pour se connecter à notre jeu, l'utilisateur doit se connecter à : + . + +================================================================================ + +================ +6. BUGS/PROBLEMS +================ + +Aucun bug n'est connu ou en cours de résolution à ce moment. + +================================================================================ + +===== +NOTES +===== + +Active port forwarder est toujours en phase en développement, alors envoyez moi +vos commentaires, les bugs que vous rencontrez et vos suggestions à + + +Si vous rencontrez des problèmes ou voulez partager vos opinions , vous pouvez +poster un message sur le forum http://gray-world.net/board/. + +================================================================================ + +====== +THANKS +====== + + Remerciements à l'équipe GW: + + à Alex + et Simon pour les tests de AF et de nombreux +conseils. + + Merci à Ilia Perevezentsev qui a lu et corrigé le +fichier README. + + Merci à Marco Solari pour de nombreuses +requêtes, suggestions et idées. + + Et merci à vous pour l'utilisation de cet outil. + +LICENCE +------- + + Active Port Forwarder est distribué sous les termes de la licence GNU - + General Public Licence version 2.0 et est copyright (c)2003,2004,2005 jeremian + . + Consultez le fichier COPYING pour plus de details. diff --git a/doc/ru/ru_README b/doc/ru/ru_README new file mode 100644 index 0000000..4e825f7 --- /dev/null +++ b/doc/ru/ru_README @@ -0,0 +1,294 @@ +AF - Active Port Forwarder v0.5.4 - README +Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm> +=================== + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +========================== + + Ïðîãðàììà Active Port Forwarder ÿâëÿåòñÿ ÷àñòüþ ïðîåêòà Gray-World.net. + + Íàøà êîìàíäà Gray-World ïðåäñòàâëÿåò íà ñàéòå http://gray-world.net ïðîåêòû è + ïóáëèêàöèè, íàä êîòîðûìè ìû ðàáîòàåì, îòíîñÿùèåñÿ ê îáëàñòè èññëåäîâàíèÿ + NACS (Ñèñòåì Êîíòðîëÿ Ñåòåâîãî Äîñòóïà), à òàêæå ê òåìå êîìïüþòåðíîé è + ñåòåâîé áåçîïàñíîñòè. + +================================================================================ + +========== +ÑÎÄÅÐÆÀÍÈÅ +========== + +ÎÏÈÑÀÍÈÅ + +1. ÓÑÒÀÍÎÂÊÀ + 1.1 Èíñòðóêöèè + 1.2 Íåîáõîäèìûå áèáëèîòåêè + 1.3 Òåñòîâûå ïëàòôîðìû +2. ÈÑÏÎËÜÇÎÂÀÍÈÅ + 2.1 afserver + 2.2 afclient +3. ÏÐÈÌÅÐÛ + 3.1 tcp-ðåæèì + 3.2 îáðàòíûé udp-ðåæèì +4. ÈÇÂÅÑÒÍÛÅ ÎØÈÁÊÈ/ÏÐÎÁËÅÌÛ + +ÇÀÌÅ×ÀÍÈß + +ÁËÀÃÎÄÀÐÍÎÑÒÈ + +================================================================================ + +======== +ÎÏÈÑÀÍÈÅ +======== + +Active port forwarder ýòî ïðîãðàììíûé èíñòðóìåíò äëÿ áåçîïàñíîãî òóíåëèðîâàíèÿ +äàííûõ. Îí èñïîëüçóåò SSL äëÿ çàùèòû ñîåäèíåíèÿ ìåæäó êëèåíòîì è ñåðâåðîì. +Èçíà÷àëüíî, ïðîãðàììà áûëà ðàçðàáîòàíà äëÿ ïðîñòîé ïåðåñûëêè äàííûõ îò òî÷êè ê +òî÷êå. Îäíàêî íåîáõîäèìîñòü îáõîäà áðàíäìàóýðà ñ öåëüþ ñäåëàòü êîìïüþòåðû +ëîêàëüíîé ñåòè äîñòóïíûìè èçâíå, ïîâëèÿëà íà äàëüíåéøåå ðàçâèòèå ïðîåêòà. + +AF ïðåäíàçíà÷åí äëÿ ëþäåé, íå èìåþùèõ âíåøíåãî IP àäðåñà è êîòîðûå õîòÿò ñäåëàòü +íåêîòîðûå ëîêàëüíûå ñåðâèñû äîñòóïíûìè â ñåòè. + + ïðîãðàììå èñïîëüçîâàíà áèáëèîòåêà zlib äëÿ ñæàòèÿ ïåðåäàâàåìûõ äàííûõ. + +Èñïîëüçîâàíèå åäèíîãî êàíàëà äëÿ ïåðåäà÷è äàííûõ è êîìàíä óïðàâëåíèÿ â ñî÷åòàíèè +ñ áóôåðèçàöèåé ïåðåñûëàåìûõ ïàêåòîâ îáåñïå÷èâàåò õîðîøóþ ïðîèçâîäèòåëüíîñòü è +ìàëîå âðåìÿ îòêëèêà ñèñòåìû. + +Äëÿ çàïóñêà afserver íå òðåáóåòñÿ ïðèâèëåãèé root, òàêæå îí íå èñïîëüçóåò +thread-û èëè äðóãèå ïðîöåññû. + +================================================================================ + +============ +1. ÓÑÒÀÍÎÂÊÀ +============ + + 1.1 Èíñòðóêöèè + -------------- + +1. Çàãðóçèòå óïàêîâàííûé èñõîäíûé êîä ñ http://www.gray-world.net/pr_af.shtml +2. Ðàñïàêóéòå - tar zxvf +3. Âûïîëíèòå êîìàíäó "make". +4. Åñëè ÷òî-òî ïîøëî íå òàê - íàïèøèòå ïèñüìî àâòîðó èëè îñòàâüòå ñîîáùåíèå íà + http://gray-world.net/board/ + + 1.2 Íåîáõîäèìûå áèáëèîòåêè + -------------------------- + +1. openssl - http://www.openssl.org/ +2. zlib - http://www.gzip.org/zlib/ + + 1.3 Òåñòîâûå ïëàòôîðìû + ---------------------- + +1. Linux: + Gentoo, Slackware, Mandrake - áûëî ñîáðàíî áåç êàêèõ-ëèáî ïðîáëåì +2. Freebsd: + 4.4, 4.9 - Íåîáõîäèì patch ñ äîìàøíåé ñòðàíèöû ïðîåêòà +3. Windows: + win32 - Âåðñèÿ ñ cygwin äîñòóïíà íà äîìàøíåé ñòðàíèöå ïðîåêòà + +================================================================================ + +================ +2. ÈÑÏÎËÜÇÎÂÀÍÈÅ +================ + + 2.1 afserver + ------------ + + Ïàðàìåòðû: + -h, --help - ïå÷àòàåò ýòó ñïðàâêó + -n, --hostname - èñïîëüçóåòñÿ ïðè ñîçäàíèè "ñëóøàþùèõ" ñîêåòîâ + (ïî óìîë÷àíèþ: èìÿ âîçâðàùàåìîå ôóíêöèåé hostname) + -l, --listenport - ïîðò ñåðâåðà - ïîëüçîâàòåëè ñîåäèíÿþòñÿ + ñ íèì (ïî óìîë÷àíèþ: 50127) + -m, --manageport - ïîðò äëÿ óïðàâëåíèÿ - äðóãàÿ ÷àñòü active + port forwarder ñîåäèíÿåòñÿ ñ íèì (ïî óìîë÷àíèþ: 50126) + -u, --users - êîëè÷åñòâî ïîëüçîâàòåëåé, èñïîëüçóþùèõ ñåðâåð + (ïî óìîë÷àíèþ: 5) + -c, --cerfile - èìÿ ôàéëà ñ ñåðòèôèêàòîì + (ïî óìîë÷àíèþ: cacert.pem) + -k, --keyfile - èìÿ ôàéëà ñ êëþ÷îì RSA (ïî óìîë÷àíèþ: server.rsa) + -f, --cfgfile - èìÿ ôàéëà ñ êîíôèãóðàöèåé äëÿ active forwarder (ñåðâåð) + -p, --proto - òèï ñåðâåðà (tcp|udp) - ñ êàêèì ïðîòîêîëîì îí áóäåò + ðàáîòàòü (ïî óìîë÷àíèþ: tcp) + -O, --heavylog - ïèñàòü âñå ñîîáùåíèÿ â logfile + -o, --lightlog - ïèñàòü íåêîòîðûå ñîîáùåíèÿ â logfile + -v, --verbose - âûâîä ñîîáùåíèé â êîíñîëü - ïðîãðàìà íå áóäåò ðàáîòàòü + êàê daemon. + --nossl - ïðîòîêîë ssl íå áóäåò èñïîëüçîâàí äëÿ ïåðåäà÷è äàííûõ (íî + áóäåò èñïîëüçîâàí äëÿ óñòàíîâêè ñîåäèíåíèé) (ïî óìîë÷àíèþ: + ssl èñïîëüçóåòñÿ âñåãäà) + --nozlib - zlib íå áóäåò èñïîëüçîâàòüñÿ äëÿ ñæàòèÿ äàííûõ + (ïî óìîë÷àíèþ: zlib èñïîëüçóåòñÿ) + --pass - çàäàòü ïàðîëü äëÿ èäåíòèôèêàöèè êëèåíòà + (ïî óìîë÷àíèþ: íåò ïàðîëÿ) + -4, --ipv4 - èñïîëüçîâàòü òîëüêî ipv4 + -6, --ipv6 - èñïîëüçîâàòü òîëüêî ipv6 + + 2.2 afclient + ------------ + + Options: + -h, --help - ïå÷àòàåò ýòó ñïðàâêó + -n, --servername - ãäå ðàáîòàåò âòîðàÿ ÷àñòü active port + forwarder (íåîáõîäèìî) + -m, --manageport - ïîðò äëÿ óïðàâëåíèÿ - ñåðâåð ñîåäèíÿåòñÿ ñ íèì + (ïî óìîë÷àíèþ: 50126) + -d, --hostname - èìÿ ëîêàëüíîãî/óäàëåííîãî ñåðâåðà - äàííûå áóäóò òóíåëèðîâàíû + íà íåãî (ïî óìîë÷àíèþ: èìÿ âîçâðàùàåìîå ôóíöèåé hostname) + -p, --portnum - ïîðò íà êîòîðûé áóäóò òóíåëèðîâàíû äàííûå (íåîáõîäèìî) + -k, --keyfile - èìÿ ôàéëà ñ êëþ÷îì RSA (ïî óìîë÷àíèþ: client.rsa) + -u, --udpmode - udp-ðåæèì - êëèåíò áóäåò èñïîëüçîâàòü udp ïðîòîêîë äëÿ + êîììóíèêàöèè ñ hostname + -U, --reverseudp - îáðàòíûé udp-ðåæèì. Udp ïàêåòû áóäóò ïåðåíàïðàâëÿòüñÿ + ñ hostname:portnum (-p) íà ñåðâåð name:portnum (-m) + -O, --heavylog - ïèñàòü âñå ñîîáùåíèÿ â logfile + -o, --lightlog - ïèñàòü íåêîòîðûå ñîîáùåíèÿ â logfile + -v, --verbose - âûâîä ñîîáùåíèé â êîíñîëü - ïðîãðàìà íå áóäåò ðàáîòàòü + êàê daemon. + --pass - çàäàòü ïàðîëü äëÿ èäåíòèôèêàöèè êëèåíòà + (ïî óìîë÷àíèþ: íåò ïàðîëÿ) + -4, --ipv4 - èñïîëüçîâàòü òîëüêî ipv4 + -6, --ipv6 - èñïîëüçîâàòü òîëüêî ipv6 + -l, --load - çàãðóçèòü ìîäóëü äëÿ ôèëüòðàöèè ïàêåòîâ + +================================================================================ + +========== +3. ÏÐÈÌÅÐÛ +========== + + 3.1 tcp-ðåæèì + ------------- + + local network |FireWall| Internet + || + || User 1 + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | \(tcp) + /(tcp) || (tcp)| User 2 + / || \ + Http server || User 3 + || + + +Èñïîëüçîâàíèå ýòîãî ðåæèìà ÷åðåçâû÷àíî ïðîñòîå. Äàâàéòå ïðåäïîëîæèì, ÷òî ìû +õîòèì ñîçäàò http ñåðâåð íà íàøåì êîìïüþòåðå, íàõîäÿùåìñÿ â ëîêàëüíîé ñåòè çà +áðàíäìàóýðîì: + +1) Ìû äîëæíû íàéòè ìàøèíó ñ âíåøíèì IP àäðåñîì è äîñòóïîì ê shell. + +2) Èñïîëüçîâàòü "make" ÷òîáû ñêîìïèëèðîâàòü AF íà íåé. (âû ìîæåòå ñïîêîéíî + óäàëÿòü ôàéëû afclient è client.rsa) + +3) Âû ìîæåòå îòðåäàêòèðîâàòü êîíôèãóðàöèîííûé ôàéë èëè ïåðåäàòü ïðîãðàììå âñå + ïàðàìåòðû èç êîíñîëè (äëÿ èñïîëüçîâàíèÿ ôàéëà íàáåðèòå -f ) : + $ ./afserver + Ýòî áóäåò ðàáîòàòü, åñëè âû õîòèòå èñïîëüçîâàòü íàñòðîéêè ïî óìîë÷àíèþ: + - hostname áóäåò âçÿò èç ôóíêöèè hostname (ýòî ðàáîòàåò çàìå÷àòåëüíî, åñëè + åñòü ñîîòâåòñòâóþùàÿ çàïèñü â /etc/hosts) + - ñåðâåð áóäåò æäàòü ïîëüçîâàòåëåé íà ïîðòó 50127 + - ñåðâåð áóäåò æäàòü êëèåíòà íà ïîðòó 50126 + - ñåðâåð áóäåò îáñëóæèâàòü ìàêèìóì 5 ïîëüçîâàòåëåé + - ñåðâåð áóäåò ïåðåíàïðàâëÿòü tcp ñîåäèíåíèÿ + - îòëàäî÷íûõ ñîîáùåíèé íå áóäåò + - èäåíòèôèêàöèé ïî ïàðîëþ íå áóäåò + - âåðñèÿ ïðîòîêîëà ip íå áóäåò çàäàíà + +4) Ìû èñïîëüçóåì "make" íà íàøåé ìàøèíå (ìîæíî óäàëèòü âñå êðîìå afclient è + client.rsa) + +5) Íàáèðàåì â êîíñîëè: + $ ./afclient -n <èìÿ ñåðâåðà> -p 80 + Ãäå <èìÿ ñåðâåðà> ñòðîêà òèïà: 'bastion.univ.gda.pl' èëè '153.19.7.200' + +6) Òåïåðü â áðàóçåðå ìû ìîæåì íàáðàòü: <èìÿ ñåðâåðà>:50127 è ïîïàäåì íà íàø + êîìïüþòåð. + + 3.2 îáðàòíûé udp-ðåæèì + ---------------------- + + local network |FireWall| Internet + || (udp) + || User 1-------AF Client + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | + /(udp) || (tcp)| + / || / + Game server || AF Client-------User 2 + || (udp) + + +Äàâàéòå òåïåðü ïîñìîòðèì êàê ìû ìîæåì èñïîëüçîâàòü af äëÿ ïåðåíàïðàâëåíèÿ udp +ïàêåòîâ. Ïðåäïîëîæèì, ÷òî ìû õîòèì ñîçäàòü èãðîâîé ñåðâåð íà íàøåì êîìïüþòåðå +(udp ïîðò 27960): + +1) - 4) òîæå ñàìîå, ÷òî è â ïåðâîì ïðèìåðå. (íî äîáàâëÿåì ïàðàìåòð: -p udp) + +5) Íàáèðàåì â êîíñîëè: + $ ./afclient -u -n <èìÿ ñåðâåðà> -p 27960 + Ãäå <èìÿ ñåðâåðà> ýòî èìÿ (èëè ip) êîìïþòåðà ãäå ðàáîòàåò íàø ñåðâåð. + +6) Ïðîöåññ ñîåäèíåíèÿ ñ èãðîâûì ñåðâåðîì áîëåå ñëîæíûé. Ïîëüçîâàòåëü äîëæåí + çàïóñòèòü fclient ÷òîáû ñäåëàòü ýòî. Îí äîëæåí óêàçàòü ñåðâåð ñ êîòîðûì îí + áóäåò ñîåäèíÿòüñÿ è ïîðò, íà êîòîðîì åãî ïðîãðàììà áóäåò ñëóøàòü: + $ ./afclient -U -d -p <ïîðò> -n <èìÿ ñåðâåðà> \ + -m <ïîðò ñåðâåðà> + + Ãäå èìÿ ìàøèíû ïîëüçîâàòåëÿ (êîòîðûé ñîåäèíÿåòñÿ ñ èãðîâûì + ñåðâåðîì), <ïîðò> - ëîêàëüíûé ïîðò, <èìÿ ñåðâåðà> - èìÿ ñåðâåðà, <ïîðò + ñåðâåðà> - ïîðò íà êîòîðîì ñåðâåð æäåò ïîëüçîâàòåëåé.Òåïåðü, ÷òîáû ïîïàñòü íà + èãðîâîé ñåðâåð, ïîëüçîâàòåëü äîëæåí ñîåäèíÿòñÿ ñ :<ïîðò>. + +================================================================================ + +============================ +4. ÈÇÂÅÑÒÍÛÅ ÎØÈÁÊÈ/ÏÐÎÁËÅÌÛ +============================ + +Íà äàííûé ìîìåíò, íåò íèêàêèõ èçâåñòíûõ ïðîáëåì. + +================================================================================ + +========= +ÇÀÌÅ×ÀÍÈß +========= + +Active port forwarder íàõîäèòñÿ â ðàçðàáîòêå, òàê ÷òî ïîæàëóéñòà, ïðèñûëàéòå +ñâîè êîììåíòàðèè, çàìå÷àíèÿ îá îøèáêàõ è ïðåäëîæåíèÿ íà jeremian [at] poczta.fm + +Åñëè ó âàñ åñòü êàêèå-ëèáî ïðîáëåìû ñ èñïîëüçîâàíèåì ïðîãðàììû èëè âû õîòèòå +ïîäåëèòüñÿ ñâîèì ìíåíèåì î íåé, ïîæàëéñòà îñòàâëÿéòå ñâîè ñîîáùåíèÿ íà: +http://gray-world.net/board/ + +================================================================================ + +============= +ÁËÀÃÎÄÀÐÍÎÑÒÈ +============= + + Áîëüøîå ñïàñèáî êîìàíäå GW: + + Alex + è Simon çà òåñòèðîâàíèå AF è ìíîæåñòâî ñîâåòîâ. + + Ñïàñèáî Ilia Perevezentsev çà êîððåêòèðîâêó àíãëèéñêîé + âåðñèè ýòîãî ôàéëà. + + È ñïàñèáî çà èñïîëüçîâàíèå AF! + +ËÈÖÅÍÇÈß +-------- + + Active Port Forwarder is distributed under the terms of the GNU General + Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. diff --git a/docs/en/README b/docs/en/README deleted file mode 100644 index 8901699..0000000 --- a/docs/en/README +++ /dev/null @@ -1,308 +0,0 @@ -AF - Active Port Forwarder v0.5.5 - README -Copyright (C) 2003,2004 jeremian - -=================== - -================================================================================ - -GRAY-WORLD.NET / Active Port Forwarder -========================== - - The Active Port Forwarder program is part of the Gray-World.net projects. - - Our Gray-World Team presents on the http://gray-world.net website the projects - and publications we are working on which are related to the NACS (Network - Access Control System) bypassing research field and to the computer and - network security topics. - -================================================================================ - -======= -SUMMARY -======= - -INTRO - -1. INSTALLATION - 1.1 Instructions - 1.2 Required libs - 1.3 Tested platforms -2. USAGE - 2.1 afserver - 2.2 afclient -3. EXAMPLES - 3.1 tcp mode - 3.2 reverse udp mode -4. BUGS/PROBLEMS - -NOTES - -THANKS - -================================================================================ - -===== -INTRO -===== - -Active port forwarder is a software tool for secure port forwarding. -It uses ssl to increase security of communication between a server and a client. -Originally, it was developed to forward data point to point. However, the need -for bypassing firewalls in order to connect to internally located computers -influenced the further development of the project. - -AF is dedicated for people, who don't have an external ip number and want to -make some services available across the net. - -Moreover, zlib is used to compress the transferred data. - -Using one, permanent data/control channel with flow control / packet buffering -provides good performance and reasonably small latency. - -Multiple clients allow to create more sophisticated tunneling scheme. - -================================================================================ - -=============== -1. INSTALLATION -=============== - - 1.1 Instructions - ---------------- - -1. Download the compressed sources from http://www.gray-world.net/pr_af.shtml -2. Unpack them with tar zxvf -3. Type "make". -4. If something goes wrong - mail the author or post a message on - http://gray-world.net/board/ - - 1.2 Required libs - ----------------- - -1. openssl - http://www.openssl.org/ -2. zlib - http://www.gzip.org/zlib/ - - 1.3 Tested platforms - -------------------- - -1. Linux: - Gentoo, Slackware, Mandrake - built without any problems -2. Freebsd: - 4.4, 4.9 - have to use patch from project homepage -3. Windows: - win32 - cygwin version is available on the project homepage - -================================================================================ - -======== -2. USAGE -======== - - 2.1 afserver - ------------ - - Options: - -n, --hostname - it's used when creating listening sockets - (default: name returned by hostname function) - -l, --listenport - listening port number - users connect - to it (default: 50127) - -m, --manageport - manage port number - second part of the active - port forwarder connects to it (default: 50126) - -t, --timeout - the timeout value for the client's connection - (default: 5) - -u, --users - the amount of users allowed to use this server - (default: 5) - -C, --clients - the number of allowed clients to use this server - (default: 1) - -U, --usrpcli - the number of allowed users per client (default: $users) - -M, --climode - strategy used for connecting users with clients (default: 1) - Available strategies: - 1. fill first client before go to next - - -c, --cerfile - the name of the file with certificate - (default: cacert.pem) - -k, --keyfile - the name of the file with RSA key (default: server.rsa) - -f, --cfgfile - the name of the file with the configuration for the - active forwarder (server) - -p, --proto - type of server (tcp|udp) - for which protocol it will be - operating (default: tcp) - -O, --heavylog - logging everything to a logfile - -o, --lightlog - logging some data to a logfile - -v, --verbose - to be verbose - program won't enter the daemon mode - (use several times for greater effect) - - --nossl - ssl is not used for transfering data (but it's still - used to establish a connection) (default: ssl is used) - --nozlib - zlib is not used for compressing data (default: - zlib is used) - --pass - set the password used for client identification - (default: no password) - - -4, --ipv4 - use ipv4 only - -6, --ipv6 - use ipv6 only - - -h, --help - prints this help - - 2.2 afclient - ------------ - - Options: - -h, --help - prints this help - -n, --servername - where the second part of the active - port forwarder is running (required) - -m, --manageport - manage port number - server must be - listening on it (default: 50126) - -d, --hostname - the name of this host/remote host - the final - destination of the packets (default: the name - returned by hostname function) - -p, --portnum - the port we are forwarding connection to (required) - -k, --keyfile - the name of the file with RSA key (default: (none)) - -u, --udpmode - udp mode - client will use udp protocol to - communicate with the hostname - -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded - from hostname:portnum (-p) to the server name:portnum - (-m) - -O, --heavylog - logging everything to a logfile - -o, --lightlog - logging some data to a logfile - -v, --verbose - to be verbose - program won't enter the daemon mode - (use several times for greater effect) - --pass - set the password used for client identification - (default: no password) - -4, --ipv4 - use ipv4 only - -6, --ipv6 - use ipv6 only - -l, --load - load a module for user's packets filtering - -L, --Load - load a module for service's packets filtering - -================================================================================ - -=========== -3. EXAMPLES -=========== - - 3.1 tcp mode - ------------ - - local network |FireWall| Internet - || - || User 1 - || /(tcp) - AF Client <---Encrypted/Compressed channel---> AF Server - / || | \(tcp) - /(tcp) || (tcp)| User 2 - / || \ - Http server || User 3 - || - - -The use of it is extremely simple. Let's suppose we want to create a http server -on our computer and we are behind a masquerade or a firewall: - -1) We have to find some machine on the net with an external ip and a shell - account. - -2) Use "make" to compile everything on that machine. (you can freely remove the - afclient and client.rsa files) - -3) You can edit the config file or just type from the console (to use the config - type -f ) : - $ ./afserver - This will work, if you want to use default values: - - hostname will be taken from hostname function (it would be ideally, if - there is appropriate registration in /etc/hosts) - - server will be listening for users on port 50127 - - server will be listening for client on port 50126 - - server will be for maximum 5 users - - server will forward tcp packets - - there will be no logging and no verbose messages - - there will be no password identification - - ip protocol family will be unspecified - -4) We use "make" on our machine (we can delete everything apart from afclient - and client.rsa) - -5) We are typing from the console: - $ ./afclient -n -p 80 - Where is a string like : 'bastion.univ.gda.pl' or - '153.19.7.200' - -6) We can now enter with a web-browser to: :50127 and we - will enter to our computer in the fact. - - 3.2 reverse udp mode - -------------------- - - local network |FireWall| Internet - || (udp) - || User 1-------AF Client - || /(tcp) - AF Client <---Encrypted/Compressed channel---> AF Server - / || | - /(udp) || (tcp)| - / || / - Game server || AF Client-------User 2 - || (udp) - - -Let's see how to use af to forward udp packets. Suppose we want to create a game -server on our computer (udp port 27960 on our machine): - -1) - 4) is the same like in example 1. (but we add option: -p udp) - -5) We are typing from the console: - $ ./afclient -u -n -p 27960 - Where is a name (or ip) of a host where our server is - running. - -6) Connecting to our game is more complicated. The user must use afclient to do - this. He has to specify the server he is connecting to and the port, which - his program will be listening on: - $ ./afclient -U -d -p -n \ - -m - Where is the name of the user machine (who wants to connect to our - game). is the port he will be connecting to. - is the name of the host where our server is running. is the - port on which the server is listening for users. In order to connect to our - game, the user has to connect to :. - -================================================================================ - -================ -4. BUGS/PROBLEMS -================ - -There are no known/open bugs at the moment. - -================================================================================ - -===== -NOTES -===== - -Active port forwarder is still under development, so please sent any comments, -bugs notices and suggestions about it to - -If you have some problems or want to share your opinions with others, feel free -to post a message at http://gray-world.net/board/ - -================================================================================ - -====== -THANKS -====== - - Big thanks to the GW Team: - - to Alex - and Simon for testing AF and a lot of advices. - - Thanks to Ilia Perevezentsev who read and corrected the -README file. - - And thanks for using this software! - -LICENSE -------- - - Active Port Forwarder is distributed under the terms of the GNU General - Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. - diff --git a/docs/fr/fr_README b/docs/fr/fr_README deleted file mode 100644 index 56e87b1..0000000 --- a/docs/fr/fr_README +++ /dev/null @@ -1,102 +0,0 @@ -AF - Active Port Forwarder v0.5.2 - fr_README -Copyright (C) 2003 jeremian - jeremian@poczta.fm -================================================ - -================================================================================ - -GRAY-WORLD.NET / Active Port Forwarder -====================================== - - Le programme Active Port Forwarder est partie intégrante des projets - Gray-World.net. - - Notre équipe présente sur le site http://gray-world.net les projets et - publications sur lesquels nous travaillons. Ces projets et publications sont - relatifs au contournement des systèmes de contrôle d'accès réseau (NACS - bypassing) ainsi qu'à la sécurité des systèmes et réseaux. - -================================================================================ - -Active port forwarder est un programme permettant de réaliser du forwarding de -port sécurisé. -Il utilise le protocole SSL pour augmenter le niveau de sécurité des -communications entre serveur et client. - -Af est destiné aux personnes sans adresse IP publique externe qui désirent -offrir des services accessibles depuis le net. - -EXEMPLE 1: - -L'utilisation de Af est extrèmement simple. Supposons que nous voulons mettre en -place un serveur http sur notre station et que nous sommes masqueradés ou placé -derrière un firewall: - -1) Nous devons tout d'abord trouver une station sur internet avec une IP -publique et un shell. - -2) Utilisez ensuite make pour compiler Af sur cette machine. (Vous pouvez par la -suite supprimer les fichiers afclient et client.rsa) - -3) Editez le fichier de configuration ou entrez sur la console: (pour utiliser -la configuration, entrez type -f ) - $ ./afserver - Si vous voulez utiliser les valeurs par défaut: - - Le nom d'hôte sera pris en compte par la fonction hostname (Il serait idéal - qu'il soit référencé dans le fichier /etc/hosts) - - Le serveur sera en écoute pour les utilisateurs sur le port 50127 - - Le serveur sera en écoute pour le client sur le port 50126 - - Le serveur sera limité à 5 utilisateurs - - Le serveur retransmettra les paquets tcp - - Aucun log ou message verbeux ne sera activé - -4) Nous utilisons make sur notre propre station (Nous pouvons ensuite supprimer -tous les fichiers sauf afclient et client.rsa) - -5) Nous entrons sur la console: - $ ./afclient -n -p 80 - Où est une chaîne du type : 'bastion.univ.gda.pl' ou - '153.19.7.200' - -6) Nous pouvons ensuite utiliser notre navigateur web avec : - :50127 et nous atteindrons notre propre station. - -EXEMPLE 2: - -Regardons comment nous pouvons utiliser af pour forwarder des paquets udp. -Supposez que nous voulons mettre en place un serveur de jeu sur notre station -(port udp 27960 sur notre station): - -1) - 4) sont les mêmes que pour l'exemple 1. (mais nous utilisons l'option: --t udp) - -5) Nous entrons sur la console: - $ ./afclient -u -n -p 27960 - Où est un nom (ou une ip) d'un hôte sur lequel notre - serveur tourne. - -6) Nous connecter à notre jeu est un peu plus compliqué. L'utilisateur doit se - servir de afclient pour cela. - Il doit spécifier le serveur auquel il veut se connecter et le port sur - lequel son programme sera en écoute: - $ ./afclient -U -d -p -n -m\ - - Où est le nom de la station utilisateur (qui veut se connecter à - notre jeu). est le port auquel il se connectera. est le nom de l'hôte sur lequel notre serveur tourne. - est le port sur lequel notre serveur est en écoute pour les utilisateurs. - Pour se connecter à notre jeu, l'utilisateur doit se connecter à : - . - -Active port forwarder est toujours en phase en développement, alors envoyez moi -vos commentaires, les bugs que vous rencontrez et vos suggestions à - - -Et merci pour votre utilisation de ce programme! - -LICENCE -------- - - Active Port Forwarder est distribué sous les termes de la licence GNU - - General Public Licence version 2.0 et est copyright (c) 2003 jeremian - . - Consultez le fichier COPYING pour plus de details. diff --git a/docs/ru/ru_README b/docs/ru/ru_README deleted file mode 100644 index 4e825f7..0000000 --- a/docs/ru/ru_README +++ /dev/null @@ -1,294 +0,0 @@ -AF - Active Port Forwarder v0.5.4 - README -Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm> -=================== - -================================================================================ - -GRAY-WORLD.NET / Active Port Forwarder -========================== - - Ïðîãðàììà Active Port Forwarder ÿâëÿåòñÿ ÷àñòüþ ïðîåêòà Gray-World.net. - - Íàøà êîìàíäà Gray-World ïðåäñòàâëÿåò íà ñàéòå http://gray-world.net ïðîåêòû è - ïóáëèêàöèè, íàä êîòîðûìè ìû ðàáîòàåì, îòíîñÿùèåñÿ ê îáëàñòè èññëåäîâàíèÿ - NACS (Ñèñòåì Êîíòðîëÿ Ñåòåâîãî Äîñòóïà), à òàêæå ê òåìå êîìïüþòåðíîé è - ñåòåâîé áåçîïàñíîñòè. - -================================================================================ - -========== -ÑÎÄÅÐÆÀÍÈÅ -========== - -ÎÏÈÑÀÍÈÅ - -1. ÓÑÒÀÍÎÂÊÀ - 1.1 Èíñòðóêöèè - 1.2 Íåîáõîäèìûå áèáëèîòåêè - 1.3 Òåñòîâûå ïëàòôîðìû -2. ÈÑÏÎËÜÇÎÂÀÍÈÅ - 2.1 afserver - 2.2 afclient -3. ÏÐÈÌÅÐÛ - 3.1 tcp-ðåæèì - 3.2 îáðàòíûé udp-ðåæèì -4. ÈÇÂÅÑÒÍÛÅ ÎØÈÁÊÈ/ÏÐÎÁËÅÌÛ - -ÇÀÌÅ×ÀÍÈß - -ÁËÀÃÎÄÀÐÍÎÑÒÈ - -================================================================================ - -======== -ÎÏÈÑÀÍÈÅ -======== - -Active port forwarder ýòî ïðîãðàììíûé èíñòðóìåíò äëÿ áåçîïàñíîãî òóíåëèðîâàíèÿ -äàííûõ. Îí èñïîëüçóåò SSL äëÿ çàùèòû ñîåäèíåíèÿ ìåæäó êëèåíòîì è ñåðâåðîì. -Èçíà÷àëüíî, ïðîãðàììà áûëà ðàçðàáîòàíà äëÿ ïðîñòîé ïåðåñûëêè äàííûõ îò òî÷êè ê -òî÷êå. Îäíàêî íåîáõîäèìîñòü îáõîäà áðàíäìàóýðà ñ öåëüþ ñäåëàòü êîìïüþòåðû -ëîêàëüíîé ñåòè äîñòóïíûìè èçâíå, ïîâëèÿëà íà äàëüíåéøåå ðàçâèòèå ïðîåêòà. - -AF ïðåäíàçíà÷åí äëÿ ëþäåé, íå èìåþùèõ âíåøíåãî IP àäðåñà è êîòîðûå õîòÿò ñäåëàòü -íåêîòîðûå ëîêàëüíûå ñåðâèñû äîñòóïíûìè â ñåòè. - - ïðîãðàììå èñïîëüçîâàíà áèáëèîòåêà zlib äëÿ ñæàòèÿ ïåðåäàâàåìûõ äàííûõ. - -Èñïîëüçîâàíèå åäèíîãî êàíàëà äëÿ ïåðåäà÷è äàííûõ è êîìàíä óïðàâëåíèÿ â ñî÷åòàíèè -ñ áóôåðèçàöèåé ïåðåñûëàåìûõ ïàêåòîâ îáåñïå÷èâàåò õîðîøóþ ïðîèçâîäèòåëüíîñòü è -ìàëîå âðåìÿ îòêëèêà ñèñòåìû. - -Äëÿ çàïóñêà afserver íå òðåáóåòñÿ ïðèâèëåãèé root, òàêæå îí íå èñïîëüçóåò -thread-û èëè äðóãèå ïðîöåññû. - -================================================================================ - -============ -1. ÓÑÒÀÍÎÂÊÀ -============ - - 1.1 Èíñòðóêöèè - -------------- - -1. Çàãðóçèòå óïàêîâàííûé èñõîäíûé êîä ñ http://www.gray-world.net/pr_af.shtml -2. Ðàñïàêóéòå - tar zxvf -3. Âûïîëíèòå êîìàíäó "make". -4. Åñëè ÷òî-òî ïîøëî íå òàê - íàïèøèòå ïèñüìî àâòîðó èëè îñòàâüòå ñîîáùåíèå íà - http://gray-world.net/board/ - - 1.2 Íåîáõîäèìûå áèáëèîòåêè - -------------------------- - -1. openssl - http://www.openssl.org/ -2. zlib - http://www.gzip.org/zlib/ - - 1.3 Òåñòîâûå ïëàòôîðìû - ---------------------- - -1. Linux: - Gentoo, Slackware, Mandrake - áûëî ñîáðàíî áåç êàêèõ-ëèáî ïðîáëåì -2. Freebsd: - 4.4, 4.9 - Íåîáõîäèì patch ñ äîìàøíåé ñòðàíèöû ïðîåêòà -3. Windows: - win32 - Âåðñèÿ ñ cygwin äîñòóïíà íà äîìàøíåé ñòðàíèöå ïðîåêòà - -================================================================================ - -================ -2. ÈÑÏÎËÜÇÎÂÀÍÈÅ -================ - - 2.1 afserver - ------------ - - Ïàðàìåòðû: - -h, --help - ïå÷àòàåò ýòó ñïðàâêó - -n, --hostname - èñïîëüçóåòñÿ ïðè ñîçäàíèè "ñëóøàþùèõ" ñîêåòîâ - (ïî óìîë÷àíèþ: èìÿ âîçâðàùàåìîå ôóíêöèåé hostname) - -l, --listenport - ïîðò ñåðâåðà - ïîëüçîâàòåëè ñîåäèíÿþòñÿ - ñ íèì (ïî óìîë÷àíèþ: 50127) - -m, --manageport - ïîðò äëÿ óïðàâëåíèÿ - äðóãàÿ ÷àñòü active - port forwarder ñîåäèíÿåòñÿ ñ íèì (ïî óìîë÷àíèþ: 50126) - -u, --users - êîëè÷åñòâî ïîëüçîâàòåëåé, èñïîëüçóþùèõ ñåðâåð - (ïî óìîë÷àíèþ: 5) - -c, --cerfile - èìÿ ôàéëà ñ ñåðòèôèêàòîì - (ïî óìîë÷àíèþ: cacert.pem) - -k, --keyfile - èìÿ ôàéëà ñ êëþ÷îì RSA (ïî óìîë÷àíèþ: server.rsa) - -f, --cfgfile - èìÿ ôàéëà ñ êîíôèãóðàöèåé äëÿ active forwarder (ñåðâåð) - -p, --proto - òèï ñåðâåðà (tcp|udp) - ñ êàêèì ïðîòîêîëîì îí áóäåò - ðàáîòàòü (ïî óìîë÷àíèþ: tcp) - -O, --heavylog - ïèñàòü âñå ñîîáùåíèÿ â logfile - -o, --lightlog - ïèñàòü íåêîòîðûå ñîîáùåíèÿ â logfile - -v, --verbose - âûâîä ñîîáùåíèé â êîíñîëü - ïðîãðàìà íå áóäåò ðàáîòàòü - êàê daemon. - --nossl - ïðîòîêîë ssl íå áóäåò èñïîëüçîâàí äëÿ ïåðåäà÷è äàííûõ (íî - áóäåò èñïîëüçîâàí äëÿ óñòàíîâêè ñîåäèíåíèé) (ïî óìîë÷àíèþ: - ssl èñïîëüçóåòñÿ âñåãäà) - --nozlib - zlib íå áóäåò èñïîëüçîâàòüñÿ äëÿ ñæàòèÿ äàííûõ - (ïî óìîë÷àíèþ: zlib èñïîëüçóåòñÿ) - --pass - çàäàòü ïàðîëü äëÿ èäåíòèôèêàöèè êëèåíòà - (ïî óìîë÷àíèþ: íåò ïàðîëÿ) - -4, --ipv4 - èñïîëüçîâàòü òîëüêî ipv4 - -6, --ipv6 - èñïîëüçîâàòü òîëüêî ipv6 - - 2.2 afclient - ------------ - - Options: - -h, --help - ïå÷àòàåò ýòó ñïðàâêó - -n, --servername - ãäå ðàáîòàåò âòîðàÿ ÷àñòü active port - forwarder (íåîáõîäèìî) - -m, --manageport - ïîðò äëÿ óïðàâëåíèÿ - ñåðâåð ñîåäèíÿåòñÿ ñ íèì - (ïî óìîë÷àíèþ: 50126) - -d, --hostname - èìÿ ëîêàëüíîãî/óäàëåííîãî ñåðâåðà - äàííûå áóäóò òóíåëèðîâàíû - íà íåãî (ïî óìîë÷àíèþ: èìÿ âîçâðàùàåìîå ôóíöèåé hostname) - -p, --portnum - ïîðò íà êîòîðûé áóäóò òóíåëèðîâàíû äàííûå (íåîáõîäèìî) - -k, --keyfile - èìÿ ôàéëà ñ êëþ÷îì RSA (ïî óìîë÷àíèþ: client.rsa) - -u, --udpmode - udp-ðåæèì - êëèåíò áóäåò èñïîëüçîâàòü udp ïðîòîêîë äëÿ - êîììóíèêàöèè ñ hostname - -U, --reverseudp - îáðàòíûé udp-ðåæèì. Udp ïàêåòû áóäóò ïåðåíàïðàâëÿòüñÿ - ñ hostname:portnum (-p) íà ñåðâåð name:portnum (-m) - -O, --heavylog - ïèñàòü âñå ñîîáùåíèÿ â logfile - -o, --lightlog - ïèñàòü íåêîòîðûå ñîîáùåíèÿ â logfile - -v, --verbose - âûâîä ñîîáùåíèé â êîíñîëü - ïðîãðàìà íå áóäåò ðàáîòàòü - êàê daemon. - --pass - çàäàòü ïàðîëü äëÿ èäåíòèôèêàöèè êëèåíòà - (ïî óìîë÷àíèþ: íåò ïàðîëÿ) - -4, --ipv4 - èñïîëüçîâàòü òîëüêî ipv4 - -6, --ipv6 - èñïîëüçîâàòü òîëüêî ipv6 - -l, --load - çàãðóçèòü ìîäóëü äëÿ ôèëüòðàöèè ïàêåòîâ - -================================================================================ - -========== -3. ÏÐÈÌÅÐÛ -========== - - 3.1 tcp-ðåæèì - ------------- - - local network |FireWall| Internet - || - || User 1 - || /(tcp) - AF Client <---Encrypted/Compressed channel---> AF Server - / || | \(tcp) - /(tcp) || (tcp)| User 2 - / || \ - Http server || User 3 - || - - -Èñïîëüçîâàíèå ýòîãî ðåæèìà ÷åðåçâû÷àíî ïðîñòîå. Äàâàéòå ïðåäïîëîæèì, ÷òî ìû -õîòèì ñîçäàò http ñåðâåð íà íàøåì êîìïüþòåðå, íàõîäÿùåìñÿ â ëîêàëüíîé ñåòè çà -áðàíäìàóýðîì: - -1) Ìû äîëæíû íàéòè ìàøèíó ñ âíåøíèì IP àäðåñîì è äîñòóïîì ê shell. - -2) Èñïîëüçîâàòü "make" ÷òîáû ñêîìïèëèðîâàòü AF íà íåé. (âû ìîæåòå ñïîêîéíî - óäàëÿòü ôàéëû afclient è client.rsa) - -3) Âû ìîæåòå îòðåäàêòèðîâàòü êîíôèãóðàöèîííûé ôàéë èëè ïåðåäàòü ïðîãðàììå âñå - ïàðàìåòðû èç êîíñîëè (äëÿ èñïîëüçîâàíèÿ ôàéëà íàáåðèòå -f ) : - $ ./afserver - Ýòî áóäåò ðàáîòàòü, åñëè âû õîòèòå èñïîëüçîâàòü íàñòðîéêè ïî óìîë÷àíèþ: - - hostname áóäåò âçÿò èç ôóíêöèè hostname (ýòî ðàáîòàåò çàìå÷àòåëüíî, åñëè - åñòü ñîîòâåòñòâóþùàÿ çàïèñü â /etc/hosts) - - ñåðâåð áóäåò æäàòü ïîëüçîâàòåëåé íà ïîðòó 50127 - - ñåðâåð áóäåò æäàòü êëèåíòà íà ïîðòó 50126 - - ñåðâåð áóäåò îáñëóæèâàòü ìàêèìóì 5 ïîëüçîâàòåëåé - - ñåðâåð áóäåò ïåðåíàïðàâëÿòü tcp ñîåäèíåíèÿ - - îòëàäî÷íûõ ñîîáùåíèé íå áóäåò - - èäåíòèôèêàöèé ïî ïàðîëþ íå áóäåò - - âåðñèÿ ïðîòîêîëà ip íå áóäåò çàäàíà - -4) Ìû èñïîëüçóåì "make" íà íàøåé ìàøèíå (ìîæíî óäàëèòü âñå êðîìå afclient è - client.rsa) - -5) Íàáèðàåì â êîíñîëè: - $ ./afclient -n <èìÿ ñåðâåðà> -p 80 - Ãäå <èìÿ ñåðâåðà> ñòðîêà òèïà: 'bastion.univ.gda.pl' èëè '153.19.7.200' - -6) Òåïåðü â áðàóçåðå ìû ìîæåì íàáðàòü: <èìÿ ñåðâåðà>:50127 è ïîïàäåì íà íàø - êîìïüþòåð. - - 3.2 îáðàòíûé udp-ðåæèì - ---------------------- - - local network |FireWall| Internet - || (udp) - || User 1-------AF Client - || /(tcp) - AF Client <---Encrypted/Compressed channel---> AF Server - / || | - /(udp) || (tcp)| - / || / - Game server || AF Client-------User 2 - || (udp) - - -Äàâàéòå òåïåðü ïîñìîòðèì êàê ìû ìîæåì èñïîëüçîâàòü af äëÿ ïåðåíàïðàâëåíèÿ udp -ïàêåòîâ. Ïðåäïîëîæèì, ÷òî ìû õîòèì ñîçäàòü èãðîâîé ñåðâåð íà íàøåì êîìïüþòåðå -(udp ïîðò 27960): - -1) - 4) òîæå ñàìîå, ÷òî è â ïåðâîì ïðèìåðå. (íî äîáàâëÿåì ïàðàìåòð: -p udp) - -5) Íàáèðàåì â êîíñîëè: - $ ./afclient -u -n <èìÿ ñåðâåðà> -p 27960 - Ãäå <èìÿ ñåðâåðà> ýòî èìÿ (èëè ip) êîìïþòåðà ãäå ðàáîòàåò íàø ñåðâåð. - -6) Ïðîöåññ ñîåäèíåíèÿ ñ èãðîâûì ñåðâåðîì áîëåå ñëîæíûé. Ïîëüçîâàòåëü äîëæåí - çàïóñòèòü fclient ÷òîáû ñäåëàòü ýòî. Îí äîëæåí óêàçàòü ñåðâåð ñ êîòîðûì îí - áóäåò ñîåäèíÿòüñÿ è ïîðò, íà êîòîðîì åãî ïðîãðàììà áóäåò ñëóøàòü: - $ ./afclient -U -d -p <ïîðò> -n <èìÿ ñåðâåðà> \ - -m <ïîðò ñåðâåðà> - - Ãäå èìÿ ìàøèíû ïîëüçîâàòåëÿ (êîòîðûé ñîåäèíÿåòñÿ ñ èãðîâûì - ñåðâåðîì), <ïîðò> - ëîêàëüíûé ïîðò, <èìÿ ñåðâåðà> - èìÿ ñåðâåðà, <ïîðò - ñåðâåðà> - ïîðò íà êîòîðîì ñåðâåð æäåò ïîëüçîâàòåëåé.Òåïåðü, ÷òîáû ïîïàñòü íà - èãðîâîé ñåðâåð, ïîëüçîâàòåëü äîëæåí ñîåäèíÿòñÿ ñ :<ïîðò>. - -================================================================================ - -============================ -4. ÈÇÂÅÑÒÍÛÅ ÎØÈÁÊÈ/ÏÐÎÁËÅÌÛ -============================ - -Íà äàííûé ìîìåíò, íåò íèêàêèõ èçâåñòíûõ ïðîáëåì. - -================================================================================ - -========= -ÇÀÌÅ×ÀÍÈß -========= - -Active port forwarder íàõîäèòñÿ â ðàçðàáîòêå, òàê ÷òî ïîæàëóéñòà, ïðèñûëàéòå -ñâîè êîììåíòàðèè, çàìå÷àíèÿ îá îøèáêàõ è ïðåäëîæåíèÿ íà jeremian [at] poczta.fm - -Åñëè ó âàñ åñòü êàêèå-ëèáî ïðîáëåìû ñ èñïîëüçîâàíèåì ïðîãðàììû èëè âû õîòèòå -ïîäåëèòüñÿ ñâîèì ìíåíèåì î íåé, ïîæàëéñòà îñòàâëÿéòå ñâîè ñîîáùåíèÿ íà: -http://gray-world.net/board/ - -================================================================================ - -============= -ÁËÀÃÎÄÀÐÍÎÑÒÈ -============= - - Áîëüøîå ñïàñèáî êîìàíäå GW: - - Alex - è Simon çà òåñòèðîâàíèå AF è ìíîæåñòâî ñîâåòîâ. - - Ñïàñèáî Ilia Perevezentsev çà êîððåêòèðîâêó àíãëèéñêîé - âåðñèè ýòîãî ôàéëà. - - È ñïàñèáî çà èñïîëüçîâàíèå AF! - -ËÈÖÅÍÇÈß --------- - - Active Port Forwarder is distributed under the terms of the GNU General - Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. diff --git a/exmodule.c b/exmodule.c deleted file mode 100644 index 09141c4..0000000 --- a/exmodule.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -/* This example module scan the message for specified string and perform - * appropriate action - */ - -/* info - * return values: - * info about module - */ - -char* -info(void) -{ - return "Module tester v0.1"; -} - -/* allow - * return values: - * 0 - allow to connect - * !=0 - drop the connection - */ - -int -allow(char* host, char* port) -{ - return 0; /* allow to connect */ -} - -/* filter - * return values: - * 0 - allow to transfer - * 1 - drop the packet - * 2 - drop the connection - * 3 - release the module - * 4 - drop the packet and release the module - * 5 - drop the connection and release the module - */ - -int -filter(char* host, unsigned char* message, int* length) -{ - int i; - for (i = 0; i < *length; ++i) { - if ((message[i] == 'M') && (message[i+1] == '1')) { - return 1; /* ignored */ - } - if ((message[i] == 'M') && (message[i+1] == '2')) { - return 2; /* dropped */ - } - if ((message[i] == 'M') && (message[i+1] == '3')) { - return 3; /* release */ - } - if ((message[i] == 'M') && (message[i+1] == '4')) { - return 4; /* ignored + release */ - } - if ((message[i] == 'M') && (message[i+1] == '5')) { - return 5; /* dropped + release */ - } - } - return 0; /* allow to transfer */ - -} diff --git a/file.c b/file.c deleted file mode 100644 index 59ff7ba..0000000 --- a/file.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "file.h" -#include "activefor.h" -#include -#include -#include -#include - -ConfigurationT -parsefile(char* name, int* status) -{ - static ConfigurationT cfg; - FILE* file = NULL; - int state, i, n; - char buff[256]; - char helpbuf1[256]; - char helpbuf2[256]; - - *status = 1; - - memset(buff, 0, 256); - - cfg.certif = NULL; - cfg.keys = NULL; - cfg.size = 0; - cfg.realmtable = NULL; - cfg.logging = 0; - cfg.logfnam = NULL; - - state = F_UNKNOWN; - - file = fopen(name, "r"); - if (file == NULL) { - return cfg; - } - - while (fgets(buff, 256, file) != NULL) { - helpbuf1[0] = 0; - sscanf(buff, "%s", helpbuf1); - if (strcmp(helpbuf1, "newrealm")==0) { - ++cfg.size; - } - } - rewind(file); - - cfg.realmtable = calloc(cfg.size, sizeof(RealmT)); - cfg.size = 0; - *status = 0; - - while (fgets(buff, 256, file) != NULL) { - (*status)++; - state = sscanf(buff, "%s %s", helpbuf1, helpbuf2); - if (helpbuf1[0] == '#') { - memset(buff, 0, 256); - continue; - } - if (state == 1) { - if (strcmp(helpbuf1, "newrealm")==0) { - ++cfg.size; - TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type); - TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type); - } - else if (cfg.size == 0) { - return cfg; - } - else if (strcmp(helpbuf1, "nossl")==0) { - TYPE_UNSET_SSL(cfg.realmtable[cfg.size-1].type); - } - else if (strcmp(helpbuf1, "nozlib")==0) { - TYPE_UNSET_ZLIB(cfg.realmtable[cfg.size-1].type); - } - else if (strcmp(helpbuf1, "ipv4")==0) { - if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) { - TYPE_SET_IPV4(cfg.realmtable[cfg.size-1].type); - } - else { - return cfg; - } - } - else if (strcmp(helpbuf1, "ipv6")==0) { - if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) { - TYPE_SET_IPV6(cfg.realmtable[cfg.size-1].type); - } - else { - return cfg; - } - } - else { - return cfg; - } - } - else if (state == 2) { - if (strcmp(helpbuf1, "certificate")==0) { - cfg.certif = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.certif, helpbuf2); - } - else if (strcmp(helpbuf1, "key")==0) { - cfg.keys = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.keys, helpbuf2); - } - else if (strcmp(helpbuf1, "heavylog")==0) { - if (cfg.logging) { - return cfg; - } - cfg.logging = 3; - cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.logfnam, helpbuf2); - } - else if (strcmp(helpbuf1, "lightlog")==0) { - if (cfg.logging) { - return cfg; - } - cfg.logging = 1; - cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.logfnam, helpbuf2); - } - else if (cfg.size == 0) { - return cfg; - } - else if (strcmp(helpbuf1, "hostname")==0) { - cfg.realmtable[cfg.size-1].hostname = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].hostname, helpbuf2); - } - else if (strcmp(helpbuf1, "listen")==0) { - cfg.realmtable[cfg.size-1].lisportnum = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].lisportnum, helpbuf2); - } - else if (strcmp(helpbuf1, "pass")==0) { - n = strlen(helpbuf2); - for (i = 0; i < n; ++i) { - cfg.realmtable[cfg.size-1].pass[i%4] += helpbuf2[i]; - } - } - else if (strcmp(helpbuf1, "manage")==0) { - cfg.realmtable[cfg.size-1].manportnum = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].manportnum, helpbuf2); - } - else if (strcmp(helpbuf1, "users")==0) { - cfg.realmtable[cfg.size-1].users = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2); - } - else if (strcmp(helpbuf1, "timeout")==0) { - cfg.realmtable[cfg.size-1].timeout = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].timeout, helpbuf2); - } - else if (strcmp(helpbuf1, "clients")==0) { - cfg.realmtable[cfg.size-1].clients = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].clients, helpbuf2); - } - else if (strcmp(helpbuf1, "usrpcli")==0) { - cfg.realmtable[cfg.size-1].usrpcli = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].usrpcli, helpbuf2); - } - else if (strcmp(helpbuf1, "climode")==0) { - cfg.realmtable[cfg.size-1].clim = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.realmtable[cfg.size-1].clim, helpbuf2); - } - else if (strcmp(helpbuf1, "proto")==0) { - if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) { - return cfg; - } - if (strcmp(helpbuf2, "tcp")==0) { - TYPE_SET_TCP(cfg.realmtable[cfg.size-1].type); - } - else if (strcmp(helpbuf2, "udp")==0) { - TYPE_SET_UDP(cfg.realmtable[cfg.size-1].type); - } - else { - return cfg; - } - } - else { - return cfg; - } - } - memset(buff, 0, 256); - } - - fclose(file); - - *status = 0; - return cfg; -} - diff --git a/file.h b/file.h deleted file mode 100644 index 56f06e3..0000000 --- a/file.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "activefor.h" -#include "network.h" -#include - -#ifndef _JS_FILE_H -#define _JS_FILE_H - -#define F_UNKNOWN 1 -#define F_IGNORE 2 -#define F_ROPTION 3 -#define F_RVALUE 4 -#define F_MIDDLE 5 - -typedef struct { - char* hostname; - char* lisportnum; - char* manportnum; - char* users; - char* clients; - char* usrpcli; - char* clim; - char* timeout; - unsigned char pass[4]; - int usercon; - int usernum; - int clicon; - int clinum; - int upcnum; - int tmout; - int listenfd; - int managefd; - int climode; - char type; - socklen_t addrlen; - struct sockaddr* cliaddr; - ConnectuserT* contable; - ConnectclientT* clitable; -} RealmT; - -typedef struct { - char* certif; - char* keys; - char* logfnam; - char logging; - int size; - RealmT* realmtable; -} ConfigurationT; - -ConfigurationT parsefile(char*, int*); /* parse the cfg file */ - -#endif - diff --git a/modules.c b/modules.c deleted file mode 100644 index 75c2a08..0000000 --- a/modules.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "modules.h" - -#include -#include - -int -loadmodule(moduleT* module) -{ - if (module->name) { - module->handle = dlopen(module->name, RTLD_NOW); - if (!module->handle) { - return 1; - } - dlerror(); - *(void**) (&module->info) = dlsym(module->handle, "info"); - *(void**) (&module->allow) = dlsym(module->handle, "allow"); - *(void**) (&module->filter) = dlsym(module->handle, "filter"); - if (dlerror() != NULL) { - return 2; - } - module->loaded = 1; - } - return 0; -} - -int -releasemodule(moduleT* module) -{ - if (ismloaded(module)) { - module->loaded = 0; - module->info = NULL; - module->allow = NULL; - module->filter = NULL; - return dlclose(module->handle); - } - return 0; -} - -int -ismloaded(moduleT* module) -{ - return module->loaded; -} diff --git a/modules.h b/modules.h deleted file mode 100644 index 7527114..0000000 --- a/modules.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_MODULES_H -#define _JS_MODULES_H - -typedef struct { - char loaded; - char* name; - void* handle; - char* (*info)(void); - int (*allow)(char*, char*); - int (*filter)(char*, unsigned char*, int*); -} moduleT; - -int loadmodule(moduleT* module); -int releasemodule(moduleT* module); -int ismloaded(moduleT* module); - -#endif diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 0000000..7e80e7c --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,3 @@ +noinst_PROGRAMS = exmodule +exmodule_SOURCES = exmodule.c +exmodule_LDFLAGS = -fPIC -shared diff --git a/modules/exmodule.c b/modules/exmodule.c new file mode 100644 index 0000000..08eb842 --- /dev/null +++ b/modules/exmodule.c @@ -0,0 +1,82 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* This example module scan the message for specified string and perform + * appropriate action + */ + +/* info + * return values: + * info about module + */ + +char* +info(void) +{ + return "Module tester v0.1"; +} + +/* allow + * return values: + * 0 - allow to connect + * !=0 - drop the connection + */ + +int +allow(char* host, char* port) +{ + return 0; /* allow to connect */ +} + +/* filter + * return values: + * 0 - allow to transfer + * 1 - drop the packet + * 2 - drop the connection + * 3 - release the module + * 4 - drop the packet and release the module + * 5 - drop the connection and release the module + */ + +int +filter(char* host, unsigned char* message, int* length) +{ + int i; + for (i = 1; i < *length; ++i) { + if (message[i-1] == 'M') { + if (message[i] == '1') { + return 1; /* ignored */ + } + if (message[i] == '2') { + return 2; /* dropped */ + } + if (message[i] == '3') { + return 3; /* release */ + } + if (message[i] == '4') { + return 4; /* ignored + release */ + } + if (message[i] == '5') { + return 5; /* dropped + release */ + } + } + } + return 0; /* allow to transfer */ +} diff --git a/network.c b/network.c deleted file mode 100644 index 01fe513..0000000 --- a/network.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "network.h" -#include "activefor.h" -#include "stats.h" -#include -#include -#include - -int -ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type) -{ - int n; - const int on = 1; - struct addrinfo hints, *res, *ressave; - - bzero(&hints, sizeof(struct addrinfo)); - hints.ai_flags = AI_PASSIVE; - if (type & 0x02) { - hints.ai_family = AF_INET; - } - else if (type & 0x04) { - hints.ai_family = AF_INET6; - } - else { - hints.ai_family = AF_UNSPEC; - } - - if (type & 0x01) { - hints.ai_socktype = SOCK_STREAM; - } - else { - hints.ai_socktype = SOCK_DGRAM; - } - - if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { - return n; - } - ressave = res; - - do { - (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if ((*sockfd) < 0) { - continue; /* error, try next one */ - } - - if (type & 0x01) { /* tcp_listen */ - setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - } - if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { - break; /* success */ - } - - close((*sockfd)); /* bind error, close and try next one */ - } while ( (res = res->ai_next) != NULL); - - if (res == NULL) { /* errno from final socket() or bind() */ - return 1; - } - - if (type & 0x01) { /* tcp_listen */ - listen((*sockfd), 1); - } - - if (addrlenp) { - *addrlenp = res->ai_addrlen; /* return size of protocol address */ - } - - freeaddrinfo(ressave); - - return(0); -} - -int -ip_connect(int* sockfd, const char *host, const char *serv, const char type) -{ - int n; - struct addrinfo hints, *res, *ressave; - - bzero(&hints, sizeof(struct addrinfo)); - if (type & 0x02) { - hints.ai_family = AF_INET; - } - else if (type & 0x04) { - hints.ai_family = AF_INET6; - } - else { - hints.ai_family = AF_UNSPEC; - } - if (type & 0x01) { - hints.ai_socktype = SOCK_STREAM; - } - else { - hints.ai_socktype = SOCK_DGRAM; - } - - if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { - return n; - } - ressave = res; - - do { - (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if ((*sockfd) < 0) { - continue; /* ignore this one */ - } - - if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { - break; /* success */ - } - - close((*sockfd)); /* ignore this one */ - } while ( (res = res->ai_next) != NULL); - - if (res == NULL) { /* errno set from final connect() */ - return 1; - } - - freeaddrinfo(ressave); - - return(0); -} - -char * -sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf) -{ - char portstr[7]; - static char str[128]; /* Unix domain is largest */ - - switch (sa->sa_family) { - case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *) sa; - - if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { - return(NULL); - } - if (namebuf) { - if (inet_ntop(AF_INET, &sin->sin_addr, namebuf, 128) == NULL) { - return(NULL); - } - } - if (ntohs(sin->sin_port) != 0) { - snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); - if (portbuf) { - snprintf(portbuf, 7, "%d", ntohs(sin->sin_port)); - } - strcat(str, portstr); - } - return(str); - } -#ifdef AF_INET6 - case AF_INET6: { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; - - if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { - return(NULL); - } - if (namebuf) { - if (inet_ntop(AF_INET6, &sin6->sin6_addr, namebuf, 128) == NULL) { - return(NULL); - } - } - if (ntohs(sin6->sin6_port) != 0) { - snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port)); - if (portbuf) { - snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port)); - } - strcat(str, portstr); - } - return(str); - } -#endif - default: { - snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); - return(str); - } - } - return (NULL); -} - -int -SSL_writen(SSL* fd, unsigned char* buf, int amount) -{ - int sent, n; - sent = 0; - while (sent < amount) { - n = SSL_write(fd, buf+sent, amount - sent); - if (n != -1) { - sent += n; - } - if (n == -1) { - if (errno != EAGAIN) - return 0; - } - } - return amount; -} - -int -SSL_readn(SSL* fd, unsigned char* buf, int amount) -{ - int sent, n; - sent = 0; - while (sent < amount) { - n = SSL_read(fd, buf+sent, amount - sent); - if (n != -1) { - sent += n; - } - if (n == 0) - return 0; - if (n == -1) { - if (errno != EAGAIN) - return 0; - } - } - return amount; -} - -int -writen(int fd, unsigned char* buf, int amount) -{ - int sent, n; - sent = 0; - while (sent < amount) { - n = write(fd, buf+sent, amount - sent); - if (n != -1) { - sent += n; - } - if (n == -1) { - if (errno != EAGAIN) - return 0; - } - } - return amount; -} - -int -readn(int fd, unsigned char* buf, int amount) -{ - int sent, n; - sent = 0; - while (sent < amount) { - n = read(fd, buf+sent, amount - sent); - if (n != -1) { - sent += n; - } - if (n == 0) - return 0; - if (n == -1) { - if (errno != EAGAIN) - return 0; - } - } - return amount; - -} - -int -send_message(char type, clifd fd, unsigned char* buf, int amount) -{ - unsigned long clen; - int length; - static unsigned char bufor[9000]; - clen = 8995; - length = amount - 5; - if (TYPE_IS_ZLIB(type)) { - memcpy(bufor, buf, 5); - if (amount > 5) { - compress(&bufor[5], &clen, &buf[5], length); - if (clen < length) { - length = clen; - TYPE_SET_COMP(length); - bufor[3] = length >> 8; /* high bits of message length */ - bufor[4] = length; /* low bits of message length */ - addtocg(amount-5 - clen); - } - } - if (TYPE_IS_SSL(type)) { - if (TYPE_IS_COMP(length)) { - return SSL_writen(fd.ssl, bufor, clen+5); - } - else { - return SSL_writen(fd.ssl, buf, amount); - } - } - else { - if (TYPE_IS_COMP(length)) { - return writen(fd.commfd, bufor, clen+5); - } - else { - return writen(fd.commfd, buf, amount); - } - } - } - else { - if (TYPE_IS_SSL(type)) { - return SSL_writen(fd.ssl, buf, amount); - } - else { - return writen(fd.commfd, buf, amount); - } - } -} - -int -get_message(char type, clifd fd, unsigned char* buf, int amount) -{ - int length; - unsigned long elen; - static unsigned char bufor[9000]; - if (amount == -5) { - if (TYPE_IS_SSL(type)) { - return SSL_read(fd.ssl, buf, 5); - } - else { - return read(fd.commfd, buf, 5); - } - } - if (TYPE_IS_ZLIB(type)) { - if (TYPE_IS_SSL(type)) { - length = SSL_readn(fd.ssl, bufor, amount&0xBFFF); - } - else { - length = readn(fd.commfd, bufor, amount&0xBFFF); - } - if (length <= 0) return length; - elen = 8096; - if (TYPE_IS_COMP(amount)) { - uncompress(buf, &elen, bufor, length); - } - else { - memcpy(buf, bufor, length); - elen = length; - } - return elen; - } - else - { - if (TYPE_IS_SSL(type)) { - return SSL_readn(fd.ssl, buf, amount); - } - else { - return readn(fd.commfd, buf, amount); - } - } -} diff --git a/network.h b/network.h deleted file mode 100644 index 1ce2ccb..0000000 --- a/network.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_NETWORK_H -#define _JS_NETWORK_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - int commfd; - SSL* ssl; -} clifd; - -int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */ -int ip_connect(int* sockfd, const char *host, const char *serv, const char type); /* socket, connect... */ -char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf); /* return the IP of connected user */ - -int send_message(char type, clifd fd, unsigned char* buf, int amount); -int get_message(char type, clifd fd, unsigned char* buf, int amount); - -int SSL_writen(SSL* fd, unsigned char* buf, int amount); -int SSL_readn(SSL* fd, unsigned char* buf, int amount); -int writen(int fd, unsigned char* buf, int amount); -int readn(int fd, unsigned char* buf, int amount); - -#endif diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..a6ccd11 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = afserver afclient +afserver_SOURCES = afserver.c network.c file.c stats.c buflist.c remoteadmin.c \ + server_check.c server_set.c server_eval.c server_find.c server_remove.c \ + make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c +afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB} +afclient_SOURCES = afclient.c network.c stats.c buflist.c modules.c remoteadmin.c \ + make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c diff --git a/src/activefor.h b/src/activefor.h new file mode 100644 index 0000000..8d07c8b --- /dev/null +++ b/src/activefor.h @@ -0,0 +1,162 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_ACTIVEFOR_H +#define _JS_ACTIVEFOR_H + +#include "network.h" +#include "buflist.h" + +#define AF_S_CONCLOSED 1 +#define AF_S_CONOPEN 2 +#define AF_S_MESSAGE 3 +#define AF_S_CLOSING 4 +#define AF_S_LOGIN 8 +#define AF_S_DONT_SEND 9 +#define AF_S_CAN_SEND 10 +#define AF_S_CANT_OPEN 12 + +#define AF_S_WRONG 13 +#define AF_S_ADMIN_LOGIN 14 +#define AF_S_ADMIN_CMD 15 + +#define S_STATE_CLEAR 0 +#define S_STATE_CLOSING 5 +#define S_STATE_OPENING 6 +#define S_STATE_OPEN 7 +#define S_STATE_STOPPED 11 + +#define AF_VER(info) info" v0.6" + +#define TYPE_TCP 1 +#define TYPE_UDP 3 +#define TYPE_SSL 4 +#define TYPE_ZLIB 8 +#define TYPE_IPV4 16 +#define TYPE_IPV6 32 +#define TYPE_COMP 0x4000 + +#define TYPE_SET_ZERO(type) (type=0) +#define TYPE_IS_SET(type) (type&1) +#define TYPE_IS_UDP(type) TYPE_IS_SET(type)&&(type&2) +#define TYPE_IS_TCP(type) TYPE_IS_SET(type)&&(!(type&2)) +#define TYPE_SET_UDP(type) (type|=TYPE_UDP) +#define TYPE_SET_TCP(type) (type|=TYPE_TCP) +#define TYPE_SET_SSL(type) (type|=TYPE_SSL) +#define TYPE_UNSET_SSL(type) (type&=(~TYPE_SSL)) +#define TYPE_IS_SSL(type) (type&TYPE_SSL) +#define TYPE_SET_ZLIB(type) (type|=TYPE_ZLIB) +#define TYPE_UNSET_ZLIB(type) (type&=(~TYPE_ZLIB)) +#define TYPE_IS_ZLIB(type) (type&TYPE_ZLIB) + +#define TYPE_SET_IPV4(type) (type|=TYPE_IPV4) +#define TYPE_UNSET_IPV4(type) (type&=(~TYPE_IPV4)) +#define TYPE_IS_IPV4(type) (type&TYPE_IPV4) +#define TYPE_SET_IPV6(type) (type|=TYPE_IPV6) +#define TYPE_UNSET_IPV6(type) (type&=(~TYPE_IPV6)) +#define TYPE_IS_IPV6(type) (type&TYPE_IPV6) +#define TYPE_SET_UNSPEC(type) (type&=(~(TYPE_IPV4|TYPE_IPV6))) +#define TYPE_IS_UNSPEC(type) (!(type&(TYPE_IPV4|TYPE_IPV6))) + +#define TYPE_SET_COMP(type) (type|=TYPE_COMP) +#define TYPE_IS_COMP(type) (type&TYPE_COMP) + +typedef struct { + char* lisportnum; + char* manportnum; + int listenfd; + int managefd; +} UsrCliT; + +typedef struct { + char state; + int connfd; + int whatcli; + int userid; + time_t connecttime; + char namebuf[128]; + char portbuf[7]; + blnodeT* head; +} ConnectuserT; + +typedef struct { + char ready; + clifd cliconn; + struct timeval tv; + int* users; + int usercon; + int usernum; + int listenfd; + int whatusrcli; + int clientnum; + time_t connecttime; + char* clientid; + char namebuf[128]; + char portbuf[7]; +} ConnectclientT; + +typedef struct { + char* hostname; + char* users; + char* clients; + char* raclients; + char* usrpcli; + char* clim; + char* timeout; + char* realmname; + unsigned char pass[4]; + int usercon; + int usernum; + int clicon; + int clinum; + int raclicon; + int raclinum; + int upcnum; + int tmout; + int climode; + int usrclinum; + int clientcounter; + int usercounter; + char type; + char dnslookups; + char baseport; + socklen_t addrlen; + struct sockaddr* cliaddr; + ConnectuserT* contable; + ConnectclientT* clitable; + ConnectclientT* raclitable; + UsrCliT* usrclitable; +} RealmT; + +typedef struct { + char* certif; + char* keys; + char* logfnam; + char* logsport; + char* dateformat; + char logging; + char socklogging; + int size; + time_t starttime; + RealmT* realmtable; +} ConfigurationT; + +#endif + diff --git a/src/afclient.c b/src/afclient.c new file mode 100644 index 0000000..cc3c0c8 --- /dev/null +++ b/src/afclient.c @@ -0,0 +1,1000 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "afclient.h" + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"udpmode", 0, 0, 'u'}, + {"reverseudp", 0, 0, 'U'}, + {"servername", 1, 0, 'n'}, + {"manageport", 1, 0, 'm'}, + {"hostname", 1, 0, 'd'}, + {"portnum", 1, 0, 'p'}, + {"verbose", 0, 0, 'v'}, + {"keyfile", 1, 0, 'k'}, + {"heavylog", 1, 0, 'O'}, + {"lightlog", 1, 0, 'o'}, + {"heavysocklog", 1, 0, 'S'}, + {"lightsocklog", 1, 0, 's'}, + {"pass", 1, 0, 301}, +#ifdef AF_INET6 + {"ipv4", 0, 0, '4'}, + {"ipv6", 0, 0, '6'}, +#endif +#ifdef HAVE_LIBDL + {"load", 1, 0, 'l'}, + {"Load", 1, 0, 'L'}, +#endif + {"id", 1, 0, 'i'}, + {"dateformat", 1, 0, 'D'}, + {"remoteadmin", 0, 0, 'r'}, + {0, 0, 0, 0} +}; + +int +main(int argc, char **argv) +{ + int i, n, numofcon, length, buflength, notsent, temp2; + ConnectuserT* contable = NULL; + clifd master; + unsigned char buff[9000]; + char hostname[100]; + int maxfdp1, usernum, usercon; + socklen_t len, addrlen; + struct sockaddr* cliaddr; + fd_set rset, allset, wset, tmpset; + char verbose = 0; + char remote = 0; + char logging = 0; + char socklogging = 0; + char* name = NULL; + char* id = NULL; + char* manage = NULL; + char* desnam = NULL; + char* despor = NULL; + char* keys = NULL; + char* logfname = NULL; + char* logsport = NULL; + char* dateformat = NULL; + char ipfam = 0; + unsigned char pass[4] = {1, 2, 3, 4}; + char udp = 0; + char reverse = 0; + char type = 0; + struct sigaction act; +#ifdef HAVE_LIBDL + moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL}; +#endif + + SSL_METHOD* method; + SSL_CTX* ctx; + + sigfillset(&(act.sa_mask)); + act.sa_flags = 0; + + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + act.sa_handler = sig_int; + sigaction(SIGINT, &act, NULL); + +#ifdef AF_INET6 +# ifdef HAVE_LIBDL + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:L:i:D:S:s:r", long_options, 0)) != -1) { +# else + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46i:D:S:s:r", long_options, 0)) != -1) { +# endif +#else +# ifdef HAVE_LIBDL + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:l:L:i:D:S:s:r", long_options, 0)) != -1) { +# else + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:i:D:S:s:r", long_options, 0)) != -1) { +# endif +#endif + switch (n) { + case 'h': { + usage(AF_VER("Active port forwarder (client)")); + break; + } + case 'n': { + name = optarg; + break; + } + case 'i': { + id = optarg; + break; + } + case 'm': { + manage = optarg; + break; + } + case 'd': { + desnam = optarg; + break; + } + case 'p': { + despor = optarg; + break; + } + case 'v': { + ++verbose; + break; + } + case 'u': { + udp = 1; + break; + } + case 'U': { + reverse = 1; + break; + } + case 'k': { + keys = optarg; + break; + } + case 'O': { + logfname = optarg; + logging = 3; + break; + } + case 'o': { + logfname = optarg; + logging = 1; + break; + } + case 'S': { + logsport = optarg; + socklogging = 3; + break; + } + case 's': { + logsport = optarg; + socklogging = 1; + break; + } + case 301: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + break; + } +#ifdef AF_INET6 + case '4': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 4; + } + break; + } + case '6': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 6; + } + break; + } +#endif +#ifdef HAVE_LIBDL + case 'l': { + module.name = optarg; + break; + } + case 'L': { + secmodule.name = optarg; + break; + } +#endif + case 'D': { + dateformat = optarg; + break; + } + case 'r': { + remote = 1; + break; + } + case '?': { + usage(""); + break; + } + } + } + + if (optind < argc) { + usage("Unrecognized non-option elements"); + } + + if (name == NULL) { + usage("Name of the server is required"); + } + if (manage == NULL) { + manage = "50126"; + if (reverse) + usage("Port on the server is required in reverse mode"); + } + if (keys == NULL) { + keys = "client.rsa"; + } + if ((reverse == 0) && (remote == 0) && (desnam == NULL)) { + gethostname(hostname, 100); + desnam = hostname; + } + if ((!remote) && (despor == NULL)) { + usage("Destination port number is required"); + } + + if ((temp2 = loginit(verbose, logging, socklogging, logfname, logsport, dateformat))) { + switch (temp2) { + case 1: + printf("Can't open file to log to... exiting\n"); + break; + case 2: + printf("Can't connect to localhost:%s... exiting\n", logsport); + break; + case 3: + printf("Can't open socket to log to... exiting\n"); + break; + } + exit(1); + } + +#ifdef HAVE_LIBDL + if (loadmodule(&module)) { + aflog(0, "Loading a module %s failed!", module.name); + exit(1); + } + if (loadmodule(&secmodule)) { + aflog(0, "Loading a module %s failed!", secmodule.name); + exit(1); + } +#endif + + TYPE_SET_SSL(type); + TYPE_SET_ZLIB(type); + +#ifdef AF_INET6 + if (ipfam == -1) { + aflog(0, "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ipfam == 4) { + TYPE_SET_IPV4(type); + } + else if (ipfam == 6) { + TYPE_SET_IPV6(type); + } +#endif + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(type)) { + ipfam |= 0x04; + } +#endif + + if (!reverse) { + SSL_library_init(); + method = SSLv3_client_method(); + ctx = SSL_CTX_new(method); + if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { + aflog(0, "Setting cipher list failed... exiting"); + exit(1); + } + if ((temp2 = create_apf_dir())) { + aflog(1, "Warning: Creating ~/.apf directory failed (%d)", temp2); + } + if ((temp2 = generate_rsa_key(&keys))) { + aflog(1, "Warning: Something bad happened when generating rsa keys... (%d)", temp2); + } + if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) { + aflog(0, "Setting rsa key failed (%s)... exiting", keys); + exit(1); + } + + if (remote) { + temp2 = -1; + if (despor) { + if (ip_listen(&n, desnam, despor, &addrlen, ipfam)) { +#ifdef AF_INET6 + aflog(0, "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor); +#else + aflog(0, "tcp_listen error for %s, %s", desnam, despor); +#endif + exit(1); + } + if (!verbose) + daemon(0, 0); + cliaddr = malloc(addrlen); + temp2 = accept(n, cliaddr, &addrlen); + } + } + + if (ip_connect(&(master.commfd), name, manage, ipfam)) { +#ifdef AF_INET6 + aflog(0, "tcp_connect_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage); +#else + aflog(0, "tcp_connect error for %s, %s", name, manage); +#endif + exit(1); + } + master.ssl = SSL_new(ctx); + if (SSL_set_fd(master.ssl, master.commfd) != 1) { + aflog(0, "Problem with initializing ssl... exiting"); + exit(1); + } + + aflog(1, "Trying SSL_connect"); + if ((n = SSL_connect(master.ssl)) == 1) { + aflog(1, "SSL_connect successfull"); + } + else { + aflog(0, "SSL_connect has failed (%d)... exiting", n); + exit(1); + } + + buff[0] = AF_S_LOGIN; + buff[1] = pass[0]; + buff[2] = pass[1]; + buff[3] = pass[2]; + buff[4] = pass[3]; + + if (remote) { + return client_admin(type, master, buff, temp2, id); + } + + send_message(type, master, buff, 5); + buff[0] = 0; + get_message(type, master, buff, -5); + + if ( buff[0] == 0 ) { + aflog(0, "Wrong password"); + exit(1); + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(0, "Server is full"); + exit(1); + } + if ( buff[0] != AF_S_LOGIN ) { + aflog(0, "Incompatible server type or server full"); + exit(1); + } + + type = buff[3]; + usernum = buff[1]; + usernum = usernum << 8; + usernum += buff[2]; + } /* !reverse */ + else { + usernum = 1; + if (ip_connect(&(master.commfd), name, manage, ipfam)) { +#ifdef AF_INET6 + aflog(0, "tcp_connect_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage); +#else + aflog(0, "tcp_connect error for %s, %s", name, manage); +#endif + exit(1); + } + master.ssl = NULL; + } + + contable = calloc( usernum, sizeof(ConnectuserT)); + if (contable == NULL) { + aflog(0, "Calloc error - unable to succesfully communicate with server"); + exit(1); + } + + len = 4; + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) { + aflog(0, "Can't get socket send buffer size - exiting..."); + exit(1); + } + + if (!verbose) + daemon(0, 0); + + FD_ZERO(&allset); + FD_ZERO(&wset); + + FD_SET(master.commfd, &allset); + maxfdp1 = master.commfd + 1; + + /* UDP REVERSE MODE */ + + if (reverse) { + ipfam = 0; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(type)) { + ipfam |= 0x04; + } +#endif + if (ip_listen(&(contable[0].connfd), desnam, despor, &addrlen, ipfam)) { +#ifdef AF_INET6 + aflog(0, "udp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor); +#else + aflog(0, "udp_listen error for %s, %s", desnam, despor); +#endif + exit(1); + } + cliaddr = malloc(addrlen); + maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1; + FD_SET(contable[0].connfd, &allset); + aflog(1, "CLIENT STARTED mode: udp reverse"); + for ( ; ; ) { + len = 4; + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (temp2 != buflength) { + buflength = temp2; + aflog(2, "Send buffer size changed..."); + } + } + len = addrlen; + rset = allset; + aflog(3, ">select"); + select(maxfdp1, &rset, NULL, NULL, NULL); + aflog(3, " >>after select..."); + + if (FD_ISSET(contable[0].connfd, &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/ + n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len); +#ifdef HAVE_LINUX_SOCKIOS_H +# ifdef SIOCOUTQ + if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { + aflog(0, "ioctl error -> exiting..."); + exit(1); + } + if (buflength <= notsent + n + 5) { /* when we can't do this */ + aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); +# else + if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { + aflog(0, "ioctl error -> exiting..."); + exit(1); + } + if (notsent <= n + 5) { /* when we can't do this */ + aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength); +# endif + } + else { +#endif + if (n > 0) { +#ifdef HAVE_LINUX_SOCKIOS_H + aflog(2, "Sending %d bytes to service (w:%d/%d) (FROM:%s)", n, +# ifdef SIOCOUTQ + notsent +# else + buflength - notsent +# endif + , buflength, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#else + aflog(2, "Sending %d bytes to service (FROM:%s)", n, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#endif + buff[0] = AF_S_MESSAGE; + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; + buff[4] = n; + writen(master.commfd, buff, n + 5); + } +#ifdef HAVE_LINUX_SOCKIOS_H + } +#endif + } /* - FD_ISSET CONTABLE[0].CONNFD RSET */ + + if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + n = readn(master.commfd, buff, 5); + if (n == 5) { + if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) { + aflog(0, "Incompatible server type (not udp?) or data corruption -> exiting..."); + exit(1); + } + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + n = readn(master.commfd, buff, length); + } + else { + n = 0; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(0, "premature quit of the server -> exiting..."); + exit(1); + } + aflog(2, "Sending %d bytes to user (TO:%s)", n, sock_ntop(cliaddr, addrlen, NULL, NULL, 0)); + sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen); + } /* - FD_ISSET MASTER.COMMFD RSET */ + } + exit(0); /* we shouldn't get here */ + } + + /* NORMAL MODE */ + + aflog(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp"); + aflog(1, "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", (TYPE_IS_TCP(type))?"tcp":"udp"); + aflog(2, "CIPHER: %s VER: %s", SSL_get_cipher_name(master.ssl), SSL_get_cipher_version(master.ssl)); +#ifdef HAVE_LIBDL + if (ismloaded(&module)) { + aflog(1, "LOADED MODULE: %s INFO: %s", module.name, module.info()); + } + if (ismloaded(&secmodule)) { + aflog(1, "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + } +#endif + if (id != NULL) { + buff[0] = AF_S_LOGIN; + buff[1] = buff[2] = 0; + n = strlen(id); + memcpy(&buff[5], id, n); + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(type, master, buff, n+5); + aflog(1, "ID SENT: %s", id); + } + + for ( ; ; ) { + rset = allset; + tmpset = wset; + aflog(3, ">select"); + select(maxfdp1, &rset, &tmpset, NULL, NULL); + aflog(3, " >>after select..."); + + for (i = 0; i < usernum; ++i) { + if ((contable[i].state == S_STATE_OPEN)||(contable[i].state == S_STATE_STOPPED)) { + if (FD_ISSET(contable[i].connfd, &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */ + aflog(3, " user[%d]: FD_ISSET", i); + n = read(contable[i].connfd, &buff[5], 8091); + if (n == -1) { + aflog(0, " error (%d): while reading from service", n); + n = 0; + } +#ifdef HAVE_LINUX_SOCKIOS_H +# ifdef SIOCOUTQ + if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { + aflog(0, "ioctl error -> exiting..."); + exit(1); + } + if (udp) { + len = 4; + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (temp2 != buflength) { + buflength = temp2; + aflog(2, "Send buffer size changed..."); + } + } + if (buflength <= notsent + n + 5) { /* when we can't send this */ + aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, notsent, buflength); +# else + if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { + aflog(0, "ioctl error -> exiting..."); + exit(1); + } + if (udp) { + len = 4; + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (temp2 != buflength) { + buflength = temp2; + aflog(2, "Send buffer size changed..."); + } + } + if (notsent <= n + 5) { /* when we can't send this */ + aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", + i, n+5, buflength, buflength-notsent, buflength); +# endif + continue; /* drop this packet */ + } + } +#endif + if (n) { +#ifdef HAVE_LIBDL + if (ismloaded(&secmodule)) { + switch ((temp2 = secmodule.filter(contable[i].namebuf, &buff[5], &n))) { + case 1: case 4: { + aflog(3, " user[%d] (by ser): PACKET IGNORED BY MODULE", i); + if (temp2 == 4) { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + } + continue; + break; + } + case 2: case 5: { + aflog(2, " user[%d] (by ser): DROPPED BY MODULE", i); + close(contable[i].connfd); + FD_CLR(contable[i].connfd, &allset); + FD_CLR(contable[i].connfd, &wset); + contable[i].state = S_STATE_CLOSING; + freebuflist(&contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + send_message(type, master, buff, 5); + if (temp2 == 5) { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + } + continue; + break; + } + case 3: { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + break; + } + } + } +#endif + buff[0] = AF_S_MESSAGE; /* sending message */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ +#ifdef HAVE_LINUX_SOCKIOS_H + aflog(2, " user[%d]: TO msglen: %d [%d/%d]", i, n, +# ifdef SIOCOUTQ + notsent +# else + buflength - notsent +# endif + , buflength); +#else + aflog(2, " user[%d]: TO msglen: %d", i, n); +#endif + send_message(type, master, buff, n+5); + } + else if (!udp) { + aflog(2, " user[%d]: CLOSING", i); + close(contable[i].connfd); + FD_CLR(contable[i].connfd, &allset); + FD_CLR(contable[i].connfd, &wset); + contable[i].state = S_STATE_CLOSING; + freebuflist(&contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + send_message(type, master, buff, 5); + } + } /* - FD_ISSET CONTABLE[i].CONNFD RSET */ + } + } + for (i = 0; i < usernum; ++i) { + if (contable[i].state == S_STATE_STOPPED) { + if (FD_ISSET(contable[i].connfd, &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */ + aflog(3, " user[%d]: FD_ISSET - WRITE", i); + n = contable[i].head->msglen - contable[i].head->actptr; + temp2 = write(contable[i].connfd, &(contable[i].head->buff[contable[i].head->actptr]), n); + if ((temp2 > 0) && (temp2 != n)) { + contable[i].head->actptr+=temp2; + } + else if ((temp2 == -1) && (errno == EAGAIN)) { + aflog(3, " user[%d]: Couldn't write?", i); + } + else if (temp2 == -1) { + close(contable[i].connfd); + FD_CLR(contable[i].connfd, &allset); + FD_CLR(contable[i].connfd, &wset); + contable[i].state = S_STATE_CLOSING; + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + send_message(type, master, buff, 5); + } + else { + deleteblnode(&contable[i].head); + if (contable[i].head == NULL) { + contable[i].state = S_STATE_OPEN; + FD_CLR(contable[i].connfd, &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + aflog(3, " FROM user[%d]: BUFFERING MESSAGE ENDED", i); + send_message(type, master, buff, 5); + } + } + } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */ + } + } + if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + aflog(3, " masterfd: FD_ISSET"); + n = get_message(type, master, buff, 5); + if (n != 5) { + aflog(2, " FATAL ERROR! (%d)", n); + if (n == -1) { + if (TYPE_IS_SSL(type)) { + get_ssl_error(&master, "FE", n); + continue; /* what happened? */ + } + } + if (n != 0) + exit(1); + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(0, " SERVER: premature quit -> exiting..."); + exit(1); + } + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + switch (buff[0]) { + case AF_S_CONCLOSED : { + aflog(4, " user[%d]: AF_S_CONCLOSED", numofcon); + if ((numofcon>=0) && (numofcon<=usernum)) { + usercon--; + if (contable[numofcon].state == S_STATE_CLOSING) { + contable[numofcon].state = S_STATE_CLEAR; + aflog(1, " user[%d]: CLOSED", numofcon); + } + else if ((contable[numofcon].state==S_STATE_OPEN) || (contable[numofcon].state==S_STATE_STOPPED)){ + aflog(1, " user[%d]: CLOSED", numofcon); + close(contable[numofcon].connfd); + FD_CLR(contable[numofcon].connfd, &allset); + FD_CLR(contable[numofcon].connfd, &wset); + contable[numofcon].state = S_STATE_CLEAR; + freebuflist(&contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + } + } + break; + } + case AF_S_CONOPEN : { + aflog(4, " user[%d]: AF_S_CONOPEN", numofcon); + if ((numofcon>=0) && (numofcon<=usernum)) { + usercon++; + if (contable[numofcon].state == S_STATE_CLEAR) { + n = get_message(type, master, buff, length); + memcpy(contable[numofcon].namebuf, buff, 128); + memcpy(contable[numofcon].portbuf,&buff[128],7); + aflog(2, " user[%d]: OPENING", numofcon); + aflog(1, "user[%d]: IP:%s PORT:%s", numofcon, + contable[numofcon].namebuf, contable[numofcon].portbuf); +#ifdef HAVE_LIBDL + if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) { + aflog(2, " IT'S NOT ALLOWED - DROPPING", numofcon); + buff[0] = AF_S_CANT_OPEN; /* not opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + usercon--; + continue; + } +#endif + if (udp) { + ipfam = 0; + } + else { + ipfam = 0x01; + } +#ifdef AF_INET6 + if (TYPE_IS_IPV4(type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(type)) { + ipfam |= 0x04; + } +#endif + if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) { + aflog(2, " CAN'T OPEN - DROPPING", numofcon); + buff[0] = AF_S_CANT_OPEN; /* not opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + usercon--; + continue; + } + temp2 = fcntl(contable[numofcon].connfd, F_GETFL, 0); + fcntl(contable[numofcon].connfd, F_SETFL, temp2 | O_NONBLOCK); + FD_SET(contable[numofcon].connfd, &allset); + maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + contable[numofcon].state = S_STATE_OPEN; + } + } + break; + } + case AF_S_MESSAGE : { + aflog(4, " user[%d]: AF_S_MESSAGE", numofcon); + aflog(2, " user[%d]: FROM msglen: %d", numofcon, length); + n = get_message(type, master, buff, length); + if ((numofcon>=0) && (numofcon<=usernum)) { + if (contable[numofcon].state == S_STATE_OPEN) { +#ifdef HAVE_LIBDL + if (ismloaded(&module)) { + switch ((temp2 = module.filter(contable[numofcon].namebuf, buff, &n))) { + case 1: case 4:{ + aflog(3, " user[%d]: PACKET IGNORED BY MODULE", numofcon); + if (temp2 == 4) { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); + } + continue; + break; + } + case 2: case 5:{ + aflog(2, " user[%d]: DROPPED BY MODULE", numofcon); + close(contable[numofcon].connfd); + FD_CLR(contable[numofcon].connfd, &allset); + FD_CLR(contable[numofcon].connfd, &wset); + contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + if (temp2 == 5) { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); + } + continue; + break; + } + case 3: { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); + break; + } + } + } +#endif + aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n); + temp2 = write(contable[numofcon].connfd, buff, n); + if ((temp2 > 0) && (temp2 != n)) { + insertblnode(&(contable[numofcon].head), temp2, n, buff); + contable[numofcon].state = S_STATE_STOPPED; + FD_SET(contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); + send_message(type, master, buff, 5); + } + else if ((temp2 == -1) && (errno == EAGAIN)) { + insertblnode(&(contable[numofcon].head), 0, n, buff); + contable[numofcon].state = S_STATE_STOPPED; + FD_SET(contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); + send_message(type, master, buff, 5); + } + else if (temp2 == -1) { + close(contable[numofcon].connfd); + FD_CLR(contable[numofcon].connfd, &allset); + FD_CLR(contable[numofcon].connfd, &wset); + contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(type, master, buff, 5); + } + } + else if (contable[numofcon].state == S_STATE_STOPPED) { + aflog(3, " FROM user[%d]: BUFFERING MESSAGE", numofcon); + insertblnode(&(contable[numofcon].head), 0, n, buff); + } + } + break; + } + case AF_S_CLOSING : { /* server shut down -> exiting... */ + aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + exit(1); + break; + } + case AF_S_DONT_SEND: { + aflog(4, " user[%d]: AF_S_DONT_SEND", numofcon); + FD_CLR(contable[numofcon].connfd, &allset); + break; + } + case AF_S_CAN_SEND: { + aflog(4, " user[%d]: AF_S_CAN_SEND", numofcon); + FD_SET(contable[numofcon].connfd, &allset); + break; + } + default : { /* unrecognized type of message -> exiting... */ + aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + exit(1); + break; + } + } + } /* - FD_ISSET MASTER.COMMFD RSET */ + } +} + +static void +usage(char* info) +{ + printf("\n%s\n\n\n", info); + printf(" Basic options:\n\n"); + printf(" -n, --servername - where the second part of the active\n"); + printf(" port forwarder is running (required)\n"); + printf(" -m, --manageport - manage port number - server must be\n"); + printf(" listening on it (default: 50126)\n"); + printf(" -d, --hostname - the name of this host/remote host - the final\n"); + printf(" destination of the packets (default: the name\n"); + printf(" returned by hostname function)\n"); + printf(" -p, --portnum - the port we are forwarding connection to (required)\n"); + printf(" -h, --help - prints this help\n\n"); + printf(" Authorization:\n\n"); + printf(" -i, --id - sends the id string to afserver\n"); + printf(" --pass - set the password used for client identification\n"); + printf(" (default: no password)\n\n"); + printf(" Configuration:\n\n"); + printf(" -k, --keyfile - the name of the file with RSA key (default: client.rsa)\n"); + printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n"); + printf(" for details) (default: %%d.%%m.%%Y %%H:%%M:%%S)\n\n"); + printf(" Modes:\n\n"); + printf(" -u, --udpmode - udp mode - client will use udp protocol to\n"); + printf(" communicate with the hostname:portnum (-p)\n"); + printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n"); + printf(" from hostname:portnum (-p) to the server name:portnum\n"); + printf(" (-m)\n"); + printf(" -r, --remoteadmin - remote administration mode. (using '-p #port' will\n"); + printf(" force afclient to use port rather then stdin-stdout)\n\n"); + printf(" Logging:\n\n"); + printf(" -O, --heavylog - logging everything to a logfile\n"); + printf(" -o, --lightlog - logging some data to a logfile\n"); + printf(" -S, --heavysocklog - logging everything to a localport\n"); + printf(" -s, --lightsocklog - logging some data to a localport\n"); + printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); + printf(" (use several times for greater effect)\n\n"); +#ifdef AF_INET6 + printf(" IP family:\n\n"); + printf(" -4, --ipv4 - use ipv4 only\n"); + printf(" -6, --ipv6 - use ipv6 only\n\n"); +#endif +#ifdef HAVE_LIBDL + printf(" Modules:\n\n"); + printf(" -l, --load - load a module for user's packets filtering\n"); + printf(" -L, --Load - load a module for service's packets filtering\n\n"); +#endif + + exit(0); +} + +static void +sig_int(int signo) +{ + aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/src/afclient.h b/src/afclient.h new file mode 100644 index 0000000..108751b --- /dev/null +++ b/src/afclient.h @@ -0,0 +1,50 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include "stats.h" +#include "modules.h" +#include "remoteadmin.h" +#include "make_ssl_handshake.h" +#include "first_run.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_SOCKIOS_H +#include +#endif +#include +#include +#include + +#include + +#ifndef _JS_AFCLIENT_H +#define _JS_AFCLIENT_H + +static void usage(char* info); +static void sig_int(int); + +#endif + diff --git a/src/afserver.c b/src/afserver.c new file mode 100644 index 0000000..d1e11b7 --- /dev/null +++ b/src/afserver.c @@ -0,0 +1,1720 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "afserver.h" + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"hostname", 1, 0, 'n'}, + {"listenport", 1, 0, 'l'}, + {"manageport", 1, 0, 'm'}, + {"timeout", 1, 0, 't'}, + {"verbose", 0, 0, 'v'}, + {"users", 1, 0, 'u'}, + {"clients", 1, 0, 'C'}, + {"realm", 1, 0, 'r'}, + {"raclients", 1, 0, 'R'}, + {"usrpcli", 1, 0, 'U'}, + {"climode", 1, 0, 'M'}, + {"cerfile", 1, 0, 'c'}, + {"keyfile", 1, 0, 'k'}, + {"cfgfile", 1, 0, 'f'}, + {"proto", 1, 0, 'p'}, + {"lightlog", 1, 0, 'o'}, + {"heavylog", 1, 0, 'O'}, + {"heavysocklog", 1, 0, 'S'}, + {"lightsocklog", 1, 0, 's'}, + {"nossl", 0, 0, 301}, + {"nozlib", 0, 0, 302}, + {"pass", 1, 0, 303}, +#ifdef AF_INET6 + {"ipv4", 0, 0, '4'}, + {"ipv6", 0, 0, '6'}, +#endif + {"baseport", 0, 0, 'b'}, + {"dnslookups", 0, 0, 311}, + {"dateformat", 1, 0, 'D'}, + {0, 0, 0, 0} +}; + +static ConfigurationT config; + +int +main(int argc, char **argv) +{ + int i, j=0, k, l, n, flags, sent = 0; + socklen_t len; + unsigned char buff[9000]; + int maxfdp1; + fd_set rset, allset, wset, tmpset; + int manconnecting, numofcon, length; + char* name = NULL; + char** listen = NULL; + int listencount = 0; + char** manage = NULL; + int managecount = 0; + char* amount = NULL; + char* clients = NULL; + char* raclients = NULL; + char* usrpcli = NULL; + char* clim = NULL; + char* filenam = NULL; + char* type = NULL; + char* timeout = NULL; + char* realmname = NULL; + unsigned char pass[4] = {1, 2, 3, 4}; + char verbose = 0; + char mode = 0; + char ipfam = 0; + char baseport = 0; + char dnslookups = 0; + RealmT* pointer = NULL; + struct sigaction act; + + char* certif = NULL; + char* keys = NULL; + char* logfnam = NULL; + char* logsport = NULL; + char* dateformat = NULL; + char logging = 0; + char socklogging = 0; + + SSL_METHOD* method; + SSL_CTX* ctx; + SSL* tmp_ssl; + + sigfillset(&(act.sa_mask)); + act.sa_flags = 0; + + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + act.sa_handler = sig_int; + sigaction(SIGINT, &act, NULL); + + TYPE_SET_SSL(mode); + TYPE_SET_ZLIB(mode); + + config.certif = NULL; + config.keys = NULL; + config.size = 0; + config.realmtable = NULL; + config.logging = 0; + config.socklogging = 0; + config.logfnam = NULL; + config.logsport = NULL; + config.dateformat = NULL; + +#ifdef AF_INET6 + while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:bD:S:s:R:r:", long_options, 0)) != -1) { +#else + while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:t:C:U:M:bD:S:s:R:r:", long_options, 0)) != -1) { +#endif + switch (n) { + case 'h': { + usage(AF_VER("Active port forwarder (server)")); + break; + } + case 'n': { + name = optarg; + break; + } + case 'l': { + ++listencount; + listen = realloc(listen, sizeof(char*)); + listen[listencount-1] = optarg; + break; + } + case 'm': { + ++managecount; + manage = realloc(manage, sizeof(char*)); + manage[managecount-1] = optarg; + break; + } + case 't': { + timeout = optarg; + break; + } + case 'v': { + ++verbose; + break; + } + case 'u': { + amount = optarg; + break; + } + case 'C': { + clients = optarg; + break; + } + case 'r': { + realmname = optarg; + break; + } + case 'R': { + raclients = optarg; + break; + } + case 'U': { + usrpcli = optarg; + break; + } + case 'M': { + clim = optarg; + break; + } + case 'c': { + certif = optarg; + break; + } + case 'k': { + keys = optarg; + break; + } + case 'p': { + type = optarg; + break; + } + case 'f': { + filenam = optarg; + break; + } + case 'O': { + logfnam = optarg; + logging = 3; + break; + } + case 'o': { + logfnam = optarg; + logging = 1; + break; + } + case 'S': { + logsport = optarg; + socklogging = 3; + break; + } + case 's': { + logsport = optarg; + socklogging = 1; + break; + } + case 301: { + TYPE_UNSET_SSL(mode); + break; + } + case 302: { + TYPE_UNSET_ZLIB(mode); + break; + } + case 303: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + sent = 1; + break; + } +#ifdef AF_INET6 + case '4': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 4; + } + break; + } + case '6': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 6; + } + break; + } +#endif + case 'b': { + baseport = 1; + break; + } + case 311: { + dnslookups = 1; + break; + } + case 'D': { + dateformat = optarg; + break; + } + case '?': { + usage(""); + break; + } + } + } + + if (optind < argc) { + usage("Unrecognized non-option elements"); + } + + if (filenam != NULL) { + config = parsefile(filenam, &n); + if (n) { + printf("parsing failed! line:%d\n", n); + exit(1); + } + else { + if (certif == NULL) { + config.certif = "cacert.pem"; + } + else { + config.certif = certif; + } + if (keys == NULL) { + config.keys = "server.rsa"; + } + else { + config.keys = keys; + } + if (logfnam != NULL) { + config.logfnam = logfnam; + } + if (logsport != NULL) { + config.logsport = logsport; + } + if (dateformat != NULL) { + config.dateformat = dateformat; + } + if (logging != 0) { + config.logging = logging; + } + if (socklogging != 0) { + config.socklogging = socklogging; + } + + if ((k = loginit(verbose, config.logging, config.socklogging, + config.logfnam, config.logsport, config.dateformat))) { + switch (k) { + case 1: + printf("Can't open file to log to... exiting\n"); + break; + case 2: + printf("Can't connect to localhost:%s... exiting\n", logsport); + break; + case 3: + printf("Can't open socket to log to... exiting\n"); + break; + } + exit(1); + } + + aflog(1, "cfg file OK! (readed realms: %d)", config.size); + if (name != NULL) + aflog(1, "Warning: hostname=%s will be ignored", name); + if (listen != NULL) + aflog(1, "Warning: listenport will be ignored"); + if (manage != NULL) + aflog(1, "Warning: manageport will be ignored"); + if (realmname != NULL) + aflog(1, "Warning: realmname=%s will be ignored", realmname); + if (sent == 1) + aflog(1, "Warning: password from command line will be ignored"); + } + } + else { + config.certif = certif; + config.keys = keys; + config.logfnam = logfnam; + config.logsport = logsport; + config.dateformat = dateformat; + config.logging = logging; + config.socklogging = socklogging; + + if ((k = loginit(verbose, config.logging, config.socklogging, + config.logfnam, config.logsport, config.dateformat))) { + switch (k) { + case 1: + printf("Can't open file to log to... exiting\n"); + break; + case 2: + printf("Can't connect to localhost:%s... exiting\n", logsport); + break; + case 3: + printf("Can't open socket to log to... exiting\n"); + break; + } + exit(1); + } + + if (listen == NULL) { + listencount = 1; + listen = calloc(1, sizeof(char*)); + listen[0] = "50127"; + } + if (manage == NULL) { + managecount = 1; + manage = calloc(1, sizeof(char*)); + manage[0] = "50126"; + } + if (managecount != listencount) { + aflog(0, "Number of listen and manage options are not the same... exiting"); + exit(1); + } + if (config.certif == NULL) { + config.certif = "cacert.pem"; + } + if (config.keys == NULL) { + config.keys = "server.rsa"; + } + if (type == NULL) { + type = "tcp"; + } + config.size = 1; + config.realmtable = calloc(config.size, sizeof(RealmT)); + config.realmtable[0].hostname = name; + config.realmtable[0].usrclinum = managecount; + config.realmtable[0].usrclitable = calloc(managecount, sizeof(UsrCliT)); + for (i = 0; i < config.realmtable[0].usrclinum; ++i) { + config.realmtable[0].usrclitable[i].lisportnum = listen[i]; + config.realmtable[0].usrclitable[i].manportnum = manage[i]; + } + config.realmtable[0].users = amount; + config.realmtable[0].clients = clients; + config.realmtable[0].raclients = raclients; + config.realmtable[0].timeout = timeout; + config.realmtable[0].usrpcli = usrpcli; + config.realmtable[0].clim = clim; + config.realmtable[0].baseport = baseport; + config.realmtable[0].dnslookups = dnslookups; + config.realmtable[0].realmname = realmname; + memcpy(config.realmtable[0].pass, pass, 4); + if (strcmp(type, "tcp") == 0) { + TYPE_SET_TCP(config.realmtable[0].type); + } + else if (strcmp(type, "udp") == 0) { + TYPE_SET_UDP(config.realmtable[0].type); + } + else { + TYPE_SET_ZERO(config.realmtable[0].type); + } +#ifdef AF_INET6 + if (ipfam == -1) { + aflog(0, "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ipfam == 4) { + TYPE_SET_IPV4(config.realmtable[0].type); + } + else if (ipfam == 6) { + TYPE_SET_IPV6(config.realmtable[0].type); + } +#endif + config.realmtable[0].type |= mode; + } + + maxfdp1 = manconnecting = 0; + + SSL_library_init(); + method = SSLv3_server_method(); + ctx = SSL_CTX_new(method); + if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { + aflog(0, "Setting ciphers list failed... exiting"); + exit(1); + } + if ((flags = create_apf_dir())) { + aflog(1, "Warning: Creating ~/.apf directory failed (%d)", flags); + } + if ((flags = generate_rsa_key(&config.keys))) { + aflog(1, "Warning: Something bad happened when generating rsa keys... (%d)", flags); + } + if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) { + aflog(0, "Setting rsa key failed (%s)... exiting", config.keys); + exit(1); + } + if ((flags = generate_certificate(&config.certif, config.keys))) { + aflog(1, "Warning: Something bad happened when generating certificate... (%d)", flags); + } + if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) { + aflog(0, "Setting certificate failed (%s)... exiting", config.certif); + exit(1); + } + + if (config.size == 0) { + aflog(0, "Working without sense is really without sense..."); + exit(1); + } + + FD_ZERO(&allset); + FD_ZERO(&wset); + + for (i = 0; i < config.size; ++i) { + if (config.realmtable[i].usrclinum == 0) { + aflog(0, "You have to specify at least one listen port and one manage port in each realm"); + exit(1); + } + for (j = 0; j < config.realmtable[i].usrclinum; ++j) { + if ((config.realmtable[i].usrclitable[j].lisportnum == NULL) || + (config.realmtable[i].usrclitable[j].manportnum == NULL)) { + aflog(0, "Missing some of the variables...\nRealm: %d\nlistenport[%d]: %s\nmanageport[%d]: %s", + i, j, config.realmtable[i].usrclitable[j].lisportnum, + j, config.realmtable[i].usrclitable[j].manportnum); + exit(1); + } + } + /* checking type of the realm */ + if (!TYPE_IS_SET(config.realmtable[i].type)) { + if (type != NULL) { + if (strcmp(type, "tcp") == 0) { + TYPE_SET_TCP(config.realmtable[i].type); + } + else if (strcmp(type, "udp") == 0) { + TYPE_SET_UDP(config.realmtable[i].type); + } + else { + TYPE_SET_TCP(config.realmtable[i].type); + } + } + else { + TYPE_SET_TCP(config.realmtable[i].type); + } + } +#ifdef AF_INET6 + /* using user's value for ipfam*/ + if (TYPE_IS_UNSPEC(config.realmtable[i].type)) { + if (ipfam == -1) { + aflog(0, "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ipfam == 4) { + TYPE_SET_IPV4(config.realmtable[i].type); + } + else if (ipfam == 6) { + TYPE_SET_IPV6(config.realmtable[i].type); + } + } +#endif + /* using user's values for zlib and ssl mode*/ + if (!TYPE_IS_SSL(mode)) { + TYPE_UNSET_SSL(config.realmtable[i].type); + } + if (!TYPE_IS_ZLIB(mode)) { + TYPE_UNSET_ZLIB(config.realmtable[i].type); + } + /* using user's baseport value*/ + if (config.realmtable[i].baseport == 0) { + config.realmtable[i].baseport = baseport; + } + /* using user's dnslookups value*/ + if (config.realmtable[i].dnslookups == 0) { + config.realmtable[i].dnslookups = dnslookups; + } + /* checking users amount */ + set_value(&(config.realmtable[i].users), amount, "5"); + check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount"); + /* checking clients amount */ + set_value(&(config.realmtable[i].clients), clients, "1"); + check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount"); + /* checking raclients amount */ + set_value(&(config.realmtable[i].raclients), raclients, "1"); + check_value(&(config.realmtable[i].raclinum), config.realmtable[i].raclients, "Invalid raclients amount"); + /* checking usrpcli value */ + set_value(&(config.realmtable[i].usrpcli), usrpcli, config.realmtable[i].users); + check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value"); + /* checking timeout value */ + set_value(&(config.realmtable[i].timeout), timeout, "5"); + check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value"); + /* checking climode value */ + set_value(&(config.realmtable[i].clim), clim, "1"); + check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value"); + /* allocating memory*/ + config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT)); + if (config.realmtable[i].contable == NULL) { + aflog(0, "Calloc error - try define smaller amount of users"); + exit(1); + } + config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT)); + if (config.realmtable[i].clitable == NULL) { + aflog(0, "Calloc error - try define smaller amount of clients"); + exit(1); + } + config.realmtable[i].raclitable = calloc( config.realmtable[i].raclinum, sizeof(ConnectclientT)); + if (config.realmtable[i].raclitable == NULL) { + aflog(0, "Calloc error - try define smaller amount of raclients"); + exit(1); + } + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(config.realmtable[i].type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(config.realmtable[i].type)) { + ipfam |= 0x04; + } +#endif + if (config.realmtable[i].baseport == 0) { + for (j = 0; j < config.realmtable[i].usrclinum; ++j) { + if (ip_listen(&(config.realmtable[i].usrclitable[j].listenfd), config.realmtable[i].hostname, + config.realmtable[i].usrclitable[j].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) { + aflog(0, +#ifdef AF_INET6 + "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "tcp_listen error for %s, %s", +#endif + config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].lisportnum); + exit(1); + } + } + } + for (j = 0; j < config.realmtable[i].usrclinum; ++j) { + if (ip_listen(&(config.realmtable[i].usrclitable[j].managefd), config.realmtable[i].hostname, + config.realmtable[i].usrclitable[j].manportnum, (&(config.realmtable[i].addrlen)), ipfam)) { + aflog(0, +#ifdef AF_INET6 + "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "tcp_listen error for %s, %s", +#endif + config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum); + exit(1); + } + } + config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); + + for (j=0; j (config.realmtable[i].usrclitable[j].managefd+1)) ? + maxfdp1 : (config.realmtable[i].usrclitable[j].managefd+1); + } + if (config.realmtable[i].baseport == 0) { + for (j = 0; j < config.realmtable[i].usrclinum; ++j) { + FD_SET(config.realmtable[i].usrclitable[j].listenfd, &allset); + maxfdp1 = (maxfdp1 > (config.realmtable[i].usrclitable[j].listenfd+1)) ? + maxfdp1 : (config.realmtable[i].usrclitable[j].listenfd+1); + } + } + config.realmtable[i].usercon = 0; + config.realmtable[i].clicon = 0; + config.realmtable[i].raclicon = 0; + for (j=0; jselect, maxfdp1: %d", maxfdp1); + if (manconnecting) { + /* find out, in what realm client is trying to connect */ + l = -1; + for (k = 0; k < config.size; ++k) { + for (j=0; j < config.realmtable[k].clinum; ++j) { + if ((config.realmtable[k].clitable[j].ready == 1) || (config.realmtable[k].clitable[j].ready == 2)) { + i = k; + k = config.size; + l = 0; + break; /* so i points to first good realm and j to good client */ + } + } + if (l == -1) { + for (j=0; j < config.realmtable[k].raclinum; ++j) { + if ((config.realmtable[k].raclitable[j].ready==1) || (config.realmtable[k].raclitable[j].ready==2)) { + i = k; + k = config.size; + l = 1; + break; /* so i points to first good realm and j to good client */ + } + } + } + } + if (!l) { + if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].clitable[j].tv))) == 0) { + close (config.realmtable[i].clitable[j].cliconn.commfd); + FD_CLR(config.realmtable[i].clitable[j].cliconn.commfd, &allset); + SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl); + config.realmtable[i].clitable[j].ready = 0; + manconnecting--; + config.realmtable[i].clicon--; + aflog(1, " realm[%s]: Client[%s]: SSL_accept failed (timeout)", + get_realmname(&config, i), get_clientname(pointer, j)); + } + } + else { + if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].raclitable[j].tv))) == 0) { + close (config.realmtable[i].raclitable[j].cliconn.commfd); + FD_CLR(config.realmtable[i].raclitable[j].cliconn.commfd, &allset); + SSL_clear(config.realmtable[i].raclitable[j].cliconn.ssl); + config.realmtable[i].raclitable[j].ready = 0; + manconnecting--; + config.realmtable[i].clicon--; + aflog(1, " realm[%s]: Client[%s] (ra): SSL_accept failed (timeout)", + get_realmname(&config, i), get_raclientname(pointer, j)); + } + } + } + else { + select(maxfdp1, &rset, &tmpset, NULL, NULL); + } + aflog(3, " >>after select..."); + + for (j = 0; j < config.size; ++j) { + pointer = (&(config.realmtable[j])); + for (i = 0; i usernum; ++i) { + if ((pointer->contable[i].state == S_STATE_OPEN) || (pointer->contable[i].state == S_STATE_STOPPED)) + if (FD_ISSET(pointer->contable[i].connfd, &rset)) { + k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); + aflog(3, " realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ + n = read(pointer->contable[i].connfd, &buff[5], 8091); + if (n == -1) { + if (errno == EAGAIN) { + continue; + } + aflog(3, " realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), errno); + n = 0; + } + if (n) { + aflog(2, " realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), n); + if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { + aflog(2, " WARNING: got packet similiar to udp"); + } + buff[0] = AF_S_MESSAGE; /* sending message */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5); + } + else { + aflog(1, " realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, + pointer->contable[i].portbuf); + close(pointer->contable[i].connfd); + FD_CLR(pointer->contable[i].connfd, &allset); + FD_CLR(pointer->contable[i].connfd, &wset); + pointer->contable[i].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + } + else { /* when forwarding udp packets */ + n = readn(pointer->contable[i].connfd, buff, 5 ); + if (n != 5) { + n = 0; + } + if (n) { + if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { + aflog(2, " realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", + get_realmname(&config, j), get_clientname(pointer, pointer->contable[i].whatcli), + get_username(pointer, k), n); + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, + buff, n+5); + } + } + else { + n = 0; + } + } + + if (n == 0) { + aflog(1, " realm[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, + pointer->contable[i].portbuf); + close(pointer->contable[i].connfd); + FD_CLR(pointer->contable[i].connfd, &allset); + FD_CLR(pointer->contable[i].connfd, &wset); + pointer->contable[i].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + + } + } + } + /* ------------------------------------ */ + for (i = 0; i usernum; ++i) { + if (pointer->contable[i].state == S_STATE_STOPPED) + if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { + k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); + aflog(3, " realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr; + sent = write(pointer->contable[i].connfd, + &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n); + if ((sent > 0) && (sent != n)) { + pointer->contable[i].head->actptr+=sent; + aflog(3, " realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), sent, n); + } + else if ((sent == -1) && (errno == EAGAIN)) { + aflog(3, " realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + } + else if (sent == -1) { + aflog(1, " realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k)); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); + close(pointer->contable[i].connfd); + FD_CLR(pointer->contable[i].connfd, &allset); + FD_CLR(pointer->contable[i].connfd, &wset); + pointer->contable[i].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + else { + aflog(3, " realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), sent, n); + deleteblnode(&pointer->contable[i].head); + if (pointer->contable[i].head == NULL) { + pointer->contable[i].state = S_STATE_OPEN; + FD_CLR(pointer->contable[i].connfd, &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + aflog(3, " realm[%s]: Client[%s]: TO user[%d]: BUFFERING MESSAGE ENDED", + get_realmname(&config, j), get_clientname(pointer, pointer->contable[i].whatcli), + get_username(pointer, k)); + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + } + } + } + /* ------------------------------------ */ + if (pointer->baseport == 0) { + for (l = 0; l < pointer->usrclinum; ++l) { + if (FD_ISSET(pointer->usrclitable[l].listenfd, &rset)) { + len = pointer->addrlen; + sent = accept(pointer->usrclitable[l].listenfd, pointer->cliaddr, &len); + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(3, " realm[%s]: listenfd: FD_ISSET", get_realmname(&config, j)); + k = find_client(pointer, pointer->climode, l); + if (pointer->clitable[k].ready == 3) { + if (pointer->usercon == pointer->usernum) { + close(sent); + aflog(3, " realm[%s]: user limit EXCEEDED", get_realmname(&config, j)); + } + else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) { + close(sent); + aflog(3, " realm[%s]: Client[%s]: usrpcli limit EXCEEDED", + get_realmname(&config, j), get_clientname(pointer, k)); + } + else { + for (i = 0; i < pointer->usernum; ++i) { + if (pointer->contable[i].state == S_STATE_CLEAR) { + pointer->contable[i].userid = pointer->usercounter; + ++(pointer->usercounter); + aflog(1, " realm[%s]: Client[%s]: new user: CONNECTING from IP: %s", + get_realmname(&config, j), get_clientname(pointer, k), + sock_ntop(pointer->cliaddr, len, pointer->contable[i].namebuf, + pointer->contable[i].portbuf, pointer->dnslookups)); + pointer->contable[i].connfd = sent; + pointer->contable[i].state = S_STATE_OPENING; + pointer->contable[i].whatcli = k; + time(&pointer->contable[i].connecttime); + pointer->usercon++; + pointer->clitable[k].usercon++; + memcpy(&buff[5], pointer->contable[i].namebuf, 128); + memcpy(&buff[133], pointer->contable[i].portbuf, 7); + n = 135; + i = find_usernum(&(pointer->clitable[k]), i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); + break; + } + } + } + } + else { + close(sent); + aflog(3, " realm[%s]: Client(%d) is NOT CONNECTED", + get_realmname(&config, j), k); + } + } + } + } + /* ------------------------------------ */ + if (pointer->baseport == 1) + for (k = 0; k < pointer->clinum; ++k) + if (pointer->clitable[k].ready == 3) /* Command file descriptor */ + if (FD_ISSET(pointer->clitable[k].listenfd, &rset)) { + len = pointer->addrlen; + sent = accept(pointer->clitable[k].listenfd, pointer->cliaddr, &len); + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(3, " realm[%s]: Client[%s]: listenfd: FD_ISSET", + get_realmname(&config, j), get_clientname(pointer, k)); + if (pointer->clitable[k].ready == 3) { + if (pointer->usercon == pointer->usernum) { + close(sent); + aflog(3, " realm[%s]: user limit EXCEEDED", get_realmname(&config, j)); + } + else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) { + close(sent); + aflog(3, " realm[%s]: Client[%s]: usrpcli limit EXCEEDED", + get_realmname(&config, j), get_clientname(pointer, k)); + } + else { + for (i = 0; i < pointer->usernum; ++i) { + if (pointer->contable[i].state == S_STATE_CLEAR) { + pointer->contable[i].userid = pointer->usercounter; + ++(pointer->usercounter); + aflog(1, " realm[%s]: Client[%s]: new user: CONNECTING from IP: %s", + get_realmname(&config, j), get_clientname(pointer, k), + sock_ntop(pointer->cliaddr, len, pointer->contable[i].namebuf, pointer->contable[i].portbuf, pointer->dnslookups)); + pointer->contable[i].connfd = sent; + pointer->contable[i].state = S_STATE_OPENING; + pointer->contable[i].whatcli = k; + time(&pointer->contable[i].connecttime); + pointer->usercon++; + pointer->clitable[k].usercon++; + memcpy(&buff[5], pointer->contable[i].namebuf, 128); + memcpy(&buff[133], pointer->contable[i].portbuf, 7); + n = 135; + i = find_usernum(&(pointer->clitable[k]), i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); + break; + } + } + } + } + } + /* ------------------------------------ */ + for (k = 0; k < pointer->clinum; ++k) + if ((pointer->clitable[k].ready != 0) && (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset))) { + if (pointer->clitable[k].ready == 1) { + make_ssl_initialize(&(pointer->clitable[k].cliconn)); + aflog(2, " realm[%s]: new Client[%s]: SSL_accept", + get_realmname(&config, j), get_clientname(pointer, k)); + switch (make_ssl_accept(&(pointer->clitable[k].cliconn))) { + case 2: { + close (pointer->clitable[k].cliconn.commfd); + FD_CLR(pointer->clitable[k].cliconn.commfd, &allset); + SSL_clear(pointer->clitable[k].cliconn.ssl); + pointer->clitable[k].ready = 0; + manconnecting--; + pointer->clicon--; + aflog(1, " realm[%s]: new Client[%s]: DENIED by SSL_accept", + get_realmname(&config, j), get_clientname(pointer, k)); + } + case 1: { + continue; + } + default: { + aflog(1, " realm[%s]: new Client[%s]: ACCEPTED by SSL_accept", + get_realmname(&config, j), get_clientname(pointer, k)); + pointer->clitable[k].ready = 2; + continue; + } + } + } + aflog(3, " realm[%s]: Client[%s]: commfd: FD_ISSET", + get_realmname(&config, j), get_clientname(pointer, k)); + if (pointer->clitable[k].ready == 2) { + n = get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, -5); + } + else { + n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5); + } + if (n == -1) { + if (errno == EAGAIN) { + aflog(4, " realm[%s]: Client[%s]: commfd: EAGAIN", + get_realmname(&config, j), get_clientname(pointer, k)); + continue; + } + else { + aflog(4, " realm[%s]: Client[%s]: commfd: ERROR: %d", + get_realmname(&config, j), get_clientname(pointer, k), errno); + n = 0; + } + } + else if (n != 5) { + if (n != 0) { + aflog(4, " realm[%s]: Client[%s]: header length = %d --> closing client", + get_realmname(&config, j), get_clientname(pointer, k), n); + } + n = 0; + } + if (n==0) { + remove_client(pointer, k, &allset, &wset, &manconnecting); + aflog(1, " realm[%s]: Client[%s]: commfd: CLOSED", + get_realmname(&config, j), get_clientname(pointer, k)); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if ((k == pointer->clinum) && (buff[0] != AF_S_LOGIN) && + (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) { + buff[0] = AF_S_WRONG; + } + if (pointer->clitable[k].ready<2) { + aflog(1, " realm[%s]: Client[%s]: Impossible behaviour --> ignoring", + get_realmname(&config, j), get_clientname(pointer, k)); + continue; + } + if ((pointer->clitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + switch (buff[0]) { + case AF_S_CONCLOSED : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + pointer->usercon--; + pointer->clitable[k].usercon--; + pointer->clitable[k].users[n] = -1; + if (pointer->contable[numofcon].state == S_STATE_CLOSING) { + pointer->contable[numofcon].state = S_STATE_CLEAR; + aflog(3, " realm[%s]: user[%d]: CLOSE CONFIRMED", + get_realmname(&config, j), get_username(pointer, numofcon)); + } + else if ((pointer->contable[numofcon].state == S_STATE_OPEN) || + (pointer->contable[numofcon].state == S_STATE_STOPPED)) { + aflog(1, " realm[%s]: user[%d]: KICKED", + get_realmname(&config, j), get_username(pointer, numofcon)); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLEAR; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_CONOPEN : { + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + if (pointer->contable[numofcon].state == S_STATE_OPENING) { + aflog(2, " realm[%s]: user[%d]: NEW", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_SET(pointer->contable[numofcon].connfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? + maxfdp1 : (pointer->contable[numofcon].connfd+1); + pointer->contable[numofcon].state = S_STATE_OPEN; + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_CANT_OPEN : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + if (pointer->contable[numofcon].state == S_STATE_OPENING) { + aflog(2, " realm[%s]: user[%d]: DROPPED", + get_realmname(&config, j), get_username(pointer, numofcon)); + pointer->usercon--; + pointer->clitable[k].usercon--; + pointer->clitable[k].users[n] = -1; + close(pointer->contable[numofcon].connfd); + pointer->contable[numofcon].state = S_STATE_CLEAR; + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_MESSAGE : { + if ((pointer->clitable[k].ready) != 3) { + remove_client(pointer, k, &allset, &wset, &manconnecting); + break; + } + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + n = get_message(pointer->type, pointer->clitable[k].cliconn, &buff[5], length); + } + else { + n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); + } + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum))) { + if (pointer->contable[numofcon].state == S_STATE_OPEN) { + aflog(2, " realm[%s]: TO user[%d]: MESSAGE length=%d", + get_realmname(&config, j), get_username(pointer, numofcon), n); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + sent = write(pointer->contable[numofcon].connfd, buff, n+5); + if (sent == -1) { + aflog(1, " realm[%s]: user[%d]: CLOSED (write-udp)", + get_realmname(&config, j), get_username(pointer, numofcon)); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + else { /* tcp */ + sent = write(pointer->contable[numofcon].connfd, buff, n); + if ((sent > 0) && (sent != n)) { + insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", + get_realmname(&config, j), get_username(pointer, numofcon), sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if ((sent == -1) && (errno == EAGAIN)) { + insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", + get_realmname(&config, j), get_username(pointer, numofcon), sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if (sent == -1) { + aflog(1, " realm[%s]: user[%d]: CLOSED (write-tcp)", + get_realmname(&config, j), get_username(pointer, numofcon)); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + } + else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { + aflog(3, " realm[%s]: TO user[%d]: BUFFERING MESSAGE (%d)", + get_realmname(&config, j), get_username(pointer, numofcon), n); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); + } + else { + insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + } + } + else if (pointer->contable[numofcon].state == S_STATE_CLOSING) { + aflog(3, " realm[%s]: TO user[%d]: IGNORED message length=%d", + get_realmname(&config, j), get_username(pointer, numofcon), n); + } + } + break; + } + case AF_S_LOGIN : { + if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + if (k != pointer->clinum) { + pointer->clitable[k].ready = 3; + aflog(1, " realm[%s]: Client[%s]: pass ok - ACCESS GRANTED", + get_realmname(&config, j), get_clientname(pointer, k)); + buff[0] = AF_S_LOGIN; /* sending message */ + buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */ + buff[2] = pointer->clitable[k].usernum; /* low bits of user number */ + buff[3] = pointer->type; /* type of connection */ + send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, 5); + manconnecting--; + if (pointer->baseport == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long(pointer->usrclitable[pointer->clitable[k].whatusrcli].lisportnum, &tmp_val)) { + aflog(1, " realm[%s]: INVALID listenport - removing Client[%s]", + get_realmname(&config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, &manconnecting); + break; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(pointer->type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(pointer->type)) { + ipfam |= 0x04; + } +#endif + while (ip_listen(&(pointer->clitable[k].listenfd), pointer->hostname, + tmp_tab, (&(pointer->addrlen)), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + FD_SET(pointer->clitable[k].listenfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->clitable[k].listenfd+1)) ? + maxfdp1 : (pointer->clitable[k].listenfd+1); + aflog(1, " realm[%s]: Client[%s]: listenport=%s", + get_realmname(&config, j), get_clientname(pointer, k), tmp_tab); + } + } + else { + aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + else if ((pointer->clitable[k].ready == 3) && (numofcon == 0)) { + n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); + buff[n] = 0; + aflog(1, " realm[%s]: Client[%s]: ID received: %s", + get_realmname(&config, j), get_clientname(pointer, k), buff); + if (pointer->clitable[k].clientid) { + free(pointer->clitable[k].clientid); + } + pointer->clitable[k].clientid = malloc(n+1); + if (pointer->clitable[k].clientid) { + memcpy(pointer->clitable[k].clientid, buff, n+1); + } + } + else { + aflog(1, " realm[%s]: Client[%s]: Wrong password - CLOSING", + get_realmname(&config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_DONT_SEND: { + aflog(3, " realm[%s]: user[%d]: STOP READING", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + break; + } + case AF_S_CAN_SEND: { + aflog(3, " realm[%s]: user[%d]: START READING", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_SET(pointer->contable[numofcon].connfd, &allset); + break; + } + case AF_S_WRONG: { + aflog(1, " realm[%s]: Client[%s]: Wrong message - CLOSING", + get_realmname(&config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, &manconnecting); + break; + } + case AF_S_ADMIN_LOGIN: { + if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + aflog(1, " realm[%s]: Client[%s]: NEW remote admin -- pass OK", + get_realmname(&config, j), get_clientname(pointer, k)); + for (l = 0; l < pointer->raclinum; ++l) { + if (pointer->raclitable[l].ready == 0) { + pointer->raclitable[l].cliconn.commfd = pointer->clitable[k].cliconn.commfd; + pointer->raclitable[l].connecttime = pointer->clitable[k].connecttime; + pointer->raclitable[l].clientnum = pointer->clitable[k].clientnum; + memcpy(pointer->raclitable[l].namebuf, pointer->clitable[k].namebuf, 128); + memcpy(pointer->raclitable[l].portbuf, pointer->clitable[k].portbuf, 7); + tmp_ssl = pointer->raclitable[l].cliconn.ssl; + pointer->raclitable[l].cliconn.ssl = pointer->clitable[k].cliconn.ssl; + pointer->clitable[k].cliconn.ssl = tmp_ssl; + pointer->clitable[k].ready = 0; + break; + } + } + if (l != pointer->raclinum) { + pointer->raclitable[l].ready = 3; + pointer->raclicon++; + manconnecting--; + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = pointer->type; /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type | TYPE_SSL, pointer->raclitable[l].cliconn, buff, n+5); + } + else { + aflog(1, " realm[%s]: Client[%s]: remote admin -- limit EXCEEDED", + get_realmname(&config, j), get_clientname(pointer, k)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, 5); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + break; + } + default : { + aflog(1, " realm[%s]: Client[%s]: Unrecognized message - CLOSING", + get_realmname(&config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + } + /* ------------------------------------ */ + for (k = 0; k < pointer->raclinum; ++k) + if ((pointer->raclitable[k].ready != 0) && (FD_ISSET(pointer->raclitable[k].cliconn.commfd, &rset))) { + if (pointer->raclitable[k].ready == 1) { + make_ssl_initialize(&(pointer->raclitable[k].cliconn)); + aflog(2, " realm[%s]: new Client[%s] (ra): SSL_accept", + get_realmname(&config, j), get_raclientname(pointer, k)); + switch (make_ssl_accept(&(pointer->raclitable[k].cliconn))) { + case 2: { + close (pointer->raclitable[k].cliconn.commfd); + FD_CLR(pointer->raclitable[k].cliconn.commfd, &allset); + SSL_clear(pointer->raclitable[k].cliconn.ssl); + pointer->raclitable[k].ready = 0; + manconnecting--; + pointer->clicon--; + aflog(1, " realm[%s]: new Client[%s] (ra): DENIED by SSL_accept", + get_realmname(&config, j), get_raclientname(pointer, k)); + } + case 1: { + continue; + } + default: { + aflog(1, " realm[%s]: new Client[%s] (ra): ACCEPTED by SSL_accept", + get_realmname(&config, j), get_raclientname(pointer, k)); + pointer->raclitable[k].ready = 2; + continue; + } + } + } + aflog(3, " realm[%s]: Client[%s] (ra): commfd: FD_ISSET", + get_realmname(&config, j), get_raclientname(pointer, k)); + n = get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, -5); + if (n == -1) { + if (errno == EAGAIN) { + aflog(4, " realm[%s]: Client[%s] (ra): commfd: EAGAIN", + get_realmname(&config, j), get_raclientname(pointer, k)); + continue; + } + else { + aflog(4, " realm[%s]: Client[%s] (ra): commfd: ERROR: %d", + get_realmname(&config, j), get_raclientname(pointer, k), errno); + n = 0; + } + } + else if (n != 5) { + if (n != 0) { + aflog(4, " realm[%s]: Client[%s] (ra): header length = %d --> closing client", + get_realmname(&config, j), get_raclientname(pointer, k), n); + } + n = 0; + } + if (n==0) { + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + aflog(1, " realm[%s]: Client[%s] (ra): commfd: CLOSED", + get_realmname(&config, j), get_raclientname(pointer, k)); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if (pointer->raclitable[k].ready<2) { + aflog(1, " realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", + get_realmname(&config, j), get_raclientname(pointer, k)); + continue; + } + if ((pointer->raclitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + switch (buff[0]) { + case AF_S_LOGIN : { + if ((pointer->raclitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + for (l = 0; l < pointer->clinum; ++l) { + if (!(pointer->clitable[l].ready)) { + aflog(1, " realm[%s]: Client[%s] (ra) --> Client[%s]", + get_realmname(&config, j), get_raclientname(pointer, k), get_clientname(pointer, l)); + pointer->clitable[l].cliconn.commfd = pointer->raclitable[k].cliconn.commfd; + pointer->clitable[l].connecttime = pointer->raclitable[k].connecttime; + pointer->clitable[l].clientnum = pointer->raclitable[k].clientnum; + memcpy(pointer->clitable[l].namebuf, pointer->raclitable[k].namebuf, 128); + memcpy(pointer->clitable[l].portbuf, pointer->raclitable[k].portbuf, 7); + tmp_ssl = pointer->clitable[l].cliconn.ssl; + pointer->clitable[l].cliconn.ssl = pointer->raclitable[k].cliconn.ssl; + pointer->raclitable[k].cliconn.ssl = tmp_ssl; + pointer->clitable[l].whatusrcli = pointer->raclitable[k].whatusrcli; + pointer->raclitable[k].ready = 0; + break; + } + } + if (l != pointer->clinum) { + pointer->clitable[l].ready = 3; + aflog(1, " realm[%s]: Client[%s]: pass ok - ACCESS GRANTED", + get_realmname(&config, j), get_clientname(pointer, l)); + buff[0] = AF_S_LOGIN; /* sending message */ + buff[1] = pointer->clitable[l].usernum >> 8;/* high bits of user number */ + buff[2] = pointer->clitable[l].usernum; /* low bits of user number */ + buff[3] = pointer->type; /* type of connection */ + send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[l].cliconn, buff, 5); + manconnecting--; + if (pointer->baseport == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long(pointer->usrclitable[pointer->clitable[l].whatusrcli].lisportnum, &tmp_val)) { + aflog(1, " realm[%s]: INVALID listenport - removing Client[%s]", + get_realmname(&config, j), get_clientname(pointer, l)); + remove_client(pointer, l, &allset, &wset, &manconnecting); + break; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(pointer->type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(pointer->type)) { + ipfam |= 0x04; + } +#endif + while (ip_listen(&(pointer->clitable[l].listenfd), pointer->hostname, + tmp_tab, (&(pointer->addrlen)), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + FD_SET(pointer->clitable[l].listenfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->clitable[l].listenfd+1)) ? + maxfdp1 : (pointer->clitable[l].listenfd+1); + aflog(1, " realm[%s]: Client[%s]: listenport=%s", + get_realmname(&config, j), get_clientname(pointer, l), tmp_tab); + } + } + else { + aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, 5); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + } + else if ((pointer->raclitable[k].ready == 3) && (numofcon == 0)) { + n = get_message(pointer->type, pointer->raclitable[k].cliconn, buff, length); + buff[n] = 0; + aflog(1, " realm[%s]: Client[%s] (ra): ID received: %s", + get_realmname(&config, j), get_raclientname(pointer, k), buff); + if (pointer->raclitable[k].clientid) { + free(pointer->raclitable[k].clientid); + } + pointer->raclitable[k].clientid = malloc(n+1); + if (pointer->raclitable[k].clientid) { + memcpy(pointer->raclitable[k].clientid, buff, n+1); + } + } + else { + aflog(1, " realm[%s]: Client[%s] (ra): Wrong password - CLOSING", + get_realmname(&config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_WRONG: { + aflog(1, " realm[%s]: Client[%s] (ra): Wrong message - CLOSING", + get_realmname(&config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + break; + } + case AF_S_ADMIN_LOGIN: { + if ((pointer->raclitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + aflog(1, " realm[%s]: Client[%s] (ra): NEW remote admin -- pass OK", + get_realmname(&config, j), get_raclientname(pointer, k)); + pointer->raclitable[k].ready = 3; + pointer->raclicon++; + manconnecting--; + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = pointer->type; /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, n+5); + } + break; + } + case AF_S_ADMIN_CMD: { + if (pointer->raclitable[k].ready == 3) { + if (serve_admin(&config, j, k, buff)) { + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + } + else { + aflog(1, " realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION", + get_realmname(&config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + default : { + aflog(1, " realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING", + get_realmname(&config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + } + } + /* ------------------------------------ */ + for (l = 0; l < pointer->usrclinum; ++l) { + if (FD_ISSET(pointer->usrclitable[l].managefd, &rset)) { + aflog(3, " realm[%s]: managefd: FD_ISSET", get_realmname(&config, j)); + len = pointer->addrlen; + sent = accept(pointer->usrclitable[l].managefd,pointer->cliaddr,&len); + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + for (k = 0; k < pointer->clinum; ++k) { + if (!(pointer->clitable[k].ready)) { + pointer->clitable[k].clientnum = pointer->clientcounter; + ++(pointer->clientcounter); + aflog(2, " realm[%s]: new Client[%s]: CONNECTING", + get_realmname(&config, j), get_clientname(pointer, k)); + pointer->clitable[k].cliconn.commfd = sent; + pointer->clitable[k].whatusrcli = l; + time(&pointer->clitable[k].connecttime); + aflog(1, " realm[%s]: new Client[%s] IP:%s", get_realmname(&config, j), get_clientname(pointer, k), + sock_ntop(pointer->cliaddr, len, pointer->clitable[k].namebuf, + pointer->clitable[k].portbuf, pointer->dnslookups)); + FD_SET(pointer->clitable[k].cliconn.commfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ? + maxfdp1 : (pointer->clitable[k].cliconn.commfd+1); + pointer->clicon++; + pointer->clitable[k].tv.tv_sec = pointer->tmout; + manconnecting++; + pointer->clitable[k].ready = 1; + break; + } + } + if (k == pointer->clinum) { + for (k = 0; k < pointer->raclinum; ++k) { + if ((!pointer->raclitable[k].ready)) { + pointer->raclitable[k].clientnum = pointer->clientcounter; + ++(pointer->clientcounter); + aflog(2, " realm[%s]: new Client[%s] (ra): CONNECTING", + get_realmname(&config, j), get_raclientname(pointer, k)); + pointer->raclitable[k].cliconn.commfd = sent; + pointer->raclitable[k].whatusrcli = l; + time(&pointer->raclitable[k].connecttime); + aflog(1, " realm[%s]: new Client[%s] (ra) IP:%s", + get_realmname(&config, j), get_raclientname(pointer, k), + sock_ntop(pointer->cliaddr, len, pointer->raclitable[k].namebuf, + pointer->raclitable[k].portbuf, pointer->dnslookups)); + FD_SET(pointer->raclitable[k].cliconn.commfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->raclitable[k].cliconn.commfd+1)) ? + maxfdp1 : (pointer->raclitable[k].cliconn.commfd+1); + pointer->clicon++; + pointer->raclitable[k].tv.tv_sec = pointer->tmout; + manconnecting++; + pointer->raclitable[k].ready = 1; + break; + } + } + if (k == pointer->raclinum) { + aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + close(sent); + } + } + } + } + } /* realms loop */ + } +} + +static void +usage(char* info) +{ + printf("\n%s\n\n\n", info); + printf(" Basic options:\n\n"); + printf(" -n, --hostname - it's used when creating listening sockets\n"); + printf(" (default: '')\n"); + printf(" -l, --listenport - listening port number - users connect\n"); + printf(" to it (default: 50127)\n"); + printf(" -m, --manageport - manage port number - second part of the active\n"); + printf(" port forwarder connects to it (default: 50126)\n"); + printf(" -h, --help - prints this help\n\n"); + printf(" Authorization:\n\n"); + printf(" --pass - set the password used for client identification\n"); + printf(" (default: no password)\n\n"); + printf(" Configuration:\n\n"); + printf(" -c, --cerfile - the name of the file with certificate\n"); + printf(" (default: cacert.pem)\n"); + printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n"); + printf(" -f, --cfgfile - the name of the file with the configuration for the\n"); + printf(" active forwarder (server)\n"); + printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n"); + printf(" for details) (default: %%d.%%m.%%Y %%H:%%M:%%S)\n\n"); + printf(" -t, --timeout - the timeout value for the client's connection\n"); + printf(" (default: 5)\n"); + printf(" -u, --users - the amount of users allowed to use this server\n"); + printf(" (default: 5)\n"); + printf(" -C, --clients - the number of allowed clients to use this server\n"); + printf(" (default: 1)\n"); + printf(" -r, --realm - set the realm name (default: none)\n"); + printf(" -R, --raclients - the number of allowed clients in remote administration\n"); + printf(" mode to use this server (default: 1)\n"); + printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n"); + printf(" -M, --climode - strategy used to connect users with clients (default: 1)\n"); + printf(" Available strategies:\n"); + printf(" 1. fill first client before go to next\n\n"); + printf(" -p, --proto - type of server (tcp|udp) - what protocol it will be\n"); + printf(" operating for (default: tcp)\n"); + printf(" -b, --baseport - listenports are temporary and differ for each client\n"); + printf(" --nossl - ssl is not used to transfer data (but it's still used\n"); + printf(" to establish a connection) (default: ssl is used)\n"); + printf(" --nozlib - zlib is not used to compress data (default: zlib is\n"); + printf(" used)\n"); + printf(" --dnslookups - try to obtain dns names of the computers rather than\n"); + printf(" their numeric IP\n\n"); + printf(" Logging:\n\n"); + printf(" -O, --heavylog - logging everything to a logfile\n"); + printf(" -o, --lightlog - logging some data to a logfile\n"); + printf(" -S, --heavysocklog - logging everything to a localport\n"); + printf(" -s, --lightsocklog - logging some data to a localport\n"); + printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); + printf(" (use several times for greater effect)\n\n"); +#ifdef AF_INET6 + printf(" IP family:\n\n"); + printf(" -4, --ipv4 - use ipv4 only\n"); + printf(" -6, --ipv6 - use ipv6 only\n\n"); +#endif + exit(0); +} + +static void +sig_int(int signo) +{ + int i, j; + unsigned char buff[5]; + for (j = 0; j < config.size; ++j) { + buff[0] = AF_S_CLOSING; /* closing */ + for (i = 0; i < config.realmtable[j].clinum+1; ++i) { + if (config.realmtable[j].clitable[i].ready == 3) { + if (config.realmtable[j].clinum == i) { + send_message(config.realmtable[j].type | TYPE_SSL, config.realmtable[j].clitable[i].cliconn, buff, 5); + } + else { + send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5); + } + } + } + } + aflog(1, "SERVER CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/src/afserver.h b/src/afserver.h new file mode 100644 index 0000000..6975af4 --- /dev/null +++ b/src/afserver.h @@ -0,0 +1,51 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include "file.h" +#include "stats.h" +#include "remoteadmin.h" +#include "server_check.h" +#include "server_set.h" +#include "server_eval.h" +#include "server_find.h" +#include "server_remove.h" +#include "make_ssl_handshake.h" +#include "first_run.h" +#include "realmnames.h" +#include "clientnames.h" +#include "usernames.h" + +#include +#include +#include +#include +#include +#include + +#ifndef _JS_AFSERVER_H +#define _JS_AFSERVER_H + +static void usage(char* info); +static void sig_int(int); + +#endif + diff --git a/src/buflist.c b/src/buflist.c new file mode 100644 index 0000000..7ee5ede --- /dev/null +++ b/src/buflist.c @@ -0,0 +1,70 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "buflist.h" + +int +insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff) +{ + blnodeT* newnode, *lastnode; + lastnode = newnode = *headRef; + while (newnode) { + lastnode = newnode; + newnode = newnode->next; + } + newnode = calloc(1, sizeof(blnodeT)); + newnode->next = NULL; + newnode->actptr = 0; + newnode->msglen = msglen - actptr; + newnode->buff = calloc(1, newnode->msglen); + if (newnode->buff == NULL) + return 1; + memcpy((char*)newnode->buff, (char*)buff+actptr, newnode->msglen); + if (lastnode) + lastnode->next = newnode; + else + *headRef = newnode; + return 0; +} + +int +deleteblnode(blnodeT** headRef) +{ + blnodeT* node = *headRef; + if (*headRef == NULL) + return 1; + *headRef = node->next; + if (node->buff != NULL) + free(node->buff); + free(node); + return 0; +} + +int +freebuflist(blnodeT** headRef) +{ + while (*headRef) { + deleteblnode(headRef); + } + return 0; +} diff --git a/src/buflist.h b/src/buflist.h new file mode 100644 index 0000000..bc96e73 --- /dev/null +++ b/src/buflist.h @@ -0,0 +1,35 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_BUFLIST_H +#define _JS_BUFLIST_H + +typedef struct blnode { + int actptr; + int msglen; + unsigned char* buff; + struct blnode* next; +} blnodeT; + +int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff); +int deleteblnode(blnodeT** headRef); +int freebuflist(blnodeT** headRef); + +#endif diff --git a/src/clientnames.c b/src/clientnames.c new file mode 100644 index 0000000..9658903 --- /dev/null +++ b/src/clientnames.c @@ -0,0 +1,129 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include "clientnames.h" + +char* +get_clientname(RealmT* pointer, int client) +{ + static char clientname[10]; + + if (pointer->clitable[client].clientid == NULL) { + memset(clientname, 0, 10); + sprintf(clientname, "%d", pointer->clitable[client].clientnum); + return clientname; + } + + return pointer->clitable[client].clientid; +} + +int +get_clientid(RealmT* pointer, char* clientname) +{ + int i, n; + char guard; + + for (i = 0; i < pointer->clinum; ++i) { + if (pointer->clitable[i].clientid != NULL) { + if (strcmp(clientname, pointer->clitable[i].clientid) == 0) { + return pointer->clitable[i].clientnum; + } + } + } + + if (sscanf(clientname, "%d%c", &i, &guard) == 1) { + n = get_clientnumber(pointer, i); + if ((n >= 0) && (n < pointer->clinum)) { + if (pointer->clitable[n].clientid == NULL) { + return i; + } + } + } + + return -1; +} + +int +get_clientnumber(RealmT* pointer, int clientid) +{ + int i; + for (i = 0; i < pointer->clinum; ++i) { + if (pointer->clitable[i].clientnum == clientid) { + return i; + } + } + + return -1; +} + +char* +get_raclientname(RealmT* pointer, int client) +{ + static char clientname[10]; + + if (pointer->raclitable[client].clientid == NULL) { + memset(clientname, 0, 10); + sprintf(clientname, "%d", pointer->raclitable[client].clientnum); + return clientname; + } + + return pointer->raclitable[client].clientid; +} + +int +get_raclientid(RealmT* pointer, char* clientname) +{ + int i, n; + char guard; + + for (i = 0; i < pointer->raclinum; ++i) { + if (pointer->raclitable[i].clientid != NULL) { + if (strcmp(clientname, pointer->raclitable[i].clientid) == 0) { + return pointer->raclitable[i].clientnum; + } + } + } + + if (sscanf(clientname, "%d%c", &i, &guard) == 1) { + n = get_raclientnumber(pointer, i); + if ((n >= 0) && (n < pointer->raclinum)) { + if (pointer->raclitable[n].clientid == NULL) { + return i; + } + } + } + + return -1; +} + +int +get_raclientnumber(RealmT* pointer, int clientid) +{ + int i; + for (i = 0; i < pointer->raclinum; ++i) { + if (pointer->raclitable[i].clientnum == clientid) { + return i; + } + } + + return -1; +} diff --git a/src/clientnames.h b/src/clientnames.h new file mode 100644 index 0000000..c93a2dc --- /dev/null +++ b/src/clientnames.h @@ -0,0 +1,35 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" + +#ifndef _JS_CLIENTNAMES_H +#define _JS_CLIENTNAMES_H + +char* get_clientname(RealmT*, int); +int get_clientid(RealmT*, char*); +int get_clientnumber(RealmT*, int); + +char* get_raclientname(RealmT*, int); +int get_raclientid(RealmT*, char*); +int get_raclientnumber(RealmT*, int); + +#endif + diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..e4cde62 --- /dev/null +++ b/src/file.c @@ -0,0 +1,373 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" +#include "activefor.h" +#include +#include +#include +#include +#include + +int +parse_line(char* buff, char* tab1, char* tab2) +{ + int state, i, j, lastDot; + state = i = j = 0; + lastDot = -1; + while (buff[i] != 0) { + if (buff[i] == '#') { + if ((i > 0) && (buff[i-1] == '\\')) { + --j; + } + else { + break; + } + } + switch (state) { + case 0: { /* before option name */ + if (!isspace(buff[i])) { + tab1[j] = buff[i]; + j = 1; + state = 1; + } + break; + } + case 1: { /* option */ + if (isspace(buff[i])) { + tab1[j] = 0; + state = 2; + j = 0; + } + else { + tab1[j] = buff[i]; + ++j; + } + break; + } + case 2: { /* before option value */ + if (!isspace(buff[i])) { + if (buff[i] != '.') { + tab2[j] = buff[i]; + j = 1; + } + state = 3; + } + break; + } + case 3: { /* option value */ + if (buff[i] == '.') { + lastDot = j; + } + else if (!isspace(buff[i])) { + lastDot = -1; + } + else if (lastDot == -1) { + lastDot = j; + } + tab2[j] = buff[i]; + ++j; + break; + } + } + ++i; + } + if (lastDot != -1) { + tab2[lastDot] = 0; + } + if (state == 3) { + return 2; + } + if (state == 0) { + return 0; + } + return 1; +} + +ConfigurationT +parsefile(char* name, int* status) +{ + static ConfigurationT cfg; + FILE* file = NULL; + int state, i, n, listencount, managecount; + char buff[256]; + char helpbuf1[256]; + char helpbuf2[256]; + + *status = 1; + + memset(buff, 0, 256); + + cfg.certif = NULL; + cfg.keys = NULL; + cfg.size = 0; + cfg.realmtable = NULL; + cfg.logging = 0; + cfg.socklogging = 0; + cfg.logfnam = NULL; + cfg.logsport = NULL; + cfg.dateformat = NULL; + + state = F_UNKNOWN; + + file = fopen(name, "r"); + if (file == NULL) { + return cfg; + } + + while (fgets(buff, 256, file) != NULL) { /* first loop - counting realm */ + helpbuf1[0] = 0; + parse_line(buff, helpbuf1, helpbuf2); + if (strcmp(helpbuf1, "realm")==0) { + ++cfg.size; + } + } + rewind(file); + + cfg.realmtable = calloc(cfg.size, sizeof(RealmT)); + for (i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include + +#ifndef _JS_FILE_H +#define _JS_FILE_H + +#define F_UNKNOWN 1 +#define F_IGNORE 2 +#define F_ROPTION 3 +#define F_RVALUE 4 +#define F_MIDDLE 5 + +ConfigurationT parsefile(char*, int*); /* parse the cfg file */ + +#endif + diff --git a/src/first_run.c b/src/first_run.c new file mode 100644 index 0000000..842a3e0 --- /dev/null +++ b/src/first_run.c @@ -0,0 +1,156 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static char* home_dir = NULL; +static char* home_dir_key = NULL; +static char* home_dir_cer = NULL; + +int +create_apf_dir() +{ + int length; + struct stat buf; + struct passwd *user = getpwuid(getuid()); + if (user == NULL) { + return 1; /* some problems witch fetching user info*/ + } + if (user->pw_dir == NULL) { + return 2; /* home directory is not set? */ + } + if (home_dir) { + free(home_dir); + home_dir = NULL; + } + length = strlen(user->pw_dir); + home_dir = calloc(1, length + 6); + if (home_dir == NULL) { + return 3; /* calloc failed */ + } + strcpy(home_dir, user->pw_dir); + if (home_dir[length] == '/') { + strcpy(&home_dir[length], ".apf"); + } + else { + strcpy(&home_dir[length], "/.apf"); + } + if (stat(home_dir, &buf)) { + if (mkdir(home_dir, 0700)) { + return 4; /* creating directory failed */ + } + } + return 0; +} + +int +generate_rsa_key(char** keyfile) +{ + int key_length, home_length, status; + char openssl_cmd[101]; + struct stat buf; + /* check in local directory first */ + if (stat(*keyfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + key_length = strlen(*keyfile); + home_length = strlen(home_dir); + if (home_dir_key) { + free(home_dir_key); + home_dir_key = NULL; + } + home_dir_key = calloc(1, home_length + key_length + 2); + if (home_dir_key == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_key, home_dir); + home_dir_key[home_length] = '/'; + strcpy(&home_dir_key[home_length+1], *keyfile); + *keyfile = home_dir_key; + if (stat(home_dir_key, &buf) == 0) { + return 0; + } + /* have to generate the key */ + if (snprintf(openssl_cmd, 101, "openssl genrsa -out %s 2048", home_dir_key) > 100) { + return 2; /* string is too long */ + } + status = system(openssl_cmd); + if (status == -1) { + return -1; + } + return WEXITSTATUS(status); +} + +int +generate_certificate(char** cerfile, char* keyfile) +{ + int cer_length, home_length, status, tmp_fd1, tmp_fd2; + char openssl_cmd[301]; + struct stat buf; + /* check in local directory first */ + if (stat(*cerfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + cer_length = strlen(*cerfile); + home_length = strlen(home_dir); + if (home_dir_cer) { + free(home_dir_cer); + home_dir_cer = NULL; + } + home_dir_cer = calloc(1, home_length + cer_length + 2); + if (home_dir_cer == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_cer, home_dir); + home_dir_cer[home_length] = '/'; + strcpy(&home_dir_cer[home_length+1], *cerfile); + *cerfile = home_dir_cer; + if (stat(home_dir_cer, &buf) == 0) { + return 0; + } + /* have to generate the certificate */ + if (snprintf(openssl_cmd, 201, "echo -e \"pl\nWar-Maz\nOlsztyn\nSHEG\nUtils productions\njeremian\njeremian@poczta.fm\" | openssl req -new -x509 -key %s -out %s -days 1095", keyfile, home_dir_cer) > 300) { + return 2; /* string is too long */ + } + tmp_fd1 = dup(STDOUT_FILENO); + tmp_fd2 = dup(STDERR_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + status = system(openssl_cmd); + dup2(tmp_fd1, STDOUT_FILENO); + dup2(tmp_fd2, STDERR_FILENO); + close(tmp_fd1); + close(tmp_fd2); + if (status == -1) { + return -1; + } + return WEXITSTATUS(status); +} diff --git a/src/first_run.h b/src/first_run.h new file mode 100644 index 0000000..5a36ff6 --- /dev/null +++ b/src/first_run.h @@ -0,0 +1,29 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_FIRST_RUN_H +#define _JS_FIRST_RUN_H + +int create_apf_dir(); +int generate_rsa_key(char**); +int generate_certificate(char**, char*); + +#endif + diff --git a/src/inet_ntop.c b/src/inet_ntop.c new file mode 100644 index 0000000..6d37620 --- /dev/null +++ b/src/inet_ntop.c @@ -0,0 +1,227 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* This is from the BIND 4.9.4 release, modified to compile by itself */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "inet_ntop.h" + +#ifndef HAVE_THIS_INET_NTOP +#define HAVE_THIS_INET_NTOP + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_ntop.c,v 8.5 1996/05/22 04:56:30 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IN6ADDRSZ 16 +#define INT16SZ 2 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const u_char *src, char *dst, size_t size); +#ifdef AF_INET6 +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); +#endif + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + sprintf(tmp, fmt, src[0], src[1], src[2], src[3]); + if (strlen(tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +#ifdef AF_INET6 +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, 0, sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + sprintf(tp, "%x", words[i]); + tp += strlen(tp); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif + +#endif diff --git a/src/inet_ntop.h b/src/inet_ntop.h new file mode 100644 index 0000000..9e49f1f --- /dev/null +++ b/src/inet_ntop.h @@ -0,0 +1,36 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef HAVE_INET_NTOP + +#include + +# ifndef _JS_INET_NTOP_H +# define _JS_INET_NTOP_H + +const char* inet_ntop(int af, const void *src, char *dst, size_t size); + +# endif + +#endif diff --git a/src/make_ssl_handshake.c b/src/make_ssl_handshake.c new file mode 100644 index 0000000..a5c97eb --- /dev/null +++ b/src/make_ssl_handshake.c @@ -0,0 +1,103 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "make_ssl_handshake.h" +#include "stats.h" + +#include + +#include +#include + +void +make_ssl_initialize(clifd *cliconn) +{ + if (SSL_set_fd(cliconn->ssl, cliconn->commfd) != 1) { + aflog(0, "Problem with initializing ssl... exiting"); + exit(1); + } +} + +int +make_ssl_accept(clifd *cliconn) +{ + int result; + if ((result = SSL_accept(cliconn->ssl)) != 1) { + return get_ssl_error(cliconn, " SSL_accept has failed", result); + } + return 0; +} + +int +get_ssl_error(clifd *cliconn, char* info, int result) +{ + int merror; +#ifdef HAVE_ERR_ERROR_STRING + char err_buff[200]; +#endif + merror = SSL_get_error(cliconn->ssl, result); + switch (merror) { + case SSL_ERROR_NONE : { + aflog(2, "%s(%d): none", info, result); + break; + } + case SSL_ERROR_ZERO_RETURN : { + aflog(2, "%s(%d): zero", info, result); + break; + } + case SSL_ERROR_WANT_READ : { + aflog(2, "%s(%d): w_read", info, result); + break; + } + case SSL_ERROR_WANT_WRITE : { + aflog(2, "%s(%d): w_write", info, result); + break; + } + case SSL_ERROR_WANT_CONNECT : { + aflog(2, "%s(%d): w_connect", info, result); + break; + } + case SSL_ERROR_WANT_X509_LOOKUP : { + aflog(2, "%s(%d): w_x509_lookup", info, result); + break; + } + case SSL_ERROR_SYSCALL : { + aflog(2, "%s(%d): syscall", info, result); + break; + } + case SSL_ERROR_SSL : { + SSL_load_error_strings(); +#ifdef HAVE_ERR_ERROR_STRING + aflog(2, "%s(%d): ssl:%s", info, result, + ERR_error_string(ERR_get_error(), err_buff)); +#else + aflog(2, "%s(%d): ssl", info, result); +#endif + break; + } + default: { + aflog(2, "%s(%d): unrecognized error (%d)", info, result, errno); + } + } + if (merror == SSL_ERROR_WANT_READ) { + return 1; + } + return 2; +} diff --git a/src/make_ssl_handshake.h b/src/make_ssl_handshake.h new file mode 100644 index 0000000..674867a --- /dev/null +++ b/src/make_ssl_handshake.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "network.h" + +#ifndef _JS_MAKE_SSL_HANDSHAKE_H +#define _JS_MAKE_SSL_HANDSHAKE_H + +void make_ssl_initialize(clifd *cliconn); +int make_ssl_accept(clifd *cliconn); +int get_ssl_error(clifd *cliconn, char* info, int result); + +#endif + diff --git a/src/modules.c b/src/modules.c new file mode 100644 index 0000000..0d153be --- /dev/null +++ b/src/modules.c @@ -0,0 +1,69 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#ifdef HAVE_LIBDL + +#include "modules.h" + +#include +#include + +int +loadmodule(moduleT* module) +{ + if (module->name) { + module->handle = dlopen(module->name, RTLD_NOW); + if (!module->handle) { + return 1; + } + dlerror(); + *(void**) (&module->info) = dlsym(module->handle, "info"); + *(void**) (&module->allow) = dlsym(module->handle, "allow"); + *(void**) (&module->filter) = dlsym(module->handle, "filter"); + if (dlerror() != NULL) { + return 2; + } + module->loaded = 1; + } + return 0; +} + +int +releasemodule(moduleT* module) +{ + if (ismloaded(module)) { + module->loaded = 0; + module->info = NULL; + module->allow = NULL; + module->filter = NULL; + return dlclose(module->handle); + } + return 0; +} + +int +ismloaded(moduleT* module) +{ + return module->loaded; +} + +#endif diff --git a/src/modules.h b/src/modules.h new file mode 100644 index 0000000..f6f8ea9 --- /dev/null +++ b/src/modules.h @@ -0,0 +1,43 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#ifdef HAVE_LIBDL + +# ifndef _JS_MODULES_H +# define _JS_MODULES_H + +typedef struct { + char loaded; + char* name; + void* handle; + char* (*info)(void); + int (*allow)(char*, char*); + int (*filter)(char*, unsigned char*, int*); +} moduleT; + +int loadmodule(moduleT* module); +int releasemodule(moduleT* module); +int ismloaded(moduleT* module); + +# endif + +#endif diff --git a/src/network.c b/src/network.c new file mode 100644 index 0000000..7618c76 --- /dev/null +++ b/src/network.c @@ -0,0 +1,484 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "inet_ntop.h" +#include "network.h" +#include "activefor.h" +#include "stats.h" +#include +#include +#include + +int +ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type) +{ +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + const int on = 1; + struct addrinfo hints, *res, *ressave; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* error, try next one */ + } + + if (type & 0x01) { /* tcp_listen */ + setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + } + if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* bind error, close and try next one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno from final socket() or bind() */ + return 1; + } + + if (type & 0x01) { /* tcp_listen */ + listen((*sockfd), 1); + } + + if (addrlenp) { + *addrlenp = res->ai_addrlen; /* return size of protocol address */ + } + + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr; + struct hostent* hostaddr; + int port; + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + if (host) { + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + if (host) { + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + } + else { + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + servaddr.sin_port = htons(port); + + if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + return 4; + } + + if (listen((*sockfd), 5)){ + return 5; + } +#endif + + return(0); +} + +int +ip_connect(int* sockfd, const char *host, const char *serv, const char type) +{ +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + struct addrinfo hints, *res, *ressave; + + bzero(&hints, sizeof(struct addrinfo)); + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* ignore this one */ + } + + if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* ignore this one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno set from final connect() */ + return 1; + } + + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr; + struct hostent* hostaddr; + int port; + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + + if (connect((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + return 3; + } +#endif + + return(0); +} + +char * +sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf, char type) +{ + char portstr[7]; + static char str[136]; /* Unix domain is largest */ + + switch (sa->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr(&sin->sin_addr, sizeof(struct in_addr), AF_INET))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin->sin_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin->sin_port)); + } + strcat(str, portstr); + } + return(str); + } +#ifdef AF_INET6 + case AF_INET6: { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin6->sin6_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port)); + } + strcat(str, portstr); + } + return(str); + } +#endif + default: { + snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); + return(str); + } + } + return NULL; +} + +int +SSL_writen(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = SSL_write(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +SSL_readn(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = SSL_read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +writen(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = write(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +readn(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; + +} + +int +send_message(char type, clifd fd, unsigned char* buf, int amount) +{ + unsigned long clen; + int length; + static unsigned char bufor[9000]; + aflog(4, " send_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + clen = 8995; + length = amount - 5; + if (TYPE_IS_ZLIB(type)) { + memcpy(bufor, buf, 5); + if (amount > 5) { + compress(&bufor[5], &clen, &buf[5], length); + if (clen < length) { + length = clen; + TYPE_SET_COMP(length); + bufor[3] = length >> 8; /* high bits of message length */ + bufor[4] = length; /* low bits of message length */ + addtocg(amount-5 - clen); + } + } + if (TYPE_IS_SSL(type)) { + if (TYPE_IS_COMP(length)) { + return SSL_writen(fd.ssl, bufor, clen+5); + } + else { + return SSL_writen(fd.ssl, buf, amount); + } + } + else { + if (TYPE_IS_COMP(length)) { + return writen(fd.commfd, bufor, clen+5); + } + else { + return writen(fd.commfd, buf, amount); + } + } + } + else { + if (TYPE_IS_SSL(type)) { + return SSL_writen(fd.ssl, buf, amount); + } + else { + return writen(fd.commfd, buf, amount); + } + } +} + +int +get_message(char type, clifd fd, unsigned char* buf, int amount) +{ + int length; + unsigned long elen; + static unsigned char bufor[9000]; + aflog(4, " get_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + if (amount == -5) { + if (TYPE_IS_SSL(type)) { + return SSL_read(fd.ssl, buf, 5); + } + else { + return read(fd.commfd, buf, 5); + } + } + if (TYPE_IS_ZLIB(type)) { + if (TYPE_IS_SSL(type)) { + length = SSL_readn(fd.ssl, bufor, amount&0xBFFF); + } + else { + length = readn(fd.commfd, bufor, amount&0xBFFF); + } + if (length <= 0) return length; + elen = 8096; + if (TYPE_IS_COMP(amount)) { + uncompress(buf, &elen, bufor, length); + } + else { + memcpy(buf, bufor, length); + elen = length; + } + return elen; + } + else + { + if (TYPE_IS_SSL(type)) { + return SSL_readn(fd.ssl, buf, amount); + } + else { + return readn(fd.commfd, buf, amount); + } + } +} diff --git a/src/network.h b/src/network.h new file mode 100644 index 0000000..401a627 --- /dev/null +++ b/src/network.h @@ -0,0 +1,54 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_NETWORK_H +#define _JS_NETWORK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + int commfd; + SSL* ssl; +} clifd; + +int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */ +int ip_connect(int* sockfd, const char *host, const char *serv, const char type); /* socket, connect... */ +char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf, char type); /* return the IP of connected user */ + +int send_message(char type, clifd fd, unsigned char* buf, int amount); +int get_message(char type, clifd fd, unsigned char* buf, int amount); + +int SSL_writen(SSL* fd, unsigned char* buf, int amount); +int SSL_readn(SSL* fd, unsigned char* buf, int amount); +int writen(int fd, unsigned char* buf, int amount); +int readn(int fd, unsigned char* buf, int amount); + +#endif diff --git a/src/realmnames.c b/src/realmnames.c new file mode 100644 index 0000000..84d9f53 --- /dev/null +++ b/src/realmnames.c @@ -0,0 +1,62 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include "realmnames.h" + +char* +get_realmname(ConfigurationT* config, int realm) +{ + static char realmname[10]; + + if (config->realmtable[realm].realmname == NULL) { + memset(realmname, 0, 10); + sprintf(realmname, "%d", realm); + return realmname; + } + + return config->realmtable[realm].realmname; +} + +int +get_realmnumber(ConfigurationT* config, char* realmname) +{ + int i; + char guard; + + for (i = 0; i < config->size; ++i) { + if (config->realmtable[i].realmname != NULL) { + if (strcmp(realmname, config->realmtable[i].realmname) == 0) { + return i; + } + } + } + + if (sscanf(realmname, "%d%c", &i, &guard) == 1) { + if ((i >= 0) && (i < config->size)) { + if (config->realmtable[i].realmname == NULL) { + return i; + } + } + } + + return -1; +} diff --git a/src/realmnames.h b/src/realmnames.h new file mode 100644 index 0000000..70ad46f --- /dev/null +++ b/src/realmnames.h @@ -0,0 +1,30 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" + +#ifndef _JS_REALMNAMES_H +#define _JS_REALMNAMES_H + +char* get_realmname(ConfigurationT*, int); +int get_realmnumber(ConfigurationT*, char*); + +#endif + diff --git a/src/remoteadmin.c b/src/remoteadmin.c new file mode 100644 index 0000000..4e777c1 --- /dev/null +++ b/src/remoteadmin.c @@ -0,0 +1,503 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "remoteadmin.h" + +static char newmessage; + +static int +parse_cmd(unsigned char* buff, int* ret) +{ + int i, j, state; + char cmd[31]; + + i = j = state = 0; + newmessage = 1; + while (buff[i] != 0) { + if (state == 1) { + if (isspace(buff[i])) { + break; + } + else { + if (j == 30) { + return 0; + } + cmd[j] = buff[i]; + ++j; + } + } + if (state == 0) { + if (!isspace(buff[i])) { + cmd[j] = buff[i]; + j = 1; + state = 1; + } + } + ++i; + } + if (state == 0) { + return 0; + } + while (isspace(buff[i])) { + ++i; + } + if (buff[i] == '.') { + ++i; + } + (*ret) = i; + cmd[j] = 0; + if (strcmp(cmd, "help") == 0) { return 1; } + if (strcmp(cmd, "lcmd") == 0) { return 2; } + if (strcmp(cmd, "info") == 0) { return 3; } + if (strcmp(cmd, "rshow") == 0) { return 4; } + if (strcmp(cmd, "cshow") == 0) { return 5; } + if (strcmp(cmd, "ushow") == 0) { return 6; } + if (strcmp(cmd, "quit") == 0) { return 7; } + return 0; +} + +static void +send_adm_message(char type, clifd master, unsigned char* buff, unsigned char st) +{ + int n; + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = st; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(type, master, buff, n+5); +} + +static void +add_to_message(unsigned char* buff, const char* format, ...) +{ + va_list ap; + int n; + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + newmessage = 0; + va_start(ap, format); + + vsprintf((char*) &buff[5+n], format, ap); + n = strlen((char*) &buff[5]); + sprintf((char*) &buff[5+n], "\n"); + + va_end(ap); +} + +static void +add_uptime_to_message(unsigned char* buff, char* info, time_t period) +{ + int hours, minutes, seconds; + + hours = period/3600; + minutes = (period/60)%60; + seconds = period%60; + + if (hours) { + add_to_message(buff, "%s: %d:%02d:%02d", info, hours, minutes, seconds); + } + else { + add_to_message(buff, "%s: %d:%02d", info, minutes, seconds); + } +} + +int +serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) +{ + int length, n, i, j, ret; + time_t now, tmp; + char type = config->realmtable[realm].type | TYPE_SSL | TYPE_ZLIB; + clifd master = config->realmtable[realm].raclitable[client].cliconn; + + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + time(&now); + + switch (buff[1]) { + case AF_RA_CMD: { + n = get_message(type, master, buff, length); + buff[n] = 0; + aflog(2, " realm[%s]: admin: message length = %d [%s]", + get_realmname(config, realm), n, buff); + switch (parse_cmd(buff, &ret)) { + case 1: { /* help */ + add_to_message(buff, AF_VER("AFSERVER")); + add_to_message(buff, "\nValid commands are:"); + add_to_message(buff, " help display help"); + add_to_message(buff, " lcmd lists available commands"); + add_to_message(buff, " info prints info about server"); + add_to_message(buff, " rshow display realms"); + add_to_message(buff, " cshow X display clients in X realm"); + add_to_message(buff, " ushow X display users in X realm"); + add_to_message(buff, " quit quit connection"); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 2: { /* lcmd */ + add_to_message(buff, "help"); + add_to_message(buff, "lcmd"); + add_to_message(buff, "info"); + add_to_message(buff, "rshow"); + add_to_message(buff, "cshow"); + add_to_message(buff, "ushow"); + add_to_message(buff, "quit"); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 3: { /* info */ + add_to_message(buff, AF_VER("Version:")); + add_to_message(buff, "Realms: %d", config->size); + add_to_message(buff, "Certificate: %s", config->certif); + add_to_message(buff, "Key: %s", config->keys); + if (config->logging) { + add_to_message(buff, "logfile: %s (verbosity:%d)", + config->logfnam, config->logging); + } + else { + add_to_message(buff, "no logfile"); + } + if (config->socklogging) { + add_to_message(buff, "logsocket: %s (verbosity:%d)", + config->logsport, config->socklogging); + } + else { + add_to_message(buff, "no logsocket"); + } + tmp = now - config->starttime; + add_uptime_to_message(buff, "Uptime", tmp); + add_to_message(buff, "Cg: %ld B", getcg()); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 4: { /* rshow */ + for (i = 0; i < config->size; ++i) { + add_to_message(buff, "\nRealm[%s]:", get_realmname(config, i)); + add_to_message(buff, "hostname: %s", config->realmtable[i].hostname); + add_to_message(buff, "users: %d (max: %d)", + config->realmtable[i].usercon, config->realmtable[i].usernum); + add_to_message(buff, "clients: %d (max: %d)", + config->realmtable[i].clicon-config->realmtable[i].raclicon, + config->realmtable[i].clinum); + add_to_message(buff, "raclients: %d (max: %d)", + config->realmtable[i].raclicon, config->realmtable[i].raclinum); + add_to_message(buff, "users per client: %s", config->realmtable[i].usrpcli); + add_to_message(buff, "user-client pairs: %d", + config->realmtable[i].usrclinum); + for (j = 0; j < config->realmtable[i].usrclinum; ++j) { + add_to_message(buff, " pair[%d]: listenport: %s, manageport: %s", j, + config->realmtable[i].usrclitable[j].lisportnum, + config->realmtable[i].usrclitable[j].manportnum); + } + add_to_message(buff, "climode: %s", config->realmtable[i].clim); + add_to_message(buff, "timeout: %s", config->realmtable[i].timeout); + add_to_message(buff, "baseport: %s", config->realmtable[i].baseport ? + "yes" : "no"); + add_to_message(buff, "ssl: %s, zlib: %s, mode: %s", + (TYPE_IS_SSL(config->realmtable[i].type))?"yes":"no", + (TYPE_IS_ZLIB(config->realmtable[i].type))?"yes":"no", + (TYPE_IS_TCP(config->realmtable[i].type))?"tcp":"udp"); + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 5: { /* cshow*/ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + for (i = 0; i < config->realmtable[n].clinum; ++i) { + if (config->realmtable[n].clitable[i].ready) { + add_to_message(buff, "\nClient[%s]:", + get_clientname(&(config->realmtable[n]), i)); + switch (config->realmtable[n].clitable[i].ready) { + case 1: { + add_to_message(buff, "state: ssl handshake"); + break; + } + case 2: { + add_to_message(buff, "state: authorization"); + break; + } + case 3: { + add_to_message(buff, "state: running"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "users: %d (max: %d)", + config->realmtable[n].clitable[i].usercon, + config->realmtable[n].clitable[i].usernum); + add_to_message(buff, "user-client pair: %d", + config->realmtable[n].clitable[i].whatusrcli); + tmp = now - config->realmtable[n].clitable[i].connecttime; + add_uptime_to_message(buff, "Connection time", tmp); + add_to_message(buff, "Id: %s", + (config->realmtable[n].clitable[i].clientid == NULL)?"": + config->realmtable[n].clitable[i].clientid); + add_to_message(buff, "IP: %s, port: %s", + config->realmtable[n].clitable[i].namebuf, + config->realmtable[n].clitable[i].portbuf); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 6: { /* ushow */ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + for (i = 0; i < config->realmtable[n].usernum; ++i) { + if (config->realmtable[n].contable[i].state != S_STATE_CLEAR) { + add_to_message(buff, "\nUser[%d]:", + get_username(&(config->realmtable[n]), i)); + switch (config->realmtable[n].contable[i].state) { + case S_STATE_CLOSING: { + add_to_message(buff, "state: closing"); + break; + } + case S_STATE_OPENING: { + add_to_message(buff, "state: opening"); + break; + } + case S_STATE_OPEN: { + add_to_message(buff, "state: running"); + break; + } + case S_STATE_STOPPED: { + add_to_message(buff, "state: stopped"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "connected to: Client[%s]", + get_clientname(&(config->realmtable[n]), + config->realmtable[n].contable[i].whatcli)); + tmp = now - config->realmtable[n].contable[i].connecttime; + add_uptime_to_message(buff, "Connection time", tmp); + add_to_message(buff, "IP: %s, port: %s", + config->realmtable[n].contable[i].namebuf, + config->realmtable[n].contable[i].portbuf); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 7: { /* quit */ + aflog(1, " realm[%s]: Client[%s] (ra): commfd: CLOSED", + get_realmname(config, realm), + get_raclientname(&(config->realmtable[realm]), client)); + send_adm_message(type, master, buff, AF_RA_KICKED); + return 1; + } + default: { + aflog(2, " realm[%s]: admin: cmd ignored", get_realmname(config, realm)); + send_adm_message(type, master, buff, AF_RA_UNDEFINED); + } + } + break; + } + case AF_RA_REPEAT: { + break; + } + default: { + aflog(1, "Unrecognized message from remote admin --> closing"); + return 1; + } + } + return 0; +} + +int +client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* id) +{ + fd_set rset, allset; + int maxfdp1, n, length, infd; + FILE *outfp, *infp; + + buff[0] = AF_S_ADMIN_LOGIN; + send_message(type, master, buff, 5); + buff[0] = 0; + get_message(type, master, buff, -5); + + if ( buff[0] == 0 ) { + aflog(0, "Wrong password"); + return 1; + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(0, "Server is full"); + return 1; + } + if ( buff[0] != AF_S_ADMIN_LOGIN ) { + aflog(0, "Incompatible server type or server full"); + return 1; + } + + aflog(1, "CLIENT STARTED mode: remote administration"); + + if (connectfd > 0) { + outfp = fdopen(connectfd, "w"); + if (outfp == NULL) { + aflog(0, "Error in opening file descriptor for writing"); + return 1; + } + infd = connectfd; + } + else { + infd = STDIN_FILENO; + outfp = stdout; + } + infp = fdopen(infd, "r"); + if (infp == NULL) { + aflog(0, "Error in opening file descriptor for reading"); + return 1; + } + + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + n = get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s\n", (char*) buff); + fflush(outfp); + + FD_ZERO(&allset); + + FD_SET(master.commfd, &allset); + FD_SET(infd, &allset); + + maxfdp1 = (infd > master.commfd) ? infd+1: master.commfd+1; + + if (id != NULL) { + buff[0] = AF_S_LOGIN; + buff[1] = buff[2] = 0; + n = strlen(id); + memcpy(&buff[5], id, n); + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(type, master, buff, n+5); + aflog(1, "ID SENT: %s", id); + } + + while (1) { + rset = allset; + select(maxfdp1, &rset, NULL, NULL, NULL); + + if (FD_ISSET(master.commfd, &rset)) { + aflog(3, " masterfd: FD_ISSET"); + n = get_message(type, master, buff, 5); + if (n != 5) { + aflog(2, " FATAL ERROR! (%d)", n); + if (n == -1) { + if (TYPE_IS_SSL(type)) { + get_ssl_error(&master, "FE", n); + continue; /* what happened? */ + } + } + if (n != 0) + return 1; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(0, " SERVER: premature quit --> exiting..."); + return 1; + } + if (buff[0] == AF_S_CLOSING) { + aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + return 0; + } + if (buff[0] != AF_S_ADMIN_CMD) { + aflog(0, " SERVER: wrong message --> exiting"); + return 1; + } + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + switch (buff[1]) { + case AF_RA_STATUS_OK: { + aflog(1, " SERVER: cmd successful"); + } + case AF_RA_FAILED: { + if (buff[1] == AF_RA_FAILED) { + aflog(1, " SERVER: cmd failed"); + } + } + case AF_RA_UNDEFINED: { + if (buff[1] == AF_RA_UNDEFINED) { + aflog(1, " SERVER: unknown cmd"); + } + n = get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s", (char*) buff); + fflush(outfp); + break; + } + case AF_RA_KICKED: { + aflog(0, " SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); + return 1; + break; + } + default: { + aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + return 1; + } + } + } + + if (FD_ISSET(infd, &rset)) { + aflog(3, " infd: FD_ISSET"); + if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ + aflog(0, " CLIENT CLOSED cg: %ld bytes", getcg()); + return 0; + } + n = strlen((char*) &buff[5]); + if ((n > 0) && (buff[n+4] == '\n')) { + --n; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = AF_RA_CMD; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(type, master, buff, n+5); + } + } +} diff --git a/src/remoteadmin.h b/src/remoteadmin.h new file mode 100644 index 0000000..cad9c76 --- /dev/null +++ b/src/remoteadmin.h @@ -0,0 +1,49 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" +#include "stats.h" +#include "activefor.h" +#include "realmnames.h" +#include "clientnames.h" +#include "usernames.h" +#include "make_ssl_handshake.h" + +#include +#include +#include +#include + +#ifndef _JS_REMOTEADMIN_H +#define _JS_REMOTEADMIN_H + +#define AF_RA_UNDEFINED 0 +#define AF_RA_CMD 1 +#define AF_RA_REPEAT 2 +#define AF_RA_STATUS_OK 3 +#define AF_RA_NOT_KNOWN 4 +#define AF_RA_FAILED 5 +#define AF_RA_KICKED 6 + +int serve_admin(ConfigurationT*, int, int, unsigned char*); +int client_admin(char, clifd, unsigned char*, int, char*); + +#endif + diff --git a/src/server_check.c b/src/server_check.c new file mode 100644 index 0000000..94069cc --- /dev/null +++ b/src/server_check.c @@ -0,0 +1,61 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include + +#include "stats.h" + +void +check_value(int* where, char* what, char* info) +{ + char* znak; + long tmp; + if ((tmp = strtol(what, &znak, 10)) >= INT_MAX) { + aflog(0, "%s: %s\n", info, what); + exit(1); + } + if (((*what) == '\0') || (*znak != '\0')) { + aflog(0, "%s: %s\n", info, what); + exit(1); + } + if (tmp <= 0) { + aflog(0, "%s: %d\n", info, *where); + exit(1); + } + (*where) = tmp; +} + +int +check_long(char* text, long* number) +{ + char* tmp; + if (((*number = strtol(text, &tmp, 10)) == LONG_MAX) || (*number == LONG_MIN)) { + return 1; + } + if ((*text != '\0') && (*tmp == '\0')) { + return 0; + } + else { + return 2; + } +} + diff --git a/src/server_check.h b/src/server_check.h new file mode 100644 index 0000000..3877426 --- /dev/null +++ b/src/server_check.h @@ -0,0 +1,28 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_CHECK_H +#define _JS_SERVER_CHECK_H + +void check_value(int* where, char* what, char* info); +int check_long(char* text, long* number); + +#endif + diff --git a/src/server_eval.c b/src/server_eval.c new file mode 100644 index 0000000..d487b01 --- /dev/null +++ b/src/server_eval.c @@ -0,0 +1,44 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "server_eval.h" + +int +eval_numofcon(RealmT* ptr, int client, int numofcon) +{ + if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) { + numofcon = ptr->clitable[client].users[numofcon]; + } + else { + numofcon = -1; + } + return numofcon; +} + +int +eval_usernum(ConnectclientT* ptr, int usernum) +{ + int i; + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->users[i] == usernum) + return i; + } + return -1; +} diff --git a/src/server_eval.h b/src/server_eval.h new file mode 100644 index 0000000..ed09e84 --- /dev/null +++ b/src/server_eval.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" +#include "activefor.h" + +#ifndef _JS_SERVER_EVAL_H +#define _JS_SERVER_EVAL_H + +int eval_numofcon(RealmT*, int, int); +int eval_usernum(ConnectclientT*, int); + +#endif + diff --git a/src/server_find.c b/src/server_find.c new file mode 100644 index 0000000..1d67640 --- /dev/null +++ b/src/server_find.c @@ -0,0 +1,56 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "server_find.h" + +int +find_client(RealmT* ptr, char mode, int usrclipair) +{ + int i; + switch(mode) { + case 1: { /* fill first client before go to next */ + for (i = 0; i < ptr->clinum; ++i) { + if ((ptr->clitable[i].ready == 3) && (ptr->clitable[i].whatusrcli == usrclipair)) { + if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) { + return i; + } + } + } + break; + } + default: { + return 0; + } + } + return 0; +} + +int +find_usernum(ConnectclientT* ptr, int usernum) +{ + int i; + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->users[i] == -1) { + ptr->users[i] = usernum; + return i; + } + } + return -1; +} diff --git a/src/server_find.h b/src/server_find.h new file mode 100644 index 0000000..36642cc --- /dev/null +++ b/src/server_find.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "file.h" + +#ifndef _JS_SERVER_FIND_H +#define _JS_SERVER_FIND_H + +int find_client(RealmT*, char, int); +int find_usernum(ConnectclientT*, int); + +#endif + diff --git a/src/server_remove.c b/src/server_remove.c new file mode 100644 index 0000000..de2df66 --- /dev/null +++ b/src/server_remove.c @@ -0,0 +1,84 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "server_remove.h" + +void +remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) +{ + int i; + if (ptr->clitable[client].ready == 3) { + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->contable[i].whatcli == client) { + if (ptr->contable[i].state != S_STATE_CLEAR) { + ptr->contable[i].state = S_STATE_CLEAR; + FD_CLR(ptr->contable[i].connfd, set); + FD_CLR(ptr->contable[i].connfd, wset); + close(ptr->contable[i].connfd); + ptr->usercon--; + } + } + } + } + for (i=0; iclitable[client].usernum; ++i) { + ptr->clitable[client].users[i] = -1; + } + if ((ptr->clinum != client) && (ptr->baseport == 1)) { + close(ptr->clitable[client].listenfd); + FD_CLR(ptr->clitable[client].listenfd, set); + } + if (ptr->clitable[client].clientid) { + free(ptr->clitable[client].clientid); + ptr->clitable[client].clientid = NULL; + } + ptr->clitable[client].usercon = 0; + close(ptr->clitable[client].cliconn.commfd); + FD_CLR(ptr->clitable[client].cliconn.commfd, set); + if (ptr->clitable[client].ready == 2) + (*con)--; + SSL_clear(ptr->clitable[client].cliconn.ssl); + ptr->clitable[client].ready = 0; + ptr->clicon--; +} + +void +remove_raclient(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) +{ + int i; + for (i=0; iraclitable[client].usernum; ++i) { + ptr->raclitable[client].users[i] = -1; + } + if (ptr->raclitable[client].clientid) { + free(ptr->raclitable[client].clientid); + ptr->raclitable[client].clientid = NULL; + } + ptr->raclitable[client].usercon = 0; + close(ptr->raclitable[client].cliconn.commfd); + FD_CLR(ptr->raclitable[client].cliconn.commfd, set); + if (ptr->raclitable[client].ready == 2) { + (*con)--; + } + SSL_clear(ptr->raclitable[client].cliconn.ssl); + ptr->clicon--; + if (ptr->raclitable[client].ready == 3) { + ptr->raclicon--; + } + ptr->raclitable[client].ready = 0; +} diff --git a/src/server_remove.h b/src/server_remove.h new file mode 100644 index 0000000..363b1cc --- /dev/null +++ b/src/server_remove.h @@ -0,0 +1,30 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" + +#ifndef _JS_SERVER_REMOVE_H +#define _JS_SERVER_REMOVE_H + +void remove_client(RealmT*, int, fd_set*, fd_set*, int*); +void remove_raclient(RealmT*, int, fd_set*, fd_set*, int*); + +#endif + diff --git a/src/server_set.c b/src/server_set.c new file mode 100644 index 0000000..c3a0058 --- /dev/null +++ b/src/server_set.c @@ -0,0 +1,34 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +void +set_value(char** dest, char* from, char* def) +{ + if ((*dest) == NULL) { + if (from != NULL) { + (*dest) = from; + } + else { + (*dest) = def; + } + } +} diff --git a/src/server_set.h b/src/server_set.h new file mode 100644 index 0000000..5bd4de5 --- /dev/null +++ b/src/server_set.h @@ -0,0 +1,27 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_SET_H +#define _JS_SERVER_SET_H + +void set_value(char** dest, char* from, char* def); + +#endif + diff --git a/src/stats.c b/src/stats.c new file mode 100644 index 0000000..82e90aa --- /dev/null +++ b/src/stats.c @@ -0,0 +1,127 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "stats.h" +#include "network.h" +#include +#include +#include +#include + +static char verlev; +static char loglev; +static char logsocklev; +static FILE* logfd; +static FILE* logsockfd; +static signed long compressgained; +static char* format = "%d.%m.%Y %H:%M:%S"; + +char* +datum(void) +{ + time_t sec; + struct tm* tm; + static char timedat[31]; + time(&sec); + tm = localtime(&sec); + memset(timedat, 0, 31); + strftime(timedat, 30, format, tm); + return timedat; +} + +int +loginit(char verl, char logl, char logsl, const char* logfname, const char* port, char* dateformat) { + int tmpfd; + verlev = loglev = 0; + if (logfd) + fclose(logfd); + logfd = NULL; + logsockfd = NULL; + verlev = verl; + loglev = logl; + logsocklev = logsl; + if (dateformat) + format = dateformat; + if (loglev) { + logfd = fopen(logfname, "a"); + if (logfd == NULL) + return 1; /* logging to a non-opened file? */ + } + if (logsocklev) { + if (ip_connect(&tmpfd, "localhost", port, 1)) + return 2; /* can't connect to localhost:port */ + logsockfd = fdopen(tmpfd, "a"); + if (logsockfd == NULL) + return 3; /* can't create FILE* to log to */ + } + return 0; +} + +void +aflog(char type, const char* format, ...) +{ + va_list ap; + + if ((verlev) || (!type)) + if (type <= verlev) { + printf("[%s] ", datum()); + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + printf("\n"); + } + if (loglev) + if (type <= loglev) { + fprintf(logfd, "[%s] ", datum()); + va_start(ap, format); + vfprintf(logfd, format, ap); + va_end(ap); + fprintf(logfd, "\n"); + fflush(logfd); + } + if (logsocklev) + if (type <= logsocklev) { + fprintf(logsockfd, "[%s] ", datum()); + va_start(ap, format); + vfprintf(logsockfd, format, ap); + va_end(ap); + fprintf(logsockfd, "\n"); + fflush(logsockfd); + } + +} + +void +addtocg(int amount) +{ + compressgained += amount; +} + +signed long +getcg(void) +{ + return compressgained; +} + +void +resetcg(void) +{ + compressgained = 0; +} diff --git a/src/stats.h b/src/stats.h new file mode 100644 index 0000000..08838ad --- /dev/null +++ b/src/stats.h @@ -0,0 +1,36 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_STATS_H +#define _JS_STATS_H + + /* initializing logging routine */ +int loginit(char verlev, char loglev, char logsocklev, const char* logfname, const char* port, char* dateformat); + /* log to a file or|and screen */ +void aflog(char type, const char* format, ...); + /* add amount to compressgained value */ +void addtocg(int amount); + /* reset the compressgained value */ +void resetcg(void); + /* returns the compressgained value */ +signed long getcg(void); + +#endif + diff --git a/src/usernames.c b/src/usernames.c new file mode 100644 index 0000000..3e4b24c --- /dev/null +++ b/src/usernames.c @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "usernames.h" + +int +get_username(RealmT* pointer, int user) +{ + return pointer->contable[user].userid; +} + +int +get_usernumber(RealmT* pointer, int userid) +{ + int i; + + for (i = 0; i < pointer->usernum; ++i) { + if (userid == pointer->contable[i].userid) { + return i; + } + } + + return -1; +} diff --git a/src/usernames.h b/src/usernames.h new file mode 100644 index 0000000..0d0cb21 --- /dev/null +++ b/src/usernames.h @@ -0,0 +1,30 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" + +#ifndef _JS_USERNAMES_H +#define _JS_USERNAMES_H + +int get_username(RealmT*, int); +int get_usernumber(RealmT*, int); + +#endif + diff --git a/stats.c b/stats.c deleted file mode 100644 index 9342afd..0000000 --- a/stats.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "stats.h" -#include -#include -#include -#include - -static char verlev; -static char loglev; -static FILE* logfd; -static signed long compressgained; - -char* -datum(void) -{ - time_t sec; - struct tm* tm; - static char timedat[20]; - time(&sec); - tm = localtime(&sec); - memset(timedat, 0, 20); - strftime(timedat, 20, "%d.%m.%Y %H:%M:%S", tm); - return timedat; -} - -int -loginit(char verl, char logl, const char* logfname) { - verlev = loglev = 0; - if (logfd) - fclose(logfd); - logfd = NULL; - verlev = verl; - loglev = logl; - if (loglev) { - logfd = fopen(logfname, "a"); - if (logfd == NULL) - return 1; /* logging to a non-opened file? */ - } - return 0; -} - -void -aflog(char type, const char* format, ...) -{ - va_list ap; - va_start(ap, format); - if (verlev) - if (type <= verlev) { - printf("[%s] ", datum()); - vfprintf(stdout, format, ap); - printf("\n"); - } - if (loglev) - if (type <= loglev) { - fprintf(logfd, "[%s] ", datum()); - vfprintf(logfd, format, ap); - fprintf(logfd, "\n"); - fflush(logfd); - } - va_end(ap); -} - -void -addtocg(int amount) -{ - compressgained += amount; -} - -signed long -getcg(void) -{ - return compressgained; -} - -void -resetcg(void) -{ - compressgained = 0; -} diff --git a/stats.h b/stats.h deleted file mode 100644 index 79b06fa..0000000 --- a/stats.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_STATS_H -#define _JS_STATS_H - -int loginit(char verlev, char loglev, const char* logfname); /* initializes logging routine */ -void aflog(char type, const char* format, ...); /* log to a file or|and screen */ -void addtocg(int amount); /* add amount to compressgained value */ -void resetcg(void); /* reset the compressgained value */ -signed long getcg(void); /* returns the compressgained value */ - -#endif - -- cgit v1.1