From 32aff2b27ccc3b3e51fb6f0bd77fe0073827c527 Mon Sep 17 00:00:00 2001 From: Jakub Sławiński Date: Tue, 7 Jun 2005 12:06:18 +0200 Subject: v0.7 - Added: http proxy tunnels between afserver and afclient - Fixed: sigint interception with threads enabled (in http proxy mode) - Fixed: FATAL ERROR in afclient in some situations after close of afserver when http proxy mode is enabled - Added: afclients can connect directly to afserver with enabled proxy mode - Fixed: timeout routine in http proxy tunnels - Added: 'rshow' command in ra mode displays 'tunneltype' - Fixed: printing IP of clients when http proxy mode is enabled - Added: 'tunneltype' per client in ra mode after 'cshow' command - Fixed: closing connection when http proxy mode is enabled - Fixed: threads initialization - Fixed: afserver closing after sigint - Fixed: afclient threads initialization - Added: 'version' option to display program version number - Modified: establishing afclient<->afserver connection - Added: 'keep-alive' option - Fixed: using 'proxyport' without 'proxyname' - Added: auto-reconnect feature to afclient - Added: 'ar-tries' and 'ar-delay' options - Modified: http proxy logging - Fixed: closing connection with afclient after receiving id - Fixed: thread closing due to wrong initialization sequence - Fixed: small bug in initialization process - Heavily Modified: logging routines - Added: audit option - Modified: default dateformat is now ISO 8601 - Modified: printing usage - Fixed: bug in threads' initialization in afclient - Added: 'timeout' and 'dateformat' options in ra mode - Modified: empty dateformat disables printing '[] ' - Added: 'audit' and 'dnslookups' options in ra mode - Fixed: afserver freeze bug - Added: 'kuser' and 'kclient' options in ra mode - Fixed: bug in starting afclient in ra mode - Added: audit log printed also after kicking the client --- ChangeLog | 37 ++ NEWS | 9 + README | 143 ++++++-- configure.ac | 13 +- doc/afclient.1 | 81 ++++- doc/afserver.1 | 85 ++++- doc/afserver.conf.5 | 25 +- doc/afserver_example.conf | 12 +- doc/en/README | 143 ++++++-- src/Makefile.am | 12 +- src/activefor.h | 13 +- src/afclient.c | 672 ++++++++++++++++------------------- src/afclient.h | 14 +- src/afserver.c | 841 +++++++++++++++++++++++++++----------------- src/afserver.h | 9 +- src/audit.c | 69 ++++ src/audit.h | 39 ++ src/buflist.c | 2 + src/client_initialization.c | 212 +++++++++++ src/client_initialization.h | 40 +++ src/client_reverse_udp.c | 183 ++++++++++ src/client_reverse_udp.h | 40 +++ src/client_shutdown.c | 48 +++ src/client_shutdown.h | 31 ++ src/client_signals.c | 42 +++ src/client_signals.h | 27 ++ src/clientnames.c | 3 +- src/file.c | 59 ++-- src/http_proxy_client.c | 380 ++++++++++++++++++++ src/http_proxy_client.h | 27 ++ src/http_proxy_functions.c | 267 ++++++++++++++ src/http_proxy_functions.h | 80 +++++ src/http_proxy_server.c | 459 ++++++++++++++++++++++++ src/http_proxy_server.h | 29 ++ src/logging.c | 391 ++++++++++++++++++++ src/logging.h | 78 ++++ src/make_ssl_handshake.c | 40 ++- src/network.c | 7 +- src/network.h | 2 + src/realmnames.c | 2 + src/remoteadmin.c | 375 +++++++++++++++++--- src/remoteadmin.h | 1 + src/server_check.c | 29 +- src/server_check.h | 1 + src/server_eval.c | 2 + src/server_find.c | 2 + src/server_get.c | 55 +++ src/server_get.h | 31 ++ src/server_signals.c | 66 ++++ src/server_signals.h | 27 ++ src/stats.c | 96 +---- src/stats.h | 10 +- src/thread_management.c | 70 ++++ src/thread_management.h | 34 ++ src/usage.c | 168 +++++++++ src/usage.h | 30 ++ src/usernames.c | 2 + 57 files changed, 4672 insertions(+), 993 deletions(-) create mode 100644 src/audit.c create mode 100644 src/audit.h create mode 100644 src/client_initialization.c create mode 100644 src/client_initialization.h create mode 100644 src/client_reverse_udp.c create mode 100644 src/client_reverse_udp.h create mode 100644 src/client_shutdown.c create mode 100644 src/client_shutdown.h create mode 100644 src/client_signals.c create mode 100644 src/client_signals.h create mode 100644 src/http_proxy_client.c create mode 100644 src/http_proxy_client.h create mode 100644 src/http_proxy_functions.c create mode 100644 src/http_proxy_functions.h create mode 100644 src/http_proxy_server.c create mode 100644 src/http_proxy_server.h create mode 100644 src/logging.c create mode 100644 src/logging.h create mode 100644 src/server_get.c create mode 100644 src/server_get.h create mode 100644 src/server_signals.c create mode 100644 src/server_signals.h create mode 100644 src/thread_management.c create mode 100644 src/thread_management.h create mode 100644 src/usage.c create mode 100644 src/usage.h diff --git a/ChangeLog b/ChangeLog index 6617f4e..4d27954 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +07.06.2005 (v0.7): + - Added: http proxy tunnels between afserver and afclient + - Fixed: sigint interception with threads enabled (in http proxy mode) + - Fixed: FATAL ERROR in afclient in some situations after close of afserver + when http proxy mode is enabled + - Added: afclients can connect directly to afserver with enabled proxy mode + - Fixed: timeout routine in http proxy tunnels + - Added: 'rshow' command in ra mode displays 'tunneltype' + - Fixed: printing IP of clients when http proxy mode is enabled + - Added: 'tunneltype' per client in ra mode after 'cshow' command + - Fixed: closing connection when http proxy mode is enabled + - Fixed: threads initialization + - Fixed: afserver closing after sigint + - Fixed: afclient threads initialization + - Added: 'version' option to display program version number + - Modified: establishing afclient<->afserver connection + - Added: 'keep-alive' option + - Fixed: using 'proxyport' without 'proxyname' + - Added: auto-reconnect feature to afclient + - Added: 'ar-tries' and 'ar-delay' options + - Modified: http proxy logging + - Fixed: closing connection with afclient after receiving id + - Fixed: thread closing due to wrong initialization sequence + - Fixed: small bug in initialization process + - Heavily Modified: logging routines + - Added: audit option + - Modified: default dateformat is now ISO 8601 + - Modified: printing usage + - Fixed: bug in threads' initialization in afclient + - Added: 'timeout' and 'dateformat' options in ra mode + - Modified: empty dateformat disables printing '[] ' + - Added: 'audit' and 'dnslookups' options in ra mode + - Fixed: afserver freeze bug + - Added: 'kuser' and 'kclient' options in ra mode + - Fixed: bug in starting afclient in ra mode + - Added: audit log printed also after kicking the client + 11.03.2005 (v0.6): - Fixed: default password incompatibilities from config file - Added: "client's id" option diff --git a/NEWS b/NEWS index 8d8e11c..45ebebe 100644 --- a/NEWS +++ b/NEWS @@ -1,2 +1,11 @@ +06.06.2005: + * apf 0.7 is ready for public release + +27.05.2005: + * check for pthread library has been included in configure script + +09.05.2005: + * source tree has been put into subversion + 18.02.2005: * source tree has been reorganized for automake/autoconf diff --git a/README b/README index 0e49c3e..d676098 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -AF - Active Port Forwarder 0.6 - README +AF - Active Port Forwarder 0.7 - README Copyright (C) 2003,2004,2005 jeremian - ================================================================= @@ -30,11 +30,13 @@ INTRO 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 +4. HTTP PROXY TUNNELS +5. LOGGING +6. MODULES +7. EXAMPLES + 7.1 tcp mode + 7.2 reverse udp mode +8. BUGS/PROBLEMS NOTES @@ -110,6 +112,7 @@ Multiple clients allow to create more sophisticated tunneling scheme. to it (default: 50127) -m, --manageport - manage port number - second part of the active port forwarder connects to it (default: 50126) + -V, --version - display version number -h, --help - prints this help Authorization: @@ -137,27 +140,24 @@ Multiple clients allow to create more sophisticated tunneling scheme. -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 to connect 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) + -p, --proto - type of server (tcp|udp) - what protocol it will be + operating for (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) + -a, --audit - additional information about connections are logged + --nossl - ssl is not used to transfer data (but it's still used + to establish a connection) (default: ssl is used) + --nozlib - zlib is not used to compress 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 + -o, --log - log choosen information to file/socket -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -166,6 +166,11 @@ Multiple clients allow to create more sophisticated tunneling scheme. -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only + HTTP PROXY: + + -P, --enableproxy - enable http proxy mode + + 2.2 afclient ------------ @@ -179,11 +184,12 @@ 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) + -V, --version - display version number -h, --help - prints this help Authorization: - -i, --id - send the id string to afserver + -i, --id - sends the id string to afserver --pass - set the password used for client identification (default: no password) @@ -192,23 +198,25 @@ Multiple clients allow to create more sophisticated tunneling scheme. -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) + -K, --keep-alive N - send keepalive packets every N seconds + (default: not send keepalive packets) + -A, --ar-tries N - try N times to reconnect to afserver after + its premature quit (default: unlimited) + -T, --ar-delay N - wait N seconds between reconnect tries (default: 5) Modes: -u, --udpmode - udp mode - client will use udp protocol to - communicate with the hostname + communicate with the hostname:portnum (-p) -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) + force afclient to use port rather than 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 + -o, --log - log choosen information to file/socket -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -222,6 +230,12 @@ Multiple clients allow to create more sophisticated tunneling scheme. -l, --load - load a module for user's packets filtering -L, --Load - load a module for service's packets filtering + HTTP PROXY: + + -P, --proxyname - the name of the machine with proxy server + -X, --proxyport - the port used by proxy server (default: 8080) + + ================================================================================ ======================== @@ -257,6 +271,25 @@ Currently available commands are: quit quit connection + timeout N X + set timeout value in X realm + + audit {0|1} X + set audit mode in X realm + + dnslookups {0|1} X + set dnslookups mode in X realm + + dateformat S + set dateformat + + kuser S + kick user named S + + kclient N + kick client with number N + + 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. @@ -265,8 +298,58 @@ When user quits (close the connection or send 'quit' command), afclient exits. ================================================================================ +===================== +4. HTTP PROXY TUNNELS +===================== + +Afclient can communicate with afserver via HTTP proxy. In order to use this +feature, afserver must be started with '-P, --enableproxy' option. Afclient must +specify the proxy host ('-P, --proxyname' option) and port ('-X, --proxyport' +option). + +Afclient with HTTP proxy mode enabled can still accept connections from +afclients, which don't use HTTP proxy mode. + +================================================================================ + +========== +5. LOGGING +========== + +Logging can be enabled by '-o, --log' option. The argument to this option must +be in the form: + target,description,msgdesc + +Where + target is file or sock + description is filename or host,port + msgdesc is the subset of: + LOG_T_ALL, + LOG_T_USER, + LOG_T_CLIENT, + LOG_T_INIT, + LOG_T_MANAGE, + LOG_T_MAIN, + LOG_I_ALL, + LOG_I_CRIT, + LOG_I_DEBUG, + LOG_I_DDEBUG, + LOG_I_INFO, + LOG_I_NOTICE, + LOG_I_WARNING, + LOG_I_ERR + + written without spaces. + + + Example: + + file,filename,LOG_T_MANAGE,LOG_I_ALL + +================================================================================ + ========== -4. MODULES +6. MODULES ========== Afclient can use external modules for user's packets filtering ('-l, --load') @@ -343,10 +426,10 @@ Modules have to be compiled with '-fPIC -shared' options. ================================================================================ =========== -5. EXAMPLES +7. EXAMPLES =========== - 5.1 tcp mode + 7.1 tcp mode ------------ local network |FireWall| Internet @@ -395,7 +478,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. - 5.2 reverse udp mode + 7.2 reverse udp mode -------------------- local network |FireWall| Internet @@ -434,7 +517,7 @@ server on our computer (udp port 27960 on our machine): ================================================================================ ================ -6. BUGS/PROBLEMS +8. BUGS/PROBLEMS ================ There are no known/open bugs at the moment. diff --git a/configure.ac b/configure.ac index 6c5c7b8..6f56eff 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ # 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_INIT([Active port forwarder], [0.7], [jeremian@poczta.fm], [apf]) +AM_INIT_AUTOMAKE([apf], [0.7]) AC_COPYRIGHT([ Copyright (C) 2003,2004,2005 jeremian - =================== @@ -56,6 +56,15 @@ AC_CHECK_LIB([dl], [dlopen], ]) AC_SUBST(LINKED_LDLIB) AC_SUBST(USE_RDYNAMIC) +AC_CHECK_LIB([pthread], [pthread_create], + [ + LINKED_PTHREADLIB="-lpthread" + AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define to 1 if you have the `pthread' library (-lpthread).]) + ], + [ + LINKED_PTHREADLIB="" + ]) +AC_SUBST(LINKED_PTHREADLIB) # Checks for header files. AC_HEADER_STDC diff --git a/doc/afclient.1 b/doc/afclient.1 index 5cdd770..7fd5a1c 100644 --- a/doc/afclient.1 +++ b/doc/afclient.1 @@ -1,4 +1,4 @@ -.TH afclient 1 "apf 0.6" Jeremian +.TH afclient 1 "apf 0.7" Jeremian .SH NAME afclient \- active port forwarder client .SH SYNOPSIS @@ -41,6 +41,9 @@ is running (required) .B -p, --portnum PORT the port we are forwarding connection to (required) +.B -V, --version + display version number + .B -h, --help prints help screen @@ -60,6 +63,15 @@ is running (required) .B -D, --dateformat FORMAT format of the date printed in logs (see 'man strftime' for details) (default: %d.%m.%Y %H:%M:%S) +.B -K, --keep-alive N + send keepalive packets every N seconds (default: not send keepalive packets) + +.B -A, --ar-tries N + try N times to reconnect to afserver after its premature quit (default: unlimited) + +.B -T, --ar-delay N + wait N seconds between reconnect tries (default: 5) + .I Modes .B -u, --udpmode @@ -69,21 +81,12 @@ is running (required) 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) + remote administration mode. (using '-p PORT' will force afclient to use port rather than 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 -o, --log LOGCMD + log choosen information to file/socket .B -v, --verbose to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -104,6 +107,14 @@ is running (required) .B -L, --Load load a module for service's packets filtering +.I HTTP PROXY + +.B -P, --proxyname + the name of the machine with proxy server + +.B -X, --proxyport + the port used by proxy server (default: 8080) + .SH "REMOTE ADMINISTRATION" Remote administration mode is enabled by @@ -141,6 +152,50 @@ command), .B afclient exits. +.SH "LOGCMD FORMAT" + +.B LOGCMD +has the following synopsis: +.B target,description,msgdesc + +Where +.B target +is +.B file +or +.B sock + +.B description +is +.B filename +or +.B host,port + +and +.B msgdesc +is the subset of: + +.B LOG_T_ALL, +.B LOG_T_USER, +.B LOG_T_CLIENT, +.B LOG_T_INIT, +.B LOG_T_MANAGE, +.B LOG_T_MAIN, +.B LOG_I_ALL, +.B LOG_I_CRIT, +.B LOG_I_DEBUG, +.B LOG_I_DDEBUG, +.B LOG_I_INFO, +.B LOG_I_NOTICE, +.B LOG_I_WARNING, +.B LOG_I_ERR + +written without spaces. + + Example: + + file,logfile,LOG_T_USER,LOG_T_CLIENT,LOG_I_INFO,LOG_I_NOTICE + .SH MODULES .B Afclient diff --git a/doc/afserver.1 b/doc/afserver.1 index 0a39c2c..cf17b49 100644 --- a/doc/afserver.1 +++ b/doc/afserver.1 @@ -1,4 +1,4 @@ -.TH afserver 1 "apf 0.6" Jeremian +.TH afserver 1 "apf 0.7" Jeremian .SH NAME afserver \- active port forwarder server .SH SYNOPSIS @@ -89,6 +89,9 @@ connects to it (default: 50126) .B -b, --baseport listenports are temporary and differ for each client +.B -a, --audit + additional information about connections are logged + .B --nossl ssl is not used to transfer data (but it's still used to establish a connection) (default: ssl is used) @@ -100,17 +103,8 @@ connects to it (default: 50126) .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 -o, --log LOGCMD + log choosen information to file/socket .B -v, --verbose to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -123,6 +117,11 @@ connects to it (default: 50126) .B -6, --ipv6 use ipv6 only +.I HTTP PROXY + +.B -P, --enableproxy + enable http proxy mode + .SH "REMOTE ADMINISTRATION" Currently available commands are: @@ -148,6 +147,68 @@ Currently available commands are: .B quit quit connection +.B timeout N X + set timeout value in X realm + +.B audit {0|1} X + set audit mode in X realm + +.B dnslookups {0|1} X + set dnslookups mode in X realm + +.B dateformat S + set dateformat + +.B kuser S + kick user named S + +.B kclient N + kick client with number N + +.SH "LOGCMD FORMAT" + +.B LOGCMD +has the following synopsis: +.B target,description,msgdesc + +Where +.B target +is +.B file +or +.B sock + +.B description +is +.B filename +or +.B host,port + +and +.B msgdesc +is the subset of: + +.B LOG_T_ALL, +.B LOG_T_USER, +.B LOG_T_CLIENT, +.B LOG_T_INIT, +.B LOG_T_MANAGE, +.B LOG_T_MAIN, +.B LOG_I_ALL, +.B LOG_I_CRIT, +.B LOG_I_DEBUG, +.B LOG_I_DDEBUG, +.B LOG_I_INFO, +.B LOG_I_NOTICE, +.B LOG_I_WARNING, +.B LOG_I_ERR + +written without spaces. + + Example: + + file,filename,LOG_T_ALL,LOG_I_CRIT,LOG_I_ERR,LOG_I_WARNING + .SH "SEE ALSO" .BR afclient (1), diff --git a/doc/afserver.conf.5 b/doc/afserver.conf.5 index b15bf2d..18d1b2a 100644 --- a/doc/afserver.conf.5 +++ b/doc/afserver.conf.5 @@ -1,4 +1,4 @@ -.TH afserver.conf 5 "apf 0.6" Jeremian +.TH afserver.conf 5 "apf 0.7" Jeremian .SH NAME afserver.conf \- Configuration File for afserver .SH INTRODUCTION @@ -22,9 +22,9 @@ uses configuration file, which name is supplied by the 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 +.B realm command and includes options describing specific realms. There may be several -.B newrealm +.B realm commands. .SH "GLOBAL OPTIONS" @@ -35,17 +35,8 @@ commands. .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 log LOGCMD + log choosen information to file/socket .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. @@ -98,6 +89,9 @@ commands. .B baseport listenports are temporary and differ for each client + +.B audit + additional information about connections are logged .B dnslookups try to obtain dns names of the computers rather than their numeric IP @@ -108,6 +102,9 @@ commands. .B ipv6 use ipv6 only +.B enableproxy + enable http proxy mode + .SH "SEE ALSO" .BR afclient (1), diff --git a/doc/afserver_example.conf b/doc/afserver_example.conf index 2046b03..f7c0be8 100644 --- a/doc/afserver_example.conf +++ b/doc/afserver_example.conf @@ -12,17 +12,13 @@ key server.rsa # type name of file -lightlog logfile -#heavylog logfile +log file,logfile,LOG_T_ALL,LOG_I_CRIT,LOG_I_ERR,LOG_I_WARNING # we we could also want to use sockets instead of files -# type port (on localhost) +#log sock,localhost,LOG_T_ALL,LOG_I_ALL -#lightsocklog 12345 -#heavysocklog 12345 - -#dateformat %d.%m.%Y %H:%M:%S +#dateformat %Y-%m-%d %H:%M:%S # And it's time to create forwarding targets (named realms here) @@ -46,9 +42,11 @@ manage 50126 #portnumber on which server is listening for afclient #nossl #don't use ssl for data transfer #nozlib #don't use zlib #baseport #listenports are temporary and differ for each client +#audit #additional information about connections are logged #dnslookups #try to obtain dns names of the computers #ipv4 #use ipv4 only #ipv6 #use ipv6 only +#enableproxy #enable http proxy mode # and now the second realm diff --git a/doc/en/README b/doc/en/README index 0e49c3e..d676098 100644 --- a/doc/en/README +++ b/doc/en/README @@ -1,4 +1,4 @@ -AF - Active Port Forwarder 0.6 - README +AF - Active Port Forwarder 0.7 - README Copyright (C) 2003,2004,2005 jeremian - ================================================================= @@ -30,11 +30,13 @@ INTRO 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 +4. HTTP PROXY TUNNELS +5. LOGGING +6. MODULES +7. EXAMPLES + 7.1 tcp mode + 7.2 reverse udp mode +8. BUGS/PROBLEMS NOTES @@ -110,6 +112,7 @@ Multiple clients allow to create more sophisticated tunneling scheme. to it (default: 50127) -m, --manageport - manage port number - second part of the active port forwarder connects to it (default: 50126) + -V, --version - display version number -h, --help - prints this help Authorization: @@ -137,27 +140,24 @@ Multiple clients allow to create more sophisticated tunneling scheme. -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 to connect 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) + -p, --proto - type of server (tcp|udp) - what protocol it will be + operating for (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) + -a, --audit - additional information about connections are logged + --nossl - ssl is not used to transfer data (but it's still used + to establish a connection) (default: ssl is used) + --nozlib - zlib is not used to compress 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 + -o, --log - log choosen information to file/socket -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -166,6 +166,11 @@ Multiple clients allow to create more sophisticated tunneling scheme. -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only + HTTP PROXY: + + -P, --enableproxy - enable http proxy mode + + 2.2 afclient ------------ @@ -179,11 +184,12 @@ 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) + -V, --version - display version number -h, --help - prints this help Authorization: - -i, --id - send the id string to afserver + -i, --id - sends the id string to afserver --pass - set the password used for client identification (default: no password) @@ -192,23 +198,25 @@ Multiple clients allow to create more sophisticated tunneling scheme. -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) + -K, --keep-alive N - send keepalive packets every N seconds + (default: not send keepalive packets) + -A, --ar-tries N - try N times to reconnect to afserver after + its premature quit (default: unlimited) + -T, --ar-delay N - wait N seconds between reconnect tries (default: 5) Modes: -u, --udpmode - udp mode - client will use udp protocol to - communicate with the hostname + communicate with the hostname:portnum (-p) -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) + force afclient to use port rather than 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 + -o, --log - log choosen information to file/socket -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) @@ -222,6 +230,12 @@ Multiple clients allow to create more sophisticated tunneling scheme. -l, --load - load a module for user's packets filtering -L, --Load - load a module for service's packets filtering + HTTP PROXY: + + -P, --proxyname - the name of the machine with proxy server + -X, --proxyport - the port used by proxy server (default: 8080) + + ================================================================================ ======================== @@ -257,6 +271,25 @@ Currently available commands are: quit quit connection + timeout N X + set timeout value in X realm + + audit {0|1} X + set audit mode in X realm + + dnslookups {0|1} X + set dnslookups mode in X realm + + dateformat S + set dateformat + + kuser S + kick user named S + + kclient N + kick client with number N + + 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. @@ -265,8 +298,58 @@ When user quits (close the connection or send 'quit' command), afclient exits. ================================================================================ +===================== +4. HTTP PROXY TUNNELS +===================== + +Afclient can communicate with afserver via HTTP proxy. In order to use this +feature, afserver must be started with '-P, --enableproxy' option. Afclient must +specify the proxy host ('-P, --proxyname' option) and port ('-X, --proxyport' +option). + +Afclient with HTTP proxy mode enabled can still accept connections from +afclients, which don't use HTTP proxy mode. + +================================================================================ + +========== +5. LOGGING +========== + +Logging can be enabled by '-o, --log' option. The argument to this option must +be in the form: + target,description,msgdesc + +Where + target is file or sock + description is filename or host,port + msgdesc is the subset of: + LOG_T_ALL, + LOG_T_USER, + LOG_T_CLIENT, + LOG_T_INIT, + LOG_T_MANAGE, + LOG_T_MAIN, + LOG_I_ALL, + LOG_I_CRIT, + LOG_I_DEBUG, + LOG_I_DDEBUG, + LOG_I_INFO, + LOG_I_NOTICE, + LOG_I_WARNING, + LOG_I_ERR + + written without spaces. + + + Example: + + file,filename,LOG_T_MANAGE,LOG_I_ALL + +================================================================================ + ========== -4. MODULES +6. MODULES ========== Afclient can use external modules for user's packets filtering ('-l, --load') @@ -343,10 +426,10 @@ Modules have to be compiled with '-fPIC -shared' options. ================================================================================ =========== -5. EXAMPLES +7. EXAMPLES =========== - 5.1 tcp mode + 7.1 tcp mode ------------ local network |FireWall| Internet @@ -395,7 +478,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. - 5.2 reverse udp mode + 7.2 reverse udp mode -------------------- local network |FireWall| Internet @@ -434,7 +517,7 @@ server on our computer (udp port 27960 on our machine): ================================================================================ ================ -6. BUGS/PROBLEMS +8. BUGS/PROBLEMS ================ There are no known/open bugs at the moment. diff --git a/src/Makefile.am b/src/Makefile.am index a6ccd11..282b514 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,13 @@ bin_PROGRAMS = afserver afclient +afserver_LDFLAGS = ${LINKED_PTHREADLIB} 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} + make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c \ + http_proxy_functions.c http_proxy_server.c server_get.c thread_management.c \ + server_signals.c usage.c logging.c audit.c +afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB} ${LINKED_PTHREADLIB} 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 + make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c \ + http_proxy_functions.c http_proxy_client.c thread_management.c \ + client_reverse_udp.c server_check.c client_initialization.c client_shutdown.c \ + client_signals.c usage.c logging.c audit.c diff --git a/src/activefor.h b/src/activefor.h index 8d07c8b..76564cb 100644 --- a/src/activefor.h +++ b/src/activefor.h @@ -23,6 +23,7 @@ #include "network.h" #include "buflist.h" +#include "audit.h" #define AF_S_CONCLOSED 1 #define AF_S_CONOPEN 2 @@ -37,13 +38,15 @@ #define AF_S_ADMIN_LOGIN 14 #define AF_S_ADMIN_CMD 15 +#define AF_S_KEEP_ALIVE 16 + #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 AF_VER(info) info" v0.7" #define TYPE_TCP 1 #define TYPE_UDP 3 @@ -110,6 +113,8 @@ typedef struct { char* clientid; char namebuf[128]; char portbuf[7]; + char tunneltype; + alnodeT* head; } ConnectclientT; typedef struct { @@ -135,8 +140,10 @@ typedef struct { int clientcounter; int usercounter; char type; + char tunneltype; char dnslookups; char baseport; + char audit; socklen_t addrlen; struct sockaddr* cliaddr; ConnectuserT* contable; @@ -148,11 +155,7 @@ typedef struct { typedef struct { char* certif; char* keys; - char* logfnam; - char* logsport; char* dateformat; - char logging; - char socklogging; int size; time_t starttime; RealmT* realmtable; diff --git a/src/afclient.c b/src/afclient.c index cc3c0c8..72f1f9c 100644 --- a/src/afclient.c +++ b/src/afclient.c @@ -32,10 +32,7 @@ static struct option long_options[] = { {"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'}, + {"log", 1, 0, 'o'}, {"pass", 1, 0, 301}, #ifdef AF_INET6 {"ipv4", 0, 0, '4'}, @@ -48,6 +45,14 @@ static struct option long_options[] = { {"id", 1, 0, 'i'}, {"dateformat", 1, 0, 'D'}, {"remoteadmin", 0, 0, 'r'}, +#ifdef HAVE_LIBPTHREAD + {"proxyname", 1, 0, 'P'}, + {"proxyport", 1, 0, 'X'}, +#endif + {"version", 0, 0, 'V'}, + {"keep-alive", 1, 0, 'K'}, + {"ar-tries", 1, 0, 'A'}, + {"ar-delay", 1, 0, 'T'}, {0, 0, 0, 0} }; @@ -63,23 +68,32 @@ main(int argc, char **argv) socklen_t len, addrlen; struct sockaddr* cliaddr; fd_set rset, allset, wset, tmpset; + struct timeval keepalive; + int timeout = 0; + int delay = 5; + int tries = -1; char verbose = 0; char remote = 0; - char logging = 0; - char socklogging = 0; + char sendkapackets = 0; char* name = NULL; +#ifdef HAVE_LIBPTHREAD + char* proxyname = NULL; + char* proxyport = NULL; +#endif 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* katimeout = NULL; + char* artries = NULL; + char* ardelay = NULL; char ipfam = 0; unsigned char pass[4] = {1, 2, 3, 4}; char udp = 0; char reverse = 0; + char tunneltype = 0; char type = 0; struct sigaction act; #ifdef HAVE_LIBDL @@ -87,38 +101,58 @@ main(int argc, char **argv) #endif SSL_METHOD* method; - SSL_CTX* ctx; - + SSL_CTX* ctx = NULL; + sigfillset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); - act.sa_handler = sig_int; + act.sa_handler = client_sig_int; sigaction(SIGINT, &act, NULL); + +#ifdef HAVE_LIBPTHREAD + remember_mainthread(); +#endif #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 +#define GETOPT_LONG_AF_INET6(x) "46"x +#else +#define GETOPT_LONG_AF_INET6(x) x +#endif +#ifdef HAVE_LIBPTHREAD +#define GETOPT_LONG_LIBPTHREAD(x) "P:X:"x +#else +#define GETOPT_LONG_LIBPTHREAD(x) x +#endif +#ifdef HAVE_LIBDL +#define GETOPT_LONG_LIBDL(x) "l:L:"x #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 +#define GETOPT_LONG_LIBDL(x) x #endif + + while ((n = getopt_long(argc, argv, + GETOPT_LONG_LIBDL(GETOPT_LONG_LIBPTHREAD(GETOPT_LONG_AF_INET6("huUn:m:d:p:vk:o:i:D:rP:X:VK:A:T:"))) + , long_options, 0)) != -1) { switch (n) { case 'h': { - usage(AF_VER("Active port forwarder (client)")); + client_long_usage(AF_VER("Active port forwarder (client)")); break; } case 'n': { name = optarg; break; } +#ifdef HAVE_LIBPTHREAD + case 'P': { + proxyname = optarg; + break; + } + case 'X': { + proxyport = optarg; + break; + } +#endif case 'i': { id = optarg; break; @@ -151,24 +185,8 @@ main(int argc, char **argv) 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; + addlogtarget(optarg); break; } case 301: { @@ -217,25 +235,58 @@ main(int argc, char **argv) remote = 1; break; } + case 'V': { + printf("%s\n", (AF_VER("Active port forwarder (client)"))); + exit(0); + break; + } + case 'K': { + katimeout = optarg; + sendkapackets = 1; + break; + } + case 'A': { + artries = optarg; + break; + } + case 'T': { + ardelay = optarg; + break; + } case '?': { - usage(""); + client_short_usage(""); break; } } } if (optind < argc) { - usage("Unrecognized non-option elements"); + client_short_usage("Unrecognized non-option elements"); } if (name == NULL) { - usage("Name of the server is required"); + client_short_usage("Name of the server is required"); } if (manage == NULL) { manage = "50126"; if (reverse) - usage("Port on the server is required in reverse mode"); + client_short_usage("Port on the server is required in reverse mode"); } +#ifdef HAVE_LIBPTHREAD + if ((proxyname) || (proxyport)) { + if (tunneltype == 0) { + tunneltype = 1; + } + else { + tunneltype = -1; + } + } + if (tunneltype == 1) { + if (proxyport == NULL) { + proxyport = "8080"; + } + } +#endif if (keys == NULL) { keys = "client.rsa"; } @@ -244,31 +295,32 @@ main(int argc, char **argv) desnam = hostname; } if ((!remote) && (despor == NULL)) { - usage("Destination port number is required"); + client_short_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); + if (sendkapackets) { + check_value(&timeout, katimeout, "Invalid timeout value"); + keepalive.tv_sec = timeout; + keepalive.tv_usec = 0; + } + if (artries) { + tries = check_value_liberal(artries, "Invalid ar-tries value"); + } + if (ardelay) { + check_value(&delay, ardelay, "Invalid ar-delay value"); } + + initializelogging(verbose, dateformat); #ifdef HAVE_LIBDL if (loadmodule(&module)) { - aflog(0, "Loading a module %s failed!", module.name); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Loading a module %s failed!", module.name); exit(1); } if (loadmodule(&secmodule)) { - aflog(0, "Loading a module %s failed!", secmodule.name); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Loading a module %s failed!", secmodule.name); exit(1); } #endif @@ -278,7 +330,8 @@ main(int argc, char **argv) #ifdef AF_INET6 if (ipfam == -1) { - aflog(0, "Conflicting types of ip protocol family... exiting"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); exit(1); } else if (ipfam == 4) { @@ -303,252 +356,87 @@ main(int argc, char **argv) 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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting cipher list failed... exiting"); exit(1); } if ((temp2 = create_apf_dir())) { - aflog(1, "Warning: Creating ~/.apf directory failed (%d)", temp2); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting rsa key failed (%s)... exiting", keys); exit(1); } + if ((!remote) && (!verbose)) + daemon(0, 0); + 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", + aflog(LOG_T_INIT, LOG_I_CRIT, + "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); + aflog(LOG_T_INIT, LOG_I_CRIT, + "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); +#ifdef HAVE_LIBPTHREAD + initialize_client_stage1(tunneltype, &master, name, manage, proxyname, proxyport, ipfam, ctx, buff, pass, 1); #else - aflog(0, "tcp_connect error for %s, %s", name, manage); + initialize_client_stage1(tunneltype, &master, name, manage, NULL, NULL, ipfam, ctx, buff, pass, 1); #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]; + + initialize_client_stage2(&type, &master, &usernum, buff, 1); } /* !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; + initialize_client_reverse_udp(&usernum, &master, name, manage, ipfam); } - 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; + initialize_client_stage3(&contable, &master, usernum, &buflength, &len, &allset, &wset, &maxfdp1, 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 */ + client_reverse_udp(contable, &master, desnam, despor, type, buff, buflength); } /* 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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "CLIENT STARTED mode: %s", (udp)?"udp":"tcp"); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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)); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "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()); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "LOADED MODULE: %s INFO: %s", module.name, module.info()); } if (ismloaded(&secmodule)) { - aflog(1, "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); } #endif if (id != NULL) { @@ -559,29 +447,46 @@ main(int argc, char **argv) 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); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "ID SENT: %s", id); } for ( ; ; ) { rset = allset; tmpset = wset; - aflog(3, ">select"); - select(maxfdp1, &rset, &tmpset, NULL, NULL); - aflog(3, " >>after select..."); + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "select"); + if (sendkapackets) { + if (select(maxfdp1, &rset, &tmpset, NULL, &keepalive) == 0) { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "timeout: sending keep-alive packet"); + buff[0] = AF_S_KEEP_ALIVE; + send_message(type, master, buff, 5); + keepalive.tv_sec = timeout; + } + } + else { + select(maxfdp1, &rset, &tmpset, NULL, NULL); + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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); + aflog(LOG_T_USER, LOG_I_ERR, + "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..."); + aflog(LOG_T_USER, LOG_I_CRIT, + "ioctl error -> exiting..."); exit(1); } if (udp) { @@ -589,14 +494,17 @@ main(int argc, char **argv) if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; - aflog(2, "Send buffer size changed..."); + aflog(LOG_T_USER, LOG_I_WARNING, + "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); + aflog(LOG_T_USER, LOG_I_WARNING, + "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..."); + aflog(LOG_T_USER, LOG_I_CRIT, + "ioctl error -> exiting..."); exit(1); } if (udp) { @@ -604,11 +512,13 @@ main(int argc, char **argv) if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; - aflog(2, "Send buffer size changed..."); + aflog(LOG_T_USER, LOG_I_WARNING, + "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", + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, buflength-notsent, buflength); # endif continue; /* drop this packet */ @@ -620,16 +530,19 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d] (by ser): PACKET IGNORED BY MODULE", i); if (temp2 == 4) { - aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "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); + aflog(LOG_T_USER, LOG_I_NOTICE, + "user[%d] (by ser): DROPPED BY MODULE", i); close(contable[i].connfd); FD_CLR(contable[i].connfd, &allset); FD_CLR(contable[i].connfd, &wset); @@ -640,14 +553,16 @@ main(int argc, char **argv) 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()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "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()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); releasemodule(&secmodule); break; } @@ -660,7 +575,8 @@ main(int argc, char **argv) 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, + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: TO msglen: %d [%d/%d]", i, n, # ifdef SIOCOUTQ notsent # else @@ -668,12 +584,14 @@ main(int argc, char **argv) # endif , buflength); #else - aflog(2, " user[%d]: TO msglen: %d", i, n); + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: TO msglen: %d", i, n); #endif send_message(type, master, buff, n+5); } else if (!udp) { - aflog(2, " user[%d]: CLOSING", i); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSING", i); close(contable[i].connfd); FD_CLR(contable[i].connfd, &allset); FD_CLR(contable[i].connfd, &wset); @@ -690,14 +608,16 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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); + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: Couldn't write?", i); } else if (temp2 == -1) { close(contable[i].connfd); @@ -717,7 +637,8 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE ENDED", i); send_message(type, master, buff, 5); } } @@ -725,10 +646,12 @@ main(int argc, char **argv) } } if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ - aflog(3, " masterfd: FD_ISSET"); + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "masterfd: FD_ISSET"); n = get_message(type, master, buff, 5); if (n != 5) { - aflog(2, " FATAL ERROR! (%d)", n); + aflog(LOG_T_CLIENT, LOG_I_ERR, + "FATAL ERROR! (%d)", n); if (n == -1) { if (TYPE_IS_SSL(type)) { get_ssl_error(&master, "FE", n); @@ -739,8 +662,59 @@ main(int argc, char **argv) exit(1); } if (n == 0) { /* server quits -> we do the same... */ - aflog(0, " SERVER: premature quit -> exiting..."); - exit(1); + i = tries; + if (i) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: premature quit -> auto-reconnect enabled"); + } + while (i) { + close_connections(usernum, &contable); + clear_master_connection(&master); + mysleep(delay); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Trying to reconnect..."); + + temp2 = 0; + if (temp2 == 0) { +#ifdef HAVE_LIBPTHREAD + if (initialize_client_stage1(tunneltype, &master, name, manage, proxyname, proxyport, + ipfam, ctx, buff, pass, 0)) { +#else + if (initialize_client_stage1(tunneltype, &master, name, manage, NULL, NULL, + ipfam, ctx, buff, pass, 0)) { +#endif + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage2(&type, &master, &usernum, buff, 0)) { + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage3(&contable, &master, usernum, &buflength, &len, &allset, + &wset, &maxfdp1, 0)) { + temp2 = 1; + } + } + + if (temp2 == 0) { + n = 1; + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Reconnected successfully..."); + break; + } + + if (i > 0) { + --i; + } + } + if (n == 0) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "SERVER: premature quit -> exiting..."); + exit(1); + } + continue; } numofcon = buff[1]; numofcon = numofcon << 8; @@ -750,15 +724,18 @@ main(int argc, char **argv) length += buff[4]; /* this is length of message */ switch (buff[0]) { case AF_S_CONCLOSED : { - aflog(4, " user[%d]: AF_S_CONCLOSED", numofcon); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSED", numofcon); } else if ((contable[numofcon].state==S_STATE_OPEN) || (contable[numofcon].state==S_STATE_STOPPED)){ - aflog(1, " user[%d]: CLOSED", numofcon); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSED", numofcon); close(contable[numofcon].connfd); FD_CLR(contable[numofcon].connfd, &allset); FD_CLR(contable[numofcon].connfd, &wset); @@ -773,19 +750,23 @@ main(int argc, char **argv) break; } case AF_S_CONOPEN : { - aflog(4, " user[%d]: AF_S_CONOPEN", numofcon); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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, + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: OPENING", numofcon); + aflog(LOG_T_USER, LOG_I_INFO, + "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); + aflog(LOG_T_USER, LOG_I_WARNING, + "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 */ @@ -809,7 +790,8 @@ main(int argc, char **argv) } #endif if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) { - aflog(2, " CAN'T OPEN - DROPPING", numofcon); + aflog(LOG_T_USER, LOG_I_WARNING, + "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 */ @@ -831,8 +813,10 @@ main(int argc, char **argv) break; } case AF_S_MESSAGE : { - aflog(4, " user[%d]: AF_S_MESSAGE", numofcon); - aflog(2, " user[%d]: FROM msglen: %d", numofcon, length); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: AF_S_MESSAGE", numofcon); + aflog(LOG_T_USER, LOG_I_DEBUG, + "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) { @@ -840,16 +824,19 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: PACKET IGNORED BY MODULE", numofcon); if (temp2 == 4) { - aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "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); + aflog(LOG_T_USER, LOG_I_NOTICE, + "user[%d]: DROPPED BY MODULE", numofcon); close(contable[numofcon].connfd); FD_CLR(contable[numofcon].connfd, &allset); FD_CLR(contable[numofcon].connfd, &wset); @@ -860,21 +847,24 @@ main(int argc, char **argv) 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()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "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()); + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE: %s INFO: %s", module.name, module.info()); releasemodule(&module); break; } } } #endif - aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n); + aflog(LOG_T_USER, LOG_I_DEBUG, + "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); @@ -883,7 +873,8 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); send_message(type, master, buff, 5); } else if ((temp2 == -1) && (errno == EAGAIN)) { @@ -893,7 +884,8 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); send_message(type, master, buff, 5); } else if (temp2 == -1) { @@ -909,29 +901,34 @@ main(int argc, char **argv) } } else if (contable[numofcon].state == S_STATE_STOPPED) { - aflog(3, " FROM user[%d]: BUFFERING MESSAGE", numofcon); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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()); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); exit(1); break; } case AF_S_DONT_SEND: { - aflog(4, " user[%d]: AF_S_DONT_SEND", numofcon); + aflog(LOG_T_USER, LOG_I_DEBUG, + "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); + aflog(LOG_T_USER, LOG_I_DEBUG, + "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()); + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); exit(1); break; } @@ -939,62 +936,3 @@ main(int argc, char **argv) } /* - 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 index 108751b..c2b52bb 100644 --- a/src/afclient.h +++ b/src/afclient.h @@ -25,6 +25,17 @@ #include "remoteadmin.h" #include "make_ssl_handshake.h" #include "first_run.h" +#include "http_proxy_client.h" +#include "thread_management.h" +#include "client_reverse_udp.h" +#include "server_check.h" +#include "client_initialization.h" +#include "http_proxy_functions.h" +#include "client_shutdown.h" +#include "client_signals.h" +#include "usage.h" +#include "logging.h" +#include "audit.h" #include #include @@ -43,8 +54,5 @@ #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 index d1e11b7..76f8ffc 100644 --- a/src/afserver.c +++ b/src/afserver.c @@ -39,10 +39,8 @@ static struct option long_options[] = { {"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'}, + {"log", 1, 0, 'o'}, + {"audit", 0, 0, 'a'}, {"nossl", 0, 0, 301}, {"nozlib", 0, 0, 302}, {"pass", 1, 0, 303}, @@ -53,10 +51,14 @@ static struct option long_options[] = { {"baseport", 0, 0, 'b'}, {"dnslookups", 0, 0, 311}, {"dateformat", 1, 0, 'D'}, +#ifdef HAVE_LIBPTHREAD + {"enableproxy", 0, 0, 'P'}, +#endif + {"version", 0, 0, 'V'}, {0, 0, 0, 0} }; -static ConfigurationT config; +ConfigurationT config; int main(int argc, char **argv) @@ -84,19 +86,20 @@ main(int argc, char **argv) unsigned char pass[4] = {1, 2, 3, 4}; char verbose = 0; char mode = 0; +#ifdef HAVE_LIBPTHREAD + char tunneltype = 0; +#endif char ipfam = 0; char baseport = 0; + char audit = 0; char dnslookups = 0; RealmT* pointer = NULL; struct sigaction act; + time_t now; 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; @@ -107,30 +110,41 @@ main(int argc, char **argv) act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); - act.sa_handler = sig_int; + act.sa_handler = server_sig_int; sigaction(SIGINT, &act, NULL); TYPE_SET_SSL(mode); TYPE_SET_ZLIB(mode); + memset(&config, 0, sizeof(config)); + 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 HAVE_LIBPTHREAD + remember_mainthread(); +#endif #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) { +#define GETOPT_LONG_AF_INET6(x) "46"x +#else +#define GETOPT_LONG_AF_INET6(x) x +#endif +#ifdef HAVE_LIBPTHREAD +#define GETOPT_LONG_LIBPTHREAD(x) "P"x #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) { +#define GETOPT_LONG_LIBPTHREAD(x) x #endif + + while ((n = getopt_long(argc, argv, + GETOPT_LONG_LIBPTHREAD(GETOPT_LONG_AF_INET6("hn:l:m:vu:c:k:f:p:o:t:C:U:M:abD:R:r:V")) + , long_options, 0)) != -1) { switch (n) { case 'h': { - usage(AF_VER("Active port forwarder (server)")); + server_long_usage(AF_VER("Active port forwarder (server)")); break; } case 'n': { @@ -197,26 +211,10 @@ main(int argc, char **argv) filenam = optarg; break; } - case 'O': { - logfnam = optarg; - logging = 3; - break; - } case 'o': { - logfnam = optarg; - logging = 1; + addlogtarget(optarg); break; } - case 'S': { - logsport = optarg; - socklogging = 3; - break; - } - case 's': { - logsport = optarg; - socklogging = 1; - break; - } case 301: { TYPE_UNSET_SSL(mode); break; @@ -258,6 +256,10 @@ main(int argc, char **argv) baseport = 1; break; } + case 'a': { + audit = 1; + break; + } case 311: { dnslookups = 1; break; @@ -266,15 +268,31 @@ main(int argc, char **argv) dateformat = optarg; break; } +#ifdef HAVE_LIBPTHREAD + case 'P': { + if (tunneltype != 0) { + tunneltype = -1; + } + else { + tunneltype = 1; + } + break; + } +#endif + case 'V': { + printf("%s\n", (AF_VER("Active port forwarder (server)"))); + exit(0); + break; + } case '?': { - usage(""); + server_short_usage(""); break; } } } if (optind < argc) { - usage("Unrecognized non-option elements"); + server_short_usage("Unrecognized non-option elements"); } if (filenam != NULL) { @@ -296,76 +314,38 @@ main(int argc, char **argv) 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); - } + + initializelogging(verbose, config.dateformat); - aflog(1, "cfg file OK! (readed realms: %d)", config.size); + aflog(LOG_T_INIT, LOG_I_INFO, + "cfg file OK! (readed realms: %d)", config.size); if (name != NULL) - aflog(1, "Warning: hostname=%s will be ignored", name); + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: hostname=%s will be ignored", name); if (listen != NULL) - aflog(1, "Warning: listenport will be ignored"); + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: listenport will be ignored"); if (manage != NULL) - aflog(1, "Warning: manageport will be ignored"); + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: manageport will be ignored"); if (realmname != NULL) - aflog(1, "Warning: realmname=%s will be ignored", realmname); + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: realmname=%s will be ignored", realmname); if (sent == 1) - aflog(1, "Warning: password from command line will be ignored"); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); - } - + initializelogging(verbose, config.dateformat); + if (listen == NULL) { listencount = 1; listen = calloc(1, sizeof(char*)); @@ -377,7 +357,8 @@ main(int argc, char **argv) manage[0] = "50126"; } if (managecount != listencount) { - aflog(0, "Number of listen and manage options are not the same... exiting"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Number of listen and manage options are not the same... exiting"); exit(1); } if (config.certif == NULL) { @@ -405,6 +386,10 @@ main(int argc, char **argv) config.realmtable[0].usrpcli = usrpcli; config.realmtable[0].clim = clim; config.realmtable[0].baseport = baseport; + config.realmtable[0].audit = audit; +#ifdef HAVE_LIBPTHREAD + config.realmtable[0].tunneltype = tunneltype; +#endif config.realmtable[0].dnslookups = dnslookups; config.realmtable[0].realmname = realmname; memcpy(config.realmtable[0].pass, pass, 4); @@ -419,7 +404,8 @@ main(int argc, char **argv) } #ifdef AF_INET6 if (ipfam == -1) { - aflog(0, "Conflicting types of ip protocol family... exiting"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); exit(1); } else if (ipfam == 4) { @@ -438,44 +424,56 @@ main(int argc, char **argv) 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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting ciphers list failed... exiting"); exit(1); } if ((flags = create_apf_dir())) { - aflog(1, "Warning: Creating ~/.apf directory failed (%d)", flags); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); + aflog(LOG_T_INIT, LOG_I_CRIT, + "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); + aflog(LOG_T_INIT, LOG_I_WARNING, + "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); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting certificate failed (%s)... exiting", config.certif); exit(1); } if (config.size == 0) { - aflog(0, "Working without sense is really without sense..."); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Working without sense is really without sense..."); exit(1); } FD_ZERO(&allset); FD_ZERO(&wset); + if (!verbose) + daemon(0, 0); + 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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "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", + aflog(LOG_T_INIT, LOG_I_CRIT, + "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); @@ -502,7 +500,8 @@ main(int argc, char **argv) /* 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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); exit(1); } else if (ipfam == 4) { @@ -524,6 +523,21 @@ main(int argc, char **argv) if (config.realmtable[i].baseport == 0) { config.realmtable[i].baseport = baseport; } + /* using user's audit value*/ + if (config.realmtable[i].audit == 0) { + config.realmtable[i].audit = audit; + } +#ifdef HAVE_LIBPTHREAD + /* using user's tunneltype value*/ + if (config.realmtable[i].tunneltype == 0) { + if (tunneltype == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of tunnel type... exiting"); + exit(1); + } + config.realmtable[i].tunneltype = tunneltype; + } +#endif /* using user's dnslookups value*/ if (config.realmtable[i].dnslookups == 0) { config.realmtable[i].dnslookups = dnslookups; @@ -549,17 +563,20 @@ main(int argc, char **argv) /* 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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "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"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of raclients"); exit(1); } ipfam = 0x01; @@ -575,7 +592,7 @@ main(int argc, char **argv) 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, + aflog(LOG_T_INIT, LOG_I_CRIT, #ifdef AF_INET6 "tcp_listen_%s error for %s, %s", (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", @@ -585,28 +602,65 @@ main(int argc, char **argv) config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].lisportnum); exit(1); } + flags = fcntl(config.realmtable[i].usrclitable[j].listenfd, F_GETFL, 0); + fcntl(config.realmtable[i].usrclitable[j].listenfd, F_SETFL, flags | O_NONBLOCK); } } 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, + switch (config.realmtable[i].tunneltype) { + case 0: { + 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(LOG_T_INIT, LOG_I_CRIT, #ifdef AF_INET6 - "tcp_listen_%s error for %s, %s", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", + "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", #else - "tcp_listen error for %s, %s", + "tcp_listen error for %s, %s", #endif - config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum); - exit(1); - } + config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum); + exit(1); + } + flags = fcntl(config.realmtable[i].usrclitable[j].managefd, F_GETFL, 0); + fcntl(config.realmtable[i].usrclitable[j].managefd, F_SETFL, flags | O_NONBLOCK); + break; + } +#ifdef HAVE_LIBPTHREAD + case 1: { + if (initialize_http_proxy_server(&(config.realmtable[i].usrclitable[j].managefd), + config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum, + (&(config.realmtable[i].addrlen)), ipfam, + config.realmtable[i].clinum + config.realmtable[i].raclinum)) { + aflog(LOG_T_INIT, LOG_I_CRIT, +#ifdef AF_INET6 + "http_proxy_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "http_proxy_listen error for %s, %s", +#endif + config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum); + exit(1); + } + flags = fcntl(config.realmtable[i].usrclitable[j].managefd, F_GETFL, 0); + fcntl(config.realmtable[i].usrclitable[j].managefd, F_SETFL, flags | O_NONBLOCK); + break; + } +#endif + default: { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Unknown tunnel type"); + exit(1); + break; + } + } } config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); for (j=0; jselect, maxfdp1: %d", maxfdp1); + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "select, maxfdp1: %d", maxfdp1); if (manconnecting) { /* find out, in what realm client is trying to connect */ l = -1; @@ -692,7 +747,8 @@ main(int argc, char **argv) config.realmtable[i].clitable[j].ready = 0; manconnecting--; config.realmtable[i].clicon--; - aflog(1, " realm[%s]: Client[%s]: SSL_accept failed (timeout)", + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]: SSL_accept failed (timeout)", get_realmname(&config, i), get_clientname(pointer, j)); } } @@ -704,7 +760,8 @@ main(int argc, char **argv) config.realmtable[i].raclitable[j].ready = 0; manconnecting--; config.realmtable[i].clicon--; - aflog(1, " realm[%s]: Client[%s] (ra): SSL_accept failed (timeout)", + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): SSL_accept failed (timeout)", get_realmname(&config, i), get_raclientname(pointer, j)); } } @@ -712,7 +769,8 @@ main(int argc, char **argv) else { select(maxfdp1, &rset, &tmpset, NULL, NULL); } - aflog(3, " >>after select..."); + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "after select..."); for (j = 0; j < config.size; ++j) { pointer = (&(config.realmtable[j])); @@ -720,23 +778,27 @@ main(int argc, char **argv) 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)); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); 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); + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i), 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); + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i), 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"); + aflog(LOG_T_USER, LOG_I_WARNING, + "WARNING: got packet similiar to udp"); } buff[0] = AF_S_MESSAGE; /* sending message */ buff[1] = k >> 8; /* high bits of user number */ @@ -746,10 +808,26 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), + get_username(pointer, i), + pointer->contable[i].namebuf, + pointer->contable[i].portbuf, + timeperiod(now - pointer->contable[i].connecttime)); + if (pointer->audit) { + insertalnode(&(pointer->clitable[pointer->contable[i].whatcli].head), + get_username(pointer, i), + pointer->contable[i].namebuf, + pointer->contable[i].portbuf, + pointer->contable[i].connecttime, + now - pointer->contable[i].connecttime); + } close(pointer->contable[i].connfd); FD_CLR(pointer->contable[i].connfd, &allset); FD_CLR(pointer->contable[i].connfd, &wset); @@ -772,9 +850,10 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_DEBUG, + "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); + get_username(pointer, i), 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, @@ -787,10 +866,18 @@ main(int argc, char **argv) } 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); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), + get_username(pointer, i), + pointer->contable[i].namebuf, + pointer->contable[i].portbuf, + timeperiod(now - pointer->contable[i].connecttime)); close(pointer->contable[i].connfd); FD_CLR(pointer->contable[i].connfd, &allset); FD_CLR(pointer->contable[i].connfd, &wset); @@ -810,24 +897,36 @@ main(int argc, char **argv) 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)); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i), 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)); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); } 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); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), + get_username(pointer, i), + pointer->contable[i].namebuf, + pointer->contable[i].portbuf, + timeperiod(now - pointer->contable[i].connecttime)); close(pointer->contable[i].connfd); FD_CLR(pointer->contable[i].connfd, &allset); FD_CLR(pointer->contable[i].connfd, &wset); @@ -839,8 +938,9 @@ main(int argc, char **argv) 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, i), sent, n); deleteblnode(&pointer->contable[i].head); if (pointer->contable[i].head == NULL) { pointer->contable[i].state = S_STATE_OPEN; @@ -848,9 +948,10 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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)); + get_username(pointer, i)); send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); } } @@ -862,18 +963,26 @@ main(int argc, char **argv) if (FD_ISSET(pointer->usrclitable[l].listenfd, &rset)) { len = pointer->addrlen; sent = accept(pointer->usrclitable[l].listenfd, pointer->cliaddr, &len); + if (sent == -1) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); + continue; + } flags = fcntl(sent, F_GETFL, 0); fcntl(sent, F_SETFL, flags | O_NONBLOCK); - aflog(3, " realm[%s]: listenfd: FD_ISSET", get_realmname(&config, j)); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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)); + aflog(LOG_T_USER, LOG_I_WARNING, + "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", + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", get_realmname(&config, j), get_clientname(pointer, k)); } else { @@ -881,7 +990,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_INFO, + "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)); @@ -908,7 +1018,8 @@ main(int argc, char **argv) } else { close(sent); - aflog(3, " realm[%s]: Client(%d) is NOT CONNECTED", + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client(%d) is NOT CONNECTED", get_realmname(&config, j), k); } } @@ -921,18 +1032,26 @@ main(int argc, char **argv) if (FD_ISSET(pointer->clitable[k].listenfd, &rset)) { len = pointer->addrlen; sent = accept(pointer->clitable[k].listenfd, pointer->cliaddr, &len); + if (sent == -1) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); + continue; + } flags = fcntl(sent, F_GETFL, 0); fcntl(sent, F_SETFL, flags | O_NONBLOCK); - aflog(3, " realm[%s]: Client[%s]: listenfd: FD_ISSET", + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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)); + aflog(LOG_T_USER, LOG_I_WARNING, + "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", + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", get_realmname(&config, j), get_clientname(pointer, k)); } else { @@ -940,7 +1059,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_INFO, + "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; @@ -970,7 +1090,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "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: { @@ -980,21 +1101,24 @@ main(int argc, char **argv) pointer->clitable[k].ready = 0; manconnecting--; pointer->clicon--; - aflog(1, " realm[%s]: new Client[%s]: DENIED by SSL_accept", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "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", + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "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", + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "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); @@ -1004,27 +1128,51 @@ main(int argc, char **argv) } if (n == -1) { if (errno == EAGAIN) { - aflog(4, " realm[%s]: Client[%s]: commfd: EAGAIN", + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "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", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "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", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: commfd: CLOSED", get_realmname(&config, j), get_clientname(pointer, k)); + time(&now); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_clientname(pointer, k), + pointer->clitable[k].namebuf, + pointer->clitable[k].portbuf, + timeperiod(now - pointer->clitable[k].connecttime)); + if (pointer->audit) { + while (pointer->clitable[k].head) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + pointer->clitable[k].head->userid, + pointer->clitable[k].head->namebuf, + pointer->clitable[k].head->portbuf, + localdate(&(pointer->clitable[k].head->connecttime)), + timeperiod(pointer->clitable[k].head->duration)); + deletealnode(&(pointer->clitable[k].head)); + } + } + remove_client(pointer, k, &allset, &wset, &manconnecting); continue; } @@ -1040,7 +1188,8 @@ main(int argc, char **argv) buff[0] = AF_S_WRONG; } if (pointer->clitable[k].ready<2) { - aflog(1, " realm[%s]: Client[%s]: Impossible behaviour --> ignoring", + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]: Impossible behaviour --> ignoring", get_realmname(&config, j), get_clientname(pointer, k)); continue; } @@ -1058,15 +1207,23 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_DEBUG, + "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", + aflog(LOG_T_USER, LOG_I_INFO, + "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); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_username(pointer, numofcon), + pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf, + timeperiod(now - pointer->contable[numofcon].connecttime)); close(pointer->contable[numofcon].connfd); FD_CLR(pointer->contable[numofcon].connfd, &allset); FD_CLR(pointer->contable[numofcon].connfd, &wset); @@ -1087,7 +1244,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_INFO, + "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)) ? @@ -1105,7 +1263,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: DROPPED", get_realmname(&config, j), get_username(pointer, numofcon)); pointer->usercon--; pointer->clitable[k].usercon--; @@ -1133,7 +1292,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_USER, LOG_I_DEBUG, + "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; @@ -1142,10 +1302,17 @@ main(int argc, char **argv) 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)", + aflog(LOG_T_USER, LOG_I_INFO, + "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); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_username(pointer, numofcon), + pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf, + timeperiod(now - pointer->contable[numofcon].connecttime)); close(pointer->contable[numofcon].connfd); FD_CLR(pointer->contable[numofcon].connfd, &allset); FD_CLR(pointer->contable[numofcon].connfd, &wset); @@ -1166,7 +1333,8 @@ main(int argc, char **argv) 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)", + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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); } @@ -1177,15 +1345,23 @@ main(int argc, char **argv) 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)", + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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)", + aflog(LOG_T_USER, LOG_I_INFO, + "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); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_username(pointer, numofcon), + pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf, + timeperiod(now - pointer->contable[numofcon].connecttime)); close(pointer->contable[numofcon].connfd); FD_CLR(pointer->contable[numofcon].connfd, &allset); FD_CLR(pointer->contable[numofcon].connfd, &wset); @@ -1199,7 +1375,8 @@ main(int argc, char **argv) } } else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { - aflog(3, " realm[%s]: TO user[%d]: BUFFERING MESSAGE (%d)", + aflog(LOG_T_USER, LOG_I_DDEBUG, + "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; @@ -1213,7 +1390,8 @@ main(int argc, char **argv) } } else if (pointer->contable[numofcon].state == S_STATE_CLOSING) { - aflog(3, " realm[%s]: TO user[%d]: IGNORED message length=%d", + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: TO user[%d]: IGNORED message length=%d", get_realmname(&config, j), get_username(pointer, numofcon), n); } } @@ -1224,7 +1402,8 @@ main(int argc, char **argv) (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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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 */ @@ -1236,7 +1415,8 @@ main(int argc, char **argv) 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]", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: INVALID listenport - removing Client[%s]", get_realmname(&config, j), get_clientname(pointer, k)); remove_client(pointer, k, &allset, &wset, &manconnecting); break; @@ -1262,12 +1442,14 @@ main(int argc, char **argv) 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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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)); + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "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); @@ -1276,7 +1458,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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); @@ -1287,26 +1470,32 @@ main(int argc, char **argv) } } else { - aflog(1, " realm[%s]: Client[%s]: Wrong password - CLOSING", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Wrong password - CLOSING", get_realmname(&config, j), get_clientname(pointer, k)); + buff[0] = AF_S_WRONG; /* sending message */ + send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5); remove_client(pointer, k, &allset, &wset, &manconnecting); } break; } case AF_S_DONT_SEND: { - aflog(3, " realm[%s]: user[%d]: STOP READING", + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "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", + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "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", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Wrong message - CLOSING", get_realmname(&config, j), get_clientname(pointer, k)); remove_client(pointer, k, &allset, &wset, &manconnecting); break; @@ -1314,12 +1503,16 @@ main(int argc, char **argv) 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", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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; +#ifdef HAVE_LIBPTHREAD + pointer->raclitable[l].tunneltype = pointer->clitable[k].tunneltype; +#endif 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); @@ -1344,7 +1537,8 @@ main(int argc, char **argv) send_message(pointer->type | TYPE_SSL, pointer->raclitable[l].cliconn, buff, n+5); } else { - aflog(1, " realm[%s]: Client[%s]: remote admin -- limit EXCEEDED", + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "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); @@ -1353,8 +1547,15 @@ main(int argc, char **argv) } break; } + case AF_S_KEEP_ALIVE: { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: Client[%s]: Keep alive packet", + get_realmname(&config, j), get_clientname(pointer, k)); + break; + } default : { - aflog(1, " realm[%s]: Client[%s]: Unrecognized message - CLOSING", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Unrecognized message - CLOSING", get_realmname(&config, j), get_clientname(pointer, k)); remove_client(pointer, k, &allset, &wset, &manconnecting); } @@ -1365,7 +1566,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "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: { @@ -1375,45 +1577,52 @@ main(int argc, char **argv) pointer->raclitable[k].ready = 0; manconnecting--; pointer->clicon--; - aflog(1, " realm[%s]: new Client[%s] (ra): DENIED by SSL_accept", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "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", + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "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", + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "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", + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "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", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "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", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "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", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): commfd: CLOSED", get_realmname(&config, j), get_raclientname(pointer, k)); continue; } @@ -1426,7 +1635,8 @@ main(int argc, char **argv) length += buff[4]; /* this is length of message */ if (pointer->raclitable[k].ready<2) { - aflog(1, " realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", get_realmname(&config, j), get_raclientname(pointer, k)); continue; } @@ -1440,10 +1650,14 @@ main(int argc, char **argv) (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]", + aflog(LOG_T_MANAGE | LOG_T_CLIENT, LOG_I_INFO, + "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; +#ifdef HAVE_LIBPTHREAD + pointer->clitable[l].tunneltype = pointer->raclitable[k].tunneltype; +#endif 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); @@ -1457,7 +1671,8 @@ main(int argc, char **argv) } if (l != pointer->clinum) { pointer->clitable[l].ready = 3; - aflog(1, " realm[%s]: Client[%s]: pass ok - ACCESS GRANTED", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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 */ @@ -1469,7 +1684,8 @@ main(int argc, char **argv) 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]", + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: INVALID listenport - removing Client[%s]", get_realmname(&config, j), get_clientname(pointer, l)); remove_client(pointer, l, &allset, &wset, &manconnecting); break; @@ -1495,12 +1711,14 @@ main(int argc, char **argv) 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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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)); + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "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); @@ -1509,7 +1727,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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); @@ -1520,14 +1739,16 @@ main(int argc, char **argv) } } else { - aflog(1, " realm[%s]: Client[%s] (ra): Wrong password - CLOSING", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "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", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): Wrong message - CLOSING", get_realmname(&config, j), get_raclientname(pointer, k)); remove_raclient(pointer, k, &allset, &wset, &manconnecting); break; @@ -1535,7 +1756,8 @@ main(int argc, char **argv) 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", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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++; @@ -1553,19 +1775,67 @@ main(int argc, char **argv) } 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); + if ((n = serve_admin(&config, j, k, buff))) { + if (n == 1) { + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "realm[%s]: Client[%s] (ra): remote admin -- closing", + get_realmname(&config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + else { + for (i = 0; i < config.size; ++i) { + l = get_clientnumber(&(config.realmtable[i]), n-2); + if (l != -1) { + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "realm[%s]: Client[%s] (ra): remote admin: KICKING realm[%s]: Client[%s]", + get_realmname(&config, j), get_raclientname(pointer, k), + get_realmname(&config, i), get_clientname(&(config.realmtable[i]), l)); + buff[0] = AF_S_CLOSING; /* closing */ + send_message(config.realmtable[i].type,config.realmtable[i].clitable[l].cliconn,buff,5); + time(&now); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s", + get_realmname(&config, j), + get_clientname(&(config.realmtable[i]), l), + config.realmtable[i].clitable[l].namebuf, + config.realmtable[i].clitable[l].portbuf, + timeperiod(now - config.realmtable[i].clitable[l].connecttime)); + if (config.realmtable[i].audit) { + while (config.realmtable[i].clitable[l].head) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + config.realmtable[i].clitable[l].head->userid, + config.realmtable[i].clitable[l].head->namebuf, + config.realmtable[i].clitable[l].head->portbuf, + localdate(&(config.realmtable[i].clitable[l].head->connecttime)), + timeperiod(config.realmtable[i].clitable[l].head->duration)); + deletealnode(&(config.realmtable[i].clitable[l].head)); + } + } + remove_client(&(config.realmtable[i]), l, &allset, &wset, &manconnecting); + break; + } + } + } } } else { - aflog(1, " realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "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; } + case AF_S_KEEP_ALIVE: { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "realm[%s]: Client[%s] (ra): Keep alive packet", + get_realmname(&config, j), get_raclientname(pointer, k)); + break; + } default : { - aflog(1, " realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING", + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING", get_realmname(&config, j), get_raclientname(pointer, k)); remove_raclient(pointer, k, &allset, &wset, &manconnecting); } @@ -1574,21 +1844,37 @@ main(int argc, char **argv) /* ------------------------------------ */ 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)); + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET", get_realmname(&config, j)); len = pointer->addrlen; - sent = accept(pointer->usrclitable[l].managefd,pointer->cliaddr,&len); +#ifdef HAVE_LIBPTHREAD + sent = get_new_socket(pointer->usrclitable[l].managefd,pointer->tunneltype,pointer->cliaddr, + &len,&tunneltype); +#else + sent = accept(pointer->usrclitable[l].managefd, pointer->cliaddr, &len); +#endif + if (sent == -1) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); + continue; + } 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", + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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), +#ifdef HAVE_LIBPTHREAD + pointer->clitable[k].tunneltype = tunneltype; +#endif + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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); @@ -1606,12 +1892,17 @@ main(int argc, char **argv) if ((!pointer->raclitable[k].ready)) { pointer->raclitable[k].clientnum = pointer->clientcounter; ++(pointer->clientcounter); - aflog(2, " realm[%s]: new Client[%s] (ra): CONNECTING", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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", +#ifdef HAVE_LIBPTHREAD + pointer->raclitable[k].tunneltype = tunneltype; +#endif + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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)); @@ -1626,7 +1917,8 @@ main(int argc, char **argv) } } if (k == pointer->raclinum) { - aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + aflog(LOG_T_CLIENT | LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); close(sent); } } @@ -1635,86 +1927,3 @@ main(int argc, char **argv) } /* 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 index 6975af4..816185d 100644 --- a/src/afserver.h +++ b/src/afserver.h @@ -33,6 +33,12 @@ #include "realmnames.h" #include "clientnames.h" #include "usernames.h" +#include "server_get.h" +#include "http_proxy_server.h" +#include "thread_management.h" +#include "server_signals.h" +#include "usage.h" +#include "logging.h" #include #include @@ -44,8 +50,5 @@ #ifndef _JS_AFSERVER_H #define _JS_AFSERVER_H -static void usage(char* info); -static void sig_int(int); - #endif diff --git a/src/audit.c b/src/audit.c new file mode 100644 index 0000000..c74b619 --- /dev/null +++ b/src/audit.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 + +#include +#include + +#include "audit.h" + +int +insertalnode(alnodeT** headRef, int uid, char* nbuf, char* pbuf, time_t ctime, time_t dur) +{ + alnodeT* newnode, *lastnode; + lastnode = newnode = *headRef; + while (newnode) { + lastnode = newnode; + newnode = newnode->next; + } + newnode = calloc(1, sizeof(alnodeT)); + newnode->userid = uid; + memcpy(newnode->namebuf, nbuf, 128); + memcpy(newnode->portbuf, pbuf, 7); + newnode->connecttime = ctime; + newnode->duration = dur; + newnode->next = NULL; + if (lastnode) + lastnode->next = newnode; + else + *headRef = newnode; + return 0; +} + +int +deletealnode(alnodeT** headRef) +{ + alnodeT* node = *headRef; + if (*headRef == NULL) + return 1; + *headRef = node->next; + free(node); + return 0; +} + +int +freeauditlist(alnodeT** headRef) +{ + while (*headRef) { + deletealnode(headRef); + } + return 0; +} diff --git a/src/audit.h b/src/audit.h new file mode 100644 index 0000000..023fd94 --- /dev/null +++ b/src/audit.h @@ -0,0 +1,39 @@ +/* + * 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 + +#ifndef _JS_AUDIT_H +#define _JS_AUDIT_H + +typedef struct alnode { + int userid; + char namebuf[128]; + char portbuf[7]; + time_t connecttime; + time_t duration; + struct alnode* next; +} alnodeT; + +int insertalnode(alnodeT** headRef, int uid, char* nbuf, char* pbuf, time_t ctime, time_t dur); +int deletealnode(alnodeT** headRef); +int freeauditlist(alnodeT** headRef); + +#endif diff --git a/src/buflist.c b/src/buflist.c index 7ee5ede..e199b11 100644 --- a/src/buflist.c +++ b/src/buflist.c @@ -18,6 +18,8 @@ * */ +#include + #include #include diff --git a/src/client_initialization.c b/src/client_initialization.c new file mode 100644 index 0000000..a5ab560 --- /dev/null +++ b/src/client_initialization.c @@ -0,0 +1,212 @@ +/* + * 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 "client_initialization.h" +#include "network.h" + +int +initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manage, + char* proxyname, char* proxyport, char ipfam, SSL_CTX* ctx, unsigned char* buff, unsigned char* pass, + char wanttoexit) +{ + int n; + switch (tunneltype) { + case 0: { + if (ip_connect(&(master->commfd), name, manage, ipfam)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect error for %s, %s", name, manage); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + break; + } +#ifdef HAVE_LIBPTHREAD + case 1: { + if (initialize_http_proxy_client(&(master->commfd), name, manage, proxyname, proxyport, ipfam)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "http_proxy_connect_%s error for %s, %s (proxy: %s, %s)", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage, proxyname, proxyport); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "http_proxy_connect error for %s, %s (proxy: %s, %s)", name, manage, proxyname, proxyport); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + break; + } +#endif + default: { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Unknown tunnel type"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + break; + } + } + master->ssl = SSL_new(ctx); + if (SSL_set_fd(master->ssl, master->commfd) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with initializing ssl... exiting"); + if (wanttoexit) { + exit(1); + } + else { + return 2; + } + } + + aflog(LOG_T_INIT, LOG_I_INFO, + "Trying SSL_connect"); + if ((n = SSL_connect(master->ssl)) == 1) { + aflog(LOG_T_INIT, LOG_I_INFO, + "SSL_connect successful"); + } + else { + aflog(LOG_T_INIT, LOG_I_CRIT, + "SSL_connect has failed (%d)... exiting", n); + if (wanttoexit) { + exit(1); + } + else { + return 3; + } + } + + buff[0] = AF_S_LOGIN; + buff[1] = pass[0]; + buff[2] = pass[1]; + buff[3] = pass[2]; + buff[4] = pass[3]; + + return 0; +} + +int +initialize_client_stage2(char *type, clifd* master, int* usernum, unsigned char* buff, char wanttoexit) +{ + send_message(*type, *master, buff, 5); + buff[0] = 0; + get_message(*type, *master, buff, -5); + + if ( buff[0] == 0 ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Connection with afserver failed"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + if ( buff[0] == AF_S_WRONG ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Wrong password"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Server is full"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + if ( buff[0] != AF_S_LOGIN ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Incompatible server type or server full"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + + *type = buff[3]; + (*usernum) = buff[1]; + (*usernum) = (*usernum) << 8; + (*usernum) += buff[2]; + return 0; +} + +int +initialize_client_stage3(ConnectuserT** contable, clifd* master, int usernum, int* buflength, socklen_t* len, + fd_set* allset, fd_set* wset, int* maxfdp1, char wanttoexit) +{ + (*contable) = calloc( usernum, sizeof(ConnectuserT)); + if ((*contable) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - unable to successfully communicate with server"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + + (*len) = 4; + if (getsockopt(master->commfd, SOL_SOCKET, SO_SNDBUF, buflength, len) == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Can't get socket send buffer size - exiting..."); + if (wanttoexit) { + exit(1); + } + else { + return 2; + } + } + + FD_ZERO(allset); + FD_ZERO(wset); + + FD_SET(master->commfd, allset); + (*maxfdp1) = master->commfd + 1; + return 0; +} diff --git a/src/client_initialization.h b/src/client_initialization.h new file mode 100644 index 0000000..b8c534a --- /dev/null +++ b/src/client_initialization.h @@ -0,0 +1,40 @@ +/* + * 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 "activefor.h" +#include "stats.h" +#include "logging.h" +#include "http_proxy_client.h" + +#include + +#ifndef _JS_CLIENT_INITIALIZATION_H +#define _JS_CLIENT_INITIALIZATION_H + +int initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manage, + char* proxyname, char* proxyport, char ipfam, SSL_CTX* ctx, unsigned char* buff, unsigned char* pass, + char wanttoexit); +int initialize_client_stage2(char *type, clifd* master, int* usernum, unsigned char* buff, char wanttoexit); +int initialize_client_stage3(ConnectuserT** contable, clifd* master, int usernum, int* buflength, + socklen_t* len, fd_set* allset, fd_set* wset, int* maxfdp1, char wanttoexit); + +#endif diff --git a/src/client_reverse_udp.c b/src/client_reverse_udp.c new file mode 100644 index 0000000..8c78386 --- /dev/null +++ b/src/client_reverse_udp.c @@ -0,0 +1,183 @@ +/* + * 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 "client_reverse_udp.h" + +#include + +void +initialize_client_reverse_udp(int* usernum, clifd* master, char* name, char* manage, char ipfam) +{ + (*usernum) = 1; + if (ip_connect(&(master->commfd), name, manage, ipfam)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect error for %s, %s", name, manage); +#endif + exit(1); + } + master->ssl = NULL; +} + +void +client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* despor, char type, + unsigned char* buff, int buflength) +{ + char ipfam; + socklen_t len, addrlen; + int maxfdp1, temp, notsent, n, length; + struct sockaddr* cliaddr; + fd_set rset, allset; + + 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(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor); +#else + aflog(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen error for %s, %s", desnam, despor); +#endif + exit(1); + } + cliaddr = malloc(addrlen); + FD_ZERO(&allset); + + FD_SET(master->commfd, &allset); + maxfdp1 = master->commfd + 1; + maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1; + FD_SET(contable[0].connfd, &allset); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "CLIENT STARTED mode: udp reverse"); + for ( ; ; ) { + len = 4; + if (getsockopt(master->commfd, SOL_SOCKET, SO_SNDBUF, &temp, &len) != -1) { + if (temp != buflength) { + buflength = temp; + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "Send buffer size changed..."); + } + } + len = addrlen; + rset = allset; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "select"); + select(maxfdp1, &rset, NULL, NULL, NULL); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "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 + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "SIOCOUTQ is defined"); + if (ioctl(master->commfd, SIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (buflength <= notsent + n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); +# else + aflog(LOG_T_MAIN< LOG_I_DDEBUG, + "TIOCOUTQ is defined"); + if (ioctl(master->commfd, TIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (notsent <= n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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(LOG_T_CLIENT, LOG_I_INFO, + "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(LOG_T_CLIENT, LOG_I_INFO, + "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(LOG_T_CLIENT, LOG_I_CRIT, + "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(LOG_T_CLIENT, LOG_I_CRIT, + "premature quit of the server -> exiting..."); + exit(1); + } + aflog(LOG_T_CLIENT, LOG_I_INFO, + "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 */ +} diff --git a/src/client_reverse_udp.h b/src/client_reverse_udp.h new file mode 100644 index 0000000..c05f583 --- /dev/null +++ b/src/client_reverse_udp.h @@ -0,0 +1,40 @@ +/* + * 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_LINUX_SOCKIOS_H +#include +#endif + +#ifndef _JS_CLIENT_REVERSE_UDP_H +#define _JS_CLIENT_REVERSE_UDP_H + +#include + +#include "activefor.h" +#include "stats.h" +#include "logging.h" + +void initialize_client_reverse_udp(int* usernum, clifd* master, char* name, char* manage, char ipfam); +void client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* despor, char type, + unsigned char* buff, int buflength); + +#endif diff --git a/src/client_shutdown.c b/src/client_shutdown.c new file mode 100644 index 0000000..4828aeb --- /dev/null +++ b/src/client_shutdown.c @@ -0,0 +1,48 @@ +/* + * 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 "client_shutdown.h" + +void +close_connections(int usernum, ConnectuserT** contable) +{ + int i; + if (*contable) { + for (i = 0; i < usernum; ++i) { + if (((*contable)[i].state==S_STATE_OPEN) || ((*contable)[i].state==S_STATE_STOPPED)) { + close((*contable)[i].connfd); + freebuflist(&(*contable)[i].head); + } + } + free(*contable); + (*contable) = NULL; + } +} + +void +clear_master_connection(clifd* master) +{ + if (master->ssl) { + SSL_free(master->ssl); + master->ssl = NULL; + } +} diff --git a/src/client_shutdown.h b/src/client_shutdown.h new file mode 100644 index 0000000..0572971 --- /dev/null +++ b/src/client_shutdown.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 + +#ifndef _JS_CLIENT_SHUTDOWN_H +#define _JS_CLIENT_SHUTDOWN_H + +#include "activefor.h" + +void close_connections(int usernum, ConnectuserT** contable); +void clear_master_connection(clifd* master); + +#endif diff --git a/src/client_signals.c b/src/client_signals.c new file mode 100644 index 0000000..ed2c7fa --- /dev/null +++ b/src/client_signals.c @@ -0,0 +1,42 @@ +/* + * 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 "client_signals.h" +#include "thread_management.h" +#include "stats.h" +#include "logging.h" + +#include + + void +client_sig_int(int signo) +{ +#ifdef HAVE_LIBPTHREAD + if (!is_this_a_mainthread()) { + return; + } +#endif + aflog(LOG_T_MAIN, LOG_I_NOTICE, + "CLIENT CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/src/client_signals.h b/src/client_signals.h new file mode 100644 index 0000000..06c280b --- /dev/null +++ b/src/client_signals.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_CLIENT_SIGNALS_H +#define _JS_CLIENT_SIGNALS_H + +void client_sig_int(int); /* INT signal handler for the afclient */ + +#endif + diff --git a/src/clientnames.c b/src/clientnames.c index 9658903..414c506 100644 --- a/src/clientnames.c +++ b/src/clientnames.c @@ -18,6 +18,8 @@ * */ +#include + #include #include #include "clientnames.h" @@ -58,7 +60,6 @@ get_clientid(RealmT* pointer, char* clientname) } } } - return -1; } diff --git a/src/file.c b/src/file.c index e4cde62..728b0c1 100644 --- a/src/file.c +++ b/src/file.c @@ -18,8 +18,12 @@ * */ +#include + #include "file.h" #include "activefor.h" +#include "logging.h" +#include "network.h" #include #include #include @@ -110,6 +114,7 @@ parsefile(char* name, int* status) char buff[256]; char helpbuf1[256]; char helpbuf2[256]; + char* tmpbuf; *status = 1; @@ -119,10 +124,6 @@ parsefile(char* name, int* status) 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; @@ -220,9 +221,23 @@ parsefile(char* name, int* status) else if (strcmp(helpbuf1, "baseport")==0) { cfg.realmtable[cfg.size-1].baseport = 1; } + else if (strcmp(helpbuf1, "audit")==0) { + cfg.realmtable[cfg.size-1].audit = 1; + } else if (strcmp(helpbuf1, "dnslookups")==0) { cfg.realmtable[cfg.size-1].dnslookups = 1; } +#ifdef HAVE_LIBPTHREAD + else if (strcmp(helpbuf1, "enableproxy")==0) { + if (cfg.realmtable[cfg.size-1].tunneltype == 0) { + cfg.realmtable[cfg.size-1].tunneltype = 1; + } + else { + return cfg; + } + } +#endif +#ifdef AF_INET6 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); @@ -239,6 +254,7 @@ parsefile(char* name, int* status) return cfg; } } +#endif else { return cfg; } @@ -260,37 +276,10 @@ parsefile(char* name, int* status) 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 (strcmp(helpbuf1, "heavysocklog")==0) { - if (cfg.socklogging) { - return cfg; - } - cfg.socklogging = 3; - cfg.logsport = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.logsport, helpbuf2); - } - else if (strcmp(helpbuf1, "lightsocklog")==0) { - if (cfg.socklogging) { - return cfg; - } - cfg.socklogging = 1; - cfg.logsport = calloc(strlen(helpbuf2)+1, sizeof(char)); - strcpy(cfg.logsport, helpbuf2); + else if (strcmp(helpbuf1, "log")==0) { + tmpbuf = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(tmpbuf, helpbuf2); + addlogtarget(tmpbuf); } else if (strcmp(helpbuf1, "dateformat")==0) { cfg.dateformat = calloc(strlen(helpbuf2)+1, sizeof(char)); diff --git a/src/http_proxy_client.c b/src/http_proxy_client.c new file mode 100644 index 0000000..2cd301a --- /dev/null +++ b/src/http_proxy_client.c @@ -0,0 +1,380 @@ +/* + * 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 "http_proxy_functions.h" +#include "http_proxy_client.h" +#include "thread_management.h" +#include "network.h" +#include "stats.h" +#include "logging.h" + +#ifdef HAVE_LIBPTHREAD +typedef struct { + int sockfd; + char *host; + char *serv; + char *proxyname; + char *proxyport; + char type; +} proxy_argT; + +static void +clean_return(int sockfd) +{ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: clean_return"); + close(sockfd); + pthread_exit(NULL); +} + +void* +http_proxy_client(void *vptr) +{ + char tab[9000]; + connection conn; + header hdr; + int j, n, maxfdp1; + fd_set rset, allset; + struct timeval tv; + int timeout = 5; + int tmp; + char *host, *serv, *proxyname, *proxyport; + char type; + proxy_argT *proxy_argptr; + + start_critical_section(); + proxy_argptr = (proxy_argT *) vptr; + + host = proxy_argptr->host; + serv = proxy_argptr->serv; + proxyname = proxy_argptr->proxyname; + proxyport = proxy_argptr->proxyport; + type = proxy_argptr->type; + conn.sockfd = proxy_argptr->sockfd; + + broadcast_condition(); + end_critical_section(); + + FD_ZERO(&allset); + tv.tv_usec = 0; + tv.tv_sec = timeout; + + memset(conn.id, 0, 10); + for (j = 0; j < 9; ++j) { + conn.id[j] = myrand(65, 90); + } + conn.id[9] = 0; + + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (postfd)..."); + if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + + + memset(tab, 0, 9000); + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing POST request..."); + if (writen(conn.postfd, (unsigned char*) tab, j) <= 0) { + clean_return(conn.sockfd); + } + + /* getfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (getfd)..."); + if (ip_connect(&conn.getfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + + memset(tab, 0, 9000); + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing GET request..."); + if (writen(conn.getfd, (unsigned char*) tab, j) <= 0) { + clean_return(conn.sockfd); + } + + set_fd(conn.sockfd, &maxfdp1, &allset); + set_fd(conn.postfd, &maxfdp1, &allset); + set_fd(conn.getfd, &maxfdp1, &allset); + conn.state = C_OPEN; + + memset(tab, 0, 9000); + + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: parsing header from getfd"); + if (parse_header(conn.getfd, tab, &hdr)) { + clean_return(conn.sockfd); + } + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: checking hdr.type"); + if (hdr.type != H_TYPE_OK) { + clean_return(conn.sockfd); + } + if (hdr.length) { + conn.received += hdr.length; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: reading message..."); + if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { + clean_return(conn.sockfd); + } + } + + while (1) { + rset = allset; + + if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: timeout"); + tv.tv_sec = timeout; + if (conn.state == C_CLOSED) { + continue; + } + if (conn.sent_ptr+1 >= 90000) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: send T"); + writen(conn.postfd, (unsigned char*) "T", 1); + conn.sent_ptr = 0; + clear_fd(&conn.postfd, &allset); + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (postfd)..."); + if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + + memset(tab, 0, 9000); + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing POST request..."); + if (writen(conn.postfd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + conn.sent_ptr = 0; + conn.ptr = 0; + conn.length = 0; + + set_fd(conn.postfd, &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: send T"); + writen(conn.postfd, (unsigned char *) "T", 1); + conn.sent_ptr += 1; + } + continue; + } + + /* sockfd */ + if (FD_ISSET(conn.sockfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(conn.sockfd)"); + if (conn.state == C_CLOSED) { + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (postfd)..."); + if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + conn.state = C_OPEN; + } + n = read(conn.sockfd, conn.buf+5, 8995); + if (n <= 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: send Q"); + writen(conn.postfd, (unsigned char *) "Q", 1); + clean_return(conn.sockfd); + } + conn.buf[0] = 'M'; + tmp = htonl(n); + memcpy(&conn.buf[1], &tmp, 4); + if (conn.sent_ptr+5 + n >= 90000) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: send message"); + writen(conn.postfd, (unsigned char *) conn.buf, 90000 - conn.sent_ptr); + conn.ptr = 90000 - conn.sent_ptr; + conn.length = 5+n - conn.ptr; + conn.sent_ptr = 0; + clear_fd(&conn.postfd, &allset); + + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (postfd)..."); + if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + + memset(tab, 0, 9000); + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing POST request..."); + if (writen(conn.postfd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + if (conn.length > 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing old data..."); + if (writen(conn.postfd, (unsigned char *) (conn.buf+conn.ptr), conn.length) <= 0) { + clean_return(conn.sockfd); + } + } + conn.sent_ptr = conn.length; + conn.ptr = 0; + conn.length = 0; + + set_fd(conn.postfd, &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: send message"); + writen(conn.postfd, (unsigned char *) conn.buf, 5+n); + conn.sent_ptr += 5+n; + } + } + + /* getfd */ + if (FD_ISSET(conn.getfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(conn.getfd)"); + n = read(conn.getfd, tab, 9000); + conn.received += n; + if (n == 0) { + conn.received = 0; + FD_CLR(conn.getfd, &allset); + close(conn.getfd); + + /* getfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: connecting (getfd)..."); + if (ip_connect(&conn.getfd, proxyname, proxyport, type)) { + clean_return(conn.sockfd); + } + + memset(tab, 0, 9000); + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: writing GET request..."); + if (writen(conn.getfd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + memset(tab, 0, 9000); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: parsing header from getfd"); + if (parse_header(conn.getfd, tab, &hdr)) { + clean_return(conn.sockfd); + } + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: checking hdr.type"); + if (hdr.type != H_TYPE_OK) { + clean_return(conn.sockfd); + } + + set_fd(conn.getfd, &maxfdp1, &allset); + if (hdr.length) { + conn.received += hdr.length; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: reading message..."); + if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { + clean_return(conn.sockfd); + } + } + } + else { + if (read_message(conn.sockfd, n, &conn, tab, 0)) { + clean_return(conn.sockfd); + } + } + } + + /* postfd */ + if (FD_ISSET(conn.postfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(conn.postfd)"); + clear_fd(&conn.postfd, &allset); + conn.state = C_CLOSED; + } + } + clean_return(conn.sockfd); +} + +int +initialize_http_proxy_client(int* sockfd, const char *host, const char *serv, + const char *proxyname, const char *proxyport, const char type) +{ + int retval; + int sockets[2]; + pthread_t proxy_thread; + static proxy_argT arg; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + (*sockfd) = sockets[0]; + + if (proxyname == NULL) { + return 1; + } + + start_critical_section(); + + arg.host = (char*) host; + arg.serv = (char*) serv; + arg.proxyname = (char*) proxyname; + arg.proxyport = (char*) proxyport; + arg.type = (char) type; + arg.sockfd = sockets[1]; + + retval = pthread_create(&proxy_thread, NULL, &http_proxy_client, &arg); + + wait_for_condition(); + + end_critical_section(); + + return retval; +} + +#endif diff --git a/src/http_proxy_client.h b/src/http_proxy_client.h new file mode 100644 index 0000000..f8ec5b7 --- /dev/null +++ b/src/http_proxy_client.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_HTTP_PROXY_CLIENT_H +#define _JS_HTTP_PROXY_CLIENT_H + +int initialize_http_proxy_client(int* sockfd, const char *host, const char *serv, + const char *proxyname, const char *proxyport, const char type); + +#endif diff --git a/src/http_proxy_functions.c b/src/http_proxy_functions.c new file mode 100644 index 0000000..b8e5849 --- /dev/null +++ b/src/http_proxy_functions.c @@ -0,0 +1,267 @@ +/* + * 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 "http_proxy_functions.h" +#include "network.h" +#include "stats.h" +#include "logging.h" + +static char isseed; + +int +myrand(int down, int up) +{ + struct timeval tv; + if (!isseed) { + gettimeofday(&tv, 0); + srand(tv.tv_sec); + isseed = 1; + } + return ( down + ( rand() % (up - down + 1) ) ); +} + +void +mysleep(double time) +{ + struct timeval tv; + tv.tv_sec = (int) time; + tv.tv_usec = (int)(time * 1000000)%1000000; + select(0, NULL, NULL, NULL, &tv); +} + +void +delete_user(connection* cnts, int i, fd_set* allset) +{ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: delete_user(%d)", i); + clear_fd(&(cnts[i].sockfd), allset); + if (!(cnts[i].state & C_POST_WAIT)) { + clear_fd(&(cnts[i].postfd), allset); + } + if ((cnts[i].type == 0) && (!(cnts[i].state & C_GET_WAIT))) { + clear_fd(&(cnts[i].getfd), allset); + } + cnts[i].state = C_CLOSED; + cnts[i].sent_ptr = cnts[i].ptr = cnts[i].length = 0; + cnts[i].type = 0; +} + +int +parse_header(int fd, char* tab, header* hdr) +{ + int n, i, j, state = 0; + char tmpt[100]; + n = read(fd, tab, 9000); + hdr->allreaded = n; + i = j = 0; + memset(tmpt, 0, 100); + hdr->ptr = 0; + hdr->length = 0; + while (i < n) { + if (j == 99) + return 1; + switch (state) { + case 0: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[j] = tab[i]; + ++j; + } + else { + tmpt[j] = 0; + if (strcmp(tmpt, "GET") == 0) { + hdr->type = H_TYPE_GET; + state = 1; + break; + } + if (strcmp(tmpt, "POST") == 0) { + hdr->type = H_TYPE_POST; + state = 1; + break; + } + if ((strcmp(tmpt, "HTTP/1.0") == 0) || (strcmp(tmpt, "HTTP/1.1") == 0)) { + hdr->type = H_TYPE_OK; + state = 6; + break; + } + return 1; + } + break; + case 1: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[0] = tab[i]; + j = 1; + state = 2; + } + break; + case 2: + if (tab[i] != '=') { + tmpt[j] = tab[i]; + ++j; + } + else { + tmpt[j] = 0; + if (strcmp(tmpt, "/yahpt.html?id")) { + return 1; + } + j = 0; + state = 3; + } + break; + case 3: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + if (j == 9) { + return 1; + } + hdr->id[j] = tab[i]; + ++j; + } + else { + if (j != 9) { + return 1; + } + hdr->id[j] = 0; + state = 4; + } + break; + case 4: + if (tab[i] == '\n') + state = 5; + break; + case 5: + if (tab[i] == '\n') { + hdr->ptr = i+1; + hdr->length = n - hdr->ptr; + return 0; + } + if (tab[i] != '\r') { + state = 4; + } + break; + case 6: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[0] = tab[i]; + j = 1; + state = 7; + } + break; + case 7: + if ((tab[i] == ' ') || (tab[i] == '\t')) { + tmpt[j] = 0; + if (strcmp(tmpt, "200")) { + return 1; + } + state = 4; + } + else { + tmpt[j] = tab[i]; + ++j; + } + break; + } + ++i; + } + return 1; +} + +void +set_fd(int fd, int* maxfdp1, fd_set* allset) +{ + FD_SET(fd, allset); + (*maxfdp1) = ((*maxfdp1) > fd) ? (*maxfdp1) : (fd + 1); +} + +void +close_fd(int* fd) +{ + close(*fd); +} + +void +clear_fd(int* fd, fd_set* set) +{ + FD_CLR(*fd, set); + close_fd(fd); +} + +int +read_message(int fd, int length, connection* client, char* tab, int ptr) +{ + int j = 0; + int tmp = 0; + while (j < length) { + if (client->curreceived + length-j > client->toreceive) { + writen(fd, (unsigned char*) (tab+ptr+j), client->toreceive - client->curreceived); + j += client->toreceive - client->curreceived; + client->curreceived += client->toreceive - client->curreceived; + if (client->read_state == 0) { + switch (tab[ptr + j]) { + case 'M': { + if (j + 5 <= length) { + memcpy(&tmp, &tab[ptr + j + 1], 4); + client->toreceive = ntohl(tmp); + client->curreceived = 0; + j += 5; + } + else if (j + 1 < length) { + memcpy(client->readed_length, &tab[ptr + j + 1], length - j - 1); + client->read_state = length - j; + j += length - j; + } + else { + ++j; + client->read_state = 1; + } + break; + } + case 'T': { + ++j; + break; + } + default: { + return 1; + } + } + } + else { + if (j + 5 - client->read_state <= length) { + memcpy(&client->readed_length[client->read_state-1], &tab[ptr + j], 5 - client->read_state); + memcpy(&tmp, client->readed_length, 4); + client->toreceive = ntohl(tmp); + client->curreceived = 0; + j += 5 - client->read_state; + client->read_state = 0; + } + else { + memcpy(&client->readed_length[client->read_state-1], &tab[ptr + j], length - j); + client->read_state += length - j; + j += length -j; + } + } + } + else { + client->curreceived += length-j; + writen(fd, (unsigned char*) (tab+ptr+j), length-j); + j += length-j; + } + } + return 0; +} diff --git a/src/http_proxy_functions.h b/src/http_proxy_functions.h new file mode 100644 index 0000000..9c9b56d --- /dev/null +++ b/src/http_proxy_functions.h @@ -0,0 +1,80 @@ +/* + * 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 + +#ifndef _JS_HTTP_PROXY_FUNCTIONS_H +#define _JS_HTTP_PROXY_FUNCTIONS_H + +#define C_CLOSED 0 +#define C_POST_WAIT 1 +#define C_GET_WAIT 2 +#define C_OPEN 4 + +#define H_TYPE_GET 0 +#define H_TYPE_POST 1 +#define H_TYPE_OK 2 +#define H_TYPE_ERROR 3 + +typedef struct { + char type; + char id[10]; + int ptr; + int length; + int allreaded; +} header; + +typedef struct { + char read_state; + char readed_length[4]; + char state; + char id[10]; + int postfd; + int getfd; + int sent_ptr; + int sockfd; + char buf[9000]; + char tmpbuf[9000]; + char tmpstate; + int tmpfd; + char type; + header tmpheader; + int ptr; + int length; + int curreceived; + int toreceive; + int received; +} connection; + +int myrand(int, int); +void mysleep(double); +int parse_header(int, char*, header*); +int read_message(int, int, connection*, char*, int); +void delete_user(connection*, int, fd_set*); +void set_fd(int, int*, fd_set*); +void close_fd(int*); +void clear_fd(int*, fd_set*); + +#endif diff --git a/src/http_proxy_server.c b/src/http_proxy_server.c new file mode 100644 index 0000000..a07d6ce --- /dev/null +++ b/src/http_proxy_server.c @@ -0,0 +1,459 @@ +/* + * 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 "http_proxy_server.h" +#include "thread_management.h" +#include "stats.h" +#include "logging.h" +#include "network.h" + +#ifdef HAVE_LIBPTHREAD + +typedef struct { + int sockfd; + char *host; + char *serv; + socklen_t *addrlenp; + char type; + int limit; +} sproxy_argT; + +int +afserver_connect(int* sockfd, int afserverfd, struct sockaddr* cliaddr, socklen_t* addrlenp, char type) +{ + int sockets[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + if (write(afserverfd, &sockets[0], 4) != 4) { + return 2; + } + if (write(afserverfd, &type, 1) != 1) { + return 3; + } + if (write(afserverfd, addrlenp, 4) != 4) { + return 3; + } + if (write(afserverfd, cliaddr, *addrlenp) != *addrlenp) { + return 5; + } + (*sockfd) = sockets[1]; + return 0; +} + +void* +http_proxy_server(void *vptr) +{ + int listenfd, connfd, afserverfd; + struct sockaddr* cliaddr; + char tab[9000]; + connection* table; + header hdr; + int i, n, maxfdp1; + fd_set rset, allset; + struct timeval tv; + int maxclients, tmp; + int timeout = 5; + socklen_t *addrlenp; + char type, nothttp; + char *host, *serv; + sproxy_argT *proxy_argptr; + + start_critical_section(); + proxy_argptr = (sproxy_argT *) vptr; + + afserverfd = proxy_argptr->sockfd; + host = proxy_argptr->host; + serv = proxy_argptr->serv; + addrlenp = proxy_argptr->addrlenp; + type = proxy_argptr->type; + maxclients = proxy_argptr->limit+1; + + broadcast_condition(); + end_critical_section(); + + table = calloc(maxclients, sizeof(connection)); + if (table == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http proxy: Can't allocate memory... exiting."); + exit(1); + } + + if (ip_listen(&listenfd, host, serv, addrlenp, type)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http proxy: Can't listen on %s:%s", host, serv); + exit(1); + } + cliaddr = malloc(*addrlenp); + + FD_ZERO(&allset); + FD_SET(listenfd, &allset); + maxfdp1 = listenfd + 1; + tv.tv_usec = 0; + tv.tv_sec = timeout; + + while (1) { + rset = allset; + + if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: timeout"); + tv.tv_sec = timeout; + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_CLOSED) || (table[i].state & C_GET_WAIT) || (table[i].type == 1)) { + continue; + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: send T to table[%d].getfd", i); + if (table[i].sent_ptr+1 >= 90000) { + writen(table[i].getfd, (unsigned char*) "T", 1); + table[i].sent_ptr = 0; + clear_fd(&table[i].getfd, &allset); + FD_CLR(table[i].sockfd, &allset); + table[i].state |= C_GET_WAIT; + } + else { + writen(table[i].getfd, (unsigned char*) "T", 1); + table[i].sent_ptr += 1; + } + } + continue; + } + + /* http proxy tunnels */ + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_CLOSED) || (table[i].type == 1)) { + continue; + } + + /* sockfd */ + if ((!(table[i].state & C_GET_WAIT)) && (FD_ISSET(table[i].sockfd, &rset))) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(table[%d].sockfd)", i); + n = read(table[i].sockfd, table[i].buf+5, 8995); + if (n <= 0) { + writen(table[i].getfd, (unsigned char*) "Q", 1); + delete_user(table, i, &allset); + continue; + } + table[i].buf[0] = 'M'; + tmp = htonl(n); + memcpy(&table[i].buf[1], &tmp, 4); + if (table[i].sent_ptr+5 + n >= 90000) { + writen(table[i].getfd, (unsigned char*) table[i].buf, 90000 - table[i].sent_ptr); + table[i].ptr = 90000 - table[i].sent_ptr; + table[i].length = 5+n - table[i].ptr; + table[i].sent_ptr = 0; + clear_fd(&table[i].getfd, &allset); + FD_CLR(table[i].sockfd, &allset); + table[i].state |= C_GET_WAIT; + continue; + } + else { + writen(table[i].getfd, (unsigned char*) table[i].buf, n+5); + table[i].sent_ptr += n+5; + } + } + + /* getfd */ + if (FD_ISSET(table[i].getfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(table[%d].getfd)", i); + delete_user(table, i, &allset); + continue; + } + + /* postfd */ + if (FD_ISSET(table[i].postfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(table[%d].postfd)", i); + n = read(table[i].postfd, tab, 9000); + if (n != 0) { + table[i].received += n; + if (read_message(table[i].sockfd, n, &table[i], tab, 0)) { + delete_user(table, i, &allset); + } + } + if ((n == 0) || (table[i].received == 90000)) { + table[i].received = 0; + clear_fd(&table[i].postfd, &allset); + table[i].state |= C_POST_WAIT; + if (table[i].tmpstate == 1) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: get old POST request..."); + table[i].state &= ~C_POST_WAIT; + table[i].postfd = table[i].tmpfd; + set_fd(table[i].postfd, &maxfdp1, &allset); + table[i].tmpstate = 0; + if (table[i].tmpheader.length) { + table[i].received += table[i].tmpheader.length; + if (read_message(table[i].sockfd, table[i].tmpheader.length, &table[i], + table[i].tmpbuf, table[i].tmpheader.ptr)) { + delete_user(table, i, &allset); + } + } + } + continue; + } + } + } + + /* direct tunnels */ + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_OPEN) && (table[i].type == 1)) { + + if (FD_ISSET(table[i].sockfd, &rset)) { + n = read(table[i].sockfd, table[i].buf, 9000); + if (n > 0) { + write(table[i].postfd, table[i].buf, n); + } + else { + delete_user(table, i, &allset); + continue; + } + } + + if (FD_ISSET(table[i].postfd, &rset)) { + n = read(table[i].postfd, tab, 9000); + if (n > 0) { + write(table[i].sockfd, tab, n); + } + else { + delete_user(table, i, &allset); + continue; + } + } + + } + } + + /* listen */ + if (FD_ISSET(listenfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http proxy: FD_ISSET(listenfd)"); + connfd = accept(listenfd, cliaddr, addrlenp); + if (connfd != -1) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: New connection..."); + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: New connection --> EAGAIN"); + } + memset(tab, 0, 9000); + nothttp = 0; + if (parse_header(connfd, tab, &hdr)) { + nothttp = 1; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: no http header..."); + } + n = -1; + for (i = 0; i < maxclients; ++i) { + if (table[i].state == C_CLOSED) { + if (n == -1) + n = i; + } + else { + if ((!nothttp) && (strcmp(table[i].id, hdr.id) == 0)) { + break; + } + } + } + if (i < maxclients) { /* the client exists */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: the client exist..."); + if (hdr.type == H_TYPE_GET) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: type GET..."); + if (!(table[i].state & C_GET_WAIT)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: not waiting for GET..."); + table[i].sent_ptr = 0; + FD_CLR(table[i].sockfd, &allset); + clear_fd(&table[i].getfd, &allset); + table[i].state |= C_GET_WAIT; + } + if (!(table[i].state & C_OPEN)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: not opened..."); + if (afserver_connect(&table[i].sockfd, afserverfd, cliaddr, addrlenp, 1)) { + memset(tab, 0, 9000); + sprintf(tab,"HTTP/1.1 400 Bad Request\r\n\r\n"); + n = strlen (tab); + write(connfd, tab, n); + close_fd(&connfd); + clear_fd(&table[i].postfd, &allset); + table[i].state = C_CLOSED; + continue; + } + table[i].state |= C_OPEN; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: OPEN..."); + } + table[i].state &= ~C_GET_WAIT; + table[i].sent_ptr = 0; + table[i].getfd = connfd; + set_fd(table[i].sockfd, &maxfdp1, &allset); + set_fd(table[i].getfd, &maxfdp1, &allset); + memset(tab, 0, 9000); + sprintf(tab, + "HTTP/1.1 200 OK\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache, no-store, must-revalidate\r\n" + "Expires: 0\r\n" + "Content-Type: text/html\r\n\r\n"); + n = strlen(tab); + if (writen(table[i].getfd, (unsigned char*) tab, n) <= 0) { + delete_user(table, i, &allset); + continue; + } + if (table[i].length) { + if (writen(table[i].getfd, (unsigned char*) (table[i].buf+table[i].ptr), table[i].length) <= 0) { + delete_user(table, i, &allset); + continue; + } + } + table[i].sent_ptr = table[i].length; + table[i].ptr = 0; + table[i].length = 0; + } + else if (hdr.type == H_TYPE_POST) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: type POST..."); + if (!(table[i].state & C_POST_WAIT)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: unexpected POST request..."); + if (table[i].tmpstate == 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: buffering POST request..."); + table[i].tmpstate = 1; + table[i].tmpfd = connfd; + memcpy(table[i].tmpbuf, tab, 9000); + table[i].tmpheader = hdr; + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: no space to buffer POST request (received from first postfd: %d)", + table[i].received); + delete_user(table, i, &allset); + } + } + else { + if (hdr.length) { + table[i].received += hdr.length; + if (read_message(table[i].sockfd, hdr.length, &table[i], tab, hdr.ptr)) { + delete_user(table, i, &allset); + } + } + table[i].state &= ~C_POST_WAIT; + table[i].postfd = connfd; + set_fd(table[i].postfd, &maxfdp1, &allset); + } + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: unrecognized type..."); + delete_user(table, i, &allset); + } + } + else if (n != -1) { /* there are free slots */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: there are free slots..."); + if (!nothttp) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: http header..."); + if (hdr.type == H_TYPE_POST) { /* POST request must be first */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: type POST..."); + table[n].state = C_GET_WAIT; + memcpy(table[n].id,hdr.id, 9); + table[n].postfd = connfd; + set_fd(table[n].postfd, &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: closing this connection..."); + close_fd(&connfd); + continue; + } + } + else { + table[n].state = C_OPEN; + table[n].postfd = connfd; + table[n].type = 1; + set_fd(table[n].postfd, &maxfdp1, &allset); + if (afserver_connect(&table[n].sockfd, afserverfd, cliaddr, addrlenp, 0)) { + clear_fd(&table[n].postfd, &allset); + table[n].state = C_CLOSED; + continue; + } + set_fd(table[n].sockfd, &maxfdp1, &allset); + write(table[n].sockfd, tab, hdr.allreaded); + } + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: closing this connection..."); + close_fd(&connfd); + continue; + } + } + } + + return 0; +} + + +int +initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit) +{ + int retval; + int sockets[2]; + pthread_t proxy_thread; + static sproxy_argT arg; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + (*sockfd) = sockets[0]; + + start_critical_section(); + + arg.host = (char*) host; + arg.serv = (char*) serv; + arg.addrlenp = addrlenp; + arg.limit = limit; + arg.type = (char) type; + arg.sockfd = sockets[1]; + + retval = pthread_create(&proxy_thread, NULL, &http_proxy_server, &arg); + + wait_for_condition(); + + end_critical_section(); + + return retval; +} + +#endif diff --git a/src/http_proxy_server.h b/src/http_proxy_server.h new file mode 100644 index 0000000..6e13549 --- /dev/null +++ b/src/http_proxy_server.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_HTTP_PROXY_SERVER_H +#define _JS_HTTP_PROXY_SERVER_H + +#include "http_proxy_functions.h" +#include "network.h" + +int initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit); + +#endif diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..650ce9e --- /dev/null +++ b/src/logging.c @@ -0,0 +1,391 @@ +/* + * 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 "logging.h" +#include "network.h" +#include +#include +#include +#include + +static llnodeT* head = NULL; +static char verlev; +static char format[51] = "%Y-%m-%d %H:%M:%S"; + +void +setdateformat(char* dateformat) +{ + if (dateformat) { + strncpy(format, dateformat, 50); + } +} + +char* +getdateformat() +{ + return format; +} + +char* +localdate(time_t* sec) +{ + struct tm* tm; + static char localdat[31]; + tm = localtime(sec); + memset(localdat, 0, 31); + strftime(localdat, 30, format, tm); + return localdat; +} + +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; +} + +llnodeT* +getloglisthead() +{ + return head; +} + +int +checkmsgti(llnodeT* target, char* tab) +{ + if (strcmp(tab, "LOG_T_ALL") == 0) { + target->msgtype |= LOG_T_ALL; + } + else if (strcmp(tab, "LOG_T_USER") == 0) { + target->msgtype |= LOG_T_USER; + } + else if (strcmp(tab, "LOG_T_CLIENT") == 0) { + target->msgtype |= LOG_T_CLIENT; + } + else if (strcmp(tab, "LOG_T_INIT") == 0) { + target->msgtype |= LOG_T_INIT; + } + else if (strcmp(tab, "LOG_T_MANAGE") == 0) { + target->msgtype |= LOG_T_MANAGE; + } + else if (strcmp(tab, "LOG_T_MAIN") == 0) { + target->msgtype |= LOG_T_MAIN; + } + else if (strcmp(tab, "LOG_I_ALL") == 0) { + target->importance |= LOG_I_ALL; + } + else if (strcmp(tab, "LOG_I_CRIT") == 0) { + target->importance |= LOG_I_CRIT; + } + else if (strcmp(tab, "LOG_I_DEBUG") == 0) { + target->importance |= LOG_I_DEBUG; + } + else if (strcmp(tab, "LOG_I_INFO") == 0) { + target->importance |= LOG_I_INFO; + } + else if (strcmp(tab, "LOG_I_NOTICE") == 0) { + target->importance |= LOG_I_NOTICE; + } + else if (strcmp(tab, "LOG_I_WARNING") == 0) { + target->importance |= LOG_I_WARNING; + } + else if (strcmp(tab, "LOG_I_ERR") == 0) { + target->importance |= LOG_I_ERR; + } + else { + return 1; /* unknown msgtype/importance */ + } + return 0; +} + +int +checklogtarget(llnodeT* target) +{ + char* ptr; + char desc[100]; + char type = 0; + char tab[100]; + int tmpfd; + int state, i; + if ((target == NULL) || (target->cmdline == NULL)) { + return 1; /* some of the important data is NULL */ + } + state = 0; /* we are at the beginning of the cmdline */ + memset(tab, 0, 100); + i = 0; + ptr = target->cmdline; + while ((*ptr) != 0) { + switch (state) { + /* beginning of the cmdline */ + case 0: { + if ((*ptr) == ',') { + tab[i] = 0; + if (strcmp(tab, "file") == 0) { + type = LOG_L_FILE; + } + else if (strcmp(tab, "sock") == 0) { + type = LOG_L_SOCK; + } + else { + return 2; /* unknown type of the target */ + } + state = 1; /* we are at the beginning of the file/sock description */ + memset(tab, 0, 100); + memset(desc, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 2; /* unknown type of the target (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the file/sock description */ + case 1: { + if ((*ptr) == ',') { + tab[i] = 0; + switch (type) { + case LOG_L_FILE: { + target->logfd = fopen(tab, "a"); + if (target->logfd == NULL) { + return 4; /* logging to a non-opened file? */ + } + state = 3; /* we want to read msgtype and importance */ + break; + } + case LOG_L_SOCK: { + strncpy(desc, tab, 99); + state = 2; /* we want to open a socket (read port first) */ + break; + } + default: { + return 2; /* unknown type of the target */ + } + } + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 3; /* wrong file/sock description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the sock port description */ + case 2: { + if ((*ptr) == ',') { + tab[i] = 0; + if (ip_connect(&tmpfd, desc, tab, 1)) { + return 5; /* can't connect to host:port */ + } + target->logfd = fdopen(tmpfd, "a"); + if (target->logfd == NULL) { + return 4; /* can't create FILE* to log to */ + } + state = 3; /* we want to read msgtype and importance */ + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 3; /* wrong file/sock description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the msgtype and importance section */ + case 3: { + if ((*ptr) == ',') { + tab[i] = 0; + if (checkmsgti(target, tab)) { + return 6; + } + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 6; /* wrong msgtype/importance description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + } + ++ptr; + } + if (i != 0) { + if (state == 3) { + tab[i] = 0; + if (checkmsgti(target, tab)) { + return 6; + } + } + else { + return 1; + } + } + return 0; +} + +void +addlogtarget(char* cmdline) +{ + llnodeT* newnode = calloc(1, sizeof(llnodeT)); + newnode->cmdline = cmdline; + newnode->next = head; + head = newnode; +} + +int +loginit(char verl, char* dateformat) +{ + llnodeT* ptr; + int n; + + verlev = 0; + if (verl) { + switch (verl) { + case 1: { + verlev = LOG_I_NOTICE | LOG_I_CRIT; + break; + } + case 2: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_CRIT; + break; + } + case 3: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_CRIT; + break; + } + case 4: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR | LOG_I_CRIT; + break; + } + case 5: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR | LOG_I_CRIT | LOG_I_DEBUG; + break; + } + default: { + verlev = LOG_I_ALL; + break; + } + } + } + + setdateformat(dateformat); + + ptr = head; + while (ptr) { + if ((n = checklogtarget(ptr)) != 0) { + return n; + } + ptr = ptr->next; + } + + return 0; +} + +void +initializelogging(char verl, char* dateformat) +{ + int k; + if ((k = loginit(verl, dateformat)) != 0) { + switch (k) { + /* wrong format of the logcmd */ + case 1: { + printf("Wrong format of the logcmd\n"); + break; + } + /* unknown type of the logging target */ + case 2: { + printf("Unknown type of the logging target\n"); + break; + } + /* wrong description of the logging target (name too long) */ + case 3: { + printf("Wrong description of the logging target (name too long)\n"); + break; + } + /* can't open file to log to */ + case 4: { + printf("Can't open file to log to\n"); + break; + } + /* can't connect to target host */ + case 5: { + printf("Can't connect to target host\n"); + break; + } + /* wrong msgtype/importance description */ + case 6: { + printf("Wrong msgtype/importance description\n"); + break; + } + } + exit(1); + } +} + +void +aflog(char type, char importance, const char* form, ...) +{ + llnodeT* ptr; + va_list ap; + + if (verlev & importance) { + if (format[0] != 0) { + printf("[%s] ", datum()); + } + va_start(ap, form); + vfprintf(stdout, form, ap); + va_end(ap); + printf("\n"); + } + + ptr = head; + while (ptr) { + if ((type & ptr->msgtype) && (importance & ptr->importance)) { + if (format[0] != 0) { + fprintf(ptr->logfd, "[%s] ", datum()); + } + va_start(ap, form); + vfprintf(ptr->logfd, form, ap); + va_end(ap); + fprintf(ptr->logfd, "\n"); + fflush(ptr->logfd); + } + ptr = ptr->next; + } +} + diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 0000000..ec9d110 --- /dev/null +++ b/src/logging.h @@ -0,0 +1,78 @@ +/* + * 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 + +#ifndef _JS_LOGGING_H +#define _JS_LOGGING_H + +/* some constants for logging functions */ + /* type of the message */ + +#define LOG_T_ALL (LOG_T_USER | LOG_T_CLIENT | LOG_T_INIT | LOG_T_MANAGE | LOG_T_MAIN) +#define LOG_T_USER 1 +#define LOG_T_CLIENT 2 +#define LOG_T_INIT 4 +#define LOG_T_MANAGE 8 +#define LOG_T_MAIN 16 + + /* importance of the message */ + +#define LOG_I_ALL (LOG_I_CRIT | LOG_I_DEBUG | LOG_I_DDEBUG | LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR) +#define LOG_I_CRIT 1 +#define LOG_I_DEBUG 2 +#define LOG_I_DDEBUG 4 +#define LOG_I_INFO 8 +#define LOG_I_NOTICE 16 +#define LOG_I_WARNING 32 +#define LOG_I_ERR 64 + + /* type of the logging target */ + +#define LOG_L_FILE 1 +#define LOG_L_SOCK 2 + +/* a structure that keeps information about logging target */ +typedef struct llnode { + char* cmdline; + char msgtype; + char importance; + FILE* logfd; + struct llnode* next; +} llnodeT; + + /* set dateformat */ +void setdateformat(char* dateformat); + /* get dateformat */ +char* getdateformat(); + /* get llnodeT head */ +llnodeT* getloglisthead(); + /* add logging target */ +void addlogtarget(char* cmdline); + /* initialize logging routine */ +void initializelogging(char verlev, char* dateformat); + /* log to a file or|and screen */ +void aflog(char type, char importance, const char* format, ...); + /* get text representation of the date */ +char* localdate(time_t* sec); + +#endif + diff --git a/src/make_ssl_handshake.c b/src/make_ssl_handshake.c index a5c97eb..d4cdd55 100644 --- a/src/make_ssl_handshake.c +++ b/src/make_ssl_handshake.c @@ -18,10 +18,11 @@ * */ +#include + #include "make_ssl_handshake.h" #include "stats.h" - -#include +#include "logging.h" #include #include @@ -30,7 +31,8 @@ void make_ssl_initialize(clifd *cliconn) { if (SSL_set_fd(cliconn->ssl, cliconn->commfd) != 1) { - aflog(0, "Problem with initializing ssl... exiting"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with initializing ssl... exiting"); exit(1); } } @@ -40,7 +42,7 @@ 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 get_ssl_error(cliconn, "SSL_accept has failed", result); } return 0; } @@ -55,45 +57,55 @@ get_ssl_error(clifd *cliconn, char* info, int result) merror = SSL_get_error(cliconn->ssl, result); switch (merror) { case SSL_ERROR_NONE : { - aflog(2, "%s(%d): none", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): none", info, result); break; } case SSL_ERROR_ZERO_RETURN : { - aflog(2, "%s(%d): zero", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): zero", info, result); break; } case SSL_ERROR_WANT_READ : { - aflog(2, "%s(%d): w_read", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_read", info, result); break; } case SSL_ERROR_WANT_WRITE : { - aflog(2, "%s(%d): w_write", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_write", info, result); break; } case SSL_ERROR_WANT_CONNECT : { - aflog(2, "%s(%d): w_connect", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_connect", info, result); break; } case SSL_ERROR_WANT_X509_LOOKUP : { - aflog(2, "%s(%d): w_x509_lookup", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_x509_lookup", info, result); break; } case SSL_ERROR_SYSCALL : { - aflog(2, "%s(%d): syscall", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%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, + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): ssl:%s", info, result, ERR_error_string(ERR_get_error(), err_buff)); #else - aflog(2, "%s(%d): ssl", info, result); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): ssl", info, result); #endif break; } default: { - aflog(2, "%s(%d): unrecognized error (%d)", info, result, errno); + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): unrecognized error (%d)", info, result, errno); } } if (merror == SSL_ERROR_WANT_READ) { diff --git a/src/network.c b/src/network.c index 7618c76..0903b4f 100644 --- a/src/network.c +++ b/src/network.c @@ -24,6 +24,7 @@ #include "network.h" #include "activefor.h" #include "stats.h" +#include "logging.h" #include #include #include @@ -395,7 +396,8 @@ 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", + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "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; @@ -444,7 +446,8 @@ 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", + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "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)) { diff --git a/src/network.h b/src/network.h index 401a627..ee03af6 100644 --- a/src/network.h +++ b/src/network.h @@ -30,7 +30,9 @@ #include #include #include +#ifdef HAVE_LIBPTHREAD #include +#endif #include #include diff --git a/src/realmnames.c b/src/realmnames.c index 84d9f53..77065bf 100644 --- a/src/realmnames.c +++ b/src/realmnames.c @@ -18,6 +18,8 @@ * */ +#include + #include #include #include "realmnames.h" diff --git a/src/remoteadmin.c b/src/remoteadmin.c index 4e777c1..c2ada6e 100644 --- a/src/remoteadmin.c +++ b/src/remoteadmin.c @@ -18,11 +18,51 @@ * */ +#include + #include "remoteadmin.h" static char newmessage; static int +parse_int(unsigned char* buff, int* ret) +{ + int intarg, i; + char guard; + if (((i = sscanf((char*) &buff[*ret], "%d%c", &intarg, &guard)) == 2) || (i == 1)) { + if (i == 1) { + guard = ' '; + } + if (!isspace(guard)) { + return -1; + } + guard = 0; + i = (*ret); + while (buff[i] != 0) { + if (guard == 0) { + if (isspace(buff[i])) { + guard = 1; + } + } + else { + if (!isspace(buff[i])) { + break; + } + } + ++i; + } + if (buff[i] == '.') { + ++i; + } + (*ret) = i; + return intarg; + } + else { + return -1; + } +} + +static int parse_cmd(unsigned char* buff, int* ret) { int i, j, state; @@ -70,6 +110,12 @@ parse_cmd(unsigned char* buff, int* ret) if (strcmp(cmd, "cshow") == 0) { return 5; } if (strcmp(cmd, "ushow") == 0) { return 6; } if (strcmp(cmd, "quit") == 0) { return 7; } + if (strcmp(cmd, "timeout") == 0) { return 8; } + if (strcmp(cmd, "audit") == 0) { return 9; } + if (strcmp(cmd, "dnslookups") == 0) { return 10; } + if (strcmp(cmd, "dateformat") == 0) { return 11; } + if (strcmp(cmd, "kuser") == 0) { return 12; } + if (strcmp(cmd, "kclient") == 0) { return 13; } return 0; } @@ -134,12 +180,16 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) { int length, n, i, j, ret; time_t now, tmp; + llnodeT* llptr; + alnodeT* alptr; + char olddf[51], newdf[51]; char type = config->realmtable[realm].type | TYPE_SSL | TYPE_ZLIB; clifd master = config->realmtable[realm].raclitable[client].cliconn; + olddf[50] = newdf[50] = 0; length = buff[3]; length = length << 8; - length += buff[4]; /* this is length of message */ + length += buff[4]; /* this is the length of a message */ time(&now); @@ -147,19 +197,26 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) case AF_RA_CMD: { n = get_message(type, master, buff, length); buff[n] = 0; - aflog(2, " realm[%s]: admin: message length = %d [%s]", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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"); + 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"); + add_to_message(buff, " timeout N X set timeout value in X realm"); + add_to_message(buff, " audit {0|1} X set audit mode in X realm"); + add_to_message(buff, " dnslookups {0|1} X set dnslookups mode in X realm"); + add_to_message(buff, " dateformat S set dateformat"); + add_to_message(buff, " kuser S kick user named S"); + add_to_message(buff, " kclient N kick client with number N"); send_adm_message(type, master, buff, AF_RA_STATUS_OK); break; } @@ -171,6 +228,12 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) add_to_message(buff, "cshow"); add_to_message(buff, "ushow"); add_to_message(buff, "quit"); + add_to_message(buff, "timeout"); + add_to_message(buff, "audit"); + add_to_message(buff, "dnslookups"); + add_to_message(buff, "dateformat"); + add_to_message(buff, "kuser"); + add_to_message(buff, "kclient"); send_adm_message(type, master, buff, AF_RA_STATUS_OK); break; } @@ -179,23 +242,17 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) 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"); + llptr = getloglisthead(); + i = 0; + while (llptr) { + add_to_message(buff, "log[%d]: %s", i, llptr->cmdline); + llptr = llptr->next; + ++i; } tmp = now - config->starttime; add_uptime_to_message(buff, "Uptime", tmp); add_to_message(buff, "Cg: %ld B", getcg()); + add_to_message(buff, "Dateformat: %s", getdateformat()); send_adm_message(type, master, buff, AF_RA_STATUS_OK); break; } @@ -219,13 +276,30 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) 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, "timeout: %d", config->realmtable[i].tmout); add_to_message(buff, "baseport: %s", config->realmtable[i].baseport ? "yes" : "no"); + add_to_message(buff, "audit: %s", config->realmtable[i].audit ? + "yes" : "no"); + add_to_message(buff, "dnslookups: %s", config->realmtable[i].dnslookups ? + "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"); + switch (config->realmtable[i].tunneltype) { + case 0: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case 1: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } } send_adm_message(type, master, buff, AF_RA_STATUS_OK); break; @@ -264,15 +338,45 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) add_to_message(buff, "Id: %s", (config->realmtable[n].clitable[i].clientid == NULL)?"": config->realmtable[n].clitable[i].clientid); + add_to_message(buff, "Number: %d", + config->realmtable[n].clitable[i].clientnum); add_to_message(buff, "IP: %s, port: %s", config->realmtable[n].clitable[i].namebuf, config->realmtable[n].clitable[i].portbuf); + switch (config->realmtable[n].clitable[i].tunneltype) { + case 0: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case 1: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } + if (config->realmtable[n].audit) { + add_to_message(buff, "auditlog:"); + alptr = config->realmtable[n].clitable[i].head; + while (alptr) { + add_to_message(buff, + "userid: %d ip: %s port: %s connected: %s duration: %s", + alptr->userid, + alptr->namebuf, + alptr->portbuf, + localdate(&(alptr->connecttime)), + timeperiod(alptr->duration)); + alptr = alptr->next; + } + } } } send_adm_message(type, master, buff, AF_RA_STATUS_OK); break; } add_to_message(buff, "Wrong realm name"); + add_to_message(buff, "Usage: cshow X , X - realm name"); send_adm_message(type, master, buff, AF_RA_FAILED); break; } @@ -318,18 +422,179 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) break; } add_to_message(buff, "Wrong realm name"); + add_to_message(buff, "Usage: ushow X , X - realm name"); send_adm_message(type, master, buff, AF_RA_FAILED); break; } case 7: { /* quit */ - aflog(1, " realm[%s]: Client[%s] (ra): commfd: CLOSED", + aflog(LOG_T_MANAGE, LOG_I_INFO, + "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; } + case 8: { /* timeout */ + i = parse_int(buff, &ret); + if (i <= 0) { + add_to_message(buff, "Invalid timeout value"); + add_to_message(buff, + "Usage: timeout N X , N - new timeout value, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + add_to_message(buff, "changed timeout: %d --> %d", + config->realmtable[n].tmout, i); + config->realmtable[n].tmout = i; + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: timeout N X , N - new timeout value, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 9: { /* audit */ + i = parse_int(buff, &ret); + if ((i != 0) && (i != 1)) { + add_to_message(buff, "Invalid audit value"); + add_to_message(buff, + "Usage: audit {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + add_to_message(buff, "changed audit: %s --> %s", + config->realmtable[n].audit ? "yes" : "no", i ? "yes" : "no"); + config->realmtable[n].audit = i; + if (i == 0) { + for (i = 0; i < config->realmtable[n].clinum; ++i) { + freeauditlist(&(config->realmtable[n].clitable[i].head)); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: audit {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 10: { /* dnslookups */ + i = parse_int(buff, &ret); + if ((i != 0) && (i != 1)) { + add_to_message(buff, "Invalid dnslookups value"); + add_to_message(buff, + "Usage: dnslookups {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + add_to_message(buff, "changed dnslookups: %s --> %s", + config->realmtable[n].dnslookups ? "yes" : "no", i ? "yes" : "no"); + config->realmtable[n].dnslookups = i; + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: dnslookups {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 11: { /* dateformat */ + strncpy(olddf, getdateformat(), 50); + strncpy(newdf, (char*) &buff[ret], 50); + add_to_message(buff, "changed dateformat: %s --> %s", + olddf, newdf); + setdateformat(newdf); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 12: { /* kuser */ + i = parse_int(buff, &ret); + if (buff[ret] != 0) { + add_to_message(buff, "Invalid user name"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + j = -1; + for (n = 0; n < config->size; ++n) { + j = get_usernumber(&(config->realmtable[n]), i); + if (j != (-1)) { + if ((config->realmtable[n].contable[j].state == S_STATE_OPEN) || + (config->realmtable[n].contable[j].state == S_STATE_STOPPED)) { + add_to_message(buff, "kicked: realm[%s] user[%d]", + get_realmname(config, n), get_username(&(config->realmtable[n]), i)); + close(config->realmtable[n].contable[j].connfd); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + } + else { + add_to_message(buff, "Invalid user"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + } + if (j == (-1)) { + add_to_message(buff, "Invalid user name"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + case 13: { /* kclient */ + i = parse_int(buff, &ret); + if (buff[ret] != 0) { + add_to_message(buff, "Invalid client number"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + j = -1; + for (n = 0; n < config->size; ++n) { + j = get_clientnumber(&(config->realmtable[n]), i); + if (j != (-1)) { + if (config->realmtable[n].clitable[j].ready) { + add_to_message(buff, "kicked: realm[%s] client[%s]", + get_realmname(config, n), + get_clientname(&(config->realmtable[n]), j)); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + return (i+2); + } + else { + add_to_message(buff, "Invalid client"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + } + if (j == (-1)) { + add_to_message(buff, "Invalid client number"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + + } default: { - aflog(2, " realm[%s]: admin: cmd ignored", get_realmname(config, realm)); + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: admin: cmd ignored", get_realmname(config, realm)); send_adm_message(type, master, buff, AF_RA_UNDEFINED); } } @@ -339,7 +604,8 @@ serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) break; } default: { - aflog(1, "Unrecognized message from remote admin --> closing"); + aflog(LOG_T_MANAGE, LOG_I_ERR, + "Unrecognized message from remote admin --> closing"); return 1; } } @@ -359,24 +625,29 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* get_message(type, master, buff, -5); if ( buff[0] == 0 ) { - aflog(0, "Wrong password"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Wrong password"); return 1; } if ( buff[0] == AF_S_CANT_OPEN ) { - aflog(0, "Server is full"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Server is full"); return 1; } if ( buff[0] != AF_S_ADMIN_LOGIN ) { - aflog(0, "Incompatible server type or server full"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Incompatible server type or server full"); return 1; } - aflog(1, "CLIENT STARTED mode: remote administration"); + aflog(LOG_T_MAIN, LOG_I_INFO, + "CLIENT STARTED mode: remote administration"); if (connectfd > 0) { outfp = fdopen(connectfd, "w"); if (outfp == NULL) { - aflog(0, "Error in opening file descriptor for writing"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for writing"); return 1; } infd = connectfd; @@ -387,7 +658,8 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* } infp = fdopen(infd, "r"); if (infp == NULL) { - aflog(0, "Error in opening file descriptor for reading"); + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for reading"); return 1; } @@ -414,7 +686,8 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* 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); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "ID SENT: %s", id); } while (1) { @@ -422,10 +695,12 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* select(maxfdp1, &rset, NULL, NULL, NULL); if (FD_ISSET(master.commfd, &rset)) { - aflog(3, " masterfd: FD_ISSET"); + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "masterfd: FD_ISSET"); n = get_message(type, master, buff, 5); if (n != 5) { - aflog(2, " FATAL ERROR! (%d)", n); + aflog(LOG_T_MANAGE, LOG_I_ERR, + "FATAL ERROR! (%d)", n); if (n == -1) { if (TYPE_IS_SSL(type)) { get_ssl_error(&master, "FE", n); @@ -436,15 +711,18 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* return 1; } if (n == 0) { /* server quits -> we do the same... */ - aflog(0, " SERVER: premature quit --> exiting..."); + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: premature quit --> exiting..."); return 1; } if (buff[0] == AF_S_CLOSING) { - aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); return 0; } if (buff[0] != AF_S_ADMIN_CMD) { - aflog(0, " SERVER: wrong message --> exiting"); + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: wrong message --> exiting"); return 1; } length = buff[3]; @@ -453,16 +731,19 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* switch (buff[1]) { case AF_RA_STATUS_OK: { - aflog(1, " SERVER: cmd successful"); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd successful"); } case AF_RA_FAILED: { if (buff[1] == AF_RA_FAILED) { - aflog(1, " SERVER: cmd failed"); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd failed"); } } case AF_RA_UNDEFINED: { if (buff[1] == AF_RA_UNDEFINED) { - aflog(1, " SERVER: unknown cmd"); + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "SERVER: unknown cmd"); } n = get_message(type, master, buff, length); buff[n] = 0; @@ -471,21 +752,25 @@ client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* break; } case AF_RA_KICKED: { - aflog(0, " SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); return 1; break; } default: { - aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); return 1; } } } if (FD_ISSET(infd, &rset)) { - aflog(3, " infd: FD_ISSET"); + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "infd: FD_ISSET"); if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ - aflog(0, " CLIENT CLOSED cg: %ld bytes", getcg()); + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "CLIENT CLOSED cg: %ld bytes", getcg()); return 0; } n = strlen((char*) &buff[5]); diff --git a/src/remoteadmin.h b/src/remoteadmin.h index cad9c76..5b176df 100644 --- a/src/remoteadmin.h +++ b/src/remoteadmin.h @@ -20,6 +20,7 @@ #include "file.h" #include "stats.h" +#include "logging.h" #include "activefor.h" #include "realmnames.h" #include "clientnames.h" diff --git a/src/server_check.c b/src/server_check.c index 94069cc..3fd1091 100644 --- a/src/server_check.c +++ b/src/server_check.c @@ -18,30 +18,45 @@ * */ +#include + #include #include #include +#include "server_check.h" #include "stats.h" +#include "logging.h" void check_value(int* where, char* what, char* info) { + long tmp = check_value_liberal(what, info); + + if (tmp <= 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "%s: %d\n", info, tmp); + exit(1); + } + (*where) = tmp; +} + +int +check_value_liberal(char* what, char* info) +{ char* znak; long tmp; if ((tmp = strtol(what, &znak, 10)) >= INT_MAX) { - aflog(0, "%s: %s\n", info, what); + aflog(LOG_T_INIT, LOG_I_CRIT, + "%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); + aflog(LOG_T_INIT, LOG_I_CRIT, + "%s: %s\n", info, what); exit(1); } - (*where) = tmp; + return tmp; } int diff --git a/src/server_check.h b/src/server_check.h index 3877426..0b4ddbf 100644 --- a/src/server_check.h +++ b/src/server_check.h @@ -22,6 +22,7 @@ #define _JS_SERVER_CHECK_H void check_value(int* where, char* what, char* info); +int check_value_liberal(char* what, char* info); int check_long(char* text, long* number); #endif diff --git a/src/server_eval.c b/src/server_eval.c index d487b01..373a310 100644 --- a/src/server_eval.c +++ b/src/server_eval.c @@ -18,6 +18,8 @@ * */ +#include + #include "server_eval.h" int diff --git a/src/server_find.c b/src/server_find.c index 1d67640..80148e4 100644 --- a/src/server_find.c +++ b/src/server_find.c @@ -18,6 +18,8 @@ * */ +#include + #include "server_find.h" int diff --git a/src/server_get.c b/src/server_get.c new file mode 100644 index 0000000..7ada39c --- /dev/null +++ b/src/server_get.c @@ -0,0 +1,55 @@ +/* + * 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 "server_get.h" +#include + +int +get_new_socket(int sockfd, char type, struct sockaddr *addr, socklen_t *addrlen, char* tunneltype) +{ + int tmp; + switch (type) { + case 0: { + return accept(sockfd, addr, addrlen); + break; + } + case 1: { + if (read(sockfd, &tmp, 4) != 4) { + return -1; + } + if (read(sockfd, tunneltype, 1) != 1) { + return -1; + } + if (read(sockfd, addrlen, 4) != 4) { + return -1; + } + if (read(sockfd, addr, *addrlen) != *addrlen) { + return -1; + } + return tmp; + break; + } + default: { + return -1; + } + } +} diff --git a/src/server_get.h b/src/server_get.h new file mode 100644 index 0000000..099e124 --- /dev/null +++ b/src/server_get.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. + * + */ + +#ifndef _JS_SERVER_GET_H +#define _JS_SERVER_GET_H + +#include +#include +#include + +int get_new_socket(int sockfd, char type, struct sockaddr *addr, socklen_t *addrlen, char* tunneltype); + +#endif + diff --git a/src/server_signals.c b/src/server_signals.c new file mode 100644 index 0000000..41cd31c --- /dev/null +++ b/src/server_signals.c @@ -0,0 +1,66 @@ +/* + * 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 "server_signals.h" +#include "activefor.h" +#include "thread_management.h" +#include "http_proxy_functions.h" +#include "stats.h" +#include "logging.h" + +extern ConfigurationT config; + + void +server_sig_int(int signo) +{ + int i, j; + unsigned char buff[5]; + +#ifdef HAVE_LIBPTHREAD + if (!is_this_a_mainthread()) { + return; + } +#endif + + 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); + } + } + for (i = 0; i < config.realmtable[j].raclinum; ++i) { + if (config.realmtable[j].raclitable[i].ready == 3) { + send_message(config.realmtable[j].type | TYPE_SSL, config.realmtable[j].raclitable[i].cliconn, buff, 5); + } + } + + } + + /* FIXME: give a time to close all connections */ + mysleep(0.1); + + aflog(LOG_T_MAIN, LOG_I_NOTICE, + "SERVER CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/src/server_signals.h b/src/server_signals.h new file mode 100644 index 0000000..babb131 --- /dev/null +++ b/src/server_signals.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_SIGNALS_H +#define _JS_SERVER_SIGNALS_H + +void server_sig_int(int); /* INT signal handler for the afserver */ + +#endif + diff --git a/src/stats.c b/src/stats.c index 82e90aa..4303a7e 100644 --- a/src/stats.c +++ b/src/stats.c @@ -18,94 +18,30 @@ * */ +#include + #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) +timeperiod(time_t period) { - 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 hours, minutes, seconds; + static char timeper[41]; + memset(timeper, 0, 41); -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); - } + hours = period/3600; + minutes = (period/60)%60; + seconds = period%60; + if (hours) { + sprintf(timeper, "%d:%02d:%02d", hours, minutes, seconds); + } + else { + sprintf(timeper, "%d:%02d", minutes, seconds); + } + return timeper; } void diff --git a/src/stats.h b/src/stats.h index 08838ad..a774ae1 100644 --- a/src/stats.h +++ b/src/stats.h @@ -18,13 +18,15 @@ * */ +#include +#include +#include + #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, ...); + /* return time period description */ +char* timeperiod(time_t period); /* add amount to compressgained value */ void addtocg(int amount); /* reset the compressgained value */ diff --git a/src/thread_management.c b/src/thread_management.c new file mode 100644 index 0000000..fcd53ab --- /dev/null +++ b/src/thread_management.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 "thread_management.h" + +#ifdef HAVE_LIBPTHREAD + +static pthread_t mainthread; +static pthread_mutex_t mainmutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t maincond = PTHREAD_COND_INITIALIZER; + +void +remember_mainthread(void) +{ + mainthread = pthread_self(); +} + +int +is_this_a_mainthread(void) +{ + if (pthread_self() == mainthread) { + return 1; + } + return 0; +} + +void +start_critical_section(void) +{ + pthread_mutex_lock( &mainmutex); +} + +void +end_critical_section(void) +{ + pthread_mutex_unlock( &mainmutex); +} + +void +wait_for_condition(void) +{ + pthread_cond_wait(&maincond, &mainmutex); +} + +void +broadcast_condition(void) +{ + pthread_cond_broadcast(&maincond); +} + +#endif diff --git a/src/thread_management.h b/src/thread_management.h new file mode 100644 index 0000000..f502d1e --- /dev/null +++ b/src/thread_management.h @@ -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. + * + */ + +#ifndef _JS_THREAD_MANAGEMENT_H +#define _JS_THREAD_MANAGEMENT_H + +#include + +void remember_mainthread(void); +int is_this_a_mainthread(void); +void start_critical_section(void); +void end_critical_section(void); +void wait_for_condition(void); +void broadcast_condition(void); + +#endif + diff --git a/src/usage.c b/src/usage.c new file mode 100644 index 0000000..4510781 --- /dev/null +++ b/src/usage.c @@ -0,0 +1,168 @@ +/* + * 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 "usage.h" +#include "network.h" + +#include +#include + + void +server_short_usage(char* info) +{ + printf("\n%s\n\n\n", info); + printf("Try `afserver --help' for more information.\n"); + + exit(1); +} + + void +server_long_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(" -V, --version - display version number\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(" -a, --audit - additional information about connections are logged\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, --log - log choosen information to file/socket\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_LIBPTHREAD + printf(" HTTP PROXY:\n\n"); + printf(" -P, --enableproxy - enable http proxy mode\n\n"); +#endif + + exit(0); +} + + void +client_short_usage(char* info) +{ + printf("\n%s\n\n\n", info); + printf("Try `afclient --help' for more information.\n"); + + exit(1); +} + +void +client_long_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(" -V, --version - display version number\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"); + printf(" -K, --keep-alive N - send keepalive packets every N seconds\n"); + printf(" (default: not send keepalive packets)\n"); + printf(" -A, --ar-tries N - try N times to reconnect to afserver after\n"); + printf(" its premature quit (default: unlimited)\n"); + printf(" -T, --ar-delay N - wait N seconds between reconnect tries (default: 5)\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 than stdin-stdout)\n\n"); + printf(" Logging:\n\n"); + printf(" -o, --log - log choosen information to file/socket\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 +#ifdef HAVE_LIBPTHREAD + printf(" HTTP PROXY:\n\n"); + printf(" -P, --proxyname - the name of the machine with proxy server\n"); + printf(" -X, --proxyport - the port used by proxy server (default: 8080)\n\n"); +#endif + + exit(0); +} diff --git a/src/usage.h b/src/usage.h new file mode 100644 index 0000000..6436020 --- /dev/null +++ b/src/usage.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. + * + */ + +#ifndef _JS_USAGE_H +#define _JS_USAGE_H + +void server_short_usage(char* info); /* short usage info printed by afserver */ +void server_long_usage(char* info); /* long usage info printed by afserver */ +void client_short_usage(char* info); /* short usage info printed by afclient */ +void client_long_usage(char* info); /* long usage info printed by afclient */ + +#endif + diff --git a/src/usernames.c b/src/usernames.c index 3e4b24c..194bfa0 100644 --- a/src/usernames.c +++ b/src/usernames.c @@ -18,6 +18,8 @@ * */ +#include + #include "usernames.h" int -- cgit v1.1