From 43e8714797d40bcf63efab428dcd25f9caf1d52b Mon Sep 17 00:00:00 2001 From: Jakub Sławiński Date: Fri, 5 Aug 2005 21:45:31 +0200 Subject: v0.7.2 - Added: http proxy basic authorization - Fixed: logging initialization after some value checking - Fixed: auto-reconnect failure when --nossl option is set - Added: auto-reconnect when afserver is not reachable on start - Added: auto-reconnect after normal afserver quit - Added: per user statistics: idle time, amount of downloaded/uploaded bytes and current download/upload rate - Added: support for https proxies - Added: possibility to bind sockets on different interfaces - Fixed: receiving incomplete headers from afclient - Fixed: close user connections by afclient --- src/Makefile.am | 26 +- src/activefor.h | 54 +- src/afclient.c | 465 ++++-- src/afclient.h | 6 +- src/afserver.c | 2987 ++++++++++++++++++++++----------------- src/afserver.h | 3 +- src/ar_options_struct.c | 296 ++++ src/ar_options_struct.h | 59 + src/audit.c | 69 - src/audit.h | 39 - src/audit_list_node_struct.c | 298 ++++ src/audit_list_node_struct.h | 58 + src/audit_list_struct.c | 140 ++ src/audit_list_struct.h | 41 + src/buf_list_node_struct.c | 270 ++++ src/buf_list_node_struct.h | 50 + src/buf_list_struct.c | 140 ++ src/buf_list_struct.h | 41 + src/buflist.c | 72 - src/buflist.h | 35 - src/client_initialization.c | 50 +- src/client_initialization.h | 10 +- src/client_remoteadmin.c | 198 +++ src/client_remoteadmin.h | 38 + src/client_reverse_udp.c | 54 +- src/client_reverse_udp.h | 6 +- src/client_shutdown.c | 17 +- src/client_shutdown.h | 3 +- src/clientnames.c | 32 +- src/connect_client_struct.c | 710 ++++++++++ src/connect_client_struct.h | 106 ++ src/connect_user_struct.c | 374 +++++ src/connect_user_struct.h | 67 + src/file.c | 20 +- src/first_run.c | 2 +- src/header_buffer_struct.c | 118 ++ src/header_buffer_struct.h | 39 + src/http_proxy_client.c | 366 +++-- src/http_proxy_client.h | 4 +- src/http_proxy_functions.c | 72 +- src/http_proxy_functions.h | 13 +- src/http_proxy_options_struct.c | 239 ++++ src/http_proxy_options_struct.h | 58 + src/http_proxy_server.c | 201 ++- src/http_proxy_server.h | 2 +- src/make_ssl_handshake.c | 14 +- src/make_ssl_handshake.h | 7 +- src/network.c | 96 -- src/network.h | 8 - src/remoteadmin.c | 788 ----------- src/remoteadmin.h | 50 - src/remoteadmin_codes.h | 32 + src/server_eval.c | 10 +- src/server_eval.h | 2 +- src/server_find.c | 15 +- src/server_find.h | 2 +- src/server_remoteadmin.c | 656 +++++++++ src/server_remoteadmin.h | 37 + src/server_remove.c | 63 +- src/server_signals.c | 16 +- src/ssl_fd_struct.c | 314 ++++ src/ssl_fd_struct.h | 48 + src/string_functions.c | 68 + src/string_functions.h | 27 + src/timeval_functions.c | 40 + src/timeval_functions.h | 29 + src/usage.c | 32 +- src/user_stats_struct.c | 368 +++++ src/user_stats_struct.h | 59 + src/usernames.c | 4 +- src/usr_cli_struct.c | 246 ++++ src/usr_cli_struct.h | 51 + 72 files changed, 8014 insertions(+), 3016 deletions(-) create mode 100644 src/ar_options_struct.c create mode 100644 src/ar_options_struct.h delete mode 100644 src/audit.c delete mode 100644 src/audit.h create mode 100644 src/audit_list_node_struct.c create mode 100644 src/audit_list_node_struct.h create mode 100644 src/audit_list_struct.c create mode 100644 src/audit_list_struct.h create mode 100644 src/buf_list_node_struct.c create mode 100644 src/buf_list_node_struct.h create mode 100644 src/buf_list_struct.c create mode 100644 src/buf_list_struct.h delete mode 100644 src/buflist.c delete mode 100644 src/buflist.h create mode 100644 src/client_remoteadmin.c create mode 100644 src/client_remoteadmin.h create mode 100644 src/connect_client_struct.c create mode 100644 src/connect_client_struct.h create mode 100644 src/connect_user_struct.c create mode 100644 src/connect_user_struct.h create mode 100644 src/header_buffer_struct.c create mode 100644 src/header_buffer_struct.h create mode 100644 src/http_proxy_options_struct.c create mode 100644 src/http_proxy_options_struct.h delete mode 100644 src/remoteadmin.c delete mode 100644 src/remoteadmin.h create mode 100644 src/remoteadmin_codes.h create mode 100644 src/server_remoteadmin.c create mode 100644 src/server_remoteadmin.h create mode 100644 src/ssl_fd_struct.c create mode 100644 src/ssl_fd_struct.h create mode 100644 src/string_functions.c create mode 100644 src/string_functions.h create mode 100644 src/timeval_functions.c create mode 100644 src/timeval_functions.h create mode 100644 src/user_stats_struct.c create mode 100644 src/user_stats_struct.h create mode 100644 src/usr_cli_struct.c create mode 100644 src/usr_cli_struct.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 9910314..f512ce8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,12 +1,18 @@ bin_PROGRAMS = afserver afclient -afserver_SOURCES = afserver.c network.c file.c stats.c buflist.c remoteadmin.c \ - server_check.c server_set.c server_eval.c server_find.c server_remove.c \ - make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c \ - http_proxy_functions.c http_proxy_server.c server_get.c thread_management.c \ - server_signals.c usage.c logging.c audit.c daemon.c +afserver_SOURCES = afserver.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \ + server_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 http_proxy_functions.c http_proxy_server.c server_get.c \ + thread_management.c server_signals.c usage.c logging.c daemon.c ssl_fd_struct.c \ + user_stats_struct.c usr_cli_struct.c connect_user_struct.c string_functions.c \ + audit_list_node_struct.c audit_list_struct.c connect_client_struct.c timeval_functions.c \ + header_buffer_struct.c afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB} -afclient_SOURCES = afclient.c network.c stats.c buflist.c modules.c remoteadmin.c \ - make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c \ - 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 daemon.c base64.c ssl_routines.c +afclient_SOURCES = afclient.c network.c stats.c buf_list_node_struct.c buf_list_struct.c modules.c \ + client_remoteadmin.c make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c \ + usernames.c http_proxy_functions.c http_proxy_client.c \ + http_proxy_options_struct.c thread_management.c client_reverse_udp.c server_check.c \ + client_initialization.c client_shutdown.c client_signals.c usage.c logging.c \ + daemon.c base64.c ssl_routines.c connect_user_struct.c user_stats_struct.c \ + string_functions.c ar_options_struct.c audit_list_node_struct.c audit_list_struct.c \ + ssl_fd_struct.c timeval_functions.c diff --git a/src/activefor.h b/src/activefor.h index d058a9c..ec2fcc5 100644 --- a/src/activefor.h +++ b/src/activefor.h @@ -22,8 +22,12 @@ #define _JS_ACTIVEFOR_H #include "network.h" -#include "buflist.h" -#include "audit.h" +#include "buf_list_struct.h" +#include "audit_list_struct.h" +#include "usr_cli_struct.h" +#include "connect_user_struct.h" +#include "ssl_fd_struct.h" +#include "connect_client_struct.h" #define AF_S_CONCLOSED 1 #define AF_S_CONOPEN 2 @@ -46,7 +50,7 @@ #define S_STATE_OPEN 7 #define S_STATE_STOPPED 11 -#define AF_VER(info) info" v0.7.1" +#define AF_VER(info) info" v0.7.2" #define TYPE_TCP 1 #define TYPE_UDP 3 @@ -82,42 +86,6 @@ #define TYPE_IS_COMP(type) (type&TYPE_COMP) typedef struct { - char* lisportnum; - char* manportnum; - int listenfd; - int managefd; -} UsrCliT; - -typedef struct { - char state; - int connfd; - int whatcli; - int userid; - time_t connecttime; - char namebuf[128]; - char portbuf[7]; - blnodeT* head; -} ConnectuserT; - -typedef struct { - char ready; - clifd cliconn; - struct timeval tv; - int* users; - int usercon; - int usernum; - int listenfd; - int whatusrcli; - int clientnum; - time_t connecttime; - char* clientid; - char namebuf[128]; - char portbuf[7]; - char tunneltype; - alnodeT* head; -} ConnectclientT; - -typedef struct { char* hostname; char* users; char* clients; @@ -146,10 +114,10 @@ typedef struct { char audit; socklen_t addrlen; struct sockaddr* cliaddr; - ConnectuserT* contable; - ConnectclientT* clitable; - ConnectclientT* raclitable; - UsrCliT* usrclitable; + ConnectUser** contable; + ConnectClient** clitable; + ConnectClient** raclitable; + UsrCli** usrclitable; } RealmT; typedef struct { diff --git a/src/afclient.c b/src/afclient.c index 798ec55..c41ee68 100644 --- a/src/afclient.c +++ b/src/afclient.c @@ -48,22 +48,32 @@ static struct option long_options[] = { {"dateformat", 1, 0, 'D'}, {"remoteadmin", 0, 0, 'r'}, #ifdef HAVE_LIBPTHREAD + {"use-https", 0, 0, 'S'}, {"proxyname", 1, 0, 'P'}, {"proxyport", 1, 0, 'X'}, + {"pa-t-basic", 0, 0, 'B'}, + {"pa-cred", 1, 0, 'C'}, #endif {"version", 0, 0, 'V'}, {"keep-alive", 1, 0, 'K'}, {"ar-tries", 1, 0, 'A'}, {"ar-delay", 1, 0, 'T'}, + {"ar-start", 0, 0, 305}, + {"ar-quit", 0, 0, 306}, + {"noar", 0, 0, 307}, {0, 0, 0, 0} }; int main(int argc, char **argv) { - int i, n, numofcon, length, buflength, notsent, temp2; - ConnectuserT* contable = NULL; - clifd master; + /* + * variables + */ + + int i, n, numofcon, length, buflength, notsent, temp, temp2; + ConnectUser** contable = NULL; + SslFd* master = SslFd_new(); unsigned char buff[9000]; char hostname[100]; int maxfdp1, usernum, usercon; @@ -72,16 +82,14 @@ main(int argc, char **argv) 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 sendkapackets = 0; char* name = NULL; #ifdef HAVE_LIBPTHREAD - char* proxyname = NULL; - char* proxyport = NULL; + HttpProxyOptions* hpo = HttpProxyOptions_new(); #endif + ArOptions* ao = ArOptions_new(); char* id = NULL; char* manage = NULL; char* desnam = NULL; @@ -90,8 +98,6 @@ main(int argc, char **argv) char* store = 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; @@ -103,10 +109,30 @@ main(int argc, char **argv) #ifdef HAVE_LIBDL moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL}; #endif - SSL_METHOD* method; SSL_CTX* ctx = NULL; + /* + * initialization + */ + +#ifdef HAVE_LIBPTHREAD + if (hpo == NULL) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } +#endif + + if (ao == NULL) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } + + if (master == NULL) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } + sigfillset(&(act.sa_mask)); act.sa_flags = 0; @@ -125,7 +151,7 @@ main(int argc, char **argv) #define GETOPT_LONG_AF_INET6(x) x #endif #ifdef HAVE_LIBPTHREAD -#define GETOPT_LONG_LIBPTHREAD(x) "P:X:"x +#define GETOPT_LONG_LIBPTHREAD(x) "SP:X:BC:"x #else #define GETOPT_LONG_LIBPTHREAD(x) x #endif @@ -136,7 +162,8 @@ main(int argc, char **argv) #endif while ((n = getopt_long(argc, argv, - GETOPT_LONG_LIBDL(GETOPT_LONG_LIBPTHREAD(GETOPT_LONG_AF_INET6("huUn:m:d:p:vk:s:o:i:D:rP:X:VK:A:T:"))) + GETOPT_LONG_LIBDL(GETOPT_LONG_LIBPTHREAD( + GETOPT_LONG_AF_INET6("huUn:m:d:p:vk:s:o:i:D:rP:X:VK:A:T:"))) , long_options, 0)) != -1) { switch (n) { case 'h': { @@ -148,12 +175,24 @@ main(int argc, char **argv) break; } #ifdef HAVE_LIBPTHREAD + case 'S': { + HttpProxyOptions_use_https(hpo); + break; + } case 'P': { - proxyname = optarg; + HttpProxyOptions_set_proxyname(hpo, optarg); break; } case 'X': { - proxyport = optarg; + HttpProxyOptions_set_proxyport(hpo, optarg); + break; + } + case 'B': { + HttpProxyOptions_set_proxyauth_type(hpo, PROXYAUTH_TYPE_BASIC); + break; + } + case 'C': { + HttpProxyOptions_set_proxyauth_cred(hpo, optarg); break; } #endif @@ -209,6 +248,18 @@ main(int argc, char **argv) ignorepkeys = 1; break; } + case 305: { + ArOptions_set_arStart(ao, AR_OPTION_ENABLED); + break; + } + case 306: { + ArOptions_set_arQuit(ao, AR_OPTION_ENABLED); + break; + } + case 307: { + ArOptions_set_arPremature(ao, AR_OPTION_DISABLED); + break; + } #ifdef AF_INET6 case '4': { if (ipfam != 0) { @@ -258,11 +309,11 @@ main(int argc, char **argv) break; } case 'A': { - artries = optarg; + ArOptions_set_s_arTries(ao, optarg); break; } case 'T': { - ardelay = optarg; + ArOptions_set_s_arDelay(ao, optarg); break; } case '?': { @@ -285,7 +336,7 @@ main(int argc, char **argv) client_short_usage("Port on the server is required in reverse mode"); } #ifdef HAVE_LIBPTHREAD - if ((proxyname) || (proxyport)) { + if ((HttpProxyOptions_get_proxyname(hpo)) || (HttpProxyOptions_get_proxyport(hpo))) { if (tunneltype == 0) { tunneltype = 1; } @@ -294,8 +345,8 @@ main(int argc, char **argv) } } if (tunneltype == 1) { - if (proxyport == NULL) { - proxyport = "8080"; + if (HttpProxyOptions_get_proxyport(hpo) == NULL) { + HttpProxyOptions_set_proxyport(hpo, "8080"); } } #endif @@ -313,19 +364,14 @@ main(int argc, char **argv) client_short_usage("Destination port number is required"); } + initializelogging(verbose, dateformat); + 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); + ArOptions_evaluate_values(ao); #ifdef HAVE_LIBDL if (loadmodule(&module)) { @@ -418,32 +464,81 @@ main(int argc, char **argv) temp2 = accept(n, cliaddr, &addrlen); } } + + } + + i = ArOptions_get_arTries(ao); + usernum = 0; + SslFd_set_fd(master, -1); + + do { + temp = 0; + if (SslFd_get_fd(master) != -1) { + close(SslFd_get_fd(master)); + } + close_connections(usernum, &contable); + SslFd_set_ssl(master, NULL); + if (!reverse) { + if (temp == 0) { #ifdef HAVE_LIBPTHREAD - initialize_client_stage1(tunneltype, &master, name, manage, proxyname, proxyport, - ipfam, ctx, buff, pass, 1, ignorepkeys); + if (initialize_client_stage1(tunneltype, master, name, manage, hpo, + ipfam, ctx, buff, pass, + (ArOptions_get_arStart(ao) == AR_OPTION_ENABLED) ? 0 : 1, + ignorepkeys)) { #else - initialize_client_stage1(tunneltype, &master, name, manage, NULL, NULL, - ipfam, ctx, buff, pass, 1, ignorepkeys); + if (initialize_client_stage1(tunneltype, master, name, manage, NULL, + ipfam, ctx, buff, pass, + (ArOptions_get_arStart(ao) == AR_OPTION_ENABLED) ? 0 : 1, + ignorepkeys)) { #endif - - if (remote) { - return client_admin(type, master, buff, temp2, id); + temp = 1; + } + } + + if ((temp == 0) && remote) { + return client_admin(type, master, buff, temp2, id); + } + + if (temp == 0) { + if (initialize_client_stage2(&type, master, &usernum, buff, + (ArOptions_get_arStart(ao) == AR_OPTION_ENABLED) ? 0 : 1)) { + temp = 1; + } + } + } /* !reverse */ + else { + if (initialize_client_reverse_udp(&usernum, master, name, manage, ipfam, + (ArOptions_get_arStart(ao) == AR_OPTION_ENABLED) ? 0 : 1)) { + temp = 1; + } } - - initialize_client_stage2(&type, &master, &usernum, buff, 1); - } /* !reverse */ - else { - initialize_client_reverse_udp(&usernum, &master, name, manage, ipfam); - } - initialize_client_stage3(&contable, &master, usernum, &buflength, &len, &allset, &wset, &maxfdp1, 1); + if (temp == 0) { + if (initialize_client_stage3(&contable, master, usernum, &buflength, &len, &allset, &wset, &maxfdp1, + (ArOptions_get_arStart(ao) == AR_OPTION_ENABLED) ? 0 : 1)) { + temp = 1; + } + } - /* UDP REVERSE MODE */ - - if (reverse) { - client_reverse_udp(contable, &master, desnam, despor, type, buff, buflength); - } + /* UDP REVERSE MODE */ + + if ((temp == 0) && reverse) { + client_reverse_udp(contable, master, desnam, despor, type, buff, buflength); + } + + if (i > 0) { + --i; + } + if ((i != 0) && (temp == 1)) { + aflog(LOG_T_INIT, LOG_I_INFO, + "Trying to reconnect..."); + mysleep(ArOptions_get_arDelay(ao)); + } + if (temp == 0) { + break; + } + } while (i); /* NORMAL MODE */ @@ -453,7 +548,8 @@ main(int argc, char **argv) "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(LOG_T_CLIENT, LOG_I_NOTICE, - "CIPHER: %s VER: %s", SSL_get_cipher_name(master.ssl), SSL_get_cipher_version(master.ssl)); + "CIPHER: %s VER: %s", SSL_get_cipher_name(SslFd_get_ssl(master)), + SSL_get_cipher_version(SslFd_get_ssl(master))); #ifdef HAVE_LIBDL if (ismloaded(&module)) { aflog(LOG_T_CLIENT, LOG_I_INFO, @@ -471,7 +567,7 @@ main(int argc, char **argv) memcpy(&buff[5], id, n); buff[3] = n >> 8; /* high bits of message length */ buff[4] = n; /* low bits of message length */ - send_message(type, master, buff, n+5); + SslFd_send_message(type, master, buff, n+5); aflog(LOG_T_CLIENT, LOG_I_INFO, "ID SENT: %s", id); } @@ -486,8 +582,9 @@ main(int argc, char **argv) aflog(LOG_T_CLIENT, LOG_I_DEBUG, "timeout: sending keep-alive packet"); buff[0] = AF_S_KEEP_ALIVE; - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); keepalive.tv_sec = timeout; + keepalive.tv_usec = 0; } } else { @@ -497,11 +594,12 @@ main(int argc, char **argv) "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 */ + if ((ConnectUser_get_state(contable[i]) == S_STATE_OPEN) || + (ConnectUser_get_state(contable[i]) == S_STATE_STOPPED)) { + if (FD_ISSET(ConnectUser_get_connFd(contable[i]), &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */ aflog(LOG_T_USER, LOG_I_DDEBUG, "user[%d]: FD_ISSET", i); - n = read(contable[i].connfd, &buff[5], 8091); + n = read(ConnectUser_get_connFd(contable[i]), &buff[5], 8091); if (n == -1) { aflog(LOG_T_USER, LOG_I_ERR, "error (%d): while reading from service", n); @@ -509,14 +607,14 @@ main(int argc, char **argv) } #ifdef HAVE_LINUX_SOCKIOS_H # ifdef SIOCOUTQ - if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { + if (ioctl(SslFd_get_fd(master), SIOCOUTQ, ¬sent)) { aflog(LOG_T_USER, LOG_I_CRIT, "ioctl error -> exiting..."); exit(1); } if (udp) { len = 4; - if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (getsockopt(SslFd_get_fd(master), SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; aflog(LOG_T_USER, LOG_I_WARNING, @@ -553,7 +651,7 @@ main(int argc, char **argv) if (n) { #ifdef HAVE_LIBDL if (ismloaded(&secmodule)) { - switch ((temp2 = secmodule.filter(contable[i].namebuf, &buff[5], &n))) { + switch ((temp2 = secmodule.filter(ConnectUser_get_nameBuf(contable[i]), &buff[5], &n))) { case 1: case 4: { aflog(LOG_T_USER, LOG_I_WARNING, "user[%d] (by ser): PACKET IGNORED BY MODULE", i); @@ -568,15 +666,15 @@ main(int argc, char **argv) case 2: case 5: { 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); - contable[i].state = S_STATE_CLOSING; - freebuflist(&contable[i].head); + close(ConnectUser_get_connFd(contable[i])); + FD_CLR(ConnectUser_get_connFd(contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[i]), &wset); + ConnectUser_set_state(contable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(contable[i])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); if (temp2 == 5) { aflog(LOG_T_MAIN, LOG_I_INFO, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); @@ -612,74 +710,76 @@ main(int argc, char **argv) aflog(LOG_T_USER, LOG_I_DEBUG, "user[%d]: TO msglen: %d", i, n); #endif - send_message(type, master, buff, n+5); + SslFd_send_message(type, master, buff, n+5); } else if (!udp) { 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); - contable[i].state = S_STATE_CLOSING; - freebuflist(&contable[i].head); + close(ConnectUser_get_connFd(contable[i])); + FD_CLR(ConnectUser_get_connFd(contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[i]), &wset); + ConnectUser_set_state(contable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(contable[i])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } } /* - FD_ISSET CONTABLE[i].CONNFD RSET */ } } for (i = 0; i < usernum; ++i) { - if (contable[i].state == S_STATE_STOPPED) { - if (FD_ISSET(contable[i].connfd, &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */ + if (ConnectUser_get_state(contable[i]) == S_STATE_STOPPED) { + if (FD_ISSET(ConnectUser_get_connFd(contable[i]), &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */ 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); + n = BufListNode_readMessageLength(BufList_get_first(ConnectUser_get_bufList(contable[i]))); + temp2 = write(ConnectUser_get_connFd(contable[i]), + BufListNode_readMessage(BufList_get_first(ConnectUser_get_bufList(contable[i]))), n); if ((temp2 > 0) && (temp2 != n)) { - contable[i].head->actptr+=temp2; + BufListNode_set_actPtr(BufList_get_first(ConnectUser_get_bufList(contable[i])), + BufListNode_get_actPtr(BufList_get_first(ConnectUser_get_bufList(contable[i]))) + temp2); } else if ((temp2 == -1) && (errno == EAGAIN)) { aflog(LOG_T_USER, LOG_I_DEBUG, "user[%d]: Couldn't write?", i); } else if (temp2 == -1) { - close(contable[i].connfd); - FD_CLR(contable[i].connfd, &allset); - FD_CLR(contable[i].connfd, &wset); - contable[i].state = S_STATE_CLOSING; + close(ConnectUser_get_connFd(contable[i])); + FD_CLR(ConnectUser_get_connFd(contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[i]), &wset); + ConnectUser_set_state(contable[i], S_STATE_CLOSING); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } else { - deleteblnode(&contable[i].head); - if (contable[i].head == NULL) { - contable[i].state = S_STATE_OPEN; - FD_CLR(contable[i].connfd, &wset); + BufList_delete_first(ConnectUser_get_bufList(contable[i])); + if (BufList_get_first(ConnectUser_get_bufList(contable[i])) == NULL) { + ConnectUser_set_state(contable[i], S_STATE_OPEN); + FD_CLR(ConnectUser_get_state(contable[i]), &wset); buff[0] = AF_S_CAN_SEND; /* stopping transfer */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ aflog(LOG_T_USER, LOG_I_DDEBUG, "FROM user[%d]: BUFFERING MESSAGE ENDED", i); - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } } } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */ } } - if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + if (FD_ISSET(SslFd_get_fd(master), &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ aflog(LOG_T_CLIENT, LOG_I_DDEBUG, "masterfd: FD_ISSET"); - n = get_message(type, master, buff, 5); + n = SslFd_get_message(type, master, buff, 5); if (n != 5) { 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); + get_ssl_error(master, "FE", n); continue; /* what happened? */ } } @@ -687,37 +787,40 @@ main(int argc, char **argv) exit(1); } if (n == 0) { /* server quits -> we do the same... */ - i = tries; + i = ArOptions_get_arTries(ao); + if (ArOptions_get_arPremature(ao) == AR_OPTION_DISABLED) { + i = 0; + } 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); + SslFd_set_ssl(master, NULL); + mysleep(ArOptions_get_arDelay(ao)); 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, + if (initialize_client_stage1(tunneltype, master, name, manage, hpo, ipfam, ctx, buff, pass, 0, ignorepkeys)) { #else - if (initialize_client_stage1(tunneltype, &master, name, manage, NULL, NULL, + if (initialize_client_stage1(tunneltype, master, name, manage, NULL, ipfam, ctx, buff, pass, 0, ignorepkeys)) { #endif temp2 = 1; } } if (temp2 == 0) { - if (initialize_client_stage2(&type, &master, &usernum, buff, 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, + if (initialize_client_stage3(&contable, master, usernum, &buflength, &len, &allset, &wset, &maxfdp1, 0)) { temp2 = 1; } @@ -753,23 +856,24 @@ main(int argc, char **argv) "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; + if (ConnectUser_get_state(contable[numofcon]) == S_STATE_CLOSING) { + ConnectUser_set_state(contable[numofcon], S_STATE_CLEAR); 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)){ + else if ((ConnectUser_get_state(contable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(contable[numofcon]) == S_STATE_STOPPED)) { 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); - contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&contable[numofcon].head); + close(ConnectUser_get_connFd(contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &wset); + ConnectUser_set_state(contable[numofcon], S_STATE_CLEAR); + BufList_clear(ConnectUser_get_bufList(contable[numofcon])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } } break; @@ -779,23 +883,24 @@ main(int argc, char **argv) "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); + if (ConnectUser_get_state(contable[numofcon]) == S_STATE_CLEAR) { + n = SslFd_get_message(type, master, buff, length); + ConnectUser_set_nameBuf(contable[numofcon], (char*) buff); + ConnectUser_set_portBuf(contable[numofcon], (char*) &buff[128]); 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); + ConnectUser_get_nameBuf(contable[numofcon]), ConnectUser_get_portBuf(contable[numofcon])); #ifdef HAVE_LIBDL - if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) { + if (ismloaded(&module) && module.allow(ConnectUser_get_nameBuf(contable[numofcon]), + ConnectUser_get_portBuf(contable[numofcon]))) { aflog(LOG_T_USER, LOG_I_WARNING, - "IT'S NOT ALLOWED - DROPPING", numofcon); + "user[%d]: IT'S NOT ALLOWED - DROPPING", numofcon); buff[0] = AF_S_CANT_OPEN; /* not opening connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); usercon--; continue; } @@ -814,25 +919,27 @@ main(int argc, char **argv) ipfam |= 0x04; } #endif - if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) { + if (ip_connect(&temp, desnam, despor, ipfam)) { aflog(LOG_T_USER, LOG_I_WARNING, - "CAN'T OPEN - DROPPING", numofcon); + "user[%d]: CAN'T CONNECT to %s:%s - DROPPING", numofcon, desnam, despor); buff[0] = AF_S_CANT_OPEN; /* not opening connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); usercon--; continue; } - temp2 = fcntl(contable[numofcon].connfd, F_GETFL, 0); - fcntl(contable[numofcon].connfd, F_SETFL, temp2 | O_NONBLOCK); - FD_SET(contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1); + ConnectUser_set_connFd(contable[numofcon], temp); + temp2 = fcntl(ConnectUser_get_connFd(contable[numofcon]), F_GETFL, 0); + fcntl(ConnectUser_get_connFd(contable[numofcon]), F_SETFL, temp2 | O_NONBLOCK); + FD_SET(ConnectUser_get_connFd(contable[numofcon]), &allset); + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(contable[numofcon]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(contable[numofcon]) + 1); buff[0] = AF_S_CONOPEN; /* opening connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); - contable[numofcon].state = S_STATE_OPEN; + SslFd_send_message(type, master, buff, 5); + ConnectUser_set_state(contable[numofcon], S_STATE_OPEN); } } break; @@ -842,12 +949,12 @@ main(int argc, char **argv) "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); + n = SslFd_get_message(type, master, buff, length); if ((numofcon>=0) && (numofcon<=usernum)) { - if (contable[numofcon].state == S_STATE_OPEN) { + if (ConnectUser_get_state(contable[numofcon]) == S_STATE_OPEN) { #ifdef HAVE_LIBDL if (ismloaded(&module)) { - switch ((temp2 = module.filter(contable[numofcon].namebuf, buff, &n))) { + switch ((temp2 = module.filter(ConnectUser_get_nameBuf(contable[numofcon]), buff, &n))) { case 1: case 4:{ aflog(LOG_T_USER, LOG_I_WARNING, "user[%d]: PACKET IGNORED BY MODULE", numofcon); @@ -862,15 +969,15 @@ main(int argc, char **argv) case 2: case 5:{ 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); - contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&contable[numofcon].head); + close(ConnectUser_get_connFd(contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &wset); + ConnectUser_set_state(contable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(contable[numofcon])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); if (temp2 == 5) { aflog(LOG_T_MAIN, LOG_I_INFO, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); @@ -890,65 +997,121 @@ main(int argc, char **argv) #endif aflog(LOG_T_USER, LOG_I_DEBUG, "user[%d]: FROM msglen: %d SENT", numofcon, n); - temp2 = write(contable[numofcon].connfd, buff, n); + temp2 = write(ConnectUser_get_connFd(contable[numofcon]), buff, n); if ((temp2 > 0) && (temp2 != n)) { - insertblnode(&(contable[numofcon].head), temp2, n, buff); - contable[numofcon].state = S_STATE_STOPPED; - FD_SET(contable[numofcon].connfd, &wset); + BufList_insert_back(ConnectUser_get_bufList(contable[numofcon]), + BufListNode_new_message(temp2, n, buff)); + ConnectUser_set_state(contable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(contable[numofcon]), &wset); buff[0] = AF_S_DONT_SEND; /* stopping transfer */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ aflog(LOG_T_USER, LOG_I_DDEBUG, "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } else if ((temp2 == -1) && (errno == EAGAIN)) { - insertblnode(&(contable[numofcon].head), 0, n, buff); - contable[numofcon].state = S_STATE_STOPPED; - FD_SET(contable[numofcon].connfd, &wset); + BufList_insert_back(ConnectUser_get_bufList(contable[numofcon]), + BufListNode_new_message(0, n, buff)); + ConnectUser_set_state(contable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(contable[numofcon]), &wset); buff[0] = AF_S_DONT_SEND; /* stopping transfer */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ aflog(LOG_T_USER, LOG_I_DDEBUG, "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } else if (temp2 == -1) { - close(contable[numofcon].connfd); - FD_CLR(contable[numofcon].connfd, &allset); - FD_CLR(contable[numofcon].connfd, &wset); - contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&contable[numofcon].head); + close(ConnectUser_get_connFd(contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &wset); + ConnectUser_set_state(contable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(contable[numofcon])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - send_message(type, master, buff, 5); + SslFd_send_message(type, master, buff, 5); } } - else if (contable[numofcon].state == S_STATE_STOPPED) { + else if (ConnectUser_get_state(contable[numofcon]) == S_STATE_STOPPED) { aflog(LOG_T_USER, LOG_I_DDEBUG, "FROM user[%d]: BUFFERING MESSAGE", numofcon); - insertblnode(&(contable[numofcon].head), 0, n, buff); + BufList_insert_back(ConnectUser_get_bufList(contable[numofcon]), + BufListNode_new_message(0, n, buff)); } } break; } - case AF_S_CLOSING : { /* server shut down -> exiting... */ - aflog(LOG_T_CLIENT, LOG_I_INFO, - "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); - exit(1); + case AF_S_CLOSING : { /* server shut down */ + n = 0; + i = ArOptions_get_arTries(ao); + if (ArOptions_get_arQuit(ao) == AR_OPTION_DISABLED) { + i = 0; + } + if (i) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: CLOSED -> auto-reconnect enabled"); + } + while (i) { + close_connections(usernum, &contable); + SslFd_set_ssl(master, NULL); + mysleep(ArOptions_get_arDelay(ao)); + 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, hpo, + ipfam, ctx, buff, pass, 0, ignorepkeys)) { +#else + if (initialize_client_stage1(tunneltype, master, name, manage, NULL, + ipfam, ctx, buff, pass, 0, ignorepkeys)) { +#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_INFO, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + exit(1); + } break; } case AF_S_DONT_SEND: { aflog(LOG_T_USER, LOG_I_DEBUG, "user[%d]: AF_S_DONT_SEND", numofcon); - FD_CLR(contable[numofcon].connfd, &allset); + FD_CLR(ConnectUser_get_connFd(contable[numofcon]), &allset); break; } case AF_S_CAN_SEND: { aflog(LOG_T_USER, LOG_I_DEBUG, "user[%d]: AF_S_CAN_SEND", numofcon); - FD_SET(contable[numofcon].connfd, &allset); + FD_SET(ConnectUser_get_connFd(contable[numofcon]), &allset); break; } default : { /* unrecognized type of message -> exiting... */ diff --git a/src/afclient.h b/src/afclient.h index 156b408..57a9f7c 100644 --- a/src/afclient.h +++ b/src/afclient.h @@ -22,7 +22,7 @@ #include "network.h" #include "stats.h" #include "modules.h" -#include "remoteadmin.h" +#include "client_remoteadmin.h" #include "make_ssl_handshake.h" #include "first_run.h" #include "http_proxy_client.h" @@ -31,12 +31,14 @@ #include "server_check.h" #include "client_initialization.h" #include "http_proxy_functions.h" +#include "http_proxy_options_struct.h" #include "client_shutdown.h" #include "client_signals.h" #include "usage.h" #include "logging.h" -#include "audit.h" +#include "audit_list_struct.h" #include "daemon.h" +#include "ar_options_struct.h" #include #include diff --git a/src/afserver.c b/src/afserver.c index 2361ebe..1066176 100644 --- a/src/afserver.c +++ b/src/afserver.c @@ -53,6 +53,9 @@ static struct option long_options[] = { {"dateformat", 1, 0, 'D'}, #ifdef HAVE_LIBPTHREAD {"enableproxy", 0, 0, 'P'}, + /* FIXME: don't need it now + {"use-https", 0, 0, 'S'}, + */ #endif {"version", 0, 0, 'V'}, {0, 0, 0, 0} @@ -63,7 +66,7 @@ ConfigurationT config; int main(int argc, char **argv) { - int i, j=0, k, l, n, flags, sent = 0; + int i, j=0, k, l, n, flags, sent = 0, temp; socklen_t len; unsigned char buff[9000]; int maxfdp1; @@ -134,162 +137,178 @@ main(int argc, char **argv) #define GETOPT_LONG_AF_INET6(x) x #endif #ifdef HAVE_LIBPTHREAD +/* FIXME: 'S' option is not needed now +#define GETOPT_LONG_LIBPTHREAD(x) "PS"x +*/ #define GETOPT_LONG_LIBPTHREAD(x) "P"x #else #define GETOPT_LONG_LIBPTHREAD(x) x #endif - while ((n = getopt_long(argc, argv, + 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': { - server_long_usage(AF_VER("Active port forwarder (server)")); - break; - } - case 'n': { - name = optarg; - break; - } - case 'l': { - ++listencount; - listen = realloc(listen, sizeof(char*)); - listen[listencount-1] = optarg; - break; - } - case 'm': { - ++managecount; - manage = realloc(manage, sizeof(char*)); - manage[managecount-1] = optarg; - break; - } - case 't': { - timeout = optarg; - break; - } - case 'v': { - ++verbose; - break; - } - case 'u': { - amount = optarg; - break; - } - case 'C': { - clients = optarg; - break; - } + switch (n) { + case 'h': { + server_long_usage(AF_VER("Active port forwarder (server)")); + break; + } + case 'n': { + name = optarg; + break; + } + case 'l': { + ++listencount; + listen = realloc(listen, sizeof(char*)); + listen[listencount-1] = optarg; + break; + } + case 'm': { + ++managecount; + manage = realloc(manage, sizeof(char*)); + manage[managecount-1] = optarg; + break; + } + case 't': { + timeout = optarg; + break; + } + case 'v': { + ++verbose; + break; + } + case 'u': { + amount = optarg; + break; + } + case 'C': { + clients = optarg; + break; + } case 'r': { - realmname = optarg; - break; - } - case 'R': { - raclients = optarg; - break; - } - case 'U': { - usrpcli = optarg; - break; - } - case 'M': { - clim = optarg; - break; - } - case 'c': { - certif = optarg; - break; - } - case 'k': { - keys = optarg; - break; - } - case 'p': { - type = optarg; - break; - } - case 'f': { - filenam = optarg; - break; - } - case 'o': { - addlogtarget(optarg); - break; - } - case 301: { - TYPE_UNSET_SSL(mode); - break; - } - case 302: { - TYPE_UNSET_ZLIB(mode); - break; - } + realmname = optarg; + break; + } + case 'R': { + raclients = optarg; + break; + } + case 'U': { + usrpcli = optarg; + break; + } + case 'M': { + clim = optarg; + break; + } + case 'c': { + certif = optarg; + break; + } + case 'k': { + keys = optarg; + break; + } + case 'p': { + type = optarg; + break; + } + case 'f': { + filenam = optarg; + break; + } + case 'o': { + addlogtarget(optarg); + break; + } + case 301: { + TYPE_UNSET_SSL(mode); + break; + } + case 302: { + TYPE_UNSET_ZLIB(mode); + break; + } case 303: { - n = strlen(optarg); - memset(pass, 0, 4); - for (i = 0; i < n; ++i) { - pass[i%4] += optarg[i]; - } - sent = 1; - break; - } + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + sent = 1; + break; + } #ifdef AF_INET6 - case '4': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 4; - } - break; - } - case '6': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 6; - } - break; - } + case '4': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 4; + } + break; + } + case '6': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 6; + } + break; + } #endif case 'b': { - baseport = 1; - break; - } + baseport = 1; + break; + } case 'a': { - audit = 1; - break; - } + audit = 1; + break; + } case 311: { - dnslookups = 1; - break; - } - case 'D': { - dateformat = optarg; - break; - } + dnslookups = 1; + break; + } + case 'D': { + dateformat = optarg; + break; + } #ifdef HAVE_LIBPTHREAD - case 'P': { - if (tunneltype != 0) { - tunneltype = -1; - } - else { - tunneltype = 1; - } - break; - } + case 'P': { + if ((tunneltype < 0) || (tunneltype > 2)) { + tunneltype = -1; + } + else { + if (tunneltype != 2) { + tunneltype = 1; + } + } + break; + } + /* FIXME: don't need it now + case 'S': { + if ((tunneltype < 0) || (tunneltype > 2)) { + tunneltype = -1; + } + else { + tunneltype = 2; + } + break; + } + */ #endif - case 'V': { - printf("%s\n", (AF_VER("Active port forwarder (server)"))); - exit(0); - break; - } - case '?': { - server_short_usage(""); - break; - } - } - } + case 'V': { + printf("%s\n", (AF_VER("Active port forwarder (server)"))); + exit(0); + break; + } + case '?': { + server_short_usage(""); + break; + } + } + } if (optind < argc) { server_short_usage("Unrecognized non-option elements"); @@ -374,10 +393,16 @@ main(int argc, char **argv) config.realmtable = calloc(config.size, sizeof(RealmT)); config.realmtable[0].hostname = name; config.realmtable[0].usrclinum = managecount; - config.realmtable[0].usrclitable = calloc(managecount, sizeof(UsrCliT)); + config.realmtable[0].usrclitable = calloc(managecount, sizeof(UsrCli*)); for (i = 0; i < config.realmtable[0].usrclinum; ++i) { - config.realmtable[0].usrclitable[i].lisportnum = listen[i]; - config.realmtable[0].usrclitable[i].manportnum = manage[i]; + config.realmtable[0].usrclitable[i] = UsrCli_new(); + if (config.realmtable[0].usrclitable[i] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with allocating memory for UsrCli structure... exiting"); + exit(1); + } + UsrCli_set_listenPortName(config.realmtable[0].usrclitable[i], listen[i]); + UsrCli_set_managePortName(config.realmtable[0].usrclitable[i], manage[i]); } config.realmtable[0].users = amount; config.realmtable[0].clients = clients; @@ -473,12 +498,12 @@ main(int argc, char **argv) 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)) { + if ((UsrCli_get_listenPortName(config.realmtable[i].usrclitable[j]) == NULL) || + (UsrCli_get_managePortName(config.realmtable[i].usrclitable[j]) == NULL)) { 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); + i, j, UsrCli_get_listenPortName(config.realmtable[i].usrclitable[j]), + j, UsrCli_get_managePortName(config.realmtable[i].usrclitable[j])); exit(1); } } @@ -564,24 +589,48 @@ main(int argc, char **argv) set_value(&(config.realmtable[i].clim), clim, "1"); check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value"); /* allocating memory*/ - config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT)); + config.realmtable[i].contable = calloc(config.realmtable[i].usernum, sizeof(ConnectUser)); if (config.realmtable[i].contable == NULL) { 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)); + for (j = 0; j < config.realmtable[i].usernum; ++j) { + config.realmtable[i].contable[j] = ConnectUser_new(); + if (config.realmtable[i].contable[j] == NULL) { + 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(ConnectClient)); if (config.realmtable[i].clitable == NULL) { 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)); + for (j = 0; j < config.realmtable[i].clinum; ++j) { + config.realmtable[i].clitable[j] = ConnectClient_new(); + if (config.realmtable[i].clitable[j] == NULL) { + 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(ConnectClient)); if (config.realmtable[i].raclitable == NULL) { aflog(LOG_T_INIT, LOG_I_CRIT, "Calloc error - try define smaller amount of raclients"); exit(1); } + for (j = 0; j < config.realmtable[i].raclinum; ++j) { + config.realmtable[i].raclitable[j] = ConnectClient_new(); + if (config.realmtable[i].raclitable[j] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of raclients"); + exit(1); + } + } ipfam = 0x01; #ifdef AF_INET6 if (TYPE_IS_IPV4(config.realmtable[i].type)) { @@ -593,60 +642,85 @@ main(int argc, char **argv) #endif if (config.realmtable[i].baseport == 0) { for (j = 0; j < config.realmtable[i].usrclinum; ++j) { - if (ip_listen(&(config.realmtable[i].usrclitable[j].listenfd), config.realmtable[i].hostname, - config.realmtable[i].usrclitable[j].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) { + if (ip_listen(&temp, UsrCli_get_listenHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_listenHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_listenPortName(config.realmtable[i].usrclitable[j]), + (&(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].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); + UsrCli_get_listenHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_listenHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_listenPortName(config.realmtable[i].usrclitable[j])); + exit(1); + } + UsrCli_set_listenFd(config.realmtable[i].usrclitable[j], temp); + flags = fcntl(UsrCli_get_listenFd(config.realmtable[i].usrclitable[j]), F_GETFL, 0); + fcntl(UsrCli_get_listenFd(config.realmtable[i].usrclitable[j]), F_SETFL, flags | O_NONBLOCK); } } for (j = 0; j < config.realmtable[i].usrclinum; ++j) { 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, + if (ip_listen(&temp, UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_managePortName(config.realmtable[i].usrclitable[j]), + (&(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); - } - flags = fcntl(config.realmtable[i].usrclitable[j].managefd, F_GETFL, 0); - fcntl(config.realmtable[i].usrclitable[j].managefd, F_SETFL, flags | O_NONBLOCK); - break; + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_managePortName(config.realmtable[i].usrclitable[j])); + exit(1); + } + UsrCli_set_manageFd(config.realmtable[i].usrclitable[j], temp); + flags = fcntl(UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]), F_GETFL, 0); + fcntl(UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]), 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, + case 1: case 2: { + if (initialize_http_proxy_server(&temp, + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_managePortName(config.realmtable[i].usrclitable[j]), + (&(config.realmtable[i].addrlen)), ipfam, + config.realmtable[i].clinum + config.realmtable[i].raclinum, + (config.realmtable[i].tunneltype - 1), + ctx)) { + 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", + "http%s_proxy_listen_%s error for %s, %s", + (config.realmtable[i].tunneltype == 2) ? "s" : "", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", #else - "http_proxy_listen error for %s, %s", + "http%s_proxy_listen error for %s, %s", + (config.realmtable[i].tunneltype == 2) ? "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; + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) ? + UsrCli_get_manageHostName(config.realmtable[i].usrclitable[j]) : + config.realmtable[i].hostname, + UsrCli_get_managePortName(config.realmtable[i].usrclitable[j])); + exit(1); + } + UsrCli_set_manageFd(config.realmtable[i].usrclitable[j], temp); + flags = fcntl(UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]), F_GETFL, 0); + fcntl(UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]), F_SETFL, flags | O_NONBLOCK); + break; } #endif default: { @@ -660,8 +734,8 @@ main(int argc, char **argv) config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); for (j=0; j (config.realmtable[i].usrclitable[j].managefd+1)) ? - maxfdp1 : (config.realmtable[i].usrclitable[j].managefd+1); + FD_SET(UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]), &allset); + maxfdp1 = (maxfdp1 > (UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]) + 1)) ? + maxfdp1 : (UsrCli_get_manageFd(config.realmtable[i].usrclitable[j]) + 1); } if (config.realmtable[i].baseport == 0) { for (j = 0; j < config.realmtable[i].usrclinum; ++j) { - FD_SET(config.realmtable[i].usrclitable[j].listenfd, &allset); - maxfdp1 = (maxfdp1 > (config.realmtable[i].usrclitable[j].listenfd+1)) ? - maxfdp1 : (config.realmtable[i].usrclitable[j].listenfd+1); + FD_SET(UsrCli_get_listenFd(config.realmtable[i].usrclitable[j]), &allset); + maxfdp1 = (maxfdp1 > (UsrCli_get_listenFd(config.realmtable[i].usrclitable[j]) + 1)) ? + maxfdp1 : (UsrCli_get_listenFd(config.realmtable[i].usrclitable[j]) + 1); } } config.realmtable[i].usercon = 0; config.realmtable[i].clicon = 0; config.realmtable[i].raclicon = 0; for (j=0; jusernum; ++i) { - if ((pointer->contable[i].state == S_STATE_OPEN) || (pointer->contable[i].state == S_STATE_STOPPED)) - if (FD_ISSET(pointer->contable[i].connfd, &rset)) { - k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); - aflog(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; + for (j = 0; j < config.size; ++j) { + pointer = (&(config.realmtable[j])); + for (i = 0; i usernum; ++i) { + if ((ConnectUser_get_state(pointer->contable[i]) == S_STATE_OPEN) || + (ConnectUser_get_state(pointer->contable[i]) == S_STATE_STOPPED)) + if (FD_ISSET(ConnectUser_get_connFd(pointer->contable[i]), &rset)) { + k = eval_usernum(pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])], i); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer,i)); + if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ + n = read(ConnectUser_get_connFd(pointer->contable[i]), &buff[5], 8091); + if (n == -1) { + if (errno == EAGAIN) { + continue; + } + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), errno); + n = 0; } - 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(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(LOG_T_USER, LOG_I_WARNING, - "WARNING: got packet similiar to udp"); + if (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, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), n); + UserStats_add_upload(ConnectUser_get_stats(pointer->contable[i]), n); + if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { + 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 */ + buff[2] = k; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, n+5); } - buff[0] = AF_S_MESSAGE; /* sending message */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5); - } - else { - aflog(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), + else { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + 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, ConnectUser_get_whatClient(pointer->contable[i])), get_username(pointer, i), - pointer->contable[i].namebuf, - pointer->contable[i].portbuf, - pointer->contable[i].connecttime, - now - pointer->contable[i].connecttime); + ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[i]))); + if (pointer->audit) { + AuditList_insert_back( + ConnectClient_get_auditList( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + AuditListNode_new_entry( + get_username(pointer, i), + ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), + ConnectUser_get_connectTime(pointer->contable[i]), + now - ConnectUser_get_connectTime(pointer->contable[i])) + ); + } + close(ConnectUser_get_connFd(pointer->contable[i])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &wset); + ConnectUser_set_state(pointer->contable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(pointer->contable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, 5); } - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - else { /* when forwarding udp packets */ - n = readn(pointer->contable[i].connfd, buff, 5 ); - if (n != 5) { - n = 0; } - if (n) { - if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { - aflog(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); - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, - buff, n+5); + else { /* when forwarding udp packets */ + n = readn(ConnectUser_get_connFd(pointer->contable[i]), buff, 5 ); + if (n != 5) { + n = 0; + } + if (n) { + if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + if ((n = readn(ConnectUser_get_connFd(pointer->contable[i]), &buff[5], length)) != 0) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", + get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), n); + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, n+5); + } + } + else { + n = 0; } } - else { - n = 0; + + if (n == 0) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(&config, j), + get_clientname(pointer, + ConnectUser_get_whatClient(pointer->contable[i])), 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, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), + ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[i]))); + close(ConnectUser_get_connFd(pointer->contable[i])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &wset); + ConnectUser_set_state(pointer->contable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(pointer->contable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, 5); } + } - - if (n == 0) { + } + } + /* ------------------------------------ */ + for (i = 0; i usernum; ++i) { + if (ConnectUser_get_state(pointer->contable[i]) == S_STATE_STOPPED) + if (FD_ISSET(ConnectUser_get_connFd(pointer->contable[i]), &tmpset)) { + k = eval_usernum(pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])], i); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i)); + n = BufListNode_readMessageLength(BufList_get_first(ConnectUser_get_bufList(pointer->contable[i]))); + sent = write(ConnectUser_get_connFd(pointer->contable[i]), + BufListNode_readMessage(BufList_get_first(ConnectUser_get_bufList(pointer->contable[i]))), n); + if ((sent > 0) && (sent != n)) { + BufListNode_set_actPtr(BufList_get_first(ConnectUser_get_bufList(pointer->contable[i])), + BufListNode_get_actPtr(BufList_get_first(ConnectUser_get_bufList(pointer->contable[i]))) + sent); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), sent, n); + } + else if ((sent == -1) && (errno == EAGAIN)) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i)); + } + else if (sent == -1) { 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)); + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + 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_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), 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); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); + ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[i]))); + close(ConnectUser_get_connFd(pointer->contable[i])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &wset); + ConnectUser_set_state(pointer->contable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(pointer->contable[i])); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = k >> 8; /* high bits of user number */ buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - - } - } - } - /* ------------------------------------ */ - for (i = 0; i usernum; ++i) { - if (pointer->contable[i].state == S_STATE_STOPPED) - if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { - k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); - aflog(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(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(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(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); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - else { - aflog(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; - FD_CLR(pointer->contable[i].connfd, &wset); - buff[0] = AF_S_CAN_SEND; /* stopping transfer */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - aflog(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, i)); - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - } - } - /* ------------------------------------ */ - if (pointer->baseport == 0) { - for (l = 0; l < pointer->usrclinum; ++l) { - if (FD_ISSET(pointer->usrclitable[l].listenfd, &rset)) { - len = pointer->addrlen; - sent = accept(pointer->usrclitable[l].listenfd, pointer->cliaddr, &len); - if (sent == -1) { - if (errno == EAGAIN) { - aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, 5); } else { aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); - } - continue; - } - flags = fcntl(sent, F_GETFL, 0); - fcntl(sent, F_SETFL, flags | O_NONBLOCK); - 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(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(LOG_T_USER, LOG_I_WARNING, - "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", - get_realmname(&config, j), get_clientname(pointer, k)); - } - else { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state == S_STATE_CLEAR) { - pointer->contable[i].userid = pointer->usercounter; - ++(pointer->usercounter); - aflog(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; - pointer->contable[i].state = S_STATE_OPENING; - pointer->contable[i].whatcli = k; - time(&pointer->contable[i].connecttime); - pointer->usercon++; - pointer->clitable[k].usercon++; - memcpy(&buff[5], pointer->contable[i].namebuf, 128); - memcpy(&buff[133], pointer->contable[i].portbuf, 7); - n = 135; - i = find_usernum(&(pointer->clitable[k]), i); - buff[0] = AF_S_CONOPEN; /* opening connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); - break; - } + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i), sent, n); + BufList_delete_first(ConnectUser_get_bufList(pointer->contable[i])); + if (BufList_get_first(ConnectUser_get_bufList(pointer->contable[i])) == NULL) { + ConnectUser_set_state(pointer->contable[i], S_STATE_OPEN); + FD_CLR(ConnectUser_get_connFd(pointer->contable[i]), &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: TO user[%d]: BUFFERING MESSAGE ENDED", + get_realmname(&config, j), + get_clientname(pointer, ConnectUser_get_whatClient(pointer->contable[i])), + get_username(pointer, i)); + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[ConnectUser_get_whatClient(pointer->contable[i])]), + buff, 5); } } } - else { - close(sent); - aflog(LOG_T_USER, LOG_I_ERR, - "realm[%s]: Client(%d) is NOT CONNECTED", - get_realmname(&config, j), k); - } - } - } - } - /* ------------------------------------ */ - if (pointer->baseport == 1) - for (k = 0; k < pointer->clinum; ++k) - if (pointer->clitable[k].ready == 3) /* Command file descriptor */ - if (FD_ISSET(pointer->clitable[k].listenfd, &rset)) { - len = pointer->addrlen; - sent = accept(pointer->clitable[k].listenfd, pointer->cliaddr, &len); - if (sent == -1) { - if (errno == EAGAIN) { - aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); - } - else { - aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); - } - continue; - } - flags = fcntl(sent, F_GETFL, 0); - fcntl(sent, F_SETFL, flags | O_NONBLOCK); - 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(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(LOG_T_USER, LOG_I_WARNING, - "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", - get_realmname(&config, j), get_clientname(pointer, k)); - } - else { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state == S_STATE_CLEAR) { - pointer->contable[i].userid = pointer->usercounter; - ++(pointer->usercounter); - aflog(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; - pointer->contable[i].state = S_STATE_OPENING; - pointer->contable[i].whatcli = k; - time(&pointer->contable[i].connecttime); - pointer->usercon++; - pointer->clitable[k].usercon++; - memcpy(&buff[5], pointer->contable[i].namebuf, 128); - memcpy(&buff[133], pointer->contable[i].portbuf, 7); - n = 135; - i = find_usernum(&(pointer->clitable[k]), i); - buff[0] = AF_S_CONOPEN; /* opening connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); - break; - } - } - } - } - } - /* ------------------------------------ */ - for (k = 0; k < pointer->clinum; ++k) - if ((pointer->clitable[k].ready != 0) && (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset))) { - if (pointer->clitable[k].ready == 1) { - make_ssl_initialize(&(pointer->clitable[k].cliconn)); - aflog(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: { - close (pointer->clitable[k].cliconn.commfd); - FD_CLR(pointer->clitable[k].cliconn.commfd, &allset); - SSL_clear(pointer->clitable[k].cliconn.ssl); - pointer->clitable[k].ready = 0; - manconnecting--; - pointer->clicon--; - aflog(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(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(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); - } - else { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5); - } - if (n == -1) { - if (errno == 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(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(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) { - 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; - } - - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - - if ((k == pointer->clinum) && (buff[0] != AF_S_LOGIN) && - (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) { - buff[0] = AF_S_WRONG; } - if (pointer->clitable[k].ready<2) { - aflog(LOG_T_CLIENT, LOG_I_WARNING, - "realm[%s]: Client[%s]: Impossible behaviour --> ignoring", - get_realmname(&config, j), get_clientname(pointer, k)); - continue; - } - if ((pointer->clitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { - buff[0] = AF_S_WRONG; - } - - switch (buff[0]) { - case AF_S_CONCLOSED : { - n = numofcon; - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - pointer->usercon--; - pointer->clitable[k].usercon--; - pointer->clitable[k].users[n] = -1; - if (pointer->contable[numofcon].state == S_STATE_CLOSING) { - pointer->contable[numofcon].state = S_STATE_CLEAR; - aflog(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(LOG_T_USER, LOG_I_INFO, - "realm[%s]: user[%d]: KICKED", - get_realmname(&config, j), get_username(pointer, numofcon)); - 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); - pointer->contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CONOPEN : { - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(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)) ? - maxfdp1 : (pointer->contable[numofcon].connfd+1); - pointer->contable[numofcon].state = S_STATE_OPEN; - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CANT_OPEN : { - n = numofcon; - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(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--; - pointer->clitable[k].users[n] = -1; - close(pointer->contable[numofcon].connfd); - pointer->contable[numofcon].state = S_STATE_CLEAR; - } + /* ------------------------------------ */ + if (pointer->baseport == 0) { + for (l = 0; l < pointer->usrclinum; ++l) { + if (FD_ISSET(UsrCli_get_listenFd(pointer->usrclitable[l]), &rset)) { + len = pointer->addrlen; + sent = accept(UsrCli_get_listenFd(pointer->usrclitable[l]), pointer->cliaddr, &len); + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); } else { - remove_client(pointer, k, &allset, &wset, &manconnecting); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); } - break; - } - case AF_S_MESSAGE : { - if ((pointer->clitable[k].ready) != 3) { - remove_client(pointer, k, &allset, &wset, &manconnecting); - break; + continue; + } + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET", get_realmname(&config, j)); + k = find_client(pointer, pointer->climode, l); + if (ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_ACCEPTED) { + if (pointer->usercon == pointer->usernum) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: user limit EXCEEDED", get_realmname(&config, j)); } - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - n = get_message(pointer->type, pointer->clitable[k].cliconn, &buff[5], length); + else if (ConnectClient_get_connected(pointer->clitable[k]) == + ConnectClient_get_limit(pointer->clitable[k])) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", + get_realmname(&config, j), get_clientname(pointer, k)); } else { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); - } - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum))) { - if (pointer->contable[numofcon].state == S_STATE_OPEN) { - aflog(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; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - sent = write(pointer->contable[numofcon].connfd, buff, n+5); - if (sent == -1) { - aflog(LOG_T_USER, LOG_I_INFO, - "realm[%s]: user[%d]: CLOSED (write-udp)", - get_realmname(&config, j), get_username(pointer, numofcon)); - 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); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { /* tcp */ - sent = write(pointer->contable[numofcon].connfd, buff, n); - if ((sent > 0) && (sent != n)) { - insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(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) && (errno == EAGAIN)) { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(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(LOG_T_USER, LOG_I_INFO, - "realm[%s]: user[%d]: CLOSED (write-tcp)", - get_realmname(&config, j), get_username(pointer, numofcon)); - 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); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - } - else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { - aflog(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; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); - } - else { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + for (i = 0; i < pointer->usernum; ++i) { + if (ConnectUser_get_state(pointer->contable[i]) == S_STATE_CLEAR) { + ConnectUser_set_userId(pointer->contable[i], pointer->usercounter); + ++(pointer->usercounter); + 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, ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), pointer->dnslookups)); + ConnectUser_set_connFd(pointer->contable[i], sent); + ConnectUser_set_state(pointer->contable[i], S_STATE_OPENING); + ConnectUser_set_whatClient(pointer->contable[i], k); + time(&now); + ConnectUser_set_connectTime(pointer->contable[i], now); + UserStats_clear(ConnectUser_get_stats(pointer->contable[i])); + UserStats_set_lastActivity(ConnectUser_get_stats(pointer->contable[i]), now); + pointer->usercon++; + ConnectClient_increase_connected(pointer->clitable[k]); + memcpy(&buff[5], ConnectUser_get_nameBuf(pointer->contable[i]), 128); + memcpy(&buff[133], ConnectUser_get_portBuf(pointer->contable[i]), 7); + n = 135; + i = find_usernum(pointer->clitable[k], i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, n+5); + break; } } - else if (pointer->contable[numofcon].state == S_STATE_CLOSING) { - 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); - } } - break; - } - case AF_S_LOGIN : { - if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && - (length==(pointer->pass[2]*256+pointer->pass[3]))) { - if (k != pointer->clinum) { - pointer->clitable[k].ready = 3; - aflog(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 */ - buff[2] = pointer->clitable[k].usernum; /* low bits of user number */ - buff[3] = pointer->type; /* type of connection */ - send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, 5); - manconnecting--; - if (pointer->baseport == 1) { - long tmp_val; - char tmp_tab[6]; - if (check_long(pointer->usrclitable[pointer->clitable[k].whatusrcli].lisportnum, &tmp_val)) { - aflog(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; - } - tmp_val = tmp_val%65536; - memset(tmp_tab, 0, 6); - sprintf(tmp_tab, "%d", (int)tmp_val); - ipfam = 0x01; -#ifdef AF_INET6 - if (TYPE_IS_IPV4(pointer->type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(pointer->type)) { - ipfam |= 0x04; - } -#endif - while (ip_listen(&(pointer->clitable[k].listenfd), pointer->hostname, - tmp_tab, (&(pointer->addrlen)), ipfam)) { - tmp_val = (tmp_val+1)%65536; - memset(tmp_tab, 0, 6); - sprintf(tmp_tab, "%d", (int)tmp_val); - } - FD_SET(pointer->clitable[k].listenfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->clitable[k].listenfd+1)) ? - maxfdp1 : (pointer->clitable[k].listenfd+1); - aflog(LOG_T_CLIENT, LOG_I_INFO, - "realm[%s]: Client[%s]: listenport=%s", - get_realmname(&config, j), get_clientname(pointer, k), tmp_tab); - } + } + else { + close(sent); + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client(%d) is NOT CONNECTED", + get_realmname(&config, j), k); + } + } + } + } + /* ------------------------------------ */ + if (pointer->baseport == 1) { + for (k = 0; k < pointer->clinum; ++k) { + if (ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_ACCEPTED) { + if (FD_ISSET(ConnectClient_get_listenFd(pointer->clitable[k]), &rset)) { + len = pointer->addrlen; + sent = accept(ConnectClient_get_listenFd(pointer->clitable[k]), pointer->cliaddr, &len); + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); } else { - 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); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); } + continue; } - else if ((pointer->clitable[k].ready == 3) && (numofcon == 0)) { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); - buff[n] = 0; - 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); - } - pointer->clitable[k].clientid = malloc(n+1); - if (pointer->clitable[k].clientid) { - memcpy(pointer->clitable[k].clientid, buff, n+1); - } + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: listenfd: FD_ISSET", + get_realmname(&config, j), get_clientname(pointer, k)); + if (pointer->usercon == pointer->usernum) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: user limit EXCEEDED", get_realmname(&config, j)); } - else { - aflog(LOG_T_CLIENT, LOG_I_ERR, - "realm[%s]: Client[%s]: Wrong password - CLOSING", + else if(ConnectClient_get_connected(pointer->clitable[k]) == + ConnectClient_get_limit(pointer->clitable[k])) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", 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(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(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(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; - } - 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(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); - tmp_ssl = pointer->raclitable[l].cliconn.ssl; - pointer->raclitable[l].cliconn.ssl = pointer->clitable[k].cliconn.ssl; - pointer->clitable[k].cliconn.ssl = tmp_ssl; - pointer->clitable[k].ready = 0; + else { + for (i = 0; i < pointer->usernum; ++i) { + if (ConnectUser_get_state(pointer->contable[i]) == S_STATE_CLEAR) { + ConnectUser_set_userId(pointer->contable[i], pointer->usercounter); + ++(pointer->usercounter); + 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, + ConnectUser_get_nameBuf(pointer->contable[i]), + ConnectUser_get_portBuf(pointer->contable[i]), pointer->dnslookups)); + ConnectUser_set_connFd(pointer->contable[i], sent); + ConnectUser_set_state(pointer->contable[i], S_STATE_OPENING); + ConnectUser_set_whatClient(pointer->contable[i], k); + time(&now); + ConnectUser_set_connectTime(pointer->contable[i], now); + UserStats_clear(ConnectUser_get_stats(pointer->contable[i])); + UserStats_set_lastActivity(ConnectUser_get_stats(pointer->contable[i]), now); + pointer->usercon++; + ConnectClient_increase_connected(pointer->clitable[k]); + memcpy(&buff[5], ConnectUser_get_nameBuf(pointer->contable[i]), 128); + memcpy(&buff[133], ConnectUser_get_portBuf(pointer->contable[i]), 7); + n = 135; + i = find_usernum(pointer->clitable[k], i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, n+5); break; } } - if (l != pointer->raclinum) { - pointer->raclitable[l].ready = 3; - pointer->raclicon++; - manconnecting--; - sprintf((char*) &buff[5], AF_VER("AFSERVER")); - n = strlen((char*) &buff[5]); - buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ - buff[1] = pointer->type; /* type of connection */ - buff[2] = AF_RA_UNDEFINED; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type | TYPE_SSL, pointer->raclitable[l].cliconn, buff, n+5); - } - else { - aflog(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); - remove_client(pointer, k, &allset, &wset, &manconnecting); - } } - 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(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); - } - } - } - /* ------------------------------------ */ - for (k = 0; k < pointer->raclinum; ++k) - if ((pointer->raclitable[k].ready != 0) && (FD_ISSET(pointer->raclitable[k].cliconn.commfd, &rset))) { - if (pointer->raclitable[k].ready == 1) { - make_ssl_initialize(&(pointer->raclitable[k].cliconn)); - aflog(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: { - close (pointer->raclitable[k].cliconn.commfd); - FD_CLR(pointer->raclitable[k].cliconn.commfd, &allset); - SSL_clear(pointer->raclitable[k].cliconn.ssl); - pointer->raclitable[k].ready = 0; - manconnecting--; - pointer->clicon--; - aflog(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(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(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(LOG_T_MANAGE, LOG_I_DDEBUG, - "realm[%s]: Client[%s] (ra): commfd: EAGAIN", - get_realmname(&config, j), get_raclientname(pointer, k)); - continue; - } - else { - 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(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(LOG_T_MANAGE, LOG_I_INFO, - "realm[%s]: Client[%s] (ra): commfd: CLOSED", - get_realmname(&config, j), get_raclientname(pointer, k)); - continue; - } - - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - - if (pointer->raclitable[k].ready<2) { - aflog(LOG_T_MANAGE, LOG_I_WARNING, - "realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", - get_realmname(&config, j), get_raclientname(pointer, k)); - continue; } - if ((pointer->raclitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { - buff[0] = AF_S_WRONG; - } - - switch (buff[0]) { - case AF_S_LOGIN : { - if ((pointer->raclitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && - (length==(pointer->pass[2]*256+pointer->pass[3]))) { - for (l = 0; l < pointer->clinum; ++l) { - if (!(pointer->clitable[l].ready)) { - aflog(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); - tmp_ssl = pointer->clitable[l].cliconn.ssl; - pointer->clitable[l].cliconn.ssl = pointer->raclitable[k].cliconn.ssl; - pointer->raclitable[k].cliconn.ssl = tmp_ssl; - pointer->clitable[l].whatusrcli = pointer->raclitable[k].whatusrcli; - pointer->raclitable[k].ready = 0; - break; - } - } - if (l != pointer->clinum) { - pointer->clitable[l].ready = 3; - aflog(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 */ - buff[2] = pointer->clitable[l].usernum; /* low bits of user number */ - buff[3] = pointer->type; /* type of connection */ - send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[l].cliconn, buff, 5); - manconnecting--; - if (pointer->baseport == 1) { - long tmp_val; - char tmp_tab[6]; - if (check_long(pointer->usrclitable[pointer->clitable[l].whatusrcli].lisportnum, &tmp_val)) { - aflog(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; - } - tmp_val = tmp_val%65536; - memset(tmp_tab, 0, 6); - sprintf(tmp_tab, "%d", (int)tmp_val); - ipfam = 0x01; -#ifdef AF_INET6 - if (TYPE_IS_IPV4(pointer->type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(pointer->type)) { - ipfam |= 0x04; - } -#endif - while (ip_listen(&(pointer->clitable[l].listenfd), pointer->hostname, - tmp_tab, (&(pointer->addrlen)), ipfam)) { - tmp_val = (tmp_val+1)%65536; - memset(tmp_tab, 0, 6); - sprintf(tmp_tab, "%d", (int)tmp_val); - } - FD_SET(pointer->clitable[l].listenfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->clitable[l].listenfd+1)) ? - maxfdp1 : (pointer->clitable[l].listenfd+1); - aflog(LOG_T_CLIENT, LOG_I_INFO, - "realm[%s]: Client[%s]: listenport=%s", - get_realmname(&config, j), get_clientname(pointer, l), tmp_tab); - } - } - else { - 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); - } - } - else if ((pointer->raclitable[k].ready == 3) && (numofcon == 0)) { - n = get_message(pointer->type, pointer->raclitable[k].cliconn, buff, length); - buff[n] = 0; - 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); - } - pointer->raclitable[k].clientid = malloc(n+1); - if (pointer->raclitable[k].clientid) { - memcpy(pointer->raclitable[k].clientid, buff, n+1); - } + /* ------------------------------------ */ + for (k = 0; k < pointer->clinum; ++k) + if ((ConnectClient_get_state(pointer->clitable[k]) > CONNECTCLIENT_STATE_FREE) && + (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k])), &rset))) { + if (ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_CONNECTING) { + make_ssl_initialize(ConnectClient_get_sslFd(pointer->clitable[k])); + 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(ConnectClient_get_sslFd(pointer->clitable[k]))) { + case 2: { + close(SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k])), &allset); + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(pointer->clitable[k]))); + ConnectClient_set_state(pointer->clitable[k], CONNECTCLIENT_STATE_FREE); + manconnecting--; + pointer->clicon--; + 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(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: new Client[%s]: ACCEPTED by SSL_accept", + get_realmname(&config, j), get_clientname(pointer, k)); + ConnectClient_set_state(pointer->clitable[k], CONNECTCLIENT_STATE_AUTHORIZING); + continue; + } + } + } + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: commfd: FD_ISSET", + get_realmname(&config, j), get_clientname(pointer, k)); + if (ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) { + n = SslFd_get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(pointer->clitable[k]))); + } + else { + n = SslFd_get_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(pointer->clitable[k]))); + } + if (n == -1) { + if (errno == 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(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(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: Client[%s]: header length = %d --> buffering", + get_realmname(&config, j), get_clientname(pointer, k), n); + HeaderBuffer_store(ConnectClient_get_header(pointer->clitable[k]), buff, n); + if (HeaderBuffer_to_read(ConnectClient_get_header(pointer->clitable[k])) == 0) { + HeaderBuffer_restore(ConnectClient_get_header(pointer->clitable[k]), buff); + n = 5; } else { - 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); + continue; } - break; - } - case AF_S_WRONG: { - 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; - } - 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(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++; - manconnecting--; - sprintf((char*) &buff[5], AF_VER("AFSERVER")); - n = strlen((char*) &buff[5]); - buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ - buff[1] = pointer->type; /* type of connection */ - buff[2] = AF_RA_UNDEFINED; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, n+5); + } + } + if (n==0) { + 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), + ConnectClient_get_nameBuf(pointer->clitable[k]), + ConnectClient_get_portBuf(pointer->clitable[k]), + timeperiod(now - ConnectClient_get_connectTime(pointer->clitable[k]))); + if (pointer->audit) { + while (AuditList_get_first(ConnectClient_get_auditList(pointer->clitable[k]))) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + AuditListNode_get_userId( + AuditList_get_first( + ConnectClient_get_auditList(pointer->clitable[k]))), + AuditListNode_get_nameBuf( + AuditList_get_first( + ConnectClient_get_auditList(pointer->clitable[k]))), + AuditListNode_get_portBuf( + AuditList_get_first( + ConnectClient_get_auditList(pointer->clitable[k]))), + localdate(AuditListNode_get_connectTimep( + AuditList_get_first( + ConnectClient_get_auditList(pointer->clitable[k])))), + timeperiod(AuditListNode_get_duration( + AuditList_get_first( + ConnectClient_get_auditList(pointer->clitable[k]))))); + AuditList_delete_first(ConnectClient_get_auditList(pointer->clitable[k])); } - break; - } - case AF_S_ADMIN_CMD: { - if (pointer->raclitable[k].ready == 3) { - 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; + } + remove_client(pointer, k, &allset, &wset, &manconnecting); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if ((k == pointer->clinum) && (buff[0] != AF_S_LOGIN) && + (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) { + buff[0] = AF_S_WRONG; + } + if (ConnectClient_get_state(pointer->clitable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) { + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]: Impossible behaviour --> ignoring", + get_realmname(&config, j), get_clientname(pointer, k)); + continue; + } + if ((ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) && + (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + switch (buff[0]) { + case AF_S_CONCLOSED : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && + (ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + pointer->usercon--; + ConnectClient_decrease_connected(pointer->clitable[k]); + ConnectClient_get_users(pointer->clitable[k])[n] = -1; + if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_CLOSING) { + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_CLEAR); + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: user[%d]: CLOSE CONFIRMED", + get_realmname(&config, j), get_username(pointer, numofcon)); + } + else if ((ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_STOPPED)) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: KICKED", + get_realmname(&config, j), get_username(pointer, numofcon)); + 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), + ConnectUser_get_nameBuf(pointer->contable[numofcon]), + ConnectUser_get_portBuf(pointer->contable[numofcon]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[numofcon]))); + close(ConnectUser_get_connFd(pointer->contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &wset); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_CLEAR); + BufList_clear(ConnectUser_get_bufList(pointer->contable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_CONOPEN : { + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && + (ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_OPENING) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: NEW", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_SET(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(pointer->contable[numofcon]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(pointer->contable[numofcon]) + 1); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_OPEN); + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_CANT_OPEN : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && + (ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_OPENING) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: DROPPED", + get_realmname(&config, j), get_username(pointer, numofcon)); + pointer->usercon--; + ConnectClient_decrease_connected(pointer->clitable[k]); + ConnectClient_get_users(pointer->clitable[k])[n] = -1; + close(ConnectUser_get_connFd(pointer->contable[numofcon])); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_CLEAR); + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_MESSAGE : { + if (ConnectClient_get_state(pointer->clitable[k]) != + CONNECTCLIENT_STATE_ACCEPTED) { + remove_client(pointer, k, &allset, &wset, &manconnecting); + break; + } + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + n = SslFd_get_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + &buff[5], length); + } + else { + n = SslFd_get_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, length); + } + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum))) { + if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_OPEN) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: TO user[%d]: MESSAGE length=%d", + get_realmname(&config, j), get_username(pointer, numofcon), n); + UserStats_add_download(ConnectUser_get_stats(pointer->contable[numofcon]), n); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + sent = write(ConnectUser_get_connFd(pointer->contable[numofcon]), buff, n+5); + if (sent == -1) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: CLOSED (write-udp)", + get_realmname(&config, j), get_username(pointer, numofcon)); + 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), + ConnectUser_get_nameBuf(pointer->contable[numofcon]), + ConnectUser_get_portBuf(pointer->contable[numofcon]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[numofcon]))); + close(ConnectUser_get_connFd(pointer->contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &wset); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(pointer->contable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + } + } + else { /* tcp */ + sent = write(ConnectUser_get_connFd(pointer->contable[numofcon]), buff, n); + if ((sent > 0) && (sent != n)) { + BufList_insert_back(ConnectUser_get_bufList(pointer->contable[numofcon]), + BufListNode_new_message(sent, n, buff)); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(pointer->contable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(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); + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + } + else if ((sent == -1) && (errno == EAGAIN)) { + BufList_insert_back(ConnectUser_get_bufList(pointer->contable[numofcon]), + BufListNode_new_message(0, n, buff)); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(pointer->contable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(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); + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + } + else if (sent == -1) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: CLOSED (write-tcp)", + get_realmname(&config, j), get_username(pointer, numofcon)); + 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), + ConnectUser_get_nameBuf(pointer->contable[numofcon]), + ConnectUser_get_portBuf(pointer->contable[numofcon]), + timeperiod(now - ConnectUser_get_connectTime(pointer->contable[numofcon]))); + close(ConnectUser_get_connFd(pointer->contable[numofcon])); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &wset); + ConnectUser_set_state(pointer->contable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(pointer->contable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + } + } + } + else if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_STOPPED) { + 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; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + BufList_insert_back(ConnectUser_get_bufList(pointer->contable[numofcon]), + BufListNode_new_message(0, n+5, buff)); + } + else { + BufList_insert_back(ConnectUser_get_bufList(pointer->contable[numofcon]), + BufListNode_new_message(0, n, buff)); + } + } + else if (ConnectUser_get_state(pointer->contable[numofcon]) == S_STATE_CLOSING) { + 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); + } + else { + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: TO user[%d]: user in wrong state - IGNORED", + get_realmname(&config, j), get_username(pointer, numofcon)); + } + } + else { + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: message to non-existing user - IGNORED", + get_realmname(&config, j)); + } + break; + } + case AF_S_LOGIN : { + if ((ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + if (k != pointer->clinum) { + ConnectClient_set_state(pointer->clitable[k], CONNECTCLIENT_STATE_ACCEPTED); + 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] = ConnectClient_get_limit( + pointer->clitable[k]) >> 8;/* high bits of user number */ + buff[2] = ConnectClient_get_limit( + pointer->clitable[k]); /* low bits of user number */ + buff[3] = pointer->type; /* type of connection */ + SslFd_send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + manconnecting--; + if (pointer->baseport == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long( + UsrCli_get_listenPortName( + pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[k])]), + &tmp_val)) { + 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; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(pointer->type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(pointer->type)) { + ipfam |= 0x04; + } +#endif + while (ip_listen(ConnectClient_get_listenFdp(pointer->clitable[k]), + UsrCli_get_listenHostName(pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[k])]) ? + UsrCli_get_listenHostName(pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[k])]) : + pointer->hostname, + tmp_tab, (&(pointer->addrlen)), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + FD_SET(ConnectClient_get_listenFd(pointer->clitable[k]), &allset); + maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(pointer->clitable[k])+1)) ? + maxfdp1 : (ConnectClient_get_listenFd(pointer->clitable[k]) + 1); + 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(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + SslFd_send_message(pointer->type | TYPE_SSL, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + else if ((ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) { + n = SslFd_get_message(pointer->type, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, length); + buff[n] = 0; + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: ID received: %s", + get_realmname(&config, j), get_clientname(pointer, k), buff); + ConnectClient_set_sClientId(pointer->clitable[k], (char*) buff); + } + else { + 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 */ + SslFd_send_message(pointer->type | TYPE_SSL, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_DONT_SEND: { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: user[%d]: STOP READING", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_CLR(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + break; + } + case AF_S_CAN_SEND: { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: user[%d]: START READING", + get_realmname(&config, j), get_username(pointer, numofcon)); + FD_SET(ConnectUser_get_connFd(pointer->contable[numofcon]), &allset); + break; + } + case AF_S_WRONG: { + 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; + } + case AF_S_ADMIN_LOGIN: { + if ((ConnectClient_get_state(pointer->clitable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon == (pointer->pass[0]*256 + pointer->pass[1])) && + (length == (pointer->pass[2]*256 + pointer->pass[3]))) { + 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 (ConnectClient_get_state(pointer->raclitable[l]) == + CONNECTCLIENT_STATE_FREE) { + SslFd_set_fd( + ConnectClient_get_sslFd(pointer->raclitable[l]), + SslFd_get_fd( + ConnectClient_get_sslFd(pointer->clitable[k]))); + ConnectClient_set_connectTime( + pointer->raclitable[l], + ConnectClient_get_connectTime(pointer->clitable[k])); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType( + pointer->raclitable[l], + ConnectClient_get_tunnelType(pointer->clitable[k])); +#endif + ConnectClient_set_clientId( + pointer->raclitable[l], + ConnectClient_get_clientId(pointer->clitable[k])); + ConnectClient_set_nameBuf( + pointer->raclitable[l], + ConnectClient_get_nameBuf(pointer->clitable[k])); + ConnectClient_set_portBuf( + pointer->raclitable[l], + ConnectClient_get_portBuf(pointer->clitable[k])); + tmp_ssl = SslFd_get_ssl( + ConnectClient_get_sslFd(pointer->raclitable[l])); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(pointer->raclitable[l]), + SslFd_get_ssl( + ConnectClient_get_sslFd(pointer->clitable[k]))); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(pointer->clitable[k]), + tmp_ssl); + ConnectClient_set_state( + pointer->clitable[k], + CONNECTCLIENT_STATE_FREE); + break; + } + } + if (l != pointer->raclinum) { + ConnectClient_set_state( + pointer->raclitable[l], + CONNECTCLIENT_STATE_ACCEPTED); + pointer->raclicon++; + manconnecting--; + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = pointer->type; /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(pointer->type | TYPE_SSL, + ConnectClient_get_sslFd( + pointer->raclitable[l]), + buff, n+5); + } + else { + 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 */ + SslFd_send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->clitable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + 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(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); } - } - } - } + } + } + /* ------------------------------------ */ + for (k = 0; k < pointer->raclinum; ++k) + if ((ConnectClient_get_state(pointer->raclitable[k]) > CONNECTCLIENT_STATE_FREE) && + (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k])), &rset))) { + if (ConnectClient_get_state(pointer->raclitable[k]) == CONNECTCLIENT_STATE_CONNECTING) { + make_ssl_initialize(ConnectClient_get_sslFd(pointer->raclitable[k])); + 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(ConnectClient_get_sslFd(pointer->raclitable[k]))) { + case 2: { + close (SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k])), &allset); + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(pointer->raclitable[k]))); + ConnectClient_set_state(pointer->raclitable[k], CONNECTCLIENT_STATE_FREE); + manconnecting--; + pointer->clicon--; + 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(LOG_T_MANAGE, LOG_I_DEBUG, + "realm[%s]: new Client[%s] (ra): ACCEPTED by SSL_accept", + get_realmname(&config, j), get_raclientname(pointer, k)); + ConnectClient_set_state(pointer->raclitable[k], CONNECTCLIENT_STATE_AUTHORIZING); + continue; + } + } + } + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "realm[%s]: Client[%s] (ra): commfd: FD_ISSET", + get_realmname(&config, j), get_raclientname(pointer, k)); + n = SslFd_get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->raclitable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(pointer->raclitable[k]))); + if (n == -1) { + if (errno == 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(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(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): header length = %d --> buffering", + get_realmname(&config, j), get_raclientname(pointer, k), n); + HeaderBuffer_store(ConnectClient_get_header(pointer->raclitable[k]), buff, n); + if (HeaderBuffer_to_read(ConnectClient_get_header(pointer->raclitable[k])) == 0) { + HeaderBuffer_restore(ConnectClient_get_header(pointer->raclitable[k]), buff); + n = 5; } else { - 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); + continue; } - 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(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); - } - } - } - /* ------------------------------------ */ - for (l = 0; l < pointer->usrclinum; ++l) { - if (FD_ISSET(pointer->usrclitable[l].managefd, &rset)) { - aflog(LOG_T_CLIENT, LOG_I_DDEBUG, - "realm[%s]: managefd: FD_ISSET", get_realmname(&config, j)); - len = pointer->addrlen; + } + } + if (n==0) { + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): commfd: CLOSED", + get_realmname(&config, j), get_raclientname(pointer, k)); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if (ConnectClient_get_state(pointer->raclitable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", + get_realmname(&config, j), get_raclientname(pointer, k)); + continue; + } + if ((ConnectClient_get_state(pointer->raclitable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) && + (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + switch (buff[0]) { + case AF_S_LOGIN : { + if ((ConnectClient_get_state(pointer->raclitable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + for (l = 0; l < pointer->clinum; ++l) { + if (ConnectClient_get_state(pointer->clitable[l]) == + CONNECTCLIENT_STATE_FREE) { + 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)); + SslFd_set_fd( + ConnectClient_get_sslFd(pointer->clitable[l]), + SslFd_get_fd( + ConnectClient_get_sslFd(pointer->raclitable[k]))); + ConnectClient_set_connectTime( + pointer->clitable[l], + ConnectClient_get_connectTime(pointer->raclitable[k])); #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); + ConnectClient_set_tunnelType( + pointer->clitable[l], + ConnectClient_get_tunnelType(pointer->raclitable[k])); #endif - if (sent == -1) { - if (errno == EAGAIN) { - aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: managefd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); - } - else { - aflog(LOG_T_USER, LOG_I_DDEBUG, - "realm[%s]: managefd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); + ConnectClient_set_clientId( + pointer->clitable[l], + ConnectClient_get_clientId(pointer->raclitable[k])); + ConnectClient_set_nameBuf( + pointer->clitable[l], + ConnectClient_get_nameBuf(pointer->raclitable[k])); + ConnectClient_set_portBuf( + pointer->clitable[l], + ConnectClient_get_portBuf(pointer->raclitable[k])); + tmp_ssl = SslFd_get_ssl( + ConnectClient_get_sslFd(pointer->clitable[l])); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(pointer->clitable[l]), + SslFd_get_ssl( + ConnectClient_get_sslFd(pointer->raclitable[k]))); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(pointer->raclitable[k]), + tmp_ssl); + ConnectClient_set_usrCliPair( + pointer->clitable[l], + ConnectClient_get_usrCliPair(pointer->raclitable[k])); + ConnectClient_set_state(pointer->raclitable[k], CONNECTCLIENT_STATE_FREE); + break; + } + } + if (l != pointer->clinum) { + ConnectClient_set_state(pointer->clitable[l], CONNECTCLIENT_STATE_ACCEPTED); + 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] = ConnectClient_get_limit( + pointer->clitable[l]) >> 8;/* high bits of user number */ + buff[2] = ConnectClient_get_limit( + pointer->clitable[l]); /* low bits of user number */ + buff[3] = pointer->type; /* type of connection */ + SslFd_send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->clitable[l]), + buff, 5); + manconnecting--; + if (pointer->baseport == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long( + UsrCli_get_listenPortName( + pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[l])]), + &tmp_val)) { + 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; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(pointer->type)) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(pointer->type)) { + ipfam |= 0x04; + } +#endif + while (ip_listen(ConnectClient_get_listenFdp(pointer->clitable[l]), + UsrCli_get_listenHostName(pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[l])]) ? + UsrCli_get_listenHostName(pointer->usrclitable[ + ConnectClient_get_usrCliPair(pointer->clitable[l])]) : + pointer->hostname, + tmp_tab, (&(pointer->addrlen)), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + FD_SET(ConnectClient_get_listenFd(pointer->clitable[l]), &allset); + maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(pointer->clitable[l])+1)) ? + maxfdp1 : (ConnectClient_get_listenFd(pointer->clitable[l])+1); + 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(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + SslFd_send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->raclitable[k]), + buff, 5); + remove_raclient(pointer, k, &allset, &wset, &manconnecting); + } + } + else if ((ConnectClient_get_state(pointer->raclitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) { + n = SslFd_get_message(pointer->type, + ConnectClient_get_sslFd( + pointer->raclitable[k]), + buff, length); + buff[n] = 0; + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): ID received: %s", + get_realmname(&config, j), get_raclientname(pointer, k), buff); + ConnectClient_set_sClientId(pointer->raclitable[k], (char*) buff); + } + else { + 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(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; + } + case AF_S_ADMIN_LOGIN: { + if ((ConnectClient_get_state(pointer->raclitable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + 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)); + ConnectClient_set_state( + pointer->raclitable[k], + CONNECTCLIENT_STATE_ACCEPTED); + pointer->raclicon++; + manconnecting--; + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = pointer->type; /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + pointer->raclitable[k]), + buff, n+5); + } + break; + } + case AF_S_ADMIN_CMD: { + if (ConnectClient_get_state(pointer->raclitable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) { + 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 */ + SslFd_send_message(config.realmtable[i].type, + ConnectClient_get_sslFd( + config.realmtable[i].clitable[l]), + 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), + ConnectClient_get_nameBuf(config.realmtable[i].clitable[l]), + ConnectClient_get_portBuf(config.realmtable[i].clitable[l]), + timeperiod(now - ConnectClient_get_connectTime( + config.realmtable[i].clitable[l]))); + if (config.realmtable[i].audit) { + while (AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l]))) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + AuditListNode_get_userId( + AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l]))), + AuditListNode_get_nameBuf( + AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l]))), + AuditListNode_get_portBuf( + AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l]))), + localdate( + AuditListNode_get_connectTimep( + AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l])))), + timeperiod( + AuditListNode_get_duration( + AuditList_get_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l]))))); + AuditList_delete_first( + ConnectClient_get_auditList( + config.realmtable[i].clitable[l])); + } + } + remove_client(&(config.realmtable[i]), l, + &allset, &wset, &manconnecting); + break; + } + } + } + } + } + else { + 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(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); + } } - 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(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); + /* ------------------------------------ */ + for (l = 0; l < pointer->usrclinum; ++l) { + if (FD_ISSET(UsrCli_get_manageFd(pointer->usrclitable[l]), &rset)) { + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET", get_realmname(&config, j)); + len = pointer->addrlen; #ifdef HAVE_LIBPTHREAD - pointer->clitable[k].tunneltype = tunneltype; + sent = get_new_socket(UsrCli_get_manageFd(pointer->usrclitable[l]), + pointer->tunneltype,pointer->cliaddr, &len, &tunneltype); +#else + sent = accept(UsrCli_get_manageFd(pointer->usrclitable[l]), pointer->cliaddr, &len); #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); - maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ? - maxfdp1 : (pointer->clitable[k].cliconn.commfd+1); - pointer->clicon++; - pointer->clitable[k].tv.tv_sec = pointer->tmout; - manconnecting++; - pointer->clitable[k].ready = 1; - break; + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET --> EAGAIN", get_realmname(&config, j)); + } + else { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET --> errno=%d", get_realmname(&config, j), errno); + } + continue; } - } - if (k == pointer->clinum) { - for (k = 0; k < pointer->raclinum; ++k) { - if ((!pointer->raclitable[k].ready)) { - pointer->raclitable[k].clientnum = pointer->clientcounter; + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + for (k = 0; k < pointer->clinum; ++k) { + if (ConnectClient_get_state(pointer->clitable[k]) == CONNECTCLIENT_STATE_FREE) { + ConnectClient_set_clientId(pointer->clitable[k], pointer->clientcounter); ++(pointer->clientcounter); - 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(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: new Client[%s]: CONNECTING", + get_realmname(&config, j), get_clientname(pointer, k)); + SslFd_set_fd(ConnectClient_get_sslFd(pointer->clitable[k]), sent); + ConnectClient_set_usrCliPair(pointer->clitable[k], l); + time(&now); + ConnectClient_set_connectTime(pointer->clitable[k], now); #ifdef HAVE_LIBPTHREAD - pointer->raclitable[k].tunneltype = tunneltype; + ConnectClient_set_tunnelType(pointer->clitable[k], 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)); - FD_SET(pointer->raclitable[k].cliconn.commfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->raclitable[k].cliconn.commfd+1)) ? - maxfdp1 : (pointer->raclitable[k].cliconn.commfd+1); + 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, ConnectClient_get_nameBuf(pointer->clitable[k]), + ConnectClient_get_portBuf(pointer->clitable[k]), pointer->dnslookups)); + FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k])), &allset); + maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k])) + 1)) ? + maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(pointer->clitable[k])) + 1); pointer->clicon++; - pointer->raclitable[k].tv.tv_sec = pointer->tmout; + ConnectClient_set_timer(pointer->clitable[k], timeval_create(pointer->tmout, 0)); manconnecting++; - pointer->raclitable[k].ready = 1; + ConnectClient_set_state(pointer->clitable[k], CONNECTCLIENT_STATE_CONNECTING); break; } } - if (k == pointer->raclinum) { - aflog(LOG_T_CLIENT | LOG_T_MANAGE, LOG_I_WARNING, - "realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); - close(sent); + if (k == pointer->clinum) { + for (k = 0; k < pointer->raclinum; ++k) { + if (ConnectClient_get_state(pointer->raclitable[k]) == + CONNECTCLIENT_STATE_FREE) { + ConnectClient_set_clientId(pointer->raclitable[k], pointer->clientcounter); + ++(pointer->clientcounter); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: new Client[%s] (ra): CONNECTING", + get_realmname(&config, j), get_raclientname(pointer, k)); + SslFd_set_fd(ConnectClient_get_sslFd(pointer->raclitable[k]), sent); + ConnectClient_set_usrCliPair(pointer->raclitable[k], l); + time(&now); + ConnectClient_set_connectTime(pointer->raclitable[k], now); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType(pointer->raclitable[k], 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, ConnectClient_get_nameBuf(pointer->raclitable[k]), + ConnectClient_get_portBuf(pointer->raclitable[k]), pointer->dnslookups)); + FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k])), &allset); + maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k])) + 1)) ? + maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(pointer->raclitable[k])) + 1); + pointer->clicon++; + ConnectClient_set_timer(pointer->raclitable[k], timeval_create(pointer->tmout, 0)); + manconnecting++; + ConnectClient_set_state(pointer->raclitable[k], CONNECTCLIENT_STATE_CONNECTING); + break; + } + } + if (k == pointer->raclinum) { + aflog(LOG_T_CLIENT | LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(&config, j)); + close(sent); + } } } } - } - } /* realms loop */ + } /* realms loop */ } } diff --git a/src/afserver.h b/src/afserver.h index 1c9dab5..dced084 100644 --- a/src/afserver.h +++ b/src/afserver.h @@ -22,7 +22,7 @@ #include "network.h" #include "file.h" #include "stats.h" -#include "remoteadmin.h" +#include "server_remoteadmin.h" #include "server_check.h" #include "server_set.h" #include "server_eval.h" @@ -40,6 +40,7 @@ #include "usage.h" #include "logging.h" #include "daemon.h" +#include "timeval_functions.h" #include #include diff --git a/src/ar_options_struct.c b/src/ar_options_struct.c new file mode 100644 index 0000000..0d95dfc --- /dev/null +++ b/src/ar_options_struct.c @@ -0,0 +1,296 @@ +/* + * 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 "ar_options_struct.h" +#include "string_functions.h" +#include "server_check.h" + +/* + * Function name: ArOptions_new + * Description: Create and initialize new ArOptions structure. + * Returns: Pointer to newly created ArOptions structure. + */ + +ArOptions* +ArOptions_new() +{ + ArOptions* tmp = calloc(1, sizeof(ArOptions)); + if (tmp == NULL) { + return NULL; + } + tmp->premature = AR_OPTION_ENABLED; + tmp->delay = 5; + tmp->tries = -1; + return tmp; +} + +/* + * Function name: ArOptions_free + * Description: Free the memory allocated for ArOptions structure. + * Arguments: ao - pointer to pointer to ArOptions structure + */ + +void +ArOptions_free(ArOptions** ao) +{ + if (ao == NULL) { + return; + } + if ((*ao) == NULL) { + return; + } + if ((*ao)->artries) { + free((*ao)->artries); + (*ao)->artries = NULL; + } + if ((*ao)->ardelay) { + free((*ao)->ardelay); + (*ao)->ardelay = NULL; + } + free((*ao)); + (*ao) = NULL; +} + +/* + * Function name: ArOptions_set_asTries + * Description: Set how many times afclient will try to reconnect. + * Arguments: ao - pointer to ArOptions structure + * tries - how many times afclient will try to reconnect + * <0 - unlimited + * 0 - disabled + * >0 - exact number + */ + +void +ArOptions_set_arTries(ArOptions* ao, int tries) +{ + if (ao == NULL) { + return; + } + ao->tries = tries; +} + +/* + * Function name: ArOptions_set_s_arTries + * Description: Set string describing how many times afclient will try to reconnect. + * This string has to be evaluated later in order to really set arTries value. + * Arguments: ao - pointer to ArOptions structure + * tries - string describing how many times afclient will try to reconnect. + */ + +void +ArOptions_set_s_arTries(ArOptions* ao, char* tries) +{ + if (ao == NULL) { + return; + } + string_cp(&(ao->artries), tries); +} + +/* + * Function name: ArOptions_set_arDelay + * Description: Set how long afclient will wait between reconnect tries. + * Arguments: ao - pointer to ArOptions structure + * delay - how long afclient will wait between reconnect tries + */ + +void +ArOptions_set_arDelay(ArOptions* ao, int delay) +{ + if (ao == NULL) { + return; + } + ao->delay = delay; +} + +/* + * Function name: ArOptions_set_s_arDelay + * Description: Set string describing how long afclient will wait between reconnect tries. + * This string has to be evaluated later in order to really set arDelay value. + * Arguments: ao - pointer to ArOptions structure + * delay - string describing how long afclient will wait between reconnect tries. + */ + +void +ArOptions_set_s_arDelay(ArOptions* ao, char* delay) +{ + if (ao == NULL) { + return; + } + string_cp(&(ao->ardelay), delay); +} + +/* + * Function name: ArOptions_set_arStart + * Description: Enable/disable auto-reconnection when afserver is not reachable on start. + * Arguments: ao - pointer to ArOptions structure + * start - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection when afserver is not reachable on start + */ + +void +ArOptions_set_arStart(ArOptions* ao, char start) +{ + if (ao == NULL) { + return; + } + ao->start = start; +} + +/* + * Function name: ArOptions_set_arQuit + * Description: Enable/disable auto-reconnection after normal afserver quit. + * Arguments: ao - pointer to ArOptions structure + * quit - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection after normal afserver quit + */ + +void +ArOptions_set_arQuit(ArOptions* ao, char quit) +{ + if (ao == NULL) { + return; + } + ao->quit = quit; +} + +/* + * Function name: ArOptions_set_arPremature + * Description: Enable/disable auto-reconnection after premature afserver quit. + * Arguments: ao - pointer to ArOptions structure + * premature - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection after premature afserver quit + */ + +void +ArOptions_set_arPremature(ArOptions* ao, char premature) +{ + if (ao == NULL) { + return; + } + ao->premature = premature; +} + +/* + * Function name: ArOptions_get_arTries + * Description: Get how many times afclient will try to reconnect. + * Arguments: ao - pointer to ArOptions structure + * Returns: How many times afclient will try to reconnect. + */ + +int +ArOptions_get_arTries(ArOptions* ao) +{ + if (ao == NULL) { + return 0; + } + return ao->tries; +} + +/* + * Function name: ArOptions_get_arDelay + * Description: Get how long afclient will wait between reconnect tries. + * Arguments: ao - pointer to ArOptions structure + * Returns: How long afclient will wait between reconnect time. + */ + +int +ArOptions_get_arDelay(ArOptions* ao) +{ + if (ao == NULL) { + return 0; + } + return ao->delay; +} + +/* + * Function name: ArOptions_get_arStart + * Description: Get status of the auto-reconnection when afserver is not reachable on start. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection when afserver is not reachable on start. + */ + +char +ArOptions_get_arStart(ArOptions* ao) +{ + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->start; +} + +/* + * Function name: ArOptions_get_arQuit + * Description: Get status of the auto-reconnection after normal afserver quit. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection after normal afserver quit. + */ + +char +ArOptions_get_arQuit(ArOptions* ao) +{ + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->quit; +} + +/* + * Function name: ArOptions_get_arPremature + * Description: Get status of the auto-reconnection after premature afserver quit. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection after premature afserver quit. + */ + +char +ArOptions_get_arPremature(ArOptions* ao) +{ + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->premature; +} + +/* + * Function name: ArOptions_evaluate_values + * Description: Evaluate arTries and arDelay values. These values are checked, when are not NULL. + * arTries have to be an integer, arDelay have to be an integer >0. If any of the + * variables is wrong, program terminates abnormally. + * Arguments: ao - pointer to ArOptions structure + */ + +void +ArOptions_evaluate_values(ArOptions* ao) +{ + if (ao == NULL) { + return; + } + if (ao->artries) { + ao->tries = check_value_liberal(ao->artries, "Invalid ar-tries value"); + } + if (ao->ardelay) { + check_value(&(ao->delay), ao->ardelay, "Invalid ar-delay value"); + } +} diff --git a/src/ar_options_struct.h b/src/ar_options_struct.h new file mode 100644 index 0000000..5d469d1 --- /dev/null +++ b/src/ar_options_struct.h @@ -0,0 +1,59 @@ +/* + * 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_AR_OPTIONS_STRUCT_H +#define _JS_AR_OPTIONS_STRUCT_H + +#define AR_OPTION_DISABLED 0 +#define AR_OPTION_ENABLED 1 + +typedef struct { + char* artries; + int tries; + char* ardelay; + int delay; + char start; + char quit; + char premature; +} ArOptions; + +/* 'constructor' */ +ArOptions* ArOptions_new(); +/* 'destructor' */ +void ArOptions_free(ArOptions** ao); +/* setters */ +void ArOptions_set_arTries(ArOptions* ao, int tries); +void ArOptions_set_s_arTries(ArOptions* ao, char* tries); +void ArOptions_set_arDelay(ArOptions* ao, int delay); +void ArOptions_set_s_arDelay(ArOptions* ao, char* delay); +void ArOptions_set_arStart(ArOptions* ao, char start); +void ArOptions_set_arQuit(ArOptions* ao, char quit); +void ArOptions_set_arPremature(ArOptions* ao, char premature); +/* getters */ +int ArOptions_get_arTries(ArOptions* ao); +int ArOptions_get_arDelay(ArOptions* ao); +char ArOptions_get_arStart(ArOptions* ao); +char ArOptions_get_arQuit(ArOptions* ao); +char ArOptions_get_arPremature(ArOptions* ao); +/* other */ +void ArOptions_evaluate_values(ArOptions* ao); + +#endif diff --git a/src/audit.c b/src/audit.c deleted file mode 100644 index c74b619..0000000 --- a/src/audit.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 deleted file mode 100644 index 023fd94..0000000 --- a/src/audit.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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/audit_list_node_struct.c b/src/audit_list_node_struct.c new file mode 100644 index 0000000..f84397f --- /dev/null +++ b/src/audit_list_node_struct.c @@ -0,0 +1,298 @@ +/* + * 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_list_node_struct.h" + +/* + * Function name: AuditListNode_new + * Description: Create and initialize new AuditListNode structure. + * Returns: Newly created AuditListNode structure. + */ + +AuditListNode* +AuditListNode_new() +{ + AuditListNode* tmp = calloc(1, sizeof(AuditListNode)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: AuditListNode_new_entry + * Description: Create and initialize new AuditListNode structure from given arguments. + * Arguments: userId - identification number of the user + * nameBuf - name of the user + * portBuf - port from which user is connected + * connectTime - start time of the connection + * duration - duration of the connection + * Returns: Newly created and initialized AuditListNode structure. + */ + +AuditListNode* +AuditListNode_new_entry(int userId, char* nameBuf, char* portBuf, + time_t connectTime, time_t duration) +{ + AuditListNode* tmp = calloc(1, sizeof(AuditListNode)); + if (tmp == NULL) { + return NULL; + } + AuditListNode_set_userId(tmp, userId); + AuditListNode_set_nameBuf(tmp, nameBuf); + AuditListNode_set_portBuf(tmp, portBuf); + AuditListNode_set_connectTime(tmp, connectTime); + AuditListNode_set_duration(tmp, duration); + return tmp; +} + +/* + * Function name: AuditListNode_free + * Description: Free the memory allocated for AuditListNode structure. + * Arguments: aln - pointer to pointer to AuditListNode structure + */ + +void +AuditListNode_free(AuditListNode** aln) +{ + if (aln == NULL) { + return; + } + if ((*aln) == NULL) { + return; + } + free((*aln)); + (*aln) = NULL; +} + +/* + * Function name: AuditListNode_set_userId + * Description: Set user identification number. + * Arguments: aln - pointer to AuditListNode structure + * userId - user identification number + */ + +void +AuditListNode_set_userId(AuditListNode* aln, int userId) +{ + if (aln == NULL) { + return; + } + aln->userId = userId; +} + +/* + * Function name: AuditListNode_set_nameBuf + * Description: Set user name. + * Arguments: aln - pointer to AuditListNode structure + * nameBuf - user name + */ + +void +AuditListNode_set_nameBuf(AuditListNode* aln, char* nameBuf) +{ + if (aln == NULL) { + return; + } + memset(aln->nameBuf, 0, 7); + strncpy(aln->nameBuf, nameBuf, 6); +} + +/* + * Function name: AuditListNode_set_portBuf + * Description: Set port from which user is connected. + * Arguments: aln - pointer to AuditListNode structure + * portBuf - port from which user is connected + */ + +void +AuditListNode_set_portBuf(AuditListNode* aln, char* portBuf) +{ + if (aln == NULL) { + return; + } + memset(aln->portBuf, 0, 7); + strncpy(aln->portBuf, portBuf, 6); +} + +/* + * Function name: AuditListNode_set_connectTime + * Description: Set start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * connectTime - start time of the connection + */ + +void +AuditListNode_set_connectTime(AuditListNode* aln, time_t connectTime) +{ + if (aln == NULL) { + return; + } + aln->connectTime = connectTime; +} + +/* + * Function name: AuditListNode_set_duration + * Description: Set duration of the connection. + * Arguments: aln - pointer to AuditListNode structure + * duration - duration of the connection + */ + +void +AuditListNode_set_duration(AuditListNode* aln, time_t duration) +{ + if (aln == NULL) { + return; + } + aln->duration = duration; +} + +/* + * Function name: AuditListNode_set_nextNode + * Description: Set next node pointer. + * Arguments: aln - pointer to AuditListNode structure + * nextNode - next node pointer + */ + +void +AuditListNode_set_nextNode(AuditListNode* aln, AuditListNode* nextNode) +{ + if (aln == NULL) { + return; + } + aln->nextNode = nextNode; +} + +/* + * Function name: AuditListNode_get_userId + * Description: Get user identification number. + * Arguments: aln - pointer to AuditListNode structure + * Returns: User identification number. + */ + +int +AuditListNode_get_userId(AuditListNode* aln) +{ + if (aln == NULL) { + return -1; + } + return aln->userId; +} + +/* + * Function name: AuditListNode_get_nameBuf + * Description: Get user name. + * Arguments: aln - pointer to AuditListNode structure + * Returns: User name. + */ + +char* +AuditListNode_get_nameBuf(AuditListNode* aln) +{ + if (aln == NULL) { + return NULL; + } + return aln->nameBuf; +} + +/* + * Function name: AuditListNode_get_portBuf + * Description: Get port from which user is connected. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Port from which user is connected. + */ + +char* +AuditListNode_get_portBuf(AuditListNode* aln) +{ + if (aln == NULL) { + return NULL; + } + return aln->portBuf; +} + +/* + * Function name: AuditListNode_get_connectTime + * Description: Get start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Start time of the connection. + */ + +time_t +AuditListNode_get_connectTime(AuditListNode* aln) +{ + if (aln == NULL) { + return 0; + } + return aln->connectTime; +} + +/* + * Function name: AuditListNode_get_duration + * Description: Get duration of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Duration of the connection. + */ + +time_t +AuditListNode_get_duration(AuditListNode* aln) +{ + if (aln == NULL) { + return 0; + } + return aln->duration; +} + +/* + * Function name: AuditListNode_get_nextNode + * Description: Get next node pointer. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Next node pointer. + */ + +AuditListNode* +AuditListNode_get_nextNode(AuditListNode* aln) +{ + if (aln == NULL) { + return NULL; + } + return aln->nextNode; +} + +/* + * Function name: AuditListNode_get_connectTimep + * Description: Get pointer to time_t variable holding start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Pointer to time_t variable holding start time of the connection. + */ + +time_t* +AuditListNode_get_connectTimep(AuditListNode* aln) +{ + if (aln == NULL) { + return 0; + } + return (&(aln->connectTime)); +} diff --git a/src/audit_list_node_struct.h b/src/audit_list_node_struct.h new file mode 100644 index 0000000..674327a --- /dev/null +++ b/src/audit_list_node_struct.h @@ -0,0 +1,58 @@ +/* + * 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_LIST_NODE_STRUCT_H +#define _JS_AUDIT_LIST_NODE_STRUCT_H + +typedef struct alnode { + int userId; + char nameBuf[128]; + char portBuf[7]; + time_t connectTime; + time_t duration; + struct alnode* nextNode; +} AuditListNode; + +/* 'constructors' */ +AuditListNode* AuditListNode_new(); +AuditListNode* AuditListNode_new_entry(int userId, char* nameBuf, char* portBuf, + time_t connectTime, time_t duration); +/* 'destructor' */ +void AuditListNode_free(AuditListNode** aln); +/* setters */ +void AuditListNode_set_userId(AuditListNode* aln, int userId); +void AuditListNode_set_nameBuf(AuditListNode* aln, char* nameBuf); +void AuditListNode_set_portBuf(AuditListNode* aln, char* portBuf); +void AuditListNode_set_connectTime(AuditListNode* aln, time_t connectTime); +void AuditListNode_set_duration(AuditListNode* aln, time_t duration); +void AuditListNode_set_nextNode(AuditListNode* aln, AuditListNode* nextNode); +/* getters */ +int AuditListNode_get_userId(AuditListNode* aln); +char* AuditListNode_get_nameBuf(AuditListNode* aln); +char* AuditListNode_get_portBuf(AuditListNode* aln); +time_t AuditListNode_get_connectTime(AuditListNode* aln); +time_t AuditListNode_get_duration(AuditListNode* aln); +AuditListNode* AuditListNode_get_nextNode(AuditListNode* aln); +/* other */ +time_t* AuditListNode_get_connectTimep(AuditListNode* aln); + +#endif diff --git a/src/audit_list_struct.c b/src/audit_list_struct.c new file mode 100644 index 0000000..24b8927 --- /dev/null +++ b/src/audit_list_struct.c @@ -0,0 +1,140 @@ +/* + * 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_list_struct.h" + +/* + * Function name: AuditList_new + * Description: Create and initialize new AuditList structure. + * Returns: Newly created AuditList structure. + */ + +AuditList* +AuditList_new() +{ + AuditList* tmp = calloc(1, sizeof(AuditList)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: AuditList_free + * Description: Free the memory allocated for AuditList structure. + * Arguments: al - pointer to pointer to AuditList structure. + */ + +void +AuditList_free(AuditList** al) +{ + if (al == NULL) { + return; + } + if ((*al) == NULL) { + return; + } + AuditList_clear((*al)); + free((*al)); + (*al) = NULL; +} + +/* + * Function name: AuditList_insert_back + * Description: Insert new node at the end of the list. + * Arguments: al - pointer to AuditList structure + * aln - pointer to AuditListNode structure + */ + +void +AuditList_insert_back(AuditList* al, AuditListNode* aln) +{ + if (al == NULL) { + return; + } + if (aln == NULL) { + return; + } + if (al->tail) { + al->tail->nextNode = aln; + } + else { + al->head = aln; + } + al->tail = aln; + aln->nextNode = NULL; +} + +/* + * Function name: AuditList_get_first + * Description: Get first node from the beginning of the list. + * Arguments: al - pointer to AuditList structure + * Returns: First node from the beginning of the list. + */ + +AuditListNode* +AuditList_get_first(AuditList* al) +{ + if (al == NULL) { + return NULL; + } + return al->head; +} + +/* + * Function name: AuditList_delete_first + * Description: Deletes first node from the beginning of the list. + * Arguments: al - pointer to AuditList structure + */ + +void +AuditList_delete_first(AuditList* al) +{ + AuditListNode* tmp = AuditList_get_first(al); + if (tmp == NULL) { + return; + } + if (tmp == al->tail) { /* this is the last node in the list */ + al->head = al->tail = NULL; + } + else { /* there are other nodes*/ + al->head = AuditListNode_get_nextNode(tmp); + } + AuditListNode_free(&tmp); +} + +/* + * Function name: AuditList_clear + * Description: Deletes all nodes from the list. + * Arguments: al - pointer to AuditList structure + */ + +void +AuditList_clear(AuditList* al) +{ + while (AuditList_get_first(al)) { + AuditList_delete_first(al); + } +} diff --git a/src/audit_list_struct.h b/src/audit_list_struct.h new file mode 100644 index 0000000..5880ec9 --- /dev/null +++ b/src/audit_list_struct.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_AUDIT_LIST_STRUCT_H +#define _JS_AUDIT_LIST_STRUCT_H + +#include "audit_list_node_struct.h" + +typedef struct auditlist { + AuditListNode* head; + AuditListNode* tail; +} AuditList; + +/* 'constructor' */ +AuditList* AuditList_new(); +/* 'destructor' */ +void AuditList_free(AuditList** al); +/* other */ +void AuditList_insert_back(AuditList* al, AuditListNode* aln); +AuditListNode* AuditList_get_first(AuditList* al); +void AuditList_delete_first(AuditList* al); +void AuditList_clear(AuditList* al); + +#endif diff --git a/src/buf_list_node_struct.c b/src/buf_list_node_struct.c new file mode 100644 index 0000000..415dd49 --- /dev/null +++ b/src/buf_list_node_struct.c @@ -0,0 +1,270 @@ +/* + * 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 "buf_list_node_struct.h" + +/* + * Function name: BufListNode_new + * Description: Create and initialize new BufListNode structure. + * Returns: Newly created BufListNode structure. + */ + +BufListNode* +BufListNode_new() +{ + BufListNode* tmp = calloc(1, sizeof(BufListNode)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: BufListNode_new_message + * Description: Create and initialize new BufListNode structure from given message + * with actual buffer pointer and message length. + * Arguments: actPtr - actual buffer pointer + * msgLen - length of the message + * message - message to be stored + * Returns: Newly created and initialized BufListNode structure. + */ + +BufListNode* +BufListNode_new_message(int actPtr, int msgLen, unsigned char* message) +{ + BufListNode* tmp = calloc(1, sizeof(BufListNode)); + if (tmp == NULL) { + return NULL; + } + BufListNode_set_message(tmp, message, msgLen); + BufListNode_set_actPtr(tmp, actPtr); + return tmp; +} + +/* + * Function name: BufListNode_free + * Description: Free the memory allocated for BufListNode structure. + * Arguments: bln - pointer to pointer to BufListNode structure + */ + +void +BufListNode_free(BufListNode** bln) +{ + if (bln == NULL) { + return; + } + if ((*bln) == NULL) { + return; + } + if ((*bln)->message) { + free((*bln)->message); + (*bln)->message = NULL; + } + free((*bln)); + (*bln) = NULL; +} + +/* + * Function name: BufListNode_set_actPtr + * Description: Set actual buffer pointer. + * Arguments: bln - pointer to BufListNode structure + * actPtr - actual buffer pointer + */ + +void +BufListNode_set_actPtr(BufListNode* bln, int actPtr) +{ + if (bln == NULL) { + return; + } + bln->actPtr = actPtr; +} + +/* + * Function name: BufListNode_set_msgLen + * Description: Set length of the message. + * Arguments: bln - pointer to BufListNode structure + * msgLen - length of the message + */ + +void +BufListNode_set_msgLen(BufListNode* bln, int msgLen) +{ + if (bln == NULL) { + return; + } + bln->msgLen = msgLen; +} + +/* + * Function name: BufListNode_set_message + * Description: Set message to be stored. + * Arguments: bln - pointer to BufListNode structure + * message - message to be stored + * msgLen - length of the message + */ + +void +BufListNode_set_message(BufListNode* bln, unsigned char* message, int msgLen) +{ + if (bln == NULL) { + return; + } + if (bln->message) { + free(bln->message); + bln->message = NULL; + } + BufListNode_set_actPtr(bln, 0); + BufListNode_set_msgLen(bln, 0); + if (message == NULL) { + return; + } + bln->message = calloc(1, msgLen); + if (bln->message == NULL) { + return; + } + memcpy(bln->message, message, msgLen); + BufListNode_set_msgLen(bln, msgLen); +} + +/* + * Function name: BufListNode_set_nextNode + * Description: Set next node pointer. + * Arguments: bln - pointer to BufListNode structure + * nextNode - next node pointer + */ + +void +BufListNode_set_nextNode(BufListNode* bln, BufListNode* nextNode) +{ + if (bln == NULL) { + return; + } + bln->nextNode = nextNode; +} + +/* + * Function name: BufListNode_get_actPtr + * Description: Get actual buffer pointer. + * Aguments: bln - pointer to BufListNode structure + * Returns: Actual buffer pointer. + */ + +int +BufListNode_get_actPtr(BufListNode* bln) +{ + if (bln == NULL) { + return -1; + } + return bln->actPtr; +} + +/* + * Function name: BufListNode_get_msgLen + * Description: Get length of the message. + * Arguments: bln - pointer to BufListNode structure + * Returns: Length of the message. + */ + +int +BufListNode_get_msgLen(BufListNode* bln) +{ + if (bln == NULL) { + return -1; + } + return bln->msgLen; +} + +/* + * Function name: BufListNode_get_message + * Description: Get stored message. + * Arguments: bln - pointer to BufListNode structure + * Returns: Stored message. + */ + +unsigned char* +BufListNode_get_message(BufListNode* bln) +{ + if (bln == NULL) { + return NULL; + } + return bln->message; +} + +/* + * Function name: BufListNode_get_nextNode + * Description: Get next node pointer. + * Arguments: bln - pointer to BufListNode structure + * Returns: Next BufListNode structure pointer or NULL, if there is no next one. + */ + +BufListNode* +BufListNode_get_nextNode(BufListNode* bln) +{ + if (bln == NULL) { + return NULL; + } + return bln->nextNode; +} + +/* + * Function name: BufListNode_readMessage + * Description: Reads the message from actual buffer pointer. + * Arguments: bln - pointer to BufListNode structure + * Returns: Tail of the message from actual buffer pointer. + */ + +unsigned char* +BufListNode_readMessage(BufListNode* bln) +{ + if (bln == NULL) { + return NULL; + } + return (&bln->message[BufListNode_get_actPtr(bln)]); +} + +/* + * Function name: BufListNode_readMessageLength + * Description: Get the amount of unread bytes in the message. + * Arguments: bln - pointer to BufListNode structure + * Returns: The amount of unread bytes in the message. + */ + +int +BufListNode_readMessageLength(BufListNode* bln) +{ + int tmp = 0; + if (bln == NULL) { + return -1; + } + if (BufListNode_get_message(bln) == NULL) { + return -1; + } + tmp = BufListNode_get_msgLen(bln) - BufListNode_get_actPtr(bln); + if (tmp < 0) { + return 0; + } + return tmp; +} diff --git a/src/buf_list_node_struct.h b/src/buf_list_node_struct.h new file mode 100644 index 0000000..36cc76a --- /dev/null +++ b/src/buf_list_node_struct.h @@ -0,0 +1,50 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_BUF_LIST_NODE_STRUCT_H +#define _JS_BUF_LIST_NODE_STRUCT_H + +typedef struct blnode { + int actPtr; + int msgLen; + unsigned char* message; + struct blnode* nextNode; +} BufListNode; + +/* 'constructors' */ +BufListNode* BufListNode_new(); +BufListNode* BufListNode_new_message(int actPtr, int msgLen, unsigned char* message); +/* 'destructor' */ +void BufListNode_free(BufListNode** bln); +/* setters */ +void BufListNode_set_actPtr(BufListNode* bln, int actPtr); +void BufListNode_set_msgLen(BufListNode* bln, int msgLen); +void BufListNode_set_message(BufListNode* bln, unsigned char* message, int msgLen); +void BufListNode_set_nextNode(BufListNode* bln, BufListNode* nextNode); +/* getters */ +int BufListNode_get_actPtr(BufListNode* bln); +int BufListNode_get_msgLen(BufListNode* bln); +unsigned char* BufListNode_get_message(BufListNode* bln); +BufListNode* BufListNode_get_nextNode(BufListNode* bln); +/* other methods */ +unsigned char* BufListNode_readMessage(BufListNode* bln); +int BufListNode_readMessageLength(BufListNode* bln); + +#endif diff --git a/src/buf_list_struct.c b/src/buf_list_struct.c new file mode 100644 index 0000000..52c8c43 --- /dev/null +++ b/src/buf_list_struct.c @@ -0,0 +1,140 @@ +/* + * 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 "buf_list_struct.h" + +/* + * Function name: BufList_new + * Description: Create and initialize new BufList structure. + * Returns: Newly created BufList structure. + */ + +BufList* +BufList_new() +{ + BufList* tmp = calloc(1, sizeof(BufList)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: BufList_free + * Description: Free the memory allocated for BufList structure. + * Arguments: bl - pointer to pointer to BufList structure. + */ + +void +BufList_free(BufList** bl) +{ + if (bl == NULL) { + return; + } + if ((*bl) == NULL) { + return; + } + BufList_clear((*bl)); + free((*bl)); + (*bl) = NULL; +} + +/* + * Function name: BufList_insert_back + * Description: Insert new node at the end of the list. + * Arguments: bl - pointer to BufList structure + * bln - pointer to BufListNode structure + */ + +void +BufList_insert_back(BufList* bl, BufListNode* bln) +{ + if (bl == NULL) { + return; + } + if (bln == NULL) { + return; + } + if (bl->tail) { + bl->tail->nextNode = bln; + } + else { + bl->head = bln; + } + bl->tail = bln; + bln->nextNode = NULL; +} + +/* + * Function name: BufList_get_first + * Description: Get first node from the beginning of the list. + * Arguments: bl - pointer to BufList structure + * Returns: First node from the beginning of the list. + */ + +BufListNode* +BufList_get_first(BufList* bl) +{ + if (bl == NULL) { + return NULL; + } + return bl->head; +} + +/* + * Function name: BufList_delete_first + * Description: Deletes first node from the beginning of the list. + * Arguments: bl - pointer to BufList structure + */ + +void +BufList_delete_first(BufList* bl) +{ + BufListNode* tmp = BufList_get_first(bl); + if (tmp == NULL) { + return; + } + if (tmp == bl->tail) { /* this is the last node in the list */ + bl->head = bl->tail = NULL; + } + else { /* there are other nodes*/ + bl->head = BufListNode_get_nextNode(tmp); + } + BufListNode_free(&tmp); +} + +/* + * Function name: BufList_clear + * Description: Deletes all nodes from the list. + * Arguments: bl - pointer to BufList structure + */ + +void +BufList_clear(BufList* bl) +{ + while (BufList_get_first(bl)) { + BufList_delete_first(bl); + } +} diff --git a/src/buf_list_struct.h b/src/buf_list_struct.h new file mode 100644 index 0000000..6ad0ec2 --- /dev/null +++ b/src/buf_list_struct.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_BUF_LIST_STRUCT_H +#define _JS_BUF_LIST_STRUCT_H + +#include "buf_list_node_struct.h" + +typedef struct buflist { + BufListNode* head; + BufListNode* tail; +} BufList; + +/* 'constructor' */ +BufList* BufList_new(); +/* 'destructor' */ +void BufList_free(BufList** bl); +/* other */ +void BufList_insert_back(BufList* bl, BufListNode* bln); +BufListNode* BufList_get_first(BufList* bl); +void BufList_delete_first(BufList* bl); +void BufList_clear(BufList* bl); + +#endif diff --git a/src/buflist.c b/src/buflist.c deleted file mode 100644 index e199b11..0000000 --- a/src/buflist.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 "buflist.h" - -int -insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff) -{ - blnodeT* newnode, *lastnode; - lastnode = newnode = *headRef; - while (newnode) { - lastnode = newnode; - newnode = newnode->next; - } - newnode = calloc(1, sizeof(blnodeT)); - newnode->next = NULL; - newnode->actptr = 0; - newnode->msglen = msglen - actptr; - newnode->buff = calloc(1, newnode->msglen); - if (newnode->buff == NULL) - return 1; - memcpy((char*)newnode->buff, (char*)buff+actptr, newnode->msglen); - if (lastnode) - lastnode->next = newnode; - else - *headRef = newnode; - return 0; -} - -int -deleteblnode(blnodeT** headRef) -{ - blnodeT* node = *headRef; - if (*headRef == NULL) - return 1; - *headRef = node->next; - if (node->buff != NULL) - free(node->buff); - free(node); - return 0; -} - -int -freebuflist(blnodeT** headRef) -{ - while (*headRef) { - deleteblnode(headRef); - } - return 0; -} diff --git a/src/buflist.h b/src/buflist.h deleted file mode 100644 index bc96e73..0000000 --- a/src/buflist.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004,2005 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _JS_BUFLIST_H -#define _JS_BUFLIST_H - -typedef struct blnode { - int actptr; - int msglen; - unsigned char* buff; - struct blnode* next; -} blnodeT; - -int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff); -int deleteblnode(blnodeT** headRef); -int freebuflist(blnodeT** headRef); - -#endif diff --git a/src/client_initialization.c b/src/client_initialization.c index c6022ae..82ac632 100644 --- a/src/client_initialization.c +++ b/src/client_initialization.c @@ -27,11 +27,11 @@ #include "ssl_routines.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, +initialize_client_stage1(char tunneltype, SslFd* master, char* name, char* manage, + HttpProxyOptions* hpo, char ipfam, SSL_CTX* ctx, unsigned char* buff, unsigned char* pass, char wanttoexit, char ignorepkeys) { - int n, nlen, elen, len; + int n, nlen, elen, len, tmp; unsigned int olen; X509* server_cert; const EVP_MD *md; @@ -42,7 +42,7 @@ initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manag unsigned char *key_buf = NULL; switch (tunneltype) { case 0: { - if (ip_connect(&(master->commfd), name, manage, ipfam)) { + if (ip_connect(&tmp, name, manage, ipfam)) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect_%s error for %s, %s", @@ -58,18 +58,21 @@ initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manag return 1; } } + SslFd_set_fd(master, tmp); break; } #ifdef HAVE_LIBPTHREAD case 1: { - if (initialize_http_proxy_client(&(master->commfd), name, manage, proxyname, proxyport, ipfam)) { + if (initialize_http_proxy_client(&tmp, name, manage, hpo, ipfam, ctx)) { #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); + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage, + HttpProxyOptions_get_proxyname(hpo), HttpProxyOptions_get_proxyport(hpo)); #else aflog(LOG_T_INIT, LOG_I_CRIT, - "http_proxy_connect error for %s, %s (proxy: %s, %s)", name, manage, proxyname, proxyport); + "http_proxy_connect error for %s, %s (proxy: %s, %s)", name, manage, + HttpProxyOptions_get_proxyname(hpo), HttpProxyOptions_get_proxyport(hpo)); #endif if (wanttoexit) { exit(1); @@ -78,6 +81,7 @@ initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manag return 1; } } + SslFd_set_fd(master, tmp); break; } #endif @@ -95,7 +99,7 @@ initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manag } master->ssl = SSL_new(ctx); - if (SSL_set_fd(master->ssl, master->commfd) != 1) { + if (SSL_set_fd(SslFd_get_ssl(master), SslFd_get_fd(master)) != 1) { aflog(LOG_T_INIT, LOG_I_CRIT, "Problem with initializing ssl... exiting"); if (wanttoexit) { @@ -201,11 +205,11 @@ initialize_client_stage1(char tunneltype, clifd* master, char* name, char* manag } int -initialize_client_stage2(char *type, clifd* master, int* usernum, unsigned char* buff, char wanttoexit) +initialize_client_stage2(char *type, SslFd* master, int* usernum, unsigned char* buff, char wanttoexit) { - send_message(*type, *master, buff, 5); + SslFd_send_message(*type | TYPE_SSL | TYPE_ZLIB, master, buff, 5); buff[0] = 0; - get_message(*type, *master, buff, -5); + SslFd_get_message(*type | TYPE_SSL | TYPE_ZLIB, master, buff, -5); if ( buff[0] == 0 ) { aflog(LOG_T_INIT, LOG_I_CRIT, @@ -256,10 +260,11 @@ initialize_client_stage2(char *type, clifd* master, int* usernum, unsigned char* } int -initialize_client_stage3(ConnectuserT** contable, clifd* master, int usernum, int* buflength, socklen_t* len, +initialize_client_stage3(ConnectUser*** contable, SslFd* master, int usernum, int* buflength, socklen_t* len, fd_set* allset, fd_set* wset, int* maxfdp1, char wanttoexit) { - (*contable) = calloc( usernum, sizeof(ConnectuserT)); + int i; + (*contable) = calloc(usernum, sizeof(ConnectUser*)); if ((*contable) == NULL) { aflog(LOG_T_INIT, LOG_I_CRIT, "Calloc error - unable to successfully communicate with server"); @@ -270,9 +275,22 @@ initialize_client_stage3(ConnectuserT** contable, clifd* master, int usernum, in return 1; } } + for (i = 0; i < usernum; ++i) { + (*contable)[i] = ConnectUser_new(); + if ((*contable)[i] == 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) { + if (getsockopt(SslFd_get_fd(master), SOL_SOCKET, SO_SNDBUF, buflength, len) == -1) { aflog(LOG_T_INIT, LOG_I_CRIT, "Can't get socket send buffer size - exiting..."); if (wanttoexit) { @@ -286,7 +304,7 @@ initialize_client_stage3(ConnectuserT** contable, clifd* master, int usernum, in FD_ZERO(allset); FD_ZERO(wset); - FD_SET(master->commfd, allset); - (*maxfdp1) = master->commfd + 1; + FD_SET(SslFd_get_fd(master), allset); + (*maxfdp1) = SslFd_get_fd(master) + 1; return 0; } diff --git a/src/client_initialization.h b/src/client_initialization.h index 89235c7..5c8c719 100644 --- a/src/client_initialization.h +++ b/src/client_initialization.h @@ -24,17 +24,19 @@ #include "stats.h" #include "logging.h" #include "http_proxy_client.h" +#include "http_proxy_options_struct.h" +#include "ssl_fd_struct.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, +int initialize_client_stage1(char tunneltype, SslFd* master, char* name, char* manage, + HttpProxyOptions* hpo, char ipfam, SSL_CTX* ctx, unsigned char* buff, unsigned char* pass, char wanttoexit, char ignorepkeys); -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, +int initialize_client_stage2(char *type, SslFd* master, int* usernum, unsigned char* buff, char wanttoexit); +int initialize_client_stage3(ConnectUser*** contable, SslFd* master, int usernum, int* buflength, socklen_t* len, fd_set* allset, fd_set* wset, int* maxfdp1, char wanttoexit); #endif diff --git a/src/client_remoteadmin.c b/src/client_remoteadmin.c new file mode 100644 index 0000000..4b89608 --- /dev/null +++ b/src/client_remoteadmin.c @@ -0,0 +1,198 @@ +/* + * 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_remoteadmin.h" + +int +client_admin(char type, SslFd* master, unsigned char* buff, int connectfd, char* id) +{ + fd_set rset, allset; + int maxfdp1, n, length, infd; + FILE *outfp, *infp; + + buff[0] = AF_S_ADMIN_LOGIN; + SslFd_send_message(type, master, buff, 5); + buff[0] = 0; + SslFd_get_message(type, master, buff, -5); + + if ( buff[0] == 0 ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Wrong password"); + return 1; + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Server is full"); + return 1; + } + if ( buff[0] != AF_S_ADMIN_LOGIN ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Incompatible server type or server full"); + return 1; + } + + aflog(LOG_T_MAIN, LOG_I_INFO, + "CLIENT STARTED mode: remote administration"); + + if (connectfd > 0) { + outfp = fdopen(connectfd, "w"); + if (outfp == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for writing"); + return 1; + } + infd = connectfd; + } + else { + infd = STDIN_FILENO; + outfp = stdout; + } + infp = fdopen(infd, "r"); + if (infp == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for reading"); + return 1; + } + + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s\n", (char*) buff); + fflush(outfp); + + FD_ZERO(&allset); + + FD_SET(SslFd_get_fd(master), &allset); + FD_SET(infd, &allset); + + maxfdp1 = (infd > SslFd_get_fd(master)) ? infd + 1 : SslFd_get_fd(master) + 1; + + if (id != NULL) { + buff[0] = AF_S_LOGIN; + buff[1] = buff[2] = 0; + n = strlen(id); + memcpy(&buff[5], id, n); + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "ID SENT: %s", id); + } + + while (1) { + rset = allset; + select(maxfdp1, &rset, NULL, NULL, NULL); + + if (FD_ISSET(SslFd_get_fd(master), &rset)) { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "masterfd: FD_ISSET"); + n = SslFd_get_message(type, master, buff, 5); + if (n != 5) { + 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); + continue; /* what happened? */ + } + } + if (n != 0) + return 1; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: premature quit --> exiting..."); + return 1; + } + if (buff[0] == AF_S_CLOSING) { + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + return 0; + } + if (buff[0] != AF_S_ADMIN_CMD) { + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: wrong message --> exiting"); + return 1; + } + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + switch (buff[1]) { + case AF_RA_STATUS_OK: { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd successful"); + } + case AF_RA_FAILED: { + if (buff[1] == AF_RA_FAILED) { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd failed"); + } + } + case AF_RA_UNDEFINED: { + if (buff[1] == AF_RA_UNDEFINED) { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "SERVER: unknown cmd"); + } + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s", (char*) buff); + fflush(outfp); + break; + } + case AF_RA_KICKED: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); + return 1; + break; + } + default: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + return 1; + } + } + } + + if (FD_ISSET(infd, &rset)) { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "infd: FD_ISSET"); + if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "CLIENT CLOSED cg: %ld bytes", getcg()); + return 0; + } + n = strlen((char*) &buff[5]); + if ((n > 0) && (buff[n+4] == '\n')) { + --n; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = AF_RA_CMD; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); + } + } +} diff --git a/src/client_remoteadmin.h b/src/client_remoteadmin.h new file mode 100644 index 0000000..b302b58 --- /dev/null +++ b/src/client_remoteadmin.h @@ -0,0 +1,38 @@ +/* + * 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_REMOTEADMIN_H +#define _JS_CLIENT_REMOTEADMIN_H + +#include +#include + +#include "remoteadmin_codes.h" +#include "activefor.h" +#include "network.h" +#include "logging.h" +#include "stats.h" +#include "make_ssl_handshake.h" +#include "ssl_fd_struct.h" + +int client_admin(char, SslFd*, unsigned char*, int, char*); + +#endif + diff --git a/src/client_reverse_udp.c b/src/client_reverse_udp.c index 8c78386..c0a1ef4 100644 --- a/src/client_reverse_udp.c +++ b/src/client_reverse_udp.c @@ -24,11 +24,13 @@ #include -void -initialize_client_reverse_udp(int* usernum, clifd* master, char* name, char* manage, char ipfam) +int +initialize_client_reverse_udp(int* usernum, SslFd* master, char* name, char* manage, char ipfam, + char wanttoexit) { + int tmp; (*usernum) = 1; - if (ip_connect(&(master->commfd), name, manage, ipfam)) { + if (ip_connect(&tmp, name, manage, ipfam)) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect_%s error for %s, %s", @@ -37,13 +39,21 @@ initialize_client_reverse_udp(int* usernum, clifd* master, char* name, char* man aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect error for %s, %s", name, manage); #endif - exit(1); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } - master->ssl = NULL; + SslFd_set_fd(master, tmp); + SslFd_set_ssl(master, NULL); + return 0; } void -client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* despor, char type, +client_reverse_udp(ConnectUser** contable, SslFd* master, char* desnam, char* despor, char type, unsigned char* buff, int buflength) { char ipfam; @@ -61,7 +71,7 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de ipfam |= 0x04; } #endif - if (ip_listen(&(contable[0].connfd), desnam, despor, &addrlen, ipfam)) { + if (ip_listen(&temp, desnam, despor, &addrlen, ipfam)) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_DEBUG, "udp_listen_%s error for %s, %s", @@ -72,18 +82,20 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de #endif exit(1); } + ConnectUser_set_connFd(contable[0], temp); 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); + FD_SET(SslFd_get_fd(master), &allset); + maxfdp1 = SslFd_get_fd(master) + 1; + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(contable[0]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(contable[0]) + 1); + FD_SET(ConnectUser_get_connFd(contable[0]), &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 (getsockopt(SslFd_get_fd(master), SOL_SOCKET, SO_SNDBUF, &temp, &len) != -1) { if (temp != buflength) { buflength = temp; aflog(LOG_T_CLIENT, LOG_I_WARNING, @@ -98,13 +110,13 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de 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); + if (FD_ISSET(ConnectUser_get_connFd(contable[0]), &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/ + n = recvfrom(ConnectUser_get_connFd(contable[0]), &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)) { + if (ioctl(SslFd_get_fd(master), SIOCOUTQ, ¬sent)) { aflog(LOG_T_CLIENT, LOG_I_CRIT, "ioctl error -> exiting..."); exit(1); @@ -115,7 +127,7 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de # else aflog(LOG_T_MAIN< LOG_I_DDEBUG, "TIOCOUTQ is defined"); - if (ioctl(master->commfd, TIOCOUTQ, ¬sent)) { + if (ioctl(SslFd_get_fd(master), TIOCOUTQ, ¬sent)) { aflog(LOG_T_CLIENT, LOG_I_CRIT, "ioctl error -> exiting..."); exit(1); @@ -146,15 +158,15 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de buff[2] = AF_S_MESSAGE; buff[3] = n >> 8; buff[4] = n; - writen(master->commfd, buff, n + 5); + writen(SslFd_get_fd(master), 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 (FD_ISSET(SslFd_get_fd(master), &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + n = readn(SslFd_get_fd(master), 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, @@ -164,7 +176,7 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de length = buff[3]; length = length << 8; length += buff[4]; /* this is length of message */ - n = readn(master->commfd, buff, length); + n = readn(SslFd_get_fd(master), buff, length); } else { n = 0; @@ -176,7 +188,7 @@ client_reverse_udp(ConnectuserT* contable, clifd* master, char* desnam, char* de } 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); + sendto(ConnectUser_get_connFd(contable[0]), 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 index c05f583..031dd8f 100644 --- a/src/client_reverse_udp.h +++ b/src/client_reverse_udp.h @@ -32,9 +32,11 @@ #include "activefor.h" #include "stats.h" #include "logging.h" +#include "ssl_fd_struct.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, +int initialize_client_reverse_udp(int* usernum, SslFd* master, char* name, char* manage, char ipfam, + char wanttoexit); +void client_reverse_udp(ConnectUser** contable, SslFd* 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 index 4828aeb..dee02d5 100644 --- a/src/client_shutdown.c +++ b/src/client_shutdown.c @@ -23,26 +23,19 @@ #include "client_shutdown.h" void -close_connections(int usernum, ConnectuserT** contable) +close_connections(int usernum, ConnectUser*** 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); + if ((ConnectUser_get_state((*contable)[i]) == S_STATE_OPEN) || + (ConnectUser_get_state((*contable)[i]) == S_STATE_STOPPED)) { + close(ConnectUser_get_connFd((*contable)[i])); } + ConnectUser_free(&(*contable)[i]); } 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 index 0572971..e0cf267 100644 --- a/src/client_shutdown.h +++ b/src/client_shutdown.h @@ -25,7 +25,6 @@ #include "activefor.h" -void close_connections(int usernum, ConnectuserT** contable); -void clear_master_connection(clifd* master); +void close_connections(int usernum, ConnectUser*** contable); #endif diff --git a/src/clientnames.c b/src/clientnames.c index 414c506..4fee9a8 100644 --- a/src/clientnames.c +++ b/src/clientnames.c @@ -29,13 +29,13 @@ get_clientname(RealmT* pointer, int client) { static char clientname[10]; - if (pointer->clitable[client].clientid == NULL) { + if (ConnectClient_get_sClientId(pointer->clitable[client]) == NULL) { memset(clientname, 0, 10); - sprintf(clientname, "%d", pointer->clitable[client].clientnum); + sprintf(clientname, "%d", ConnectClient_get_clientId(pointer->clitable[client])); return clientname; } - return pointer->clitable[client].clientid; + return ConnectClient_get_sClientId(pointer->clitable[client]); } int @@ -45,9 +45,9 @@ get_clientid(RealmT* pointer, char* clientname) char guard; for (i = 0; i < pointer->clinum; ++i) { - if (pointer->clitable[i].clientid != NULL) { - if (strcmp(clientname, pointer->clitable[i].clientid) == 0) { - return pointer->clitable[i].clientnum; + if (ConnectClient_get_sClientId(pointer->clitable[i]) != NULL) { + if (strcmp(clientname, ConnectClient_get_sClientId(pointer->clitable[i])) == 0) { + return ConnectClient_get_clientId(pointer->clitable[i]); } } } @@ -55,7 +55,7 @@ get_clientid(RealmT* pointer, char* clientname) if (sscanf(clientname, "%d%c", &i, &guard) == 1) { n = get_clientnumber(pointer, i); if ((n >= 0) && (n < pointer->clinum)) { - if (pointer->clitable[n].clientid == NULL) { + if (ConnectClient_get_sClientId(pointer->clitable[n]) == NULL) { return i; } } @@ -68,7 +68,7 @@ get_clientnumber(RealmT* pointer, int clientid) { int i; for (i = 0; i < pointer->clinum; ++i) { - if (pointer->clitable[i].clientnum == clientid) { + if (ConnectClient_get_clientId(pointer->clitable[i]) == clientid) { return i; } } @@ -81,13 +81,13 @@ get_raclientname(RealmT* pointer, int client) { static char clientname[10]; - if (pointer->raclitable[client].clientid == NULL) { + if (ConnectClient_get_sClientId(pointer->raclitable[client]) == NULL) { memset(clientname, 0, 10); - sprintf(clientname, "%d", pointer->raclitable[client].clientnum); + sprintf(clientname, "%d", ConnectClient_get_clientId(pointer->raclitable[client])); return clientname; } - return pointer->raclitable[client].clientid; + return ConnectClient_get_sClientId(pointer->raclitable[client]); } int @@ -97,9 +97,9 @@ get_raclientid(RealmT* pointer, char* clientname) char guard; for (i = 0; i < pointer->raclinum; ++i) { - if (pointer->raclitable[i].clientid != NULL) { - if (strcmp(clientname, pointer->raclitable[i].clientid) == 0) { - return pointer->raclitable[i].clientnum; + if (ConnectClient_get_sClientId(pointer->raclitable[i]) != NULL) { + if (strcmp(clientname, ConnectClient_get_sClientId(pointer->raclitable[i])) == 0) { + return ConnectClient_get_clientId(pointer->raclitable[i]); } } } @@ -107,7 +107,7 @@ get_raclientid(RealmT* pointer, char* clientname) if (sscanf(clientname, "%d%c", &i, &guard) == 1) { n = get_raclientnumber(pointer, i); if ((n >= 0) && (n < pointer->raclinum)) { - if (pointer->raclitable[n].clientid == NULL) { + if (ConnectClient_get_sClientId(pointer->raclitable[n]) == NULL) { return i; } } @@ -121,7 +121,7 @@ get_raclientnumber(RealmT* pointer, int clientid) { int i; for (i = 0; i < pointer->raclinum; ++i) { - if (pointer->raclitable[i].clientnum == clientid) { + if (ConnectClient_get_clientId(pointer->raclitable[i]) == clientid) { return i; } } diff --git a/src/connect_client_struct.c b/src/connect_client_struct.c new file mode 100644 index 0000000..a121eeb --- /dev/null +++ b/src/connect_client_struct.c @@ -0,0 +1,710 @@ +/* + * 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 "string_functions.h" +#include "timeval_functions.h" +#include "connect_client_struct.h" + +/* + * Function name: ConnectClient_new + * Description: Create and initialize new ConnectClient structure. + * Returns: Pointer to newly created ConnectClient structure. + */ + +ConnectClient* +ConnectClient_new() +{ + ConnectClient* tmp = calloc(1, sizeof(ConnectClient)); + if (tmp == NULL) { + return NULL; + } + tmp->sslFd = SslFd_new(); + if (tmp->sslFd == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + tmp->auditList = AuditList_new(); + if (tmp->auditList == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + tmp->header = HeaderBuffer_new(); + if (tmp->header == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + return tmp; +} + +/* + * Function name: ConnectClient_free + * Description: Free the memory allocated for ConnectClient structure. + * Arguments: cc - pointer to pointer to ConnectClient structure + */ + +void +ConnectClient_free(ConnectClient** cc) +{ + SslFd* sftmp; + AuditList* altmp; + if (cc == NULL) { + return; + } + if ((*cc) == NULL) { + return; + } + sftmp = ConnectClient_get_sslFd((*cc)); + altmp = ConnectClient_get_auditList((*cc)); + SslFd_free(&sftmp); + AuditList_free(&altmp); + if ((*cc)->users) { + free((*cc)->users); + (*cc)->users = NULL; + } + if ((*cc)->sClientId) { + free((*cc)->sClientId); + (*cc)->sClientId = NULL; + } + free((*cc)); + (*cc) = NULL; +} + +/* + * Function name: ConnectClient_set_state + * Description: Set state of the connected client. + * Arguments: cc - pointer to ConnectClient structure + * state - state of the connected client + */ + +void +ConnectClient_set_state(ConnectClient* cc, char state) +{ + if (cc == NULL) { + return; + } + cc->state = state; +} + +/* + * Function name: ConnectClient_set_sslFd + * Description: Set SslFd structure. + * Arguments: cc - pointer to ConnectClient structure + * sf - SslFd structure + */ + +void +ConnectClient_set_sslFd(ConnectClient* cc, SslFd* sf) +{ + SslFd* sftmp; + if (cc == NULL) { + return; + } + sftmp = ConnectClient_get_sslFd(cc); + SslFd_free(&sftmp); + cc->sslFd = sf; +} + +/* + * Function name: ConnectClient_set_timer + * Description: Set timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * timer - timer of the client used for internal time counting + */ + +void +ConnectClient_set_timer(ConnectClient* cc, struct timeval timer) +{ + if (cc == NULL) { + return; + } + cc->timer = timer; +} + +/* + * Function name: ConnectClient_set_users + * Description: Set users descriptor table. + * Arguments: cc - pointer to ConnectClient structure + * users - users descriptor table + */ + +void +ConnectClient_set_users(ConnectClient* cc, int* users) +{ + if (cc == NULL) { + return; + } + if (cc->users) { + free(cc->users); + } + cc->users = users; +} + +/* + * Functions name: ConnectClient_set_connected + * Description: Set number of connected users. + * Arguments: cc - pointer to ConnectClient structure + * connected - number of connected users + */ + +void +ConnectClient_set_connected(ConnectClient* cc, int connected) +{ + if (cc == NULL) { + return; + } + cc->connected = connected; +} + +/* + * Function name: ConnectClient_set_limit + * Description: Set limit of connected users. + * Arguments: cc - pointer to ConnectClient structure + * limit - limit of connected users + */ + +void +ConnectClient_set_limit(ConnectClient* cc, int limit) +{ + if (cc == NULL) { + return; + } + cc->limit = limit; +} + +/* + * Function name: ConnectClient_set_listenFd + * Description: Set listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * listenFd - listen socket descriptor + */ + +void +ConnectClient_set_listenFd(ConnectClient* cc, int listenFd) +{ + if (cc == NULL) { + return; + } + cc->listenFd = listenFd; +} + +/* + * Function name: ConnectClient_set_usrCliPair + * Description: Set user-client pair number. + * Arguments: cc - pointer to ConnectClient structure + * usrCliPair - user-client pair number + */ + +void +ConnectClient_set_usrCliPair(ConnectClient* cc, int usrCliPair) +{ + if (cc == NULL) { + return; + } + cc->usrCliPair = usrCliPair; +} + +/* + * Function name: ConnectClient_set_clientId + * Description: Set client identification number. + * Arguments: cc - pointer to ConnectClient structure + * clientId - client identification number + */ + +void +ConnectClient_set_clientId(ConnectClient* cc, int clientId) +{ + if (cc == NULL) { + return; + } + cc->clientId = clientId; +} + +/* + * Function name: ConnectClient_set_connectTime + * Description: Set start time of the connection. + * Arguments: cc - pointer to ConnectClient structure + * connectTime - start time of the connection + */ + +void +ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime) +{ + if (cc == NULL) { + return; + } + cc->connectTime = connectTime; +} + +/* + * Function name: ConnectClient_set_sClientId + * Description: Set client identification string. + * Arguments: cc - pointer to ConnectClient structure + * sClientId - client identification string + */ + +void +ConnectClient_set_sClientId(ConnectClient* cc, char* sClientId) +{ + if (cc == NULL) { + return; + } + string_cp(&(cc->sClientId), sClientId); +} + +/* + * Function name: ConnectClient_set_nameBuf + * Description: Set name of the client. + * Arguments: cc - pointer to ConnectClient structure + * nameBuf - name of the client + */ + +void +ConnectClient_set_nameBuf(ConnectClient* cc, char* nameBuf) +{ + if (cc == NULL) { + return; + } + memset(cc->nameBuf, 0, 128); + strncpy(cc->nameBuf, nameBuf, 127); +} + +/* + * Function name: ConnectClient_set_portBuf + * Description: Set port from which client is connected. + * Arguments: cc - pointer to ConnectClient structure + * portBuf - port from which client is connected + */ + +void +ConnectClient_set_portBuf(ConnectClient* cc, char* portBuf) +{ + if (cc == NULL) { + return; + } + memset(cc->portBuf, 0, 7); + strncpy(cc->portBuf, portBuf, 6); +} + +/* + * Function name: ConnectClient_set_tunnelType + * Description: Set tupe of the client tunnel. + * Arguments: cc - pointer to ConnectClient structure + * tunnelType - tupe of the client tunnel + */ + +void +ConnectClient_set_tunnelType(ConnectClient* cc, char tunnelType) +{ + if (cc == NULL) { + return; + } + cc->tunnelType = tunnelType; +} + +/* + * Function name: ConnectClient_set_auditList + * Description: Set audit list for the audit feature. + * Arguments: cc - pointer to ConnectClient structure + * al - audit list for the audit feature + */ + +void +ConnectClient_set_auditList(ConnectClient* cc, AuditList* al) +{ + AuditList* altmp; + if (cc == NULL) { + return; + } + altmp = ConnectClient_get_auditList(cc); + AuditList_free(&altmp); + cc->auditList = al; +} + +/* + * Function name: ConnectClient_set_header + * Description: Set header buffer for incomplete headers. + * Arguments: cc - pointer to ConnectClient structure + * hb - header buffer for incomplete headers + */ + +void +ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb) +{ + HeaderBuffer* hbtmp; + if (cc == NULL) { + return; + } + hbtmp = ConnectClient_get_header(cc); + HeaderBuffer_free(&hbtmp); + cc->header = hb; +} + +/* + * Function name: ConnectClient_get_state + * Description: Get state of the connected client. + * Arguments: cc - pointer to ConnectClient structure + * Returns: State of the connected client. + */ + +char +ConnectClient_get_state(ConnectClient* cc) +{ + if (cc == NULL) { + return CONNECTCLIENT_STATE_UNKNOWN; + } + return cc->state; +} + +/* + * Function name: ConnectClient_get_sslFd + * Description: Get SslFd structure. + * Arguments: cc - pointer to ConnectClient structure + * Returns: SslFd structure. + */ + +SslFd* +ConnectClient_get_sslFd(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->sslFd; +} + +/* + * Function name: ConnectClient_get_timer + * Description: Get timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Timer of the client used for internal time counting. + */ + +struct timeval +ConnectClient_get_timer(ConnectClient* cc) +{ + if (cc == NULL) { + return timeval_create(0, 0); + } + return cc->timer; +} + +/* + * Function name: ConnectClient_get_users + * Description: Get users descriptor table. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Users descriptor table. + */ + +int* +ConnectClient_get_users(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->users; +} + +/* + * Function name: ConnectClient_get_connected + * Description: Get number of connected users. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Number of connected users. + */ + +int +ConnectClient_get_connected(ConnectClient* cc) +{ + if (cc == NULL) { + return -1; + } + return cc->connected; +} + +/* + * Function name: ConnectClient_get_limit + * Description: Get limit of connected users. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Limit of connected users. + */ + +int +ConnectClient_get_limit(ConnectClient* cc) +{ + if (cc == NULL) { + return -1; + } + return cc->limit; +} + +/* + * Function name: ConnectClient_get_listenFd + * Description: Get listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Listen socket descriptor. + */ + +int +ConnectClient_get_listenFd(ConnectClient* cc) +{ + if (cc == NULL) { + return -1; + } + return cc->listenFd; +} + +/* + * Function name: ConnectClient_get_usrCliPair + * Description: Get user-client pair number. + * Arguments: cc - pointer to ConnectClient structure + * Returns: User-client pair number. + */ + +int +ConnectClient_get_usrCliPair(ConnectClient* cc) +{ + if (cc == NULL) { + return -1; + } + return cc->usrCliPair; +} + +/* + * Function name: ConnectClient_get_clientId + * Description: Get client identification number. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Client identification number. + */ + +int +ConnectClient_get_clientId(ConnectClient* cc) +{ + if (cc == NULL) { + return -1; + } + return cc->clientId; +} + +/* + * Function name: ConnectClient_get_connectTime + * Description: Get start time of the connection. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Start time of the connection. + */ + +time_t +ConnectClient_get_connectTime(ConnectClient* cc) +{ + if (cc == NULL) { + return 0; + } + return cc->connectTime; +} + +/* + * Function name: ConnectClient_get_sClientId + * Description: Get client identification string. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Client identification string. + */ + +char* +ConnectClient_get_sClientId(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->sClientId; +} + +/* + * Function name: ConnectClient_get_nameBuf + * Description: Get name of the client. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Name of the client. + */ + +char* +ConnectClient_get_nameBuf(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->nameBuf; +} + +/* + * Function name: ConnectClient_get_portBuf + * Description: Get port from which client is connected. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Port from which client is connected. + */ + +char* +ConnectClient_get_portBuf(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->portBuf; +} + +/* + * Function name: ConnectClient_get_tunnelType + * Description: Get tupe of the client tunnel. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Tupe of the client tunnel. + */ + +char +ConnectClient_get_tunnelType(ConnectClient* cc) +{ + if (cc == NULL) { + return CONNECTCLIENT_TUNNELTYPE_UNKNOWN; + } + return cc->tunnelType; +} + +/* + * Function name: ConnectClient_get_auditList + * Description: Get audit list for the audit feature. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Audit list for the audit feature. + */ + +AuditList* +ConnectClient_get_auditList(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->auditList; +} + +/* + * Function name: ConnectClient_get_header + * Description: Get header buffer for incomplete headers. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Header buffer for incomplete headers. + */ + +HeaderBuffer* +ConnectClient_get_header(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return cc->header; +} + +/* + * Function name: ConnectClient_create_users + * Description: Create user descriptor table. Memory for the table is allocated according + * to the previously set 'limit' value. All the descriptors are set to -1. + * Arguments: cc - pointer to ConnectClient structure + * Returns: >0 - there were some problems with memory allocation + * 0 - everything was ok + */ + +int +ConnectClient_create_users(ConnectClient* cc) +{ + int i, limit; + if (cc == NULL) { + return 1; + } + limit = ConnectClient_get_limit(cc); + if (limit == -1) { + return 2; + } + cc->users = malloc(limit * sizeof(int)); + if (cc->users == NULL) { + return 3; + } + for (i = 0; i < limit; ++i) { + cc->users[i] = -1; + } + return 0; +} + +/* + * Function name: ConnectClient_get_timerp + * Description: Get pointer to timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Pointer to timer of the client used for internal time counting. + */ + +struct timeval* +ConnectClient_get_timerp(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return (&(cc->timer)); +} + +/* + * Function name: ConnectClient_increase_connected + * Description: Increase number of connected users. + * Arguments: cc - pointer to ConnectClient structure + */ + +void +ConnectClient_increase_connected(ConnectClient* cc) +{ + if (cc == NULL) { + return; + } + ConnectClient_set_connected(cc, ConnectClient_get_connected(cc) + 1); +} + +/* + * Function name: ConnectClient_decrease_connected + * Description: Decrease number of connected users. + * Arguments: cc - pointer to ConnectClient structure + */ + +void +ConnectClient_decrease_connected(ConnectClient* cc) +{ + if (cc == NULL) { + return; + } + ConnectClient_set_connected(cc, ConnectClient_get_connected(cc) - 1); +} + +/* + * Function name: ConnectClient_get_listenFdp + * Description: Get pointer to listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Pointer to listen socket descriptor. + */ + +int* +ConnectClient_get_listenFdp(ConnectClient* cc) +{ + if (cc == NULL) { + return NULL; + } + return (&(cc->listenFd)); +} diff --git a/src/connect_client_struct.h b/src/connect_client_struct.h new file mode 100644 index 0000000..b5891e6 --- /dev/null +++ b/src/connect_client_struct.h @@ -0,0 +1,106 @@ +/* + * 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_CONNECT_CLIENT_STRUCT_H +#define _JS_CONNECT_CLIENT_STRUCT_H + +#include + +#include "ssl_fd_struct.h" +#include "audit_list_struct.h" +#include "header_buffer_struct.h" + +#define CONNECTCLIENT_STATE_UNKNOWN -1 +#define CONNECTCLIENT_STATE_FREE 0 +#define CONNECTCLIENT_STATE_CONNECTING 1 +#define CONNECTCLIENT_STATE_AUTHORIZING 2 +#define CONNECTCLIENT_STATE_ACCEPTED 3 + +#define CONNECTCLIENT_TUNNELTYPE_UNKNOWN -1 +#define CONNECTCLIENT_TUNNELTYPE_DIRECT 0 +#define CONNECTCLIENT_TUNNELTYPE_HTTPPROXY 1 +#define CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY 2 + +typedef struct { + char state; + SslFd* sslFd; + struct timeval timer; + int* users; + int connected; + int limit; + int listenFd; + int usrCliPair; + int clientId; + time_t connectTime; + char* sClientId; + char nameBuf[128]; + char portBuf[7]; + char tunnelType; + AuditList* auditList; + HeaderBuffer* header; +} ConnectClient; + +/* 'constructor' */ +ConnectClient* ConnectClient_new(); +/* 'destructor' */ +void ConnectClient_free(ConnectClient** cc); +/* setters */ +void ConnectClient_set_state(ConnectClient* cc, char state); +void ConnectClient_set_sslFd(ConnectClient* cc, SslFd* sf); +void ConnectClient_set_timer(ConnectClient* cc, struct timeval timer); +void ConnectClient_set_users(ConnectClient* cc, int* users); +void ConnectClient_set_connected(ConnectClient* cc, int connected); +void ConnectClient_set_limit(ConnectClient* cc, int limit); +void ConnectClient_set_listenFd(ConnectClient* cc, int listenFd); +void ConnectClient_set_usrCliPair(ConnectClient* cc, int usrCliPair); +void ConnectClient_set_clientId(ConnectClient* cc, int clientId); +void ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime); +void ConnectClient_set_sClientId(ConnectClient* cc, char* sClientId); +void ConnectClient_set_nameBuf(ConnectClient* cc, char* nameBuf); +void ConnectClient_set_portBuf(ConnectClient* cc, char* portBuf); +void ConnectClient_set_tunnelType(ConnectClient* cc, char tunnelType); +void ConnectClient_set_auditList(ConnectClient* cc, AuditList* al); +void ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb); +/* getters */ +char ConnectClient_get_state(ConnectClient* cc); +SslFd* ConnectClient_get_sslFd(ConnectClient* cc); +struct timeval ConnectClient_get_timer(ConnectClient* cc); +int* ConnectClient_get_users(ConnectClient* cc); +int ConnectClient_get_connected(ConnectClient* cc); +int ConnectClient_get_limit(ConnectClient* cc); +int ConnectClient_get_listenFd(ConnectClient* cc); +int ConnectClient_get_usrCliPair(ConnectClient* cc); +int ConnectClient_get_clientId(ConnectClient* cc); +time_t ConnectClient_get_connectTime(ConnectClient* cc); +char* ConnectClient_get_sClientId(ConnectClient* cc); +char* ConnectClient_get_nameBuf(ConnectClient* cc); +char* ConnectClient_get_portBuf(ConnectClient* cc); +char ConnectClient_get_tunnelType(ConnectClient* cc); +AuditList* ConnectClient_get_auditList(ConnectClient* cc); +HeaderBuffer* ConnectClient_get_header(ConnectClient* cc); +/* other */ +int ConnectClient_create_users(ConnectClient* cc); +struct timeval* ConnectClient_get_timerp(ConnectClient* cc); +void ConnectClient_increase_connected(ConnectClient* cc); +void ConnectClient_decrease_connected(ConnectClient* cc); +int* ConnectClient_get_listenFdp(ConnectClient* cc); + +#endif diff --git a/src/connect_user_struct.c b/src/connect_user_struct.c new file mode 100644 index 0000000..ac133ba --- /dev/null +++ b/src/connect_user_struct.c @@ -0,0 +1,374 @@ +/* + * 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 "activefor.h" +#include "connect_user_struct.h" + +/* + * Function name: ConnectUser_new + * Description: Create and initialize new ConnectUser structure. + * Returns: Newly created ConnectUser structure. + */ + +ConnectUser* +ConnectUser_new() +{ + ConnectUser* tmp = calloc(1, sizeof(ConnectUser)); + if (tmp == NULL) { + return NULL; + } + tmp->bufList = BufList_new(); + if (tmp->bufList == NULL) { + ConnectUser_free(&tmp); + return NULL; + } + tmp->stats = UserStats_new(); + if (tmp->stats == NULL) { + ConnectUser_free(&tmp); + return NULL; + } + return tmp; +} + +/* + * Function name: ConnectUser_free + * Description: Free the memory allocated for ConnectUser structure. + * Arguments: cu - pointer to pointer to ConnectUser structure + */ + +void +ConnectUser_free(ConnectUser** cu) +{ + BufList* bftmp; + UserStats* ustmp; + if (cu == NULL) { + return; + } + if ((*cu) == NULL) { + return; + } + bftmp = ConnectUser_get_bufList((*cu)); + ustmp = ConnectUser_get_stats((*cu)); + BufList_free(&bftmp); + UserStats_free(&ustmp); + free((*cu)); + (*cu) = NULL; +} + +/* + * Function name: ConnectUser_set_state + * Description: Set state of the connected user. + * Arguments: cu - pointer to ConnectUser structure + * state - state of the connected User + */ + +void +ConnectUser_set_state(ConnectUser* cu, char state) +{ + if (cu == NULL) { + return; + } + cu->state = state; +} + +/* + * Function name: ConnectUser_set_connFd + * Description: Set connection's file descriptor. + * Arguments: cu - pointer to ConnectUser structure + * connFd - connection's file descriptor + */ + +void +ConnectUser_set_connFd(ConnectUser* cu, int connFd) +{ + if (cu == NULL) { + return; + } + cu->connFd = connFd; +} + +/* + * Function name: ConnectUser_set_whatClient + * Description: Set client number, to which this user is connected to. + * Arguments: cu - pointer to ConnectUser structure + * whatClient - client number, to which this user is connected to + */ + +void +ConnectUser_set_whatClient(ConnectUser* cu, int whatClient) +{ + if (cu == NULL) { + return; + } + cu->whatClient = whatClient; +} + +/* + * Function name: ConnectUser_set_userId + * Description: Set user identification number. + * Arguments: cu - pointer to ConnectUser structure + * userId - user identification number + */ + +void +ConnectUser_set_userId(ConnectUser* cu, int userId) +{ + if (cu == NULL) { + return; + } + cu->userId = userId; +} + +/* + * Function name: ConnectUser_set_connectTime + * Description: Set connect time of the user. + * Arguments: cu - pointer to ConnectUser structure + * connectTime - connect time of the user + */ + +void +ConnectUser_set_connectTime(ConnectUser* cu, time_t connectTime) +{ + if (cu == NULL) { + return; + } + cu->connectTime = connectTime; +} + +/* + * Function name: ConnectUser_set_nameBuf + * Description: Set name of the user. + * Arguments: cu - pointer to ConnectUser structure + * nameBuf - name of the user + */ + +void +ConnectUser_set_nameBuf(ConnectUser* cu, char* nameBuf) +{ + if (cu == NULL) { + return; + } + memset(cu->nameBuf, 0, 128); + strncpy(cu->nameBuf, nameBuf, 127); +} + +/* + * Function name: ConnectUser_set_portBuf + * Description: Set port from which user is connected. + * Arguments: cu - pointer to ConnectUser structure + * portBuf - port from which user is connected + */ + +void +ConnectUser_set_portBuf(ConnectUser* cu, char* portBuf) +{ + if (cu == NULL) { + return; + } + memset(cu->portBuf, 0, 7); + strncpy(cu->portBuf, portBuf, 6); +} + +/* + * Function name: ConnectUser_set_bufList + * Description: Set buffer list for incoming packets. + * Arguments: cu - pointer to ConnectUser structure + * bufList - buffer list for incoming packets + */ + +void +ConnectUser_set_bufList(ConnectUser* cu, BufList* bufList) +{ + BufList* bftmp; + if (cu == NULL) { + return; + } + bftmp = ConnectUser_get_bufList(cu); + BufList_free(&bftmp); + cu->bufList = bufList; +} + +/* + * Function name: ConnectUser_set_stats + * Description: Set stats object for this user. + * Arguments: cu - pointer to ConnectUser structure + * stats - stats object for this user + */ + +void +ConnectUser_set_stats(ConnectUser* cu, UserStats* stats) +{ + UserStats* ustmp; + if (cu == NULL) { + return; + } + ustmp = ConnectUser_get_stats(cu); + UserStats_free(&ustmp); + cu->stats = stats; +} + +/* + * Function name: ConnectUser_get_state + * Description: Get state of the connected user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: State of the connected user. + */ + +char +ConnectUser_get_state(ConnectUser* cu) +{ + if (cu == NULL) { + return S_STATE_CLEAR; + } + return cu->state; +} + +/* + * Function name: ConnectUser_get_connFd + * Description: Get connection's file descriptor. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Connection's file descriptor. + */ + +int +ConnectUser_get_connFd(ConnectUser* cu) +{ + if (cu == NULL) { + return -1; + } + return cu->connFd; +} + +/* + * Function name: ConnectUser_get_whatClient + * Description: Get client number, to which this user is connected to. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Client number, to which this user is connected to. + */ + +int +ConnectUser_get_whatClient(ConnectUser* cu) +{ + if (cu == NULL) { + return -1; + } + return cu->whatClient; +} + +/* + * Function name: ConnectUser_get_userId + * Description: Get user identification number. + * Arguments: cu - pointer to ConnectUser structure + * Returns: User identification number. + */ + +int +ConnectUser_get_userId(ConnectUser* cu) +{ + if (cu == NULL) { + return -1; + } + return cu->userId; +} + +/* + * Function name: ConnectUser_get_connectTime + * Description: Get connect time of the user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Connect time of the user. + */ + +time_t +ConnectUser_get_connectTime(ConnectUser* cu) +{ + if (cu == NULL) { + return 0; + } + return cu->connectTime; +} + +/* + * Function name: ConnectUser_get_nameBuf + * Description: Get name of the user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Name of the user. + */ + +char* +ConnectUser_get_nameBuf(ConnectUser* cu) +{ + if (cu == NULL) { + return NULL; + } + return cu->nameBuf; +} + +/* + * Function name: ConnectUser_get_portBuf + * Description: Get port from which user is connected. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Port from which user is connected. + */ + +char* +ConnectUser_get_portBuf(ConnectUser* cu) +{ + if (cu == NULL) { + return NULL; + } + return cu->portBuf; +} + +/* + * Function name: ConnectUser_get_bufList + * Description: Get buffer list for incoming packets. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Buffer list for incoming packets. + */ + +BufList* +ConnectUser_get_bufList(ConnectUser* cu) +{ + if (cu == NULL) { + return NULL; + } + return cu->bufList; +} + +/* + * Function name: ConnectUser_get_stats + * Description: Get stats object for this user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Stats object for this user. + */ + +UserStats* +ConnectUser_get_stats(ConnectUser* cu) +{ + if (cu == NULL) { + return NULL; + } + return cu->stats; +} diff --git a/src/connect_user_struct.h b/src/connect_user_struct.h new file mode 100644 index 0000000..2c7aeee --- /dev/null +++ b/src/connect_user_struct.h @@ -0,0 +1,67 @@ +/* + * 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_CONNECT_USER_STRUCT_H +#define _JS_CONNECT_USER_STRUCT_H + +#include + +#include "buf_list_struct.h" +#include "user_stats_struct.h" + +typedef struct { + char state; + int connFd; + int whatClient; + int userId; + time_t connectTime; + char nameBuf[128]; + char portBuf[7]; + BufList* bufList; + UserStats* stats; +} ConnectUser; + +/* 'constructor' */ +ConnectUser* ConnectUser_new(); +/* 'destructor' */ +void ConnectUser_free(ConnectUser** cu); +/* setters */ +void ConnectUser_set_state(ConnectUser* cu, char state); +void ConnectUser_set_connFd(ConnectUser* cu, int connFd); +void ConnectUser_set_whatClient(ConnectUser* cu, int whatClient); +void ConnectUser_set_userId(ConnectUser* cu, int userId); +void ConnectUser_set_connectTime(ConnectUser* cu, time_t connectTime); +void ConnectUser_set_nameBuf(ConnectUser* cu, char* nameBuf); +void ConnectUser_set_portBuf(ConnectUser* cu, char* portBuf); +void ConnectUser_set_bufList(ConnectUser* cu, BufList* bufList); +void ConnectUser_set_stats(ConnectUser* cu, UserStats* stats); +/* getters */ +char ConnectUser_get_state(ConnectUser* cu); +int ConnectUser_get_connFd(ConnectUser* cu); +int ConnectUser_get_whatClient(ConnectUser* cu); +int ConnectUser_get_userId(ConnectUser* cu); +time_t ConnectUser_get_connectTime(ConnectUser* cu); +char* ConnectUser_get_nameBuf(ConnectUser* cu); +char* ConnectUser_get_portBuf(ConnectUser* cu); +BufList* ConnectUser_get_bufList(ConnectUser* cu); +UserStats* ConnectUser_get_stats(ConnectUser* cu); + +#endif diff --git a/src/file.c b/src/file.c index 728b0c1..297503b 100644 --- a/src/file.c +++ b/src/file.c @@ -110,7 +110,7 @@ parsefile(char* name, int* status) { static ConfigurationT cfg; FILE* file = NULL; - int state, i, n, listencount, managecount; + int state, i, j, n, listencount, managecount; char buff[256]; char helpbuf1[256]; char helpbuf2[256]; @@ -187,8 +187,16 @@ parsefile(char* name, int* status) return cfg; } - for (i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include + +#include "header_buffer_struct.h" + +/* + * Function name: HeaderBuffer_new + * Description: Create and initialize new HeaderBuffer structure. + * Returns: Pointer to newly created HeaderBuffer structure. + */ + +HeaderBuffer* +HeaderBuffer_new() +{ + HeaderBuffer* tmp = calloc(1, sizeof(HeaderBuffer)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: HeaderBuffer_free + * Description: Free the memory allocated for HeaderBuffer structure. + * Arguments: hb - pointer to pointer to HeaderBuffer structure + */ + +void +HeaderBuffer_free(HeaderBuffer** hb) +{ + if (hb == NULL) { + return; + } + if ((*hb) == NULL) { + return; + } + free((*hb)); + (*hb) = NULL; +} + +/* + * Function name: HeaderBuffer_to_read + * Description: Evaluate how much bytes are needed to fill the header buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * Returns: How much bytes are needed to fill the header buffer. + */ + +int +HeaderBuffer_to_read(HeaderBuffer* hb) +{ + if (hb == NULL) { + return -1; + } + return (5 - hb->readed); +} + +/* + * Function name: HeaderBuffer_store + * Description: Store readed part of the header in the buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * buff - reader bytes + * n - how much bytes were readed + */ + +void +HeaderBuffer_store(HeaderBuffer* hb, unsigned char* buff, int n) +{ + if (hb == NULL) { + return; + } + if ((hb->readed + n) > 5) { + return; + } + if (n <= 0) { + return; + } + memcpy(&hb->tab[hb->readed], buff, n); + hb->readed += n; +} + +/* + * Function name: HeaderBuffer_restore + * Description: Restore the full header from the buffer. It's not checked, if the full header is in the buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * buff - place to restore the full header to + */ + +void +HeaderBuffer_restore(HeaderBuffer* hb, unsigned char* buff) +{ + if (hb == NULL) { + return; + } + memcpy(buff, hb->tab, 5); + hb->readed = 0; +} diff --git a/src/header_buffer_struct.h b/src/header_buffer_struct.h new file mode 100644 index 0000000..fe9d6e5 --- /dev/null +++ b/src/header_buffer_struct.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. + * + */ + +#ifndef _JS_HEADER_BUFFER_STRUCT_H +#define _JS_HEADER_BUFFER_STRUCT_H + +typedef struct { + unsigned char tab[5]; + int readed; +} HeaderBuffer; + +/* 'constructor' */ +HeaderBuffer* HeaderBuffer_new(); +/* 'destructor' */ +void HeaderBuffer_free(HeaderBuffer** hb); +/* other */ +int HeaderBuffer_to_read(HeaderBuffer* hb); +void HeaderBuffer_store(HeaderBuffer* hb, unsigned char* buff, int n); +void HeaderBuffer_restore(HeaderBuffer* hb, unsigned char* buff); + +#endif + diff --git a/src/http_proxy_client.c b/src/http_proxy_client.c index 2cd301a..9f0cc7c 100644 --- a/src/http_proxy_client.c +++ b/src/http_proxy_client.c @@ -26,15 +26,16 @@ #include "network.h" #include "stats.h" #include "logging.h" +#include "base64.h" #ifdef HAVE_LIBPTHREAD typedef struct { int sockfd; char *host; char *serv; - char *proxyname; - char *proxyport; + HttpProxyOptions* hpo; char type; + SSL_CTX* ctx; } proxy_argT; static void @@ -57,8 +58,10 @@ http_proxy_client(void *vptr) struct timeval tv; int timeout = 5; int tmp; - char *host, *serv, *proxyname, *proxyport; - char type; + char *host, *serv, *proxyname, *proxyport, *credentials, *name = ""; + char b64cred[100]; + char type, authtype, https; + SSL_CTX* ctx; proxy_argT *proxy_argptr; start_critical_section(); @@ -66,14 +69,60 @@ http_proxy_client(void *vptr) host = proxy_argptr->host; serv = proxy_argptr->serv; - proxyname = proxy_argptr->proxyname; - proxyport = proxy_argptr->proxyport; + proxyname = HttpProxyOptions_get_proxyname(proxy_argptr->hpo); + proxyport = HttpProxyOptions_get_proxyport(proxy_argptr->hpo); + credentials = HttpProxyOptions_get_proxyauth_cred(proxy_argptr->hpo); type = proxy_argptr->type; + authtype = HttpProxyOptions_get_proxyauth_type(proxy_argptr->hpo); conn.sockfd = proxy_argptr->sockfd; + https = HttpProxyOptions_is_https(proxy_argptr->hpo); + ctx = proxy_argptr->ctx; broadcast_condition(); end_critical_section(); + conn.postFd = SslFd_new(); + conn.getFd = SslFd_new(); + conn.tmpFd = SslFd_new(); + if ((conn.postFd == NULL) || (conn.getFd == NULL) || (conn.tmpFd == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + + if (https) { + name = "s"; + SslFd_set_ssl(conn.postFd, SSL_new(ctx)); + SslFd_set_ssl(conn.getFd, SSL_new(ctx)); + SslFd_set_ssl(conn.tmpFd, SSL_new(ctx)); + if ((SslFd_get_ssl(conn.postFd) == NULL) || + (SslFd_get_ssl(conn.getFd) == NULL) || + (SslFd_get_ssl(conn.tmpFd) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + } + + if (authtype == PROXYAUTH_TYPE_WRONG) { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "Wrong type of proxy authorizaton --> switching to no authorization"); + credentials = NULL; + } + + if (credentials) { + if (b64_ntop((unsigned char*)credentials, strlen(credentials), b64cred, 100) == -1) { + aflog(LOG_T_MAIN, LOG_I_ERR, + "Cannot encode credentials for proxy authorization"); + b64cred[0] = 0; + } + else { + if (authtype == PROXYAUTH_TYPE_NOTSET) { + authtype = PROXYAUTH_TYPE_BASIC; + } + } + } + FD_ZERO(&allset); tv.tv_usec = 0; tv.tv_sec = timeout; @@ -86,65 +135,111 @@ http_proxy_client(void *vptr) /* postfd */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: connecting (postfd)..."); - if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } - + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + 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" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + 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) { + "http%s proxy: writing POST request...", name); + if (http_write(https, 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)) { + "http%s proxy: connecting (getfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } + SslFd_set_fd(conn.getFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.getFd), SslFd_get_fd(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + 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) { + "http%s proxy: writing GET request...", name); + if (http_write(https, 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); + set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset); + set_fd(SslFd_get_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)) { + "http%s proxy: parsing header from getfd", name); + if (parse_header(conn.getFd, tab, &hdr, https)) { clean_return(conn.sockfd); } aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: checking hdr.type"); + "http%s proxy: checking hdr.type", name); 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..."); + "http%s proxy: reading message...", name); if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { clean_return(conn.sockfd); } @@ -155,46 +250,70 @@ http_proxy_client(void *vptr) if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: timeout"); + "http%s proxy: timeout", name); 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); + "http%s proxy: send T", name); + http_write(https, conn.postFd, (unsigned char*) "T", 1); conn.sent_ptr = 0; - clear_fd(&conn.postfd, &allset); + clear_sslFd(conn.postFd, &allset); /* postfd */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: connecting (postfd)..."); - if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } - + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + 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" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + 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) { + "http%s proxy: writing POST request...", name); + if (http_write(https, 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); + set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset); } else { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: send T"); - writen(conn.postfd, (unsigned char *) "T", 1); + "http%s proxy: send T", name); + http_write(https, conn.postFd, (unsigned char *) "T", 1); conn.sent_ptr += 1; } continue; @@ -203,21 +322,34 @@ http_proxy_client(void *vptr) /* sockfd */ if (FD_ISSET(conn.sockfd, &rset)) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: FD_ISSET(conn.sockfd)"); + "http%s proxy: FD_ISSET(conn.sockfd)", name); 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)) { + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + "http%s proxy: send Q", name); + http_write(https, conn.postFd, (unsigned char *) "Q", 1); clean_return(conn.sockfd); } conn.buf[0] = 'M'; @@ -225,36 +357,60 @@ http_proxy_client(void *vptr) 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); + "http%s proxy: send message", name); + http_write(https, 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); + clear_sslFd(conn.postFd, &allset); /* postfd */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: connecting (postfd)..."); - if (ip_connect(&conn.postfd, proxyname, proxyport, type)) { + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + 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" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + 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) { + "http%s proxy: writing POST request...", name); + if (http_write(https, 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) { + "http%s proxy: writing old data...", name); + if (http_write(https, conn.postFd, (unsigned char *) (conn.buf+conn.ptr), conn.length) <= 0) { clean_return(conn.sockfd); } } @@ -262,62 +418,84 @@ http_proxy_client(void *vptr) conn.ptr = 0; conn.length = 0; - set_fd(conn.postfd, &maxfdp1, &allset); + set_fd(SslFd_get_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); + "http%s proxy: send message", name); + http_write(https, conn.postFd, (unsigned char *) conn.buf, 5+n); conn.sent_ptr += 5+n; } } /* getfd */ - if (FD_ISSET(conn.getfd, &rset)) { + if (FD_ISSET(SslFd_get_fd(conn.getFd), &rset)) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: FD_ISSET(conn.getfd)"); - n = read(conn.getfd, tab, 9000); + "http%s proxy: FD_ISSET(conn.getfd)", name); + n = http_read(https, conn.getFd, (unsigned char*) tab, 9000); conn.received += n; if (n == 0) { conn.received = 0; - FD_CLR(conn.getfd, &allset); - close(conn.getfd); + clear_sslFd(conn.getFd, &allset); /* getfd */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: connecting (getfd)..."); - if (ip_connect(&conn.getfd, proxyname, proxyport, type)) { + "http%s proxy: connecting (getfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type)) { clean_return(conn.sockfd); } + SslFd_set_fd(conn.getFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.getFd), SslFd_get_fd(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + 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); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + 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) { + "http%s proxy: writing GET request...", name); + if (http_write(https, 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)) { + "http%s proxy: parsing header from getfd", name); + if (parse_header(conn.getFd, tab, &hdr, https)) { clean_return(conn.sockfd); } aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: checking hdr.type"); + "http%s proxy: checking hdr.type", name); if (hdr.type != H_TYPE_OK) { clean_return(conn.sockfd); } - set_fd(conn.getfd, &maxfdp1, &allset); + set_fd(SslFd_get_fd(conn.getFd), &maxfdp1, &allset); if (hdr.length) { conn.received += hdr.length; aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: reading message..."); + "http%s proxy: reading message...", name); if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { clean_return(conn.sockfd); } @@ -331,10 +509,10 @@ http_proxy_client(void *vptr) } /* postfd */ - if (FD_ISSET(conn.postfd, &rset)) { + if (FD_ISSET(SslFd_get_fd(conn.postFd), &rset)) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: FD_ISSET(conn.postfd)"); - clear_fd(&conn.postfd, &allset); + "http%s proxy: FD_ISSET(conn.postfd)", name); + clear_sslFd(conn.postFd, &allset); conn.state = C_CLOSED; } } @@ -343,7 +521,7 @@ http_proxy_client(void *vptr) int initialize_http_proxy_client(int* sockfd, const char *host, const char *serv, - const char *proxyname, const char *proxyport, const char type) + HttpProxyOptions* hpo, const char type, SSL_CTX* ctx) { int retval; int sockets[2]; @@ -355,7 +533,7 @@ initialize_http_proxy_client(int* sockfd, const char *host, const char *serv, } (*sockfd) = sockets[0]; - if (proxyname == NULL) { + if (HttpProxyOptions_get_proxyname(hpo) == NULL) { return 1; } @@ -363,10 +541,10 @@ initialize_http_proxy_client(int* sockfd, const char *host, const char *serv, arg.host = (char*) host; arg.serv = (char*) serv; - arg.proxyname = (char*) proxyname; - arg.proxyport = (char*) proxyport; + arg.hpo = hpo; arg.type = (char) type; arg.sockfd = sockets[1]; + arg.ctx = ctx; retval = pthread_create(&proxy_thread, NULL, &http_proxy_client, &arg); diff --git a/src/http_proxy_client.h b/src/http_proxy_client.h index f8ec5b7..31044f3 100644 --- a/src/http_proxy_client.h +++ b/src/http_proxy_client.h @@ -18,10 +18,12 @@ * */ +#include "http_proxy_options_struct.h" + #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); + HttpProxyOptions* hpo, const char type, SSL_CTX* ctx); #endif diff --git a/src/http_proxy_functions.c b/src/http_proxy_functions.c index b8e5849..2c3d680 100644 --- a/src/http_proxy_functions.c +++ b/src/http_proxy_functions.c @@ -55,10 +55,10 @@ delete_user(connection* cnts, int i, fd_set* allset) "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); + clear_sslFd(cnts[i].postFd, allset); } if ((cnts[i].type == 0) && (!(cnts[i].state & C_GET_WAIT))) { - clear_fd(&(cnts[i].getfd), allset); + clear_sslFd(cnts[i].getFd, allset); } cnts[i].state = C_CLOSED; cnts[i].sent_ptr = cnts[i].ptr = cnts[i].length = 0; @@ -66,11 +66,16 @@ delete_user(connection* cnts, int i, fd_set* allset) } int -parse_header(int fd, char* tab, header* hdr) +parse_header(SslFd* sf, char* tab, header* hdr, char https) { int n, i, j, state = 0; char tmpt[100]; - n = read(fd, tab, 9000); + if (https) { + n = SSL_read(SslFd_get_ssl(sf), tab, 9000); + } + else { + n = read(SslFd_get_fd(sf), tab, 9000); + } hdr->allreaded = n; i = j = 0; memset(tmpt, 0, 100); @@ -265,3 +270,62 @@ read_message(int fd, int length, connection* client, char* tab, int ptr) } return 0; } + +/* + * Function name: clear sslFd + * Description: Close the socket encapsulated in SslFd structure, remove this file descriptor + * from fd_set and clear ssl structure. + * Arguments: sf - pointer to SslFd structure + * set - pointer to fd_set structure + */ + +void +clear_sslFd(SslFd* sf, fd_set* set) +{ + clear_fd((&(sf->fd)), set); + if (SslFd_get_ssl(sf)) { + SSL_clear(SslFd_get_ssl(sf)); + } +} + +/* + * Function name: http_write + * Description: Write the message via http/https proxy. + * Arguments: https - if the https proxy will be used instead of http proxy + * sf - pointer to SslFd structure + * buf - buffer containing the data to send + * amount - how much butes will be send + * Returns: The result of writen or SSL_writen function, depending on 'https' value. + */ + +int +http_write(char https, SslFd* sf, unsigned char* buf, int amount) +{ + if (https) { + return SSL_writen(SslFd_get_ssl(sf), buf, amount); + } + else { + return writen(SslFd_get_fd(sf), buf, amount); + } +} + +/* + * Function name: http_read + * Description: Read the message via http/https proxy. + * Arguments: https - if the https proxy will be used instead of http proxy + * sf - pointer to SslFd structure + * buf - buffer for the received data + * amount - how much bytes will be received + * Returns: The result of read or SSL_read function, depending on 'https' value. + */ + +int +http_read(char https, SslFd* sf, unsigned char* buf, int amount) +{ + if (https) { + return SSL_read(SslFd_get_ssl(sf), buf, amount); + } + else { + return read(SslFd_get_fd(sf), buf, amount); + } +} diff --git a/src/http_proxy_functions.h b/src/http_proxy_functions.h index 9c9b56d..4384d93 100644 --- a/src/http_proxy_functions.h +++ b/src/http_proxy_functions.h @@ -25,6 +25,8 @@ #include #include +#include "ssl_fd_struct.h" + #ifndef _JS_HTTP_PROXY_FUNCTIONS_H #define _JS_HTTP_PROXY_FUNCTIONS_H @@ -51,14 +53,14 @@ typedef struct { char readed_length[4]; char state; char id[10]; - int postfd; - int getfd; + SslFd* postFd; + SslFd* getFd; int sent_ptr; int sockfd; char buf[9000]; char tmpbuf[9000]; char tmpstate; - int tmpfd; + SslFd* tmpFd; char type; header tmpheader; int ptr; @@ -70,11 +72,14 @@ typedef struct { int myrand(int, int); void mysleep(double); -int parse_header(int, char*, header*); +int parse_header(SslFd*, char*, header*, char); 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*); +void clear_sslFd(SslFd*, fd_set*); +int http_write(char, SslFd*, unsigned char*, int); +int http_read(char, SslFd*, unsigned char*, int); #endif diff --git a/src/http_proxy_options_struct.c b/src/http_proxy_options_struct.c new file mode 100644 index 0000000..d884df7 --- /dev/null +++ b/src/http_proxy_options_struct.c @@ -0,0 +1,239 @@ +/* + * 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 "http_proxy_options_struct.h" +#include "string_functions.h" + +/* + * Function name: HttpProxyOptions_new + * Description: Create and initialize new HttpProxyOptions structure. + * Returns: Pointer to newly created HttpProxyOptions structure. + */ + +HttpProxyOptions* +HttpProxyOptions_new() +{ + HttpProxyOptions* tmp = calloc(1, sizeof(HttpProxyOptions)); + if (tmp == NULL) { + return NULL; + } + tmp->proxyauth_type = PROXYAUTH_TYPE_NOTSET; + return tmp; +} + +/* + * Function name: HttpProxyOptions_free + * Description: Free the memory allocated for HttpProxyOptions structure. + * Arguments: hpo - pointer to pointer to HttpProxyOptions structure + */ + +void +HttpProxyOptions_free(HttpProxyOptions** hpo) +{ + if (hpo == NULL) { + return; + } + if ((*hpo) == NULL) { + return; + } + if ((*hpo)->proxyname) { + free((*hpo)->proxyname); + (*hpo)->proxyname = NULL; + } + if ((*hpo)->proxyport) { + free((*hpo)->proxyport); + (*hpo)->proxyport = NULL; + } + if ((*hpo)->proxyauth_cred) { + free((*hpo)->proxyauth_cred); + (*hpo)->proxyauth_cred = NULL; + } + free((*hpo)); + (*hpo) = NULL; +} + +/* + * Function name: HttpProxyOptions_set_proxyname + * Description: Set name of the http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyname - name of the http proxy server + */ + +void +HttpProxyOptions_set_proxyname(HttpProxyOptions* hpo, char* proxyname) +{ + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyname), proxyname); +} + +/* + * Function name: HttpProxyOptions_set_proxyport + * Description: Set port on which http proxy server is listening. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyport - port on which http proxy server is listening + */ + +void +HttpProxyOptions_set_proxyport(HttpProxyOptions* hpo, char* proxyport) +{ + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyport), proxyport); +} + +/* + * Function name: HttpProxyOptions_set_proxyauth_cred + * Description: Set credentials for http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyauth_cred - credentials for http proxy server + */ + +void +HttpProxyOptions_set_proxyauth_cred(HttpProxyOptions* hpo, char* proxyauth_cred) +{ + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyauth_cred), proxyauth_cred); +} + +/* + * Function name: HttpProxyOptions_set_proxyauth_type + * Description: Set type of the proxy authorization. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyauth_type - type of the proxy authorization + */ + +void +HttpProxyOptions_set_proxyauth_type(HttpProxyOptions* hpo, char proxyauth_type) +{ + if (hpo == NULL) { + return; + } + if (hpo->proxyauth_type != PROXYAUTH_TYPE_NOTSET) { + hpo->proxyauth_type = PROXYAUTH_TYPE_WRONG; + return; + } + hpo->proxyauth_type = proxyauth_type; +} + +/* + * Function name: HttpProxyOptions_get_proxyname + * Description: Get name of the http proxy server + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Name of the http proxy server or NULL, if name not set. + */ + +char* +HttpProxyOptions_get_proxyname(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return NULL; + } + return hpo->proxyname; +} + +/* + * Function name: HttpProxyOptions_get_proxyport + * Description: Get port on which http proxy server is listening. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Port on which http proxy server is listening or NULL, if port not set. + */ + +char* +HttpProxyOptions_get_proxyport(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return NULL; + } + return hpo->proxyport; +} + +/* + * Function name: HttpProxyOptions_get_proxyauth_cred + * Description: Get credentials for http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Credentials for http proxy server or NULL, if not set. + */ + +char* +HttpProxyOptions_get_proxyauth_cred(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return NULL; + } + return hpo->proxyauth_cred; +} + +/* + * Function name: HttpProxyOptions_get_proxyauth_type + * Description: Get type of the proxy authorization. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Type of the proxy authorization. + */ + +char +HttpProxyOptions_get_proxyauth_type(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return PROXYAUTH_TYPE_WRONG; + } + return hpo->proxyauth_type; +} + +/* + * Function name: HttpProxyOptions_use_https + * Description: Enable use of https proxy instead of http proxy. + * Arguments: hpo - pointer to HttpProxyOptions structure + */ + +void +HttpProxyOptions_use_https(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return; + } + hpo->useHttps = USEHTTPS_ON; +} + +/* + * Function name: HttpProxyOptions_is_https + * Description: Check if the use of https proxy is enabled. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: USEHTTPS_OFF - http proxy will be used + * USEHTTPS_ON - https proxy will be used + */ + +char +HttpProxyOptions_is_https(HttpProxyOptions* hpo) +{ + if (hpo == NULL) { + return USEHTTPS_OFF; + } + return hpo->useHttps; +} diff --git a/src/http_proxy_options_struct.h b/src/http_proxy_options_struct.h new file mode 100644 index 0000000..848dda9 --- /dev/null +++ b/src/http_proxy_options_struct.h @@ -0,0 +1,58 @@ +/* + * 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_OPTIONS_STRUCT_H +#define _JS_HTTP_PROXY_OPTIONS_STRUCT_H + +#define PROXYAUTH_TYPE_NOTSET 0 +#define PROXYAUTH_TYPE_WRONG -1 +#define PROXYAUTH_TYPE_BASIC 1 + +#define USEHTTPS_OFF 0 +#define USEHTTPS_ON 1 + +typedef struct { + char* proxyname; + char* proxyport; + char* proxyauth_cred; + char proxyauth_type; + char useHttps; +} HttpProxyOptions; + +/* 'constructor' */ +HttpProxyOptions* HttpProxyOptions_new(); +/* 'destructor' */ +void HttpProxyOptions_free(HttpProxyOptions** hpo); +/* setters */ +void HttpProxyOptions_set_proxyname(HttpProxyOptions* hpo, char* proxyname); +void HttpProxyOptions_set_proxyport(HttpProxyOptions* hpo, char* proxyport); +void HttpProxyOptions_set_proxyauth_cred(HttpProxyOptions* hpo, char* proxyauth_cred); +void HttpProxyOptions_set_proxyauth_type(HttpProxyOptions* hpo, char proxyauth_type); +/* getters */ +char* HttpProxyOptions_get_proxyname(HttpProxyOptions* hpo); +char* HttpProxyOptions_get_proxyport(HttpProxyOptions* hpo); +char* HttpProxyOptions_get_proxyauth_cred(HttpProxyOptions* hpo); +char HttpProxyOptions_get_proxyauth_type(HttpProxyOptions* hpo); +/* other */ +void HttpProxyOptions_use_https(HttpProxyOptions* hpo); +char HttpProxyOptions_is_https(HttpProxyOptions* hpo); + +#endif + diff --git a/src/http_proxy_server.c b/src/http_proxy_server.c index f98026c..45db302 100644 --- a/src/http_proxy_server.c +++ b/src/http_proxy_server.c @@ -20,6 +20,7 @@ #include +#include "make_ssl_handshake.h" #include "http_proxy_server.h" #include "thread_management.h" #include "stats.h" @@ -35,6 +36,8 @@ typedef struct { socklen_t *addrlenp; char type; int limit; + char https; + SSL_CTX* ctx; } sproxy_argT; int @@ -63,7 +66,8 @@ afserver_connect(int* sockfd, int afserverfd, struct sockaddr* cliaddr, socklen_ void* http_proxy_server(void *vptr) { - int listenfd, connfd, afserverfd; + int listenfd, afserverfd; + SslFd* connFd; struct sockaddr* cliaddr; char tab[9000]; connection* table; @@ -74,8 +78,9 @@ http_proxy_server(void *vptr) int maxclients, tmp; int timeout = 5; socklen_t *addrlenp; - char type, nothttp; - char *host, *serv; + char type, nothttp, https; + char *host, *serv, *name = ""; + SSL_CTX* ctx; sproxy_argT *proxy_argptr; start_critical_section(); @@ -87,20 +92,62 @@ http_proxy_server(void *vptr) addrlenp = proxy_argptr->addrlenp; type = proxy_argptr->type; maxclients = proxy_argptr->limit+1; + https = proxy_argptr->https; + ctx = proxy_argptr->ctx; broadcast_condition(); end_critical_section(); + if (https) { + name = "s"; + } + table = calloc(maxclients, sizeof(connection)); if (table == NULL) { aflog(LOG_T_INIT, LOG_I_CRIT, - "http proxy: Can't allocate memory... exiting."); + "http%s proxy: Can't allocate memory... exiting.", name); exit(1); } + for (i = 0; i < maxclients; ++i) { + table[i].postFd = SslFd_new(); + table[i].getFd = SslFd_new(); + table[i].tmpFd = SslFd_new(); + if ((table[i].postFd == NULL) || (table[i].getFd == NULL) || (table[i].tmpFd == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + if (https) { + SslFd_set_ssl(table[i].postFd, SSL_new(ctx)); + SslFd_set_ssl(table[i].getFd, SSL_new(ctx)); + SslFd_set_ssl(table[i].tmpFd, SSL_new(ctx)); + if ((SslFd_get_ssl(table[i].postFd) == NULL) || + (SslFd_get_ssl(table[i].getFd) == NULL) || + (SslFd_get_ssl(table[i].tmpFd) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + } + } + connFd = SslFd_new(); + if (connFd == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + if (https) { + SslFd_set_ssl(connFd, SSL_new(ctx)); + if (SslFd_get_ssl(connFd) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + 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); + "http%s proxy: Can't listen on %s:%s", name, host, serv); exit(1); } cliaddr = malloc(*addrlenp); @@ -116,23 +163,23 @@ http_proxy_server(void *vptr) if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: timeout"); + "http%s proxy: timeout", name); 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); + "http%s proxy: send T to table[%d].getfd", name, i); if (table[i].sent_ptr+1 >= 90000) { - writen(table[i].getfd, (unsigned char*) "T", 1); + http_write(https, table[i].getFd, (unsigned char*) "T", 1); table[i].sent_ptr = 0; - clear_fd(&table[i].getfd, &allset); + clear_sslFd(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); + http_write(https, table[i].getFd, (unsigned char*) "T", 1); table[i].sent_ptr += 1; } } @@ -148,10 +195,10 @@ http_proxy_server(void *vptr) /* 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); + "http%s proxy: FD_ISSET(table[%d].sockfd)", name, i); n = read(table[i].sockfd, table[i].buf+5, 8995); if (n <= 0) { - writen(table[i].getfd, (unsigned char*) "Q", 1); + http_write(https, table[i].getFd, (unsigned char*) "Q", 1); delete_user(table, i, &allset); continue; } @@ -159,34 +206,34 @@ http_proxy_server(void *vptr) 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); + http_write(https, 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); + clear_sslFd(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); + http_write(https, table[i].getFd, (unsigned char*) table[i].buf, n+5); table[i].sent_ptr += n+5; } } /* getfd */ - if (FD_ISSET(table[i].getfd, &rset)) { + if (FD_ISSET(SslFd_get_fd(table[i].getFd), &rset)) { aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http proxy: FD_ISSET(table[%d].getfd)", i); + "http%s proxy: FD_ISSET(table[%d].getfd)", name, i); delete_user(table, i, &allset); continue; } /* postfd */ - if (FD_ISSET(table[i].postfd, &rset)) { + if (FD_ISSET(SslFd_get_fd(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); + "http%s proxy: FD_ISSET(table[%d].postfd)", name, i); + n = http_read(https, table[i].postFd, (unsigned char*) tab, 9000); if (n != 0) { table[i].received += n; if (read_message(table[i].sockfd, n, &table[i], tab, 0)) { @@ -195,14 +242,14 @@ http_proxy_server(void *vptr) } if ((n == 0) || (table[i].received == 90000)) { table[i].received = 0; - clear_fd(&table[i].postfd, &allset); + clear_sslFd(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..."); + "http%s proxy: get old POST request...", name); table[i].state &= ~C_POST_WAIT; - table[i].postfd = table[i].tmpfd; - set_fd(table[i].postfd, &maxfdp1, &allset); + SslFd_swap_content(table[i].postFd, table[i].tmpFd); + set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); table[i].tmpstate = 0; if (table[i].tmpheader.length) { table[i].received += table[i].tmpheader.length; @@ -224,7 +271,7 @@ http_proxy_server(void *vptr) 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); + writen(SslFd_get_fd(table[i].postFd), (unsigned char*) table[i].buf, n); } else { delete_user(table, i, &allset); @@ -232,10 +279,10 @@ http_proxy_server(void *vptr) } } - if (FD_ISSET(table[i].postfd, &rset)) { - n = read(table[i].postfd, tab, 9000); + if (FD_ISSET(SslFd_get_fd(table[i].postFd), &rset)) { + n = read(SslFd_get_fd(table[i].postFd), tab, 9000); if (n > 0) { - write(table[i].sockfd, tab, n); + writen(table[i].sockfd, (unsigned char*) tab, n); } else { delete_user(table, i, &allset); @@ -249,23 +296,34 @@ http_proxy_server(void *vptr) /* 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) { + "http%s proxy: FD_ISSET(listenfd)", name); + tmp = accept(listenfd, cliaddr, addrlenp); + if (tmp != -1) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: New connection..."); + "http%s proxy: New connection...", name); + SslFd_set_fd(connFd, tmp); + if (https) { + make_ssl_initialize(connFd); + if (make_ssl_accept(connFd)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "https proxy: DENIED by SSL_accept"); + close(SslFd_get_fd(connFd)); + SSL_clear(SslFd_get_ssl(connFd)); + continue; + } + } } else { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: New connection --> EAGAIN"); + "http%s proxy: New connection --> EAGAIN", name); continue; } memset(tab, 0, 9000); nothttp = 0; - if (parse_header(connfd, tab, &hdr)) { + if (parse_header(connFd, tab, &hdr, https)) { nothttp = 1; aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: no http header..."); + "http%s proxy: no http header...", name); } n = -1; for (i = 0; i < maxclients; ++i) { @@ -281,40 +339,41 @@ http_proxy_server(void *vptr) } if (i < maxclients) { /* the client exists */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: the client exist..."); + "http%s proxy: the client exist...", name); if (hdr.type == H_TYPE_GET) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: type GET..."); + "http%s proxy: type GET...", name); if (!(table[i].state & C_GET_WAIT)) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: not waiting for GET..."); + "http%s proxy: not waiting for GET...", name); table[i].sent_ptr = 0; FD_CLR(table[i].sockfd, &allset); - clear_fd(&table[i].getfd, &allset); + clear_sslFd(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..."); + "http%s proxy: not opened...", name); 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); + http_write(https, connFd, (unsigned char*) tab, n); + close_fd((&(connFd->fd))); + SSL_clear(SslFd_get_ssl(connFd)); + clear_sslFd(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..."); + "http%s proxy: OPEN...", name); } table[i].state &= ~C_GET_WAIT; table[i].sent_ptr = 0; - table[i].getfd = connfd; + SslFd_swap_content(table[i].getFd, connFd); set_fd(table[i].sockfd, &maxfdp1, &allset); - set_fd(table[i].getfd, &maxfdp1, &allset); + set_fd(SslFd_get_fd(table[i].getFd), &maxfdp1, &allset); memset(tab, 0, 9000); sprintf(tab, "HTTP/1.1 200 OK\r\n" @@ -325,12 +384,13 @@ http_proxy_server(void *vptr) "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) { + if (writen(SslFd_get_fd(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) { + if (writen(SslFd_get_fd(table[i].getFd), + (unsigned char*) (table[i].buf+table[i].ptr), table[i].length) <= 0) { delete_user(table, i, &allset); continue; } @@ -341,21 +401,21 @@ http_proxy_server(void *vptr) } else if (hdr.type == H_TYPE_POST) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: type POST..."); + "http%s proxy: type POST...", name); if (!(table[i].state & C_POST_WAIT)) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: unexpected POST request..."); + "http%s proxy: unexpected POST request...", name); if (table[i].tmpstate == 0) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: buffering POST request..."); + "http%s proxy: buffering POST request...", name); table[i].tmpstate = 1; - table[i].tmpfd = connfd; + SslFd_swap_content(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)", + "http%s proxy: no space to buffer POST request (received from first postfd: %d)", name, table[i].received); delete_user(table, i, &allset); } @@ -368,44 +428,45 @@ http_proxy_server(void *vptr) } } table[i].state &= ~C_POST_WAIT; - table[i].postfd = connfd; - set_fd(table[i].postfd, &maxfdp1, &allset); + SslFd_swap_content(table[i].postFd, connFd); + set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); } } else { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: unrecognized type..."); + "http%s proxy: unrecognized type...", name); 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..."); + "http%s proxy: there are free slots...", name); if (!nothttp) { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: http header..."); + "http%s proxy: http header...", name); if (hdr.type == H_TYPE_POST) { /* POST request must be first */ aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: type POST..."); + "http%s proxy: type POST...", name); table[n].state = C_GET_WAIT; memcpy(table[n].id,hdr.id, 9); - table[n].postfd = connfd; - set_fd(table[n].postfd, &maxfdp1, &allset); + SslFd_swap_content(table[n].postFd, connFd); + set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); } else { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: closing this connection..."); - close_fd(&connfd); + "http%s proxy: closing this connection...", name); + close_fd((&(connFd->fd))); + SSL_clear(SslFd_get_ssl(connFd)); continue; } } else { table[n].state = C_OPEN; - table[n].postfd = connfd; + SslFd_set_fd(table[n].postFd, SslFd_get_fd(connFd)); table[n].type = 1; - set_fd(table[n].postfd, &maxfdp1, &allset); + set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); if (afserver_connect(&table[n].sockfd, afserverfd, cliaddr, addrlenp, 0)) { - clear_fd(&table[n].postfd, &allset); + clear_sslFd(table[n].postFd, &allset); table[n].state = C_CLOSED; continue; } @@ -415,8 +476,8 @@ http_proxy_server(void *vptr) } else { aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http proxy: closing this connection..."); - close_fd(&connfd); + "http%s proxy: closing this connection...", name); + close_fd((&(connFd->fd))); continue; } } @@ -427,7 +488,7 @@ http_proxy_server(void *vptr) int -initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit) +initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit, char https, SSL_CTX* ctx) { int retval; int sockets[2]; @@ -447,6 +508,8 @@ initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, so arg.limit = limit; arg.type = (char) type; arg.sockfd = sockets[1]; + arg.https = https; + arg.ctx = ctx; retval = pthread_create(&proxy_thread, NULL, &http_proxy_server, &arg); diff --git a/src/http_proxy_server.h b/src/http_proxy_server.h index 6e13549..21c8c4b 100644 --- a/src/http_proxy_server.h +++ b/src/http_proxy_server.h @@ -24,6 +24,6 @@ #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); +int initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit, char https, SSL_CTX* ctx); #endif diff --git a/src/make_ssl_handshake.c b/src/make_ssl_handshake.c index ffb4ebd..a7bf9bd 100644 --- a/src/make_ssl_handshake.c +++ b/src/make_ssl_handshake.c @@ -28,9 +28,9 @@ #include void -make_ssl_initialize(clifd *cliconn) +make_ssl_initialize(SslFd* sf) { - if (SSL_set_fd(cliconn->ssl, cliconn->commfd) != 1) { + if (SSL_set_fd(SslFd_get_ssl(sf), SslFd_get_fd(sf)) != 1) { aflog(LOG_T_INIT, LOG_I_CRIT, "Problem with initializing ssl... exiting"); exit(1); @@ -38,23 +38,23 @@ make_ssl_initialize(clifd *cliconn) } int -make_ssl_accept(clifd *cliconn) +make_ssl_accept(SslFd* sf) { int result; - if ((result = SSL_accept(cliconn->ssl)) != 1) { - return get_ssl_error(cliconn, "SSL_accept has failed", result); + if ((result = SSL_accept(SslFd_get_ssl(sf))) != 1) { + return get_ssl_error(sf, "SSL_accept has failed", result); } return 0; } int -get_ssl_error(clifd *cliconn, char* info, int result) +get_ssl_error(SslFd* sf, char* info, int result) { int merror; #ifdef HAVE_ERR_ERROR_STRING char err_buff[200]; #endif - merror = SSL_get_error(cliconn->ssl, result); + merror = SSL_get_error(SslFd_get_ssl(sf), result); switch (merror) { case SSL_ERROR_NONE : { aflog(LOG_T_MAIN, LOG_I_WARNING, diff --git a/src/make_ssl_handshake.h b/src/make_ssl_handshake.h index 674867a..d195912 100644 --- a/src/make_ssl_handshake.h +++ b/src/make_ssl_handshake.h @@ -19,13 +19,14 @@ */ #include "network.h" +#include "ssl_fd_struct.h" #ifndef _JS_MAKE_SSL_HANDSHAKE_H #define _JS_MAKE_SSL_HANDSHAKE_H -void make_ssl_initialize(clifd *cliconn); -int make_ssl_accept(clifd *cliconn); -int get_ssl_error(clifd *cliconn, char* info, int result); +void make_ssl_initialize(SslFd* sf); +int make_ssl_accept(SslFd* sf); +int get_ssl_error(SslFd* sf, char* info, int result); #endif diff --git a/src/network.c b/src/network.c index 0903b4f..38569cc 100644 --- a/src/network.c +++ b/src/network.c @@ -389,99 +389,3 @@ readn(int fd, unsigned char* buf, int amount) return amount; } - -int -send_message(char type, clifd fd, unsigned char* buf, int amount) -{ - unsigned long clen; - int length; - static unsigned char bufor[9000]; - aflog(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; - if (TYPE_IS_ZLIB(type)) { - memcpy(bufor, buf, 5); - if (amount > 5) { - compress(&bufor[5], &clen, &buf[5], length); - if (clen < length) { - length = clen; - TYPE_SET_COMP(length); - bufor[3] = length >> 8; /* high bits of message length */ - bufor[4] = length; /* low bits of message length */ - addtocg(amount-5 - clen); - } - } - if (TYPE_IS_SSL(type)) { - if (TYPE_IS_COMP(length)) { - return SSL_writen(fd.ssl, bufor, clen+5); - } - else { - return SSL_writen(fd.ssl, buf, amount); - } - } - else { - if (TYPE_IS_COMP(length)) { - return writen(fd.commfd, bufor, clen+5); - } - else { - return writen(fd.commfd, buf, amount); - } - } - } - else { - if (TYPE_IS_SSL(type)) { - return SSL_writen(fd.ssl, buf, amount); - } - else { - return writen(fd.commfd, buf, amount); - } - } -} - -int -get_message(char type, clifd fd, unsigned char* buf, int amount) -{ - int length; - unsigned long elen; - static unsigned char bufor[9000]; - aflog(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)) { - return SSL_read(fd.ssl, buf, 5); - } - else { - return read(fd.commfd, buf, 5); - } - } - if (TYPE_IS_ZLIB(type)) { - if (TYPE_IS_SSL(type)) { - length = SSL_readn(fd.ssl, bufor, amount&0xBFFF); - } - else { - length = readn(fd.commfd, bufor, amount&0xBFFF); - } - if (length <= 0) return length; - elen = 8096; - if (TYPE_IS_COMP(amount)) { - uncompress(buf, &elen, bufor, length); - } - else { - memcpy(buf, bufor, length); - elen = length; - } - return elen; - } - else - { - if (TYPE_IS_SSL(type)) { - return SSL_readn(fd.ssl, buf, amount); - } - else { - return readn(fd.commfd, buf, amount); - } - } -} diff --git a/src/network.h b/src/network.h index ee03af6..6c7e640 100644 --- a/src/network.h +++ b/src/network.h @@ -36,18 +36,10 @@ #include #include -typedef struct { - int commfd; - SSL* ssl; -} clifd; - int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */ int ip_connect(int* sockfd, const char *host, const char *serv, const char type); /* socket, connect... */ char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf, char type); /* return the IP of connected user */ -int send_message(char type, clifd fd, unsigned char* buf, int amount); -int get_message(char type, clifd fd, unsigned char* buf, int amount); - int SSL_writen(SSL* fd, unsigned char* buf, int amount); int SSL_readn(SSL* fd, unsigned char* buf, int amount); int writen(int fd, unsigned char* buf, int amount); diff --git a/src/remoteadmin.c b/src/remoteadmin.c deleted file mode 100644 index c2ada6e..0000000 --- a/src/remoteadmin.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * 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 "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; - char cmd[31]; - - i = j = state = 0; - newmessage = 1; - while (buff[i] != 0) { - if (state == 1) { - if (isspace(buff[i])) { - break; - } - else { - if (j == 30) { - return 0; - } - cmd[j] = buff[i]; - ++j; - } - } - if (state == 0) { - if (!isspace(buff[i])) { - cmd[j] = buff[i]; - j = 1; - state = 1; - } - } - ++i; - } - if (state == 0) { - return 0; - } - while (isspace(buff[i])) { - ++i; - } - if (buff[i] == '.') { - ++i; - } - (*ret) = i; - cmd[j] = 0; - if (strcmp(cmd, "help") == 0) { return 1; } - if (strcmp(cmd, "lcmd") == 0) { return 2; } - if (strcmp(cmd, "info") == 0) { return 3; } - if (strcmp(cmd, "rshow") == 0) { return 4; } - if (strcmp(cmd, "cshow") == 0) { return 5; } - if (strcmp(cmd, "ushow") == 0) { return 6; } - if (strcmp(cmd, "quit") == 0) { return 7; } - 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; -} - -static void -send_adm_message(char type, clifd master, unsigned char* buff, unsigned char st) -{ - int n; - if (!newmessage) { - n = strlen((char*) &buff[5]); - } - else { - n = 0; - } - buff[0] = AF_S_ADMIN_CMD; - buff[1] = st; - buff[2] = AF_RA_UNDEFINED; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(type, master, buff, n+5); -} - -static void -add_to_message(unsigned char* buff, const char* format, ...) -{ - va_list ap; - int n; - if (!newmessage) { - n = strlen((char*) &buff[5]); - } - else { - n = 0; - } - newmessage = 0; - va_start(ap, format); - - vsprintf((char*) &buff[5+n], format, ap); - n = strlen((char*) &buff[5]); - sprintf((char*) &buff[5+n], "\n"); - - va_end(ap); -} - -static void -add_uptime_to_message(unsigned char* buff, char* info, time_t period) -{ - int hours, minutes, seconds; - - hours = period/3600; - minutes = (period/60)%60; - seconds = period%60; - - if (hours) { - add_to_message(buff, "%s: %d:%02d:%02d", info, hours, minutes, seconds); - } - else { - add_to_message(buff, "%s: %d:%02d", info, minutes, seconds); - } -} - -int -serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) -{ - int length, n, i, j, ret; - time_t now, tmp; - 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 the length of a message */ - - time(&now); - - switch (buff[1]) { - case AF_RA_CMD: { - n = get_message(type, master, buff, length); - buff[n] = 0; - 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, " 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; - } - case 2: { /* lcmd */ - add_to_message(buff, "help"); - add_to_message(buff, "lcmd"); - add_to_message(buff, "info"); - add_to_message(buff, "rshow"); - add_to_message(buff, "cshow"); - add_to_message(buff, "ushow"); - add_to_message(buff, "quit"); - 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; - } - case 3: { /* info */ - add_to_message(buff, AF_VER("Version:")); - add_to_message(buff, "Realms: %d", config->size); - add_to_message(buff, "Certificate: %s", config->certif); - add_to_message(buff, "Key: %s", config->keys); - 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; - } - case 4: { /* rshow */ - for (i = 0; i < config->size; ++i) { - add_to_message(buff, "\nRealm[%s]:", get_realmname(config, i)); - add_to_message(buff, "hostname: %s", config->realmtable[i].hostname); - add_to_message(buff, "users: %d (max: %d)", - config->realmtable[i].usercon, config->realmtable[i].usernum); - add_to_message(buff, "clients: %d (max: %d)", - config->realmtable[i].clicon-config->realmtable[i].raclicon, - config->realmtable[i].clinum); - add_to_message(buff, "raclients: %d (max: %d)", - config->realmtable[i].raclicon, config->realmtable[i].raclinum); - add_to_message(buff, "users per client: %s", config->realmtable[i].usrpcli); - add_to_message(buff, "user-client pairs: %d", - config->realmtable[i].usrclinum); - for (j = 0; j < config->realmtable[i].usrclinum; ++j) { - add_to_message(buff, " pair[%d]: listenport: %s, manageport: %s", j, - config->realmtable[i].usrclitable[j].lisportnum, - config->realmtable[i].usrclitable[j].manportnum); - } - add_to_message(buff, "climode: %s", config->realmtable[i].clim); - add_to_message(buff, "timeout: %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; - } - case 5: { /* cshow*/ - n = get_realmnumber(config, (char*) &buff[ret]); - if ((n >= 0) && (n < config->size)) { - for (i = 0; i < config->realmtable[n].clinum; ++i) { - if (config->realmtable[n].clitable[i].ready) { - add_to_message(buff, "\nClient[%s]:", - get_clientname(&(config->realmtable[n]), i)); - switch (config->realmtable[n].clitable[i].ready) { - case 1: { - add_to_message(buff, "state: ssl handshake"); - break; - } - case 2: { - add_to_message(buff, "state: authorization"); - break; - } - case 3: { - add_to_message(buff, "state: running"); - break; - } - default: { - add_to_message(buff, "state: unknown"); - } - } - add_to_message(buff, "users: %d (max: %d)", - config->realmtable[n].clitable[i].usercon, - config->realmtable[n].clitable[i].usernum); - add_to_message(buff, "user-client pair: %d", - config->realmtable[n].clitable[i].whatusrcli); - tmp = now - config->realmtable[n].clitable[i].connecttime; - add_uptime_to_message(buff, "Connection time", tmp); - add_to_message(buff, "Id: %s", - (config->realmtable[n].clitable[i].clientid == NULL)?"": - config->realmtable[n].clitable[i].clientid); - add_to_message(buff, "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; - } - case 6: { /* ushow */ - n = get_realmnumber(config, (char*) &buff[ret]); - if ((n >= 0) && (n < config->size)) { - for (i = 0; i < config->realmtable[n].usernum; ++i) { - if (config->realmtable[n].contable[i].state != S_STATE_CLEAR) { - add_to_message(buff, "\nUser[%d]:", - get_username(&(config->realmtable[n]), i)); - switch (config->realmtable[n].contable[i].state) { - case S_STATE_CLOSING: { - add_to_message(buff, "state: closing"); - break; - } - case S_STATE_OPENING: { - add_to_message(buff, "state: opening"); - break; - } - case S_STATE_OPEN: { - add_to_message(buff, "state: running"); - break; - } - case S_STATE_STOPPED: { - add_to_message(buff, "state: stopped"); - break; - } - default: { - add_to_message(buff, "state: unknown"); - } - } - add_to_message(buff, "connected to: Client[%s]", - get_clientname(&(config->realmtable[n]), - config->realmtable[n].contable[i].whatcli)); - tmp = now - config->realmtable[n].contable[i].connecttime; - add_uptime_to_message(buff, "Connection time", tmp); - add_to_message(buff, "IP: %s, port: %s", - config->realmtable[n].contable[i].namebuf, - config->realmtable[n].contable[i].portbuf); - } - } - send_adm_message(type, master, buff, AF_RA_STATUS_OK); - break; - } - add_to_message(buff, "Wrong realm name"); - add_to_message(buff, "Usage: ushow X , X - realm name"); - send_adm_message(type, master, buff, AF_RA_FAILED); - break; - } - case 7: { /* quit */ - 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(LOG_T_MANAGE, LOG_I_WARNING, - "realm[%s]: admin: cmd ignored", get_realmname(config, realm)); - send_adm_message(type, master, buff, AF_RA_UNDEFINED); - } - } - break; - } - case AF_RA_REPEAT: { - break; - } - default: { - aflog(LOG_T_MANAGE, LOG_I_ERR, - "Unrecognized message from remote admin --> closing"); - return 1; - } - } - return 0; -} - -int -client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* id) -{ - fd_set rset, allset; - int maxfdp1, n, length, infd; - FILE *outfp, *infp; - - buff[0] = AF_S_ADMIN_LOGIN; - send_message(type, master, buff, 5); - buff[0] = 0; - get_message(type, master, buff, -5); - - if ( buff[0] == 0 ) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "Wrong password"); - return 1; - } - if ( buff[0] == AF_S_CANT_OPEN ) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "Server is full"); - return 1; - } - if ( buff[0] != AF_S_ADMIN_LOGIN ) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "Incompatible server type or server full"); - return 1; - } - - aflog(LOG_T_MAIN, LOG_I_INFO, - "CLIENT STARTED mode: remote administration"); - - if (connectfd > 0) { - outfp = fdopen(connectfd, "w"); - if (outfp == NULL) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "Error in opening file descriptor for writing"); - return 1; - } - infd = connectfd; - } - else { - infd = STDIN_FILENO; - outfp = stdout; - } - infp = fdopen(infd, "r"); - if (infp == NULL) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "Error in opening file descriptor for reading"); - return 1; - } - - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - n = get_message(type, master, buff, length); - buff[n] = 0; - fprintf(outfp, "%s\n", (char*) buff); - fflush(outfp); - - FD_ZERO(&allset); - - FD_SET(master.commfd, &allset); - FD_SET(infd, &allset); - - maxfdp1 = (infd > master.commfd) ? infd+1: master.commfd+1; - - if (id != NULL) { - buff[0] = AF_S_LOGIN; - buff[1] = buff[2] = 0; - n = strlen(id); - memcpy(&buff[5], id, n); - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(type, master, buff, n+5); - aflog(LOG_T_MANAGE, LOG_I_INFO, - "ID SENT: %s", id); - } - - while (1) { - rset = allset; - select(maxfdp1, &rset, NULL, NULL, NULL); - - if (FD_ISSET(master.commfd, &rset)) { - aflog(LOG_T_MANAGE, LOG_I_DEBUG, - "masterfd: FD_ISSET"); - n = get_message(type, master, buff, 5); - if (n != 5) { - 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); - continue; /* what happened? */ - } - } - if (n != 0) - return 1; - } - if (n == 0) { /* server quits -> we do the same... */ - aflog(LOG_T_MANAGE, LOG_I_CRIT, - "SERVER: premature quit --> exiting..."); - return 1; - } - if (buff[0] == AF_S_CLOSING) { - aflog(LOG_T_MANAGE, LOG_I_CRIT, - "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); - return 0; - } - if (buff[0] != AF_S_ADMIN_CMD) { - aflog(LOG_T_MANAGE, LOG_I_CRIT, - "SERVER: wrong message --> exiting"); - return 1; - } - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - - switch (buff[1]) { - case AF_RA_STATUS_OK: { - aflog(LOG_T_MANAGE, LOG_I_INFO, - "SERVER: cmd successful"); - } - case AF_RA_FAILED: { - if (buff[1] == AF_RA_FAILED) { - aflog(LOG_T_MANAGE, LOG_I_INFO, - "SERVER: cmd failed"); - } - } - case AF_RA_UNDEFINED: { - if (buff[1] == AF_RA_UNDEFINED) { - aflog(LOG_T_MANAGE, LOG_I_WARNING, - "SERVER: unknown cmd"); - } - n = get_message(type, master, buff, length); - buff[n] = 0; - fprintf(outfp, "%s", (char*) buff); - fflush(outfp); - break; - } - case AF_RA_KICKED: { - aflog(LOG_T_MANAGE, LOG_I_ERR, - "SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); - return 1; - break; - } - default: { - aflog(LOG_T_MANAGE, LOG_I_ERR, - "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); - return 1; - } - } - } - - if (FD_ISSET(infd, &rset)) { - aflog(LOG_T_MANAGE, LOG_I_DEBUG, - "infd: FD_ISSET"); - if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ - aflog(LOG_T_MANAGE, LOG_I_NOTICE, - "CLIENT CLOSED cg: %ld bytes", getcg()); - return 0; - } - n = strlen((char*) &buff[5]); - if ((n > 0) && (buff[n+4] == '\n')) { - --n; - } - buff[0] = AF_S_ADMIN_CMD; - buff[1] = AF_RA_CMD; - buff[2] = AF_RA_UNDEFINED; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(type, master, buff, n+5); - } - } -} diff --git a/src/remoteadmin.h b/src/remoteadmin.h deleted file mode 100644 index 5b176df..0000000 --- a/src/remoteadmin.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004,2005 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "file.h" -#include "stats.h" -#include "logging.h" -#include "activefor.h" -#include "realmnames.h" -#include "clientnames.h" -#include "usernames.h" -#include "make_ssl_handshake.h" - -#include -#include -#include -#include - -#ifndef _JS_REMOTEADMIN_H -#define _JS_REMOTEADMIN_H - -#define AF_RA_UNDEFINED 0 -#define AF_RA_CMD 1 -#define AF_RA_REPEAT 2 -#define AF_RA_STATUS_OK 3 -#define AF_RA_NOT_KNOWN 4 -#define AF_RA_FAILED 5 -#define AF_RA_KICKED 6 - -int serve_admin(ConfigurationT*, int, int, unsigned char*); -int client_admin(char, clifd, unsigned char*, int, char*); - -#endif - diff --git a/src/remoteadmin_codes.h b/src/remoteadmin_codes.h new file mode 100644 index 0000000..02f3164 --- /dev/null +++ b/src/remoteadmin_codes.h @@ -0,0 +1,32 @@ +/* + * 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_REMOTEADMIN_CODES_H +#define _JS_REMOTEADMIN_CODES_H + +#define AF_RA_UNDEFINED 0 +#define AF_RA_CMD 1 +#define AF_RA_REPEAT 2 +#define AF_RA_STATUS_OK 3 +#define AF_RA_NOT_KNOWN 4 +#define AF_RA_FAILED 5 +#define AF_RA_KICKED 6 + +#endif diff --git a/src/server_eval.c b/src/server_eval.c index 373a310..4996621 100644 --- a/src/server_eval.c +++ b/src/server_eval.c @@ -25,8 +25,8 @@ int eval_numofcon(RealmT* ptr, int client, int numofcon) { - if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) { - numofcon = ptr->clitable[client].users[numofcon]; + if ((numofcon >= 0) && (numofcon < ConnectClient_get_limit(ptr->clitable[client]))) { + numofcon = ConnectClient_get_users(ptr->clitable[client])[numofcon]; } else { numofcon = -1; @@ -35,11 +35,11 @@ eval_numofcon(RealmT* ptr, int client, int numofcon) } int -eval_usernum(ConnectclientT* ptr, int usernum) +eval_usernum(ConnectClient* ptr, int usernum) { int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == usernum) + for (i = 0; i < ConnectClient_get_limit(ptr); ++i) { + if (ConnectClient_get_users(ptr)[i] == usernum) return i; } return -1; diff --git a/src/server_eval.h b/src/server_eval.h index ed09e84..297e6ec 100644 --- a/src/server_eval.h +++ b/src/server_eval.h @@ -25,7 +25,7 @@ #define _JS_SERVER_EVAL_H int eval_numofcon(RealmT*, int, int); -int eval_usernum(ConnectclientT*, int); +int eval_usernum(ConnectClient*, int); #endif diff --git a/src/server_find.c b/src/server_find.c index 80148e4..73cb9ba 100644 --- a/src/server_find.c +++ b/src/server_find.c @@ -29,8 +29,11 @@ find_client(RealmT* ptr, char mode, int usrclipair) switch(mode) { case 1: { /* fill first client before go to next */ for (i = 0; i < ptr->clinum; ++i) { - if ((ptr->clitable[i].ready == 3) && (ptr->clitable[i].whatusrcli == usrclipair)) { - if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) { + if ((ConnectClient_get_state(ptr->clitable[i]) == + CONNECTCLIENT_STATE_ACCEPTED) && + (ConnectClient_get_usrCliPair(ptr->clitable[i]) == usrclipair)) { + if (ConnectClient_get_connected(ptr->clitable[i]) < + ConnectClient_get_limit(ptr->clitable[i])) { return i; } } @@ -45,12 +48,12 @@ find_client(RealmT* ptr, char mode, int usrclipair) } int -find_usernum(ConnectclientT* ptr, int usernum) +find_usernum(ConnectClient* ptr, int usernum) { int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == -1) { - ptr->users[i] = usernum; + for (i = 0; i < ConnectClient_get_limit(ptr); ++i) { + if (ConnectClient_get_users(ptr)[i] == -1) { + ConnectClient_get_users(ptr)[i] = usernum; return i; } } diff --git a/src/server_find.h b/src/server_find.h index 36642cc..dcfe5b5 100644 --- a/src/server_find.h +++ b/src/server_find.h @@ -25,7 +25,7 @@ #define _JS_SERVER_FIND_H int find_client(RealmT*, char, int); -int find_usernum(ConnectclientT*, int); +int find_usernum(ConnectClient*, int); #endif diff --git a/src/server_remoteadmin.c b/src/server_remoteadmin.c new file mode 100644 index 0000000..79d174b --- /dev/null +++ b/src/server_remoteadmin.c @@ -0,0 +1,656 @@ +/* + * 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_remoteadmin.h" + +static char newmessage; + +/* + * Function name: parse_int + * Description: This function parses the string as an integer and updates the buffer's + * parse pointer. + * Arguments: buff - string to parse + * ret - buffer's parse pointer + * Returns: Parsed integer value or -1, if something goes wrong. + */ + +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; + char cmd[31]; + + i = j = state = 0; + newmessage = 1; + while (buff[i] != 0) { + if (state == 1) { + if (isspace(buff[i])) { + break; + } + else { + if (j == 30) { + return 0; + } + cmd[j] = buff[i]; + ++j; + } + } + if (state == 0) { + if (!isspace(buff[i])) { + cmd[j] = buff[i]; + j = 1; + state = 1; + } + } + ++i; + } + if (state == 0) { + return 0; + } + while (isspace(buff[i])) { + ++i; + } + if (buff[i] == '.') { + ++i; + } + (*ret) = i; + cmd[j] = 0; + if (strcmp(cmd, "help") == 0) { return 1; } + if (strcmp(cmd, "lcmd") == 0) { return 2; } + if (strcmp(cmd, "info") == 0) { return 3; } + if (strcmp(cmd, "rshow") == 0) { return 4; } + if (strcmp(cmd, "cshow") == 0) { return 5; } + if (strcmp(cmd, "ushow") == 0) { return 6; } + if (strcmp(cmd, "quit") == 0) { return 7; } + 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; +} + +static void +send_adm_message(char type, SslFd* master, unsigned char* buff, unsigned char st) +{ + int n; + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = st; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); +} + +static void +add_to_message(unsigned char* buff, const char* format, ...) +{ + va_list ap; + int n; + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + newmessage = 0; + va_start(ap, format); + + vsprintf((char*) &buff[5+n], format, ap); + n = strlen((char*) &buff[5]); + sprintf((char*) &buff[5+n], "\n"); + + va_end(ap); +} + +static void +add_uptime_to_message(unsigned char* buff, char* info, time_t period) +{ + int hours, minutes, seconds; + + hours = period/3600; + minutes = (period/60)%60; + seconds = period%60; + + if (hours) { + add_to_message(buff, "%s: %d:%02d:%02d", info, hours, minutes, seconds); + } + else { + add_to_message(buff, "%s: %d:%02d", info, minutes, seconds); + } +} + +int +serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff) +{ + int length, n, i, j, ret; + time_t now, tmp; + llnodeT* llptr; + AuditListNode* alptr; + char olddf[51], newdf[51]; + char type = config->realmtable[realm].type | TYPE_SSL | TYPE_ZLIB; + SslFd* master = ConnectClient_get_sslFd(config->realmtable[realm].raclitable[client]); + + olddf[50] = newdf[50] = 0; + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is the length of a message */ + + time(&now); + + switch (buff[1]) { + case AF_RA_CMD: { + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + 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, " 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; + } + case 2: { /* lcmd */ + add_to_message(buff, "help"); + add_to_message(buff, "lcmd"); + add_to_message(buff, "info"); + add_to_message(buff, "rshow"); + add_to_message(buff, "cshow"); + add_to_message(buff, "ushow"); + add_to_message(buff, "quit"); + 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; + } + case 3: { /* info */ + add_to_message(buff, AF_VER("Version:")); + add_to_message(buff, "Realms: %d", config->size); + add_to_message(buff, "Certificate: %s", config->certif); + add_to_message(buff, "Key: %s", config->keys); + 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; + } + case 4: { /* rshow */ + for (i = 0; i < config->size; ++i) { + add_to_message(buff, "\nRealm[%s]:", get_realmname(config, i)); + add_to_message(buff, "hostname: %s", config->realmtable[i].hostname); + add_to_message(buff, "users: %d (max: %d)", + config->realmtable[i].usercon, config->realmtable[i].usernum); + add_to_message(buff, "clients: %d (max: %d)", + config->realmtable[i].clicon-config->realmtable[i].raclicon, + config->realmtable[i].clinum); + add_to_message(buff, "raclients: %d (max: %d)", + config->realmtable[i].raclicon, config->realmtable[i].raclinum); + add_to_message(buff, "users per client: %s", config->realmtable[i].usrpcli); + add_to_message(buff, "user-client pairs: %d", + config->realmtable[i].usrclinum); + for (j = 0; j < config->realmtable[i].usrclinum; ++j) { + add_to_message(buff, " pair[%d]: listenport: %s, manageport: %s", j, + UsrCli_get_listenPortName(config->realmtable[i].usrclitable[j]), + UsrCli_get_managePortName(config->realmtable[i].usrclitable[j])); + } + add_to_message(buff, "climode: %s", config->realmtable[i].clim); + 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 CONNECTCLIENT_TUNNELTYPE_DIRECT: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPPROXY: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY: { + add_to_message(buff, "tunneltype: https proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 5: { /* cshow*/ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + for (i = 0; i < config->realmtable[n].clinum; ++i) { + if (ConnectClient_get_state(config->realmtable[n].clitable[i]) != + CONNECTCLIENT_STATE_FREE) { + add_to_message(buff, "\nClient[%s]:", + get_clientname(&(config->realmtable[n]), i)); + switch (ConnectClient_get_state(config->realmtable[n].clitable[i])) { + case CONNECTCLIENT_STATE_CONNECTING: { + add_to_message(buff, "state: ssl handshake"); + break; + } + case CONNECTCLIENT_STATE_AUTHORIZING: { + add_to_message(buff, "state: authorization"); + break; + } + case CONNECTCLIENT_STATE_ACCEPTED: { + add_to_message(buff, "state: running"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "users: %d (max: %d)", + ConnectClient_get_connected(config->realmtable[n].clitable[i]), + ConnectClient_get_limit(config->realmtable[n].clitable[i])); + add_to_message(buff, "user-client pair: %d", + ConnectClient_get_usrCliPair(config->realmtable[n].clitable[i])); + tmp = now - ConnectClient_get_connectTime( + config->realmtable[n].clitable[i]); + add_uptime_to_message(buff, "Connection time", tmp); + add_to_message(buff, "Id: %s", + (ConnectClient_get_sClientId( + config->realmtable[n].clitable[i]) == NULL)?"": + ConnectClient_get_sClientId(config->realmtable[n].clitable[i])); + add_to_message(buff, "Number: %d", + ConnectClient_get_clientId(config->realmtable[n].clitable[i])); + add_to_message(buff, "IP: %s, port: %s", + ConnectClient_get_nameBuf(config->realmtable[n].clitable[i]), + ConnectClient_get_portBuf(config->realmtable[n].clitable[i])); + switch (ConnectClient_get_tunnelType( + config->realmtable[n].clitable[i])) { + case CONNECTCLIENT_TUNNELTYPE_DIRECT: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPPROXY: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY: { + add_to_message(buff, "tunneltype: https proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } + if (config->realmtable[n].audit) { + add_to_message(buff, "auditlog:"); + alptr = AuditList_get_first( + ConnectClient_get_auditList(config->realmtable[n].clitable[i])); + while (alptr) { + add_to_message(buff, + "userid: %d ip: %s port: %s connected: %s duration: %s", + AuditListNode_get_userId(alptr), + AuditListNode_get_nameBuf(alptr), + AuditListNode_get_portBuf(alptr), + localdate(AuditListNode_get_connectTimep(alptr)), + timeperiod(AuditListNode_get_duration(alptr))); + alptr = AuditListNode_get_nextNode(alptr); + } + } + } + } + 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; + } + case 6: { /* ushow */ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < config->size)) { + for (i = 0; i < config->realmtable[n].usernum; ++i) { + if (ConnectUser_get_state(config->realmtable[n].contable[i]) != + S_STATE_CLEAR) { + add_to_message(buff, "\nUser[%d]:", + get_username(&(config->realmtable[n]), i)); + switch (ConnectUser_get_state(config->realmtable[n].contable[i])) { + case S_STATE_CLOSING: { + add_to_message(buff, "state: closing"); + break; + } + case S_STATE_OPENING: { + add_to_message(buff, "state: opening"); + break; + } + case S_STATE_OPEN: { + add_to_message(buff, "state: running"); + break; + } + case S_STATE_STOPPED: { + add_to_message(buff, "state: stopped"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "connected to: Client[%s]", + get_clientname(&(config->realmtable[n]), + ConnectUser_get_whatClient(config->realmtable[n].contable[i]))); + tmp = now-ConnectUser_get_connectTime(config->realmtable[n].contable[i]); + add_uptime_to_message(buff, "Connection time", tmp); + tmp = now - UserStats_get_lastActivity( + ConnectUser_get_stats(config->realmtable[n].contable[i])); + add_uptime_to_message(buff, "Idle time", tmp); + add_to_message(buff, "IP: %s, port: %s", + ConnectUser_get_nameBuf(config->realmtable[n].contable[i]), + ConnectUser_get_portBuf(config->realmtable[n].contable[i])); + add_to_message(buff, "Downloaded: %d bytes", + UserStats_get_totalDownloadedBytes( + ConnectUser_get_stats(config->realmtable[n].contable[i]))); + add_to_message(buff, "download speed: %.2f B/s", + UserStats_get_downloadSpeed( + ConnectUser_get_stats(config->realmtable[n].contable[i]))); + add_to_message(buff, "Uploaded: %d bytes", + UserStats_get_totalUploadedBytes( + ConnectUser_get_stats(config->realmtable[n].contable[i]))); + add_to_message(buff, "upload speed: %.2f B/s", + UserStats_get_uploadSpeed( + ConnectUser_get_stats(config->realmtable[n].contable[i]))); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + 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(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) { + AuditList_clear( + ConnectClient_get_auditList( + config->realmtable[n].clitable[i])); + } + } + 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 ((ConnectUser_get_state(config->realmtable[n].contable[j]) == + S_STATE_OPEN) || + (ConnectUser_get_state(config->realmtable[n].contable[j]) == + S_STATE_STOPPED)) { + add_to_message(buff, "kicked: realm[%s] user[%d]", + get_realmname(config, n), get_username(&(config->realmtable[n]), i)); + close(ConnectUser_get_connFd(config->realmtable[n].contable[j])); + 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 (ConnectClient_get_state(config->realmtable[n].clitable[j]) > + CONNECTCLIENT_STATE_FREE) { + 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(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: admin: cmd ignored", get_realmname(config, realm)); + send_adm_message(type, master, buff, AF_RA_UNDEFINED); + } + } + break; + } + case AF_RA_REPEAT: { + break; + } + default: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "Unrecognized message from remote admin --> closing"); + return 1; + } + } + return 0; +} diff --git a/src/server_remoteadmin.h b/src/server_remoteadmin.h new file mode 100644 index 0000000..a85070e --- /dev/null +++ b/src/server_remoteadmin.h @@ -0,0 +1,37 @@ +/* + * 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_REMOTEADMIN_H +#define _JS_SERVER_REMOTEADMIN_H + +#include +#include + +#include "remoteadmin_codes.h" +#include "activefor.h" +#include "logging.h" +#include "stats.h" +#include "clientnames.h" +#include "realmnames.h" +#include "usernames.h" + +int serve_admin(ConfigurationT*, int, int, unsigned char*); + +#endif diff --git a/src/server_remove.c b/src/server_remove.c index de2df66..003c484 100644 --- a/src/server_remove.c +++ b/src/server_remove.c @@ -24,37 +24,35 @@ void remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) { int i; - if (ptr->clitable[client].ready == 3) { + if (ConnectClient_get_state(ptr->clitable[client]) == CONNECTCLIENT_STATE_ACCEPTED) { for (i = 0; i < ptr->usernum; ++i) { - if (ptr->contable[i].whatcli == client) { - if (ptr->contable[i].state != S_STATE_CLEAR) { - ptr->contable[i].state = S_STATE_CLEAR; - FD_CLR(ptr->contable[i].connfd, set); - FD_CLR(ptr->contable[i].connfd, wset); - close(ptr->contable[i].connfd); + if (ConnectUser_get_whatClient(ptr->contable[i]) == client) { + if (ConnectUser_get_state(ptr->contable[i]) != S_STATE_CLEAR) { + ConnectUser_set_state(ptr->contable[i], S_STATE_CLEAR); + FD_CLR(ConnectUser_get_connFd(ptr->contable[i]), set); + FD_CLR(ConnectUser_get_connFd(ptr->contable[i]), wset); + close(ConnectUser_get_connFd(ptr->contable[i])); ptr->usercon--; } } } } - for (i=0; iclitable[client].usernum; ++i) { - ptr->clitable[client].users[i] = -1; + for (i = 0; i < ConnectClient_get_limit(ptr->clitable[client]); ++i) { + ConnectClient_get_users(ptr->clitable[client])[i] = -1; } if ((ptr->clinum != client) && (ptr->baseport == 1)) { - close(ptr->clitable[client].listenfd); - FD_CLR(ptr->clitable[client].listenfd, set); + close(ConnectClient_get_listenFd(ptr->clitable[client])); + FD_CLR(ConnectClient_get_listenFd(ptr->clitable[client]), set); } - if (ptr->clitable[client].clientid) { - free(ptr->clitable[client].clientid); - ptr->clitable[client].clientid = NULL; - } - ptr->clitable[client].usercon = 0; - close(ptr->clitable[client].cliconn.commfd); - FD_CLR(ptr->clitable[client].cliconn.commfd, set); - if (ptr->clitable[client].ready == 2) + ConnectClient_set_sClientId(ptr->clitable[client], NULL); + ConnectClient_set_connected(ptr->clitable[client], 0); + close(SslFd_get_fd(ConnectClient_get_sslFd(ptr->clitable[client]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ptr->clitable[client])), set); + if (ConnectClient_get_state(ptr->clitable[client]) == CONNECTCLIENT_STATE_AUTHORIZING) { (*con)--; - SSL_clear(ptr->clitable[client].cliconn.ssl); - ptr->clitable[client].ready = 0; + } + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ptr->clitable[client]))); + ConnectClient_set_state(ptr->clitable[client], CONNECTCLIENT_STATE_FREE); ptr->clicon--; } @@ -62,23 +60,20 @@ void remove_raclient(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) { int i; - for (i=0; iraclitable[client].usernum; ++i) { - ptr->raclitable[client].users[i] = -1; - } - if (ptr->raclitable[client].clientid) { - free(ptr->raclitable[client].clientid); - ptr->raclitable[client].clientid = NULL; + for (i = 0; i < ConnectClient_get_limit(ptr->raclitable[client]); ++i) { + ConnectClient_get_users(ptr->raclitable[client])[i] = -1; } - ptr->raclitable[client].usercon = 0; - close(ptr->raclitable[client].cliconn.commfd); - FD_CLR(ptr->raclitable[client].cliconn.commfd, set); - if (ptr->raclitable[client].ready == 2) { + ConnectClient_set_sClientId(ptr->raclitable[client], NULL); + ConnectClient_set_connected(ptr->raclitable[client], 0); + close(SslFd_get_fd(ConnectClient_get_sslFd(ptr->raclitable[client]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ptr->raclitable[client])), set); + if (ConnectClient_get_state(ptr->raclitable[client]) == CONNECTCLIENT_STATE_AUTHORIZING) { (*con)--; } - SSL_clear(ptr->raclitable[client].cliconn.ssl); + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ptr->raclitable[client]))); ptr->clicon--; - if (ptr->raclitable[client].ready == 3) { + if (ConnectClient_get_state(ptr->raclitable[client]) == CONNECTCLIENT_STATE_ACCEPTED) { ptr->raclicon--; } - ptr->raclitable[client].ready = 0; + ConnectClient_set_state(ptr->raclitable[client], CONNECTCLIENT_STATE_FREE); } diff --git a/src/server_signals.c b/src/server_signals.c index 41cd31c..ae5388d 100644 --- a/src/server_signals.c +++ b/src/server_signals.c @@ -44,13 +44,21 @@ server_sig_int(int signo) 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); + if (ConnectClient_get_state(config.realmtable[j].clitable[i]) == + CONNECTCLIENT_STATE_ACCEPTED) { + SslFd_send_message(config.realmtable[j].type, + ConnectClient_get_sslFd( + config.realmtable[j].clitable[i]), + 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); + if (ConnectClient_get_state(config.realmtable[j].raclitable[i]) == + CONNECTCLIENT_STATE_ACCEPTED) { + SslFd_send_message(config.realmtable[j].type | TYPE_SSL, + ConnectClient_get_sslFd( + config.realmtable[j].raclitable[i]), + buff, 5); } } diff --git a/src/ssl_fd_struct.c b/src/ssl_fd_struct.c new file mode 100644 index 0000000..61bf98c --- /dev/null +++ b/src/ssl_fd_struct.c @@ -0,0 +1,314 @@ +/* + * 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 "activefor.h" +#include "stats.h" +#include "logging.h" +#include "ssl_fd_struct.h" + +/* + * Function name: SslFd_new + * Description: Create and initialize new SslFd structure. + * Returns: Pointer to newly created SslFd structure. + */ + +SslFd* +SslFd_new() +{ + SslFd* tmp = calloc(1, sizeof(SslFd)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: SslFd_free + * Description: Free the memory allocated for SslFd structure. + * Arguments: sf - pointer to pointer to SslFd structure + */ + +void +SslFd_free(SslFd** sf) +{ + if (sf == NULL) { + return; + } + if ((*sf) == NULL) { + return; + } + if ((*sf)->ssl) { + SSL_free((*sf)->ssl); + (*sf)->ssl = NULL; + } + free((*sf)); + (*sf) = NULL; +} + +/* + * Function name: SslFd_set_fd + * Description: Set file descriptor of the used socket. + * Arguments: sf - pointer to SslFd structure + * fd - file descriptor of the used socket + */ + +void +SslFd_set_fd(SslFd* sf, int fd) +{ + if (sf == NULL) { + return; + } + sf->fd = fd; +} + +/* + * Function name: SslFd_set_ssl_general + * Description: Set ssl object for the used socket. Free previous ssl object if 'free' argument is not 0. + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + * free - free previous ssl object + */ + +void +SslFd_set_ssl_general(SslFd* sf, SSL* ssl, int free) +{ + if (sf == NULL) { + return; + } + if ((free) && (sf->ssl)) { + SSL_free(sf->ssl); + } + sf->ssl = ssl; +} + + +/* + * Function name: SslFd_set_ssl + * Description: Set ssl object for the used socket. + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + */ + +void +SslFd_set_ssl(SslFd* sf, SSL* ssl) +{ + SslFd_set_ssl_general(sf, ssl, 1); +} + +/* + * Function name: SslFd_set_ssl_nf + * Description: Set ssl object for the used socket. Don't free previous ssl object + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + */ + +void +SslFd_set_ssl_nf(SslFd* sf, SSL* ssl) +{ + SslFd_set_ssl_general(sf, ssl, 0); +} + +/* + * Function name: SslFd_set_ssl + * Description: Get file descriptor of the used socket. + * Arguments: sf - pointer to SslFd structure + * Returns: File descriptor of the used socket. + */ + +int +SslFd_get_fd(SslFd* sf) +{ + if (sf == NULL) { + return -1; + } + return sf->fd; +} + +/* + * Function name: SslFd_get_ssl + * Description: Get ssl object for the used socket. + * Arguments: sf - pointer to SslFd structure + * Returns: Ssl object for the used socket. + */ + +SSL* +SslFd_get_ssl(SslFd* sf) +{ + if (sf == NULL) { + return NULL; + } + return sf->ssl; +} + +/* + * Function name: SslFd_send_message + * Description: Send message from 'buf' of the length 'amount' to the socket + * encapsulated in SslFd structure. 'type' is used to keep + * information about ip family, using of ssl, using of zlib and more. + * Arguments: type - type of the connection + * sf - pointer to SslFd structure + * buf - buffer which keeps data to send + * amount - amount of data to send + * Returns: Amount of bytes written or -1, if some error occured. + */ + +int +SslFd_send_message(char type, SslFd* sf, unsigned char* buf, int amount) +{ + unsigned long clen; + int length; + static unsigned char buffer[9000]; + + if ((sf == NULL) || (buf == NULL)) { + return -1; + } + + 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; + if (TYPE_IS_ZLIB(type)) { + memcpy(buffer, buf, 5); + if (amount > 5) { + compress(&buffer[5], &clen, &buf[5], length); + if (clen < length) { + length = clen; + TYPE_SET_COMP(length); + buffer[3] = length >> 8; /* high bits of message length */ + buffer[4] = length; /* low bits of message length */ + addtocg(amount-5 - clen); + } + } + if (TYPE_IS_SSL(type)) { + if (TYPE_IS_COMP(length)) { + return SSL_writen(sf->ssl, buffer, clen+5); + } + else { + return SSL_writen(sf->ssl, buf, amount); + } + } + else { + if (TYPE_IS_COMP(length)) { + return writen(sf->fd, buffer, clen+5); + } + else { + return writen(sf->fd, buf, amount); + } + } + } + else { + if (TYPE_IS_SSL(type)) { + return SSL_writen(sf->ssl, buf, amount); + } + else { + return writen(sf->fd, buf, amount); + } + } +} + +/* + * Function name: SslFd_get_message + * Description: Get message from the socket encapsulated in SslFd structure + * and write it to the 'buf'. Message is 'amount' butes long. + * 'type' is used to keep information about ip family, using of + * ssl, using of zlib and more. + * Arguments: type - type of the connection + * sf - pointer to SslFd structure + * buf - buffer which will keep received data + * amount - length of the message to receive + * Returns: Amount of bytes received or -1, if some error occured. + */ + +int +SslFd_get_message(char type, SslFd* sf, unsigned char* buf, int amount) +{ + int length; + unsigned long elen; + static unsigned char bufor[9000]; + if ((sf == NULL) || (buf == NULL)) { + return -1; + } + 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 < 0) { + if (TYPE_IS_SSL(type)) { + return SSL_read(sf->ssl, buf, -amount); + } + else { + return read(sf->fd, buf, -amount); + } + } + if (TYPE_IS_ZLIB(type)) { + if (TYPE_IS_SSL(type)) { + length = SSL_readn(sf->ssl, bufor, amount&0xBFFF); + } + else { + length = readn(sf->fd, bufor, amount&0xBFFF); + } + if (length <= 0) return length; + elen = 8096; + if (TYPE_IS_COMP(amount)) { + uncompress(buf, &elen, bufor, length); + } + else { + memcpy(buf, bufor, length); + elen = length; + } + return elen; + } + else + { + if (TYPE_IS_SSL(type)) { + return SSL_readn(sf->ssl, buf, amount); + } + else { + return readn(sf->fd, buf, amount); + } + } +} + +/* + * Function name: SslFd_swap_content + * Description: Swap the content of two SslFd structures. + * Arguments: sf1 - first pointer to SslFd structure + * sf2 - second pointer to SslFd structure + */ + +void +SslFd_swap_content(SslFd* sf1, SslFd* sf2) +{ + int tmpfd; + SSL* tmpssl; + + tmpfd = SslFd_get_fd(sf1); + tmpssl = SslFd_get_ssl(sf2); + SslFd_set_fd(sf1, SslFd_get_fd(sf2)); + SslFd_set_ssl(sf1, SslFd_get_ssl(sf2)); + SslFd_set_fd(sf2, tmpfd); + SslFd_set_ssl(sf2, tmpssl); +} diff --git a/src/ssl_fd_struct.h b/src/ssl_fd_struct.h new file mode 100644 index 0000000..badc01f --- /dev/null +++ b/src/ssl_fd_struct.h @@ -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. + * + */ + + +#ifndef _JS_SSL_FD_STRUCT_H +#define _JS_SSL_FD_STRUCT_H + +#include + +typedef struct { + int fd; + SSL* ssl; +} SslFd; + +/* 'constructor' */ +SslFd* SslFd_new(); +/* 'destructor' */ +void SslFd_free(SslFd** sf); +/* setters */ +void SslFd_set_fd(SslFd* sf, int fd); +void SslFd_set_ssl(SslFd* sf, SSL* ssl); +void SslFd_set_ssl_nf(SslFd* sf, SSL* ssl); +/* getters */ +int SslFd_get_fd(SslFd* sf); +SSL* SslFd_get_ssl(SslFd* sf); +/* other */ +int SslFd_send_message(char type, SslFd* sf, unsigned char* buf, int amount); +int SslFd_get_message(char type, SslFd* sf, unsigned char* buf, int amount); +void SslFd_swap_content(SslFd* sf1, SslFd* sf2); + +#endif diff --git a/src/string_functions.c b/src/string_functions.c new file mode 100644 index 0000000..471d3eb --- /dev/null +++ b/src/string_functions.c @@ -0,0 +1,68 @@ +/* + * 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 "string_functions.h" + +/* + * Function name: string_cp + * Description: Firstly, the memory allocated for *dest is released. After this, new memory is allocated + * and string from src is copied to newly created location. *dest is pointing to new string. + * Arguments: dest - pointer to pointer to string previously allocated by malloc family functions. + * If dest is NULL, memory will be allocated and returned from the function. In latter + * case dest will be unchanged + * src - string containing data for copying. If src is NULL, new memory is not allocated, but + * the old one is still released. + */ + +char* +string_cp(char** dest, char* src) +{ + char* tmp; + int len = 0; + + /* 1. releasing memory allocated by *dest */ + if (dest != NULL) { + if ((*dest) != NULL) { + free((*dest)); + (*dest) = NULL; + } + } + /* if src is null, there is nothing more to do */ + if (src == NULL) { + return NULL; + } + /* 2. allocating new memory */ + len = strlen(src); + tmp = calloc(1, len + 1); + if (tmp == NULL) { + return NULL; + } + /* 3. copying data from src */ + strncpy(tmp, src, len); + if (dest != NULL) { + (*dest) = tmp; + } + return tmp; +} diff --git a/src/string_functions.h b/src/string_functions.h new file mode 100644 index 0000000..30667bc --- /dev/null +++ b/src/string_functions.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_STRING_FUNCTIONS_H +#define _JS_STRING_FUNCTIONS_H + +char* string_cp(char** dest, char* src); + +#endif + diff --git a/src/timeval_functions.c b/src/timeval_functions.c new file mode 100644 index 0000000..f916e35 --- /dev/null +++ b/src/timeval_functions.c @@ -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 "timeval_functions.h" + +/* + * Function name: timeval_create + * Description: Initialize and return timeval structure. + * Arguments: tv_sec - seconds + * tv_usec - microseconds + * Returns: Initialized timeval structure. + */ + +struct timeval +timeval_create(long tv_sec, long tv_usec) +{ + struct timeval tmp; + tmp.tv_sec = tv_sec; + tmp.tv_usec = tv_usec; + return tmp; +} diff --git a/src/timeval_functions.h b/src/timeval_functions.h new file mode 100644 index 0000000..790850a --- /dev/null +++ b/src/timeval_functions.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_TIMEVAL_FUNCTIONS_H +#define _JS_TIMEVAL_FUNCTIONS_H + +#include + +struct timeval timeval_create(long tv_sec, long tv_usec); + +#endif + diff --git a/src/usage.c b/src/usage.c index 7d73f61..67e7046 100644 --- a/src/usage.c +++ b/src/usage.c @@ -42,10 +42,10 @@ server_long_usage(char* 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(" -l, --listenport - listening [host:]port - users connect to it\n"); + printf(" (default: 50127)\n"); + printf(" -m, --manageport - manage [host:]port - afclient connects to it\n"); + printf(" (default: 50126)\n"); printf(" -V, --version - display version number\n"); printf(" -h, --help - prints this help\n\n"); printf(" Authorization:\n\n"); @@ -94,6 +94,10 @@ server_long_usage(char* info) #ifdef HAVE_LIBPTHREAD printf(" HTTP PROXY:\n\n"); printf(" -P, --enableproxy - enable http proxy mode\n\n"); + /* FIXME: afclient is always trying to get http page, so this option is not needed now + printf(" -S, --use-https - use https proxy instead of http proxy. '-P' option\n"); + printf(" will be set implicitly\n\n"); + */ #endif exit(0); @@ -135,9 +139,15 @@ client_long_usage(char* info) 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(" (default: not send keepalive packets)\n\n"); + printf(" Auto-reconnection:\n\n"); + printf(" --ar-start - enable auto-reconnection when afserver is not\n"); + printf(" reachable on start (default: disabled)\n"); + printf(" --ar-quit - enable auto-reconnection after normal afserver quit\n"); + printf(" (default: disabled)\n"); + printf(" --noar - disable auto-reconnection after premature afserver\n"); + printf(" quit (default: enabled)\n"); + printf(" -A, --ar-tries N - try N times to reconnect (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"); @@ -162,9 +172,13 @@ client_long_usage(char* info) printf(" -L, --Load - load a module for service's packets filtering\n\n"); #endif #ifdef HAVE_LIBPTHREAD - printf(" HTTP PROXY:\n\n"); + printf(" HTTP/HTTPS PROXY:\n\n"); + printf(" -S, --use-https - use https proxy instead of http proxy\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"); + printf(" -X, --proxyport - the port used by proxy server (default: 8080)\n"); + printf(" -C, --pa-cred U:P - the user (U) and password (P) used in proxy\n"); + printf(" authorization\n"); + printf(" -B, --pa-t-basic - the Basic type of proxy authorization (default)\n\n"); #endif exit(0); diff --git a/src/user_stats_struct.c b/src/user_stats_struct.c new file mode 100644 index 0000000..4c917a7 --- /dev/null +++ b/src/user_stats_struct.c @@ -0,0 +1,368 @@ +/* + * 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 "user_stats_struct.h" + +/* + * Function name: UserStats_new + * Descriotion: Create and initialize new UserStats structure. + * Returns: Pointer to newly created UserStats structure. + */ + +UserStats* +UserStats_new() +{ + UserStats* tmp = calloc(1, sizeof(UserStats)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: UserStats_free + * Description: Free the memory allocated for UserStats structure. + * Arguments: us - pointer to pointer to UserStats structure + */ + +void +UserStats_free(UserStats** us) +{ + if (us == NULL) { + return; + } + if ((*us) == NULL) { + return; + } + free((*us)); + (*us) = NULL; +} + +/* + * Function name: UserStats_set_lastActivity + * Description: Set time of the last user activity (upload or download). + * Arguments: us - pointer to UserStats structure + * lastActivity - time of the last user activity + */ + +void +UserStats_set_lastActivity(UserStats* us, time_t lastActivity) +{ + if (us == NULL) { + return; + } + us->lastActivity = lastActivity; +} + +/* + * Function name: UserStats_set_totalDownloadedBytes + * Description: Set total amount of downloaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * totalDownloadedBytes - total amount of downloaded bytes by the user + */ + +void +UserStats_set_totalDownloadedBytes(UserStats* us, int totalDownloadedBytes) +{ + if (us == NULL) { + return; + } + us->totalDownloadedBytes = totalDownloadedBytes; +} + +/* + * Function name: UserStats_set_totalUploadedBytes + * Description: Set total amount of uploaded byte by the user. + * Arguments: us - pointer to UserStats structure + * totalUploadedBytes - total amount of uploaded bytes by the user + */ + +void +UserStats_set_totalUploadedBytes(UserStats* us, int totalUploadedBytes) +{ + if (us == NULL) { + return; + } + us->totalUploadedBytes = totalUploadedBytes; +} + +/* + * Function name: UserStats_get_lastActivity + * Description: Get time of the last user activity (upload or download). + * Arguments: us - pointer to UserStats structure + * Returns: Time of the last user activity. + */ + +time_t +UserStats_get_lastActivity(UserStats* us) +{ + if (us == NULL) { + return 0; + } + return us->lastActivity; +} + +/* + * Function name: UserStats_get_totalDownloadedBytes + * Description: Get total amount of downloaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * Returns: Total amount of downloaded bytes by the user. + */ + +int +UserStats_get_totalDownloadedBytes(UserStats* us) +{ + if (us == NULL) { + return 0; + } + return us->totalDownloadedBytes; +} + +/* + * Function name: UserStats_get_totalUploadedBytes + * Description: Get total amount of uploaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * Returns: Total amount of uploaded bytes by the user. + */ + +int +UserStats_get_totalUploadedBytes(UserStats* us) +{ + if (us == NULL) { + return 0; + } + return us->totalUploadedBytes; +} + +/* + * Function name: UserStats_add_download + * Description: Add bytes to the totalDownloadedBytes, update the lastActivity + * and downloadSpeed. + * Arguments: us - pointer to UserStats structure + * bytes - amount of bytes to add + */ + +void +UserStats_add_download(UserStats* us, int bytes) +{ + time_t now; + if (us == NULL) { + return; + } + + /* get the current time */ + time(&now); + + /* update counters */ + switch (now - us->lastDSQChange) { + case 0: { + us->downloadSpeedQueue[us->downloadSQP] += bytes; + break; + } + case 2: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + } + case 1: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = bytes; + break; + } + default: { + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; + us->downloadSpeedQueue[us->downloadSQP] = bytes; + } + } + + /* update total upload */ + us->totalDownloadedBytes += bytes; + + /* update last activity */ + us->lastActivity = now; + + /* update last speed queue change */ + us->lastDSQChange = now; +} + +/* + * Function name: UserStats_add_upload + * Description: Add bytes to the totalUploadedBytes, update the lastActivity + * and uploadSpeed. + * Arguments: us - pointer to UserStats structure + * bytes - amount of bytes to add + */ + +void +UserStats_add_upload(UserStats* us, int bytes) +{ + time_t now; + if (us == NULL) { + return; + } + + /* get the current time */ + time(&now); + + /* update counters */ + switch (now - us->lastUSQChange) { + case 0: { + us->uploadSpeedQueue[us->uploadSQP] += bytes; + break; + } + case 2: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + } + case 1: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = bytes; + break; + } + default: { + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + us->uploadSpeedQueue[us->uploadSQP] = bytes; + } + } + + /* update total upload */ + us->totalUploadedBytes += bytes; + + /* update last activity */ + us->lastActivity = now; + + /* update last speed queue change */ + us->lastUSQChange = now; +} + +/* + * Function name: UserStats_get_downloadSpeed + * Description: Get the average download speed from the last three seconds. + * Arguments: us - pointer to UserStats structure + * Returns: The average download speed from the last three seconds. + */ + +double +UserStats_get_downloadSpeed(UserStats* us) +{ + time_t now; + if (us == NULL) { + return 0.0; + } + + /* get the current time */ + time(&now); + + /* update pointer */ + switch (now - us->lastDSQChange) { + case 0: { + break; + } + case 2: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + } + case 1: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + break; + } + default: { + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; + } + } + + /* update last speed queue change */ + us->lastDSQChange = now; + + /* return current download speed */ + return (((double)(us->downloadSpeedQueue[0] + us->downloadSpeedQueue[1] + us->downloadSpeedQueue[2])) / 3.0); +} + +/* + * Function name: UserStats_get_uploadSpeed + * Description: Get the average upload speed from the last three seconds. + * Arguments: us - pointer to UserStats structure + * Returns: The average upload speed from the last three seconds. + */ + +double +UserStats_get_uploadSpeed(UserStats* us) +{ + time_t now; + if (us == NULL) { + return 0.0; + } + + /* get the current time */ + time(&now); + + /* update pointer */ + switch (now - us->lastUSQChange) { + case 0: { + break; + } + case 2: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + } + case 1: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + break; + } + default: { + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + } + } + + /* update last speed queue change */ + us->lastUSQChange = now; + + /* return current download speed */ + return (((double)(us->uploadSpeedQueue[0] + us->uploadSpeedQueue[1] + us->uploadSpeedQueue[2])) / 3.0); +} + +/* + * Function name: UserStats_clear + * Description: Clear the UserStats structure. Set all variables to default values. + * Arguments: us - pointer to UserStats structure + */ + +void +UserStats_clear(UserStats* us) +{ + if (us == NULL) { + return; + } + us->lastActivity = 0; + us->lastUSQChange = 0; + us->lastDSQChange = 0; + us->totalDownloadedBytes = 0; + us->totalUploadedBytes = 0; + us->uploadSQP = 0; + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + us->downloadSQP = 0; + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; +} diff --git a/src/user_stats_struct.h b/src/user_stats_struct.h new file mode 100644 index 0000000..633edd5 --- /dev/null +++ b/src/user_stats_struct.h @@ -0,0 +1,59 @@ +/* + * 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_USER_STATS_STRUCT_H +#define _JS_USER_STATS_STRUCT_H + +#include + +typedef struct { + time_t lastActivity; + time_t lastUSQChange; + time_t lastDSQChange; + int totalDownloadedBytes; + int totalUploadedBytes; + int uploadSQP; + int uploadSpeedQueue[3]; + int downloadSQP; + int downloadSpeedQueue[3]; +} UserStats; + +/* 'constructor' */ +UserStats* UserStats_new(); +/* 'destructor' */ +void UserStats_free(UserStats** us); +/* setters */ +void UserStats_set_lastActivity(UserStats* us, time_t lastActivity); +void UserStats_set_totalDownloadedBytes(UserStats* us, int totalDownloadedBytes); +void UserStats_set_totalUploadedBytes(UserStats* us, int totalUploadedBytes); +/* getters */ +time_t UserStats_get_lastActivity(UserStats* us); +int UserStats_get_totalDownloadedBytes(UserStats* us); +int UserStats_get_totalUploadedBytes(UserStats* us); +/* other methods */ +void UserStats_add_download(UserStats* us, int bytes); +void UserStats_add_upload(UserStats* us, int bytes); +double UserStats_get_downloadSpeed(UserStats* us); +double UserStats_get_uploadSpeed(UserStats* us); +/* other */ +void UserStats_clear(UserStats* us); + +#endif diff --git a/src/usernames.c b/src/usernames.c index 194bfa0..175cced 100644 --- a/src/usernames.c +++ b/src/usernames.c @@ -25,7 +25,7 @@ int get_username(RealmT* pointer, int user) { - return pointer->contable[user].userid; + return ConnectUser_get_userId(pointer->contable[user]); } int @@ -34,7 +34,7 @@ get_usernumber(RealmT* pointer, int userid) int i; for (i = 0; i < pointer->usernum; ++i) { - if (userid == pointer->contable[i].userid) { + if (userid == ConnectUser_get_userId(pointer->contable[i])) { return i; } } diff --git a/src/usr_cli_struct.c b/src/usr_cli_struct.c new file mode 100644 index 0000000..fee84a9 --- /dev/null +++ b/src/usr_cli_struct.c @@ -0,0 +1,246 @@ +/* + * 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 "usr_cli_struct.h" +#include "string_functions.h" + +/* + * Function name: UsrCli_new + * Description: Create and initialize new UsrCli structure. + * Returns: Newly created UsrCli structure. + */ + +UsrCli* +UsrCli_new() +{ + UsrCli* tmp = calloc(1, sizeof(UsrCli)); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: UsrCli_free + * Description: Free the memory allocated for UsrCli structure. + * Arguments: uc - pointer to pointer to UsrCli structure + */ + +void +UsrCli_free(UsrCli** uc) +{ + if (uc == NULL) { + return; + } + if ((*uc) == NULL) { + return; + } + if ((*uc)->listenPortName) { + free((*uc)->listenPortName); + (*uc)->listenPortName = NULL; + } + if ((*uc)->managePortName) { + free((*uc)->managePortName); + (*uc)->managePortName = NULL; + } + free((*uc)); + (*uc) = NULL; +} + +/* Function name: UsrCli_set_listenPortName + * Description: Set listen port name. + * Arguments: uc - pointer to UsrCli structure + * listenPortName - listen port name + */ + +void +UsrCli_set_listenPortName(UsrCli* uc, char* listenPortName) +{ + char* tmp; + if (uc == NULL) { + return; + } + if ((tmp = rindex(listenPortName, ':')) != NULL) { + (*tmp) = 0; + ++tmp; + string_cp(&(uc->listenHostName), listenPortName); + string_cp(&(uc->listenPortName), tmp); + } + else { + string_cp(&(uc->listenPortName), listenPortName); + } +} + +/* + * Function name: UsrCli_set_managePortName + * Description: Set manage port name. + * Arguments: uc - pointer to UsrCli structure + * managePortName - manage port name + */ + +void +UsrCli_set_managePortName(UsrCli* uc, char* managePortName) +{ + char* tmp; + if (uc == NULL) { + return; + } + if ((tmp = rindex(managePortName, ':')) != NULL) { + (*tmp) = 0; + ++tmp; + string_cp(&(uc->manageHostName), managePortName); + string_cp(&(uc->managePortName), tmp); + } + else { + string_cp(&(uc->managePortName), managePortName); + } +} + +/* + * Function name: UsrCli_set_listenFd + * Description: Set listen file descriptor. + * Arguments: uc - pointer to UsrCli structure + * listenFd - listen file descriptor + */ + +void +UsrCli_set_listenFd(UsrCli* uc, int listenFd) +{ + if (uc == NULL) { + return; + } + uc->listenFd = listenFd; +} + +/* + * Function name: UsrCli_set_manageFd + * Description: Set manage file descriptor. + * Arguments: uc - pointer to UsrCli structure + * manageFd - manage file descriptor + */ + +void +UsrCli_set_manageFd(UsrCli* uc, int manageFd) +{ + if (uc == NULL) { + return; + } + uc->manageFd = manageFd; +} + +/* Function name: UsrCli_get_listenPortName + * Description: Get listen port name. + * Arguments: uc - pointer to UsrCli structure + * Returns: Listen port name. + */ + +char* +UsrCli_get_listenPortName(UsrCli* uc) +{ + if (uc == NULL) { + return NULL; + } + return uc->listenPortName; +} + +/* + * Function name: UsrCli_get_managePortName + * Description: Get manage port name. + * Arguments: uc - pointer to UsrCli structure + * Returns: Manage port name. + */ + +char* +UsrCli_get_managePortName(UsrCli* uc) +{ + if (uc == NULL) { + return NULL; + } + return uc->managePortName; +} + +/* + * Function name: UsrCli_get_listenFd + * Description: Get listen file descriptor. + * Arguments: uc - pointer to UsrCli structure + * Returns: Listen file descriptor. + */ + +int +UsrCli_get_listenFd(UsrCli* uc) +{ + if (uc == NULL) { + return -1; + } + return uc->listenFd; +} + +/* + * Function name: UsrCli_get_manageFd + * Description: Get manage file descriptor. + * Arguments: uc - pointer to UsrCli structure + * Returns: Manage file desciptor. + */ + +int +UsrCli_get_manageFd(UsrCli* uc) +{ + if (uc == NULL) { + return -1; + } + return uc->manageFd; +} + +/* + * Function name: UsrCli_get_listenHostName + * Description: Get host name used for listenFd in ip_connect function or NULL, if not set. + * Arguments: uc - pointer to UsrCli structure + * Returns: Host name used for listenFd in ip_connect function or NULL, if not set. + */ + +char* +UsrCli_get_listenHostName(UsrCli* uc) +{ + if (uc == NULL) { + return NULL; + } + return uc->listenHostName; +} + +/* + * Function name: UsrCli_get_manageHostName + * Description: Get host name used for manageFd in ip_connect function or NULL, if not set. + * Arguments: uc - pointer to UsrCli structure + * Returns: Host name used for manageFd in ip_connect function or NULL, if not set. + */ + +char* +UsrCli_get_manageHostName(UsrCli* uc) +{ + if (uc == NULL) { + return NULL; + } + return uc->manageHostName; +} diff --git a/src/usr_cli_struct.h b/src/usr_cli_struct.h new file mode 100644 index 0000000..e86bd04 --- /dev/null +++ b/src/usr_cli_struct.h @@ -0,0 +1,51 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_USR_CLI_STRUCT_H +#define _JS_USR_CLI_STRUCT_H + +typedef struct { + char* listenHostName; + char* manageHostName; + char* listenPortName; + char* managePortName; + int listenFd; + int manageFd; +} UsrCli; + +/* 'constructor' */ +UsrCli* UsrCli_new(); +/* 'destructor' */ +void UsrCli_free(UsrCli** uc); +/* setters */ +void UsrCli_set_listenPortName(UsrCli* uc, char* listenPortName); +void UsrCli_set_managePortName(UsrCli* uc, char* managePortName); +void UsrCli_set_listenFd(UsrCli* uc, int listenFd); +void UsrCli_set_manageFd(UsrCli* uc, int manageFd); +/* getters */ +char* UsrCli_get_listenPortName(UsrCli* uc); +char* UsrCli_get_managePortName(UsrCli* uc); +int UsrCli_get_listenFd(UsrCli* uc); +int UsrCli_get_manageFd(UsrCli* uc); +char* UsrCli_get_listenHostName(UsrCli* uc); +char* UsrCli_get_manageHostName(UsrCli* uc); + +#endif -- cgit v1.1