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 --- 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 + 48 files changed, 4232 insertions(+), 885 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 (limited to 'src') 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