From 8a5f0141a346ad4b94d09313a2ec9a52efa7cf59 Mon Sep 17 00:00:00 2001 From: Jakub SЕ‚awiЕ„ski Date: Tue, 12 Oct 2004 00:07:33 +0200 Subject: v0.5.5 - Added: rsa key generation by afclient - Modified: afclient is now generating keys by default - Fixed: major bug in packet buffering - Added: 'timeout', 'clients' and 'usrpcli' options - Fixed: parsing 'users' option - Modified: module management routines - Added: module support for service's packet filtering - Fixed: few minor bugs in closing connection routines - Added: possibility to use several clients per realm - Modified: there is no need for 'users', 'timeout', 'clients', 'proto', 'usrpcli' and 'climode' options in config file when default values are acceptable --- AUTHORS | 7 +- Changelog | 72 ++-- Makefile | 12 +- README | 47 ++- activefor.h | 12 +- afclient.c | 157 +++++-- afserver.c | 1195 ++++++++++++++++++++++++++++++----------------------- buflist.c | 15 +- config | 24 +- docs/ru/ru_README | 294 +++++++++++++ exmodule.c | 37 +- file.c | 16 + file.h | 13 +- modules.c | 63 +++ modules.h | 37 ++ 15 files changed, 1357 insertions(+), 644 deletions(-) create mode 100644 docs/ru/ru_README create mode 100644 modules.c create mode 100644 modules.h diff --git a/AUTHORS b/AUTHORS index 10c79d5..6446e90 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,8 @@ Author: - o jeremian + o jeremian French translation: - o Simon CASTRO + o Simon CASTRO + +Russian translation: + o Alex Dyatlov diff --git a/Changelog b/Changelog index 2b3e214..af4e6af 100644 --- a/Changelog +++ b/Changelog @@ -1,36 +1,50 @@ +11.10.2004 (v0.5.5): + - Added: rsa key generation by afclient + - Modified: afclient is now generating keys by default + - Fixed: major bug in packet buffering + - Added: 'timeout', 'clients' and 'usrpcli' options + - Fixed: parsing 'users' option + - Modified: module management routines + - Added: module support for service's packet filtering + - Fixed: few minor bugs in closing connection routines + - Added: possibility to use several clients per realm + - Modified: there is no need for 'users', 'timeout', 'clients', + 'proto', 'usrpcli' and 'climode' options in config + file when default values are acceptable + 26.05.2004 (v0.5.4): - - Fixed: default password incompatibilities - - Modified: Server listening behaviour - - Added: Module support for client's packet filtering - - Modified: client behaviour after unsuccessful connection - - Fixed: printing ipv6 addresses - - Added: IP protocol family strict choice: 'ipv4' and 'ipv6' - - Added: flow control / packet buffering - - Fixed: signal handling - - Fixed: client freeze in udp reverse mode with zlib enabled + - Fixed: default password incompatibilities + - Modified: server listening behaviour + - Added: module support for client's packet filtering + - Modified: client behaviour after unsuccessful connection + - Fixed: printing ipv6 addresses + - Added: IP protocol family strict choice: 'ipv4' and 'ipv6' + - Added: flow control / packet buffering + - Fixed: signal handling + - Fixed: client freeze in udp reverse mode with zlib enabled 09.01.2004 (v0.5.3): - - Added: client password identification (weak) - - Added: sigint interception and server closing - - Modified: communication between server and client - - Added: 'nossl' and 'nozlib' modes - - Added: zlib support - - Lightly Modified: verbose mode - - Modified/Added: help screen and long options support - + - Added: client password identification (weak) + - Added: sigint interception and server closing + - Modified: communication between server and client + - Added: 'nossl' and 'nozlib' modes + - Added: zlib support + - Lightly Modified: verbose mode + - Modified/Added: help screen and long options support + 06.12.2003 (v0.5.2): - - Added: types of realm - - Added: logging to a file - - Fixed: major bug in communication between server and client - - Fixed: deformed packets in udp protocol forwarding - + - Added: types of realm + - Added: logging to a file + - Fixed: major bug in communication between server and client + - Fixed: deformed packets in udp protocol forwarding + 04.12.2003 (v0.5.1): - - Fixed: Some data transfer problems - - Added: udp protocol tunneling/forwarding - - Fixed: bug in parsing the config file - - Improved: making connection between server and client - - Lightly modified: verbose mode (added double v mode) + - Fixed: some data transfer problems + - Added: udp protocol tunneling/forwarding + - Fixed: bug in parsing the config file + - Improved: making connection between server and client + - Lightly modified: verbose mode (added double v mode) 23.11.2003 (v0.5): - - This is the first release - - There are no known major bugs + - This is the first release + - There are no known major bugs diff --git a/Makefile b/Makefile index f6064d5..09c9034 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,17 @@ CC=gcc CFLAGS=-pedantic -Wall -O2 programs=afserver afclient -security=server.rsa client.rsa cacert.pem +security=server.rsa cacert.pem +serdepends=afserver.c network.o file.o stats.o buflist.o +clidepends=afclient.c network.o stats.o buflist.o modules.o all: compi $(programs) ok1 secure -afserver: afserver.c network.o file.o stats.o buflist.o - $(CC) $(CFLAGS) -lssl -lz afserver.c network.o file.o stats.o buflist.o -o afserver +afserver: $(serdepends) + $(CC) $(CFLAGS) -lssl -lz $(serdepends) -o afserver -afclient: afclient.c network.o stats.o buflist.o - $(CC) $(CFLAGS) -rdynamic -lssl -lz -ldl afclient.c network.o stats.o buflist.o -o afclient +afclient: $(clidepends) + $(CC) $(CFLAGS) -rdynamic -lssl -lz -ldl $(clidepends) -o afclient %.o: %.c %.h $(CC) $(CFLAGS) -c $*.c diff --git a/README b/README index e9ded51..8901699 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -AF - Active Port Forwarder v0.5.4 - README +AF - Active Port Forwarder v0.5.5 - README Copyright (C) 2003,2004 jeremian - =================== @@ -7,10 +7,10 @@ Copyright (C) 2003,2004 jeremian - GRAY-WORLD.NET / Active Port Forwarder ========================== - The Active Port Forwarder program is part of the Gray-World.net projects. + The Active Port Forwarder program is part of the Gray-World.net projects. Our Gray-World Team presents on the http://gray-world.net website the projects - and publications we are working on which are related to the NACS (Network + and publications we are working on which are related to the NACS (Network Access Control System) bypassing research field and to the computer and network security topics. @@ -44,13 +44,13 @@ THANKS INTRO ===== -Active port forwarder is a software tool for secure port forwarding. +Active port forwarder is a software tool for secure port forwarding. It uses ssl to increase security of communication between a server and a client. Originally, it was developed to forward data point to point. However, the need for bypassing firewalls in order to connect to internally located computers influenced the further development of the project. -AF is dedicated for people, who don't have an external ip number and want to +AF is dedicated for people, who don't have an external ip number and want to make some services available across the net. Moreover, zlib is used to compress the transferred data. @@ -58,6 +58,8 @@ Moreover, zlib is used to compress the transferred data. Using one, permanent data/control channel with flow control / packet buffering provides good performance and reasonably small latency. +Multiple clients allow to create more sophisticated tunneling scheme. + ================================================================================ =============== @@ -99,15 +101,23 @@ provides good performance and reasonably small latency. ------------ Options: - -h, --help - prints this help -n, --hostname - it's used when creating listening sockets (default: name returned by hostname function) -l, --listenport - listening port number - users connect to it (default: 50127) -m, --manageport - manage port number - second part of the active port forwarder connects to it (default: 50126) + -t, --timeout - the timeout value for the client's connection + (default: 5) -u, --users - the amount of users allowed to use this server (default: 5) + -C, --clients - the number of allowed clients to use this server + (default: 1) + -U, --usrpcli - the number of allowed users per client (default: $users) + -M, --climode - strategy used for connecting users with clients (default: 1) + Available strategies: + 1. fill first client before go to next + -c, --cerfile - the name of the file with certificate (default: cacert.pem) -k, --keyfile - the name of the file with RSA key (default: server.rsa) @@ -119,15 +129,19 @@ provides good performance and reasonably small latency. -o, --lightlog - logging some data to a logfile -v, --verbose - to be verbose - program won't enter the daemon mode (use several times for greater effect) - --nossl - ssl is not used for transferring data (but it's still + + --nossl - ssl is not used for transfering data (but it's still used to establish a connection) (default: ssl is used) --nozlib - zlib is not used for compressing data (default: zlib is used) --pass - set the password used for client identification (default: no password) + -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only + -h, --help - prints this help + 2.2 afclient ------------ @@ -140,13 +154,13 @@ provides good performance and reasonably small latency. -d, --hostname - the name of this host/remote host - the final destination of the packets (default: the name returned by hostname function) - -p, --portnum - the port we are forwarding the connection to (required) - -k, --keyfile - the name of the file with RSA key (default: client.rsa) + -p, --portnum - the port we are forwarding connection to (required) + -k, --keyfile - the name of the file with RSA key (default: (none)) -u, --udpmode - udp mode - client will use udp protocol to communicate with the hostname -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded from hostname:portnum (-p) to the server name:portnum - (-m) + (-m) -O, --heavylog - logging everything to a logfile -o, --lightlog - logging some data to a logfile -v, --verbose - to be verbose - program won't enter the daemon mode @@ -155,7 +169,8 @@ provides good performance and reasonably small latency. (default: no password) -4, --ipv4 - use ipv4 only -6, --ipv6 - use ipv6 only - -l, --load - load a module for packets filtering + -l, --load - load a module for user's packets filtering + -L, --Load - load a module for service's packets filtering ================================================================================ @@ -181,7 +196,7 @@ provides good performance and reasonably small latency. The use of it is extremely simple. Let's suppose we want to create a http server on our computer and we are behind a masquerade or a firewall: -1) We have to find some machine on the net with an external ip and a shell +1) We have to find some machine on the net with an external ip and a shell account. 2) Use "make" to compile everything on that machine. (you can freely remove the @@ -191,7 +206,7 @@ on our computer and we are behind a masquerade or a firewall: type -f ) : $ ./afserver This will work, if you want to use default values: - - hostname will be taken from hostname function (it would be ideally, if + - hostname will be taken from hostname function (it would be ideally, if there is appropriate registration in /etc/hosts) - server will be listening for users on port 50127 - server will be listening for client on port 50126 @@ -230,10 +245,10 @@ on our computer and we are behind a masquerade or a firewall: Let's see how to use af to forward udp packets. Suppose we want to create a game server on our computer (udp port 27960 on our machine): -1) - 4) is the same like in example 1. (but we add option: -p udp) +1) - 4) is the same like in example 1. (but we add option: -p udp) 5) We are typing from the console: - $ ./afclient -u -n -p 27960 + $ ./afclient -u -n -p 27960 Where is a name (or ip) of a host where our server is running. @@ -287,7 +302,7 @@ README file. LICENSE ------- - Active Port Forwarder is distributed under the terms of the GNU General + Active Port Forwarder is distributed under the terms of the GNU General Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. diff --git a/activefor.h b/activefor.h index 4c819c0..18211e1 100644 --- a/activefor.h +++ b/activefor.h @@ -39,7 +39,7 @@ #define S_STATE_OPEN 7 #define S_STATE_STOPPED 11 -#define AF_VER(info) info" v0.5.4" +#define AF_VER(info) info" v0.5.5" #define TYPE_TCP 1 #define TYPE_UDP 3 @@ -79,8 +79,18 @@ typedef struct { int connfd; char namebuf[128]; char portbuf[7]; + int whatcli; blnodeT* head; } ConnectuserT; +typedef struct { + char ready; + clifd cliconn; + struct timeval tv; + int* users; + int usercon; + int usernum; +} ConnectclientT; + #endif diff --git a/afclient.c b/afclient.c index 0eed4f3..61ab6b8 100644 --- a/afclient.c +++ b/afclient.c @@ -21,7 +21,9 @@ #include "activefor.h" #include "network.h" #include "stats.h" +#include "modules.h" +#include #include #include #include @@ -30,12 +32,12 @@ #include #include #include -#include #include static void usage(char* info); static void sig_int(int); +static void callback(int, int, void*); static struct option long_options[] = { {"help", 0, 0, 'h'}, @@ -53,6 +55,7 @@ static struct option long_options[] = { {"ipv4", 0, 0, '4'}, {"ipv6", 0, 0, '6'}, {"load", 1, 0, 'l'}, + {"Load", 1, 0, 'L'}, {0, 0, 0, 0} }; @@ -83,17 +86,11 @@ main(int argc, char **argv) char reverse = 0; char type = 0; struct sigaction act; - struct { - char loaded; - char* name; - void* handle; - char* (*info)(void); - int (*allow)(char*, char*); - int (*filter)(char*, unsigned char*, int*); - } module = {0, NULL, NULL, NULL, NULL}; + moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL}; SSL_METHOD* method; SSL_CTX* ctx; + RSA* rsa; sigfillset(&(act.sa_mask)); act.sa_flags = 0; @@ -103,7 +100,7 @@ main(int argc, char **argv) act.sa_handler = sig_int; sigaction(SIGINT, &act, NULL); - while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:", long_options, 0)) != -1) { + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:L:", long_options, 0)) != -1) { switch (n) { case 'h': { usage(AF_VER("Active port forwarder (client)")); @@ -181,6 +178,10 @@ main(int argc, char **argv) module.name = optarg; break; } + case 'L': { + secmodule.name = optarg; + break; + } case '?': { usage(""); break; @@ -207,26 +208,16 @@ main(int argc, char **argv) if (despor == NULL) { usage("Destination port number is required"); } - if (keys == NULL) { - keys = "client.rsa"; - } - if (module.name) { - module.handle = dlopen(module.name, RTLD_NOW); - if (!module.handle) { - printf("Can't load a module: %s\n", dlerror()); - exit(1); - } - dlerror(); - *(void**) (&module.info) = dlsym(module.handle, "info"); - *(void**) (&module.allow) = dlsym(module.handle, "allow"); - *(void**) (&module.filter) = dlsym(module.handle, "filter"); - if (dlerror() != NULL) { + + if (loadmodule(&module)) { printf("Loading a module %s failed!\n", module.name); exit(1); - } - module.loaded = 1; } - + if (loadmodule(&secmodule)) { + printf("Loading a module %s failed!\n", secmodule.name); + exit(1); + } + TYPE_SET_SSL(type); TYPE_SET_ZLIB(type); @@ -262,9 +253,32 @@ main(int argc, char **argv) printf("Setting cipher list failed... exiting\n"); exit(1); } - if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) { - printf("Setting rsa key failed (%s)... exiting\n", keys); - exit(1); + if (keys == NULL) { + gettimeofday(&tv, 0); + srand(tv.tv_sec); + if (verbose) + printf("Generating RSA key...\n"); + if (verbose>1) { + rsa = RSA_generate_key(2048, 65537, callback, NULL); + printf("\n"); + } + else { + rsa = RSA_generate_key(2048, 65537, NULL, NULL); + } + if (verbose) { + if (RSA_check_key(rsa)==1) { + printf(" OK!\n"); + } + else { + printf(" FAILED\n"); + } + } + } + else { + if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) { + printf("Setting rsa key failed (%s)... exiting\n", keys); + exit(1); + } } master.ssl = SSL_new(ctx); if (SSL_set_fd(master.ssl, master.commfd) != 1) { @@ -313,7 +327,7 @@ main(int argc, char **argv) contable = calloc( usernum, sizeof(ConnectuserT)); if (contable == NULL) { - printf("Calloc error - unable to succesfully comunicate with server\n"); + printf("Calloc error - unable to succesfully communicate with server\n"); exit(1); } @@ -422,7 +436,6 @@ main(int argc, char **argv) n = 0; } if (n == 0) { /* server quits -> we do the same... */ - gettimeofday(&tv, 0); aflog(0, "premature quit of the server -> exiting..."); exit(1); } @@ -439,9 +452,12 @@ main(int argc, char **argv) aflog(1, "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(type))?"yes":"no", (TYPE_IS_ZLIB(type))?"yes":"no", (TYPE_IS_TCP(type))?"tcp":"udp"); aflog(2, "CIPHER: %s VER: %s", SSL_get_cipher_name(master.ssl), SSL_get_cipher_version(master.ssl)); - if (module.loaded) { + if (ismloaded(&module)) { aflog(1, "LOADED MODULE: %s INFO: %s", module.name, module.info()); } + if (ismloaded(&secmodule)) { + aflog(1, "LOADED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + } for ( ; ; ) { rset = allset; @@ -495,6 +511,42 @@ main(int argc, char **argv) } } if (n) { + if (ismloaded(&secmodule)) { + switch ((temp2 = secmodule.filter(contable[i].namebuf, &buff[5], &n))) { + case 1: case 4: { + aflog(3, " user[%d] (by ser): PACKET IGNORED BY MODULE", i); + if (temp2 == 4) { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + } + continue; + break; + } + case 2: case 5: { + aflog(2, " user[%d] (by ser): DROPPED BY MODULE", i); + close(contable[i].connfd); + FD_CLR(contable[i].connfd, &allset); + FD_CLR(contable[i].connfd, &wset); + contable[i].state = S_STATE_CLOSING; + freebuflist(&contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + send_message(type, master, buff, 5); + if (temp2 == 5) { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + } + continue; + break; + } + case 3: { + aflog(1, "RELEASED MODULE (ser): %s INFO: %s", secmodule.name, secmodule.info()); + releasemodule(&secmodule); + break; + } + } + } buff[0] = AF_S_MESSAGE; /* sending message */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ @@ -654,7 +706,7 @@ main(int argc, char **argv) aflog(2, " user[%d]: OPENING", numofcon); aflog(1, "user[%d]: IP:%s PORT:%s", numofcon, contable[numofcon].namebuf, contable[numofcon].portbuf); - if (module.loaded && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) { + if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) { aflog(2, " IT'S NOT ALLOWED - DROPPING", numofcon); buff[0] = AF_S_CANT_OPEN; /* not opening connection */ buff[1] = numofcon >> 8; /* high bits of user number */ @@ -702,14 +754,18 @@ main(int argc, char **argv) n = get_message(type, master, buff, length); if ((numofcon>=0) && (numofcon<=usernum)) { if (contable[numofcon].state == S_STATE_OPEN) { - if (module.loaded) { - switch (module.filter(contable[numofcon].namebuf, buff, &n)) { - case 1: { + if (ismloaded(&module)) { + switch ((temp2 = module.filter(contable[numofcon].namebuf, buff, &n))) { + case 1: case 4:{ aflog(3, " user[%d]: PACKET IGNORED BY MODULE", numofcon); + if (temp2 == 4) { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); + } continue; break; } - case 2: { + case 2: case 5:{ aflog(2, " user[%d]: DROPPED BY MODULE", numofcon); close(contable[numofcon].connfd); FD_CLR(contable[numofcon].connfd, &allset); @@ -720,6 +776,16 @@ main(int argc, char **argv) buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ send_message(type, master, buff, 5); + if (temp2 == 5) { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); + } + continue; + break; + } + case 3: { + aflog(1, "RELEASED MODULE: %s INFO: %s", module.name, module.info()); + releasemodule(&module); break; } } @@ -751,6 +817,7 @@ main(int argc, char **argv) FD_CLR(contable[numofcon].connfd, &allset); FD_CLR(contable[numofcon].connfd, &wset); contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&contable[numofcon].head); buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ @@ -801,7 +868,7 @@ usage(char* info) printf(" destination of the packets (default: the name\n"); printf(" returned by hostname function)\n"); printf(" -p, --portnum - the port we are forwarding connection to (required)\n"); - printf(" -k, --keyfile - the name of the file with RSA key (default: client.rsa)\n"); + printf(" -k, --keyfile - the name of the file with RSA key (default: (none))\n"); printf(" -u, --udpmode - udp mode - client will use udp protocol to\n"); printf(" communicate with the hostname\n"); printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n"); @@ -815,7 +882,8 @@ usage(char* info) printf(" (default: no password)\n"); printf(" -4, --ipv4 - use ipv4 only\n"); printf(" -6, --ipv6 - use ipv6 only\n"); - printf(" -l, --load - load a module for packets filtering\n\n"); + printf(" -l, --load - load a module for user's packets filtering\n"); + printf(" -L, --Load - load a module for service's packets filtering\n\n"); exit(0); } @@ -826,3 +894,12 @@ sig_int(int signo) aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg()); exit(0); } + +void +callback(int i, int j, void* k) +{ + if (k == NULL) { + printf("%d", i); + fflush(stdout); + } +} diff --git a/afserver.c b/afserver.c index 86fb85e..369ef69 100644 --- a/afserver.c +++ b/afserver.c @@ -28,19 +28,29 @@ #include #include #include - +#include #include static void usage(char* info); static void sig_int(int); +static void remove_client(RealmT*, int, fd_set*, fd_set*, int*); +static int find_client(RealmT*, char); +static int eval_numofcon(RealmT*, int, int); +static int eval_usernum(ConnectclientT*, int); +static int find_usernum(ConnectclientT*, int); +static void check_value(int*, char*, char*); static struct option long_options[] = { {"help", 0, 0, 'h'}, {"hostname", 1, 0, 'n'}, {"listenport", 1, 0, 'l'}, {"manageport", 1, 0, 'm'}, + {"timeout", 1, 0, 't'}, {"verbose", 0, 0, 'v'}, {"users", 1, 0, 'u'}, + {"clients", 1, 0, 'C'}, + {"usrpcli", 1, 0, 'U'}, + {"climode", 1, 0, 'M'}, {"cerfile", 1, 0, 'c'}, {"keyfile", 1, 0, 'k'}, {"cfgfile", 1, 0, 'f'}, @@ -60,7 +70,7 @@ static ConfigurationT config; int main(int argc, char **argv) { - int i, j, n, flags, sent; + int i, j=0, k, n, flags, sent; socklen_t len; unsigned char buff[9000]; char hostname[100]; @@ -71,9 +81,12 @@ main(int argc, char **argv) char* listen = NULL; char* manage = NULL; char* amount = NULL; + char* clients = NULL; + char* usrpcli = NULL; + char* clim = NULL; char* filenam = NULL; char* type = NULL; - char* znak; + char* timeout = NULL; unsigned char pass[4] = {1, 2, 3, 4}; char verbose = 0; char mode = 0; @@ -102,7 +115,7 @@ main(int argc, char **argv) config.logging = 0; config.logfnam = NULL; - while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46", long_options, 0)) != -1) { + while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:", long_options, 0)) != -1) { switch (n) { case 'h': { usage(AF_VER("Active port forwarder (server)")); @@ -120,6 +133,10 @@ main(int argc, char **argv) manage = optarg; break; } + case 't': { + timeout = optarg; + break; + } case 'v': { ++verbose; break; @@ -128,6 +145,18 @@ main(int argc, char **argv) amount = optarg; break; } + case 'C': { + clients = optarg; + break; + } + case 'U': { + usrpcli = optarg; + break; + } + case 'M': { + clim = optarg; + break; + } case 'c': { config.certif = optarg; break; @@ -146,7 +175,7 @@ main(int argc, char **argv) } case 'O': { config.logfnam = optarg; - config.logging = 2; + config.logging = 3; break; } case 'o': { @@ -162,14 +191,14 @@ main(int argc, char **argv) TYPE_UNSET_ZLIB(mode); break; } - case 303: { - n = strlen(optarg); - memset(pass, 0, 4); - for (i = 0; i < n; ++i) { - pass[i%4] += optarg[i]; - } - break; - } + case 303: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + break; + } case '4': { if (ipfam != 0) { ipfam = -1; @@ -222,9 +251,21 @@ main(int argc, char **argv) if (manage == NULL) { manage = "50126"; } + if (timeout == NULL) { + timeout = "5"; + } if (amount == NULL) { amount = "5"; } + if (clients == NULL) { + clients = "1"; + } + if (usrpcli == NULL) { + usrpcli = amount; + } + if (clim == NULL) { + clim = "1"; + } if (config.certif == NULL) { config.certif = "cacert.pem"; } @@ -240,6 +281,10 @@ main(int argc, char **argv) config.realmtable[0].lisportnum = listen; config.realmtable[0].manportnum = manage; config.realmtable[0].users = amount; + config.realmtable[0].clients = clients; + config.realmtable[0].timeout = timeout; + config.realmtable[0].usrpcli = usrpcli; + config.realmtable[0].clim = clim; memcpy(config.realmtable[0].pass, pass, 4); if (strcmp(type, "tcp") == 0) { TYPE_SET_TCP(config.realmtable[0].type); @@ -273,9 +318,9 @@ main(int argc, char **argv) exit(1); } if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) { - printf("Setting rsa key failed (%s)... exiting\n", config.keys); - exit(1); - } + printf("Setting rsa key failed (%s)... exiting\n", config.keys); + exit(1); + } if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) { printf("Setting certificate failed (%s)... exiting\n", config.certif); exit(1); @@ -292,34 +337,54 @@ main(int argc, char **argv) for (i = 0; i < config.size; ++i) { if ((config.realmtable[i].hostname == NULL) || (config.realmtable[i].lisportnum == NULL) || - (config.realmtable[i].manportnum == NULL) || - (config.realmtable[i].users == NULL)) { + (config.realmtable[i].manportnum == NULL)) { printf("Missing some of the configurable variables...\n"); - printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\nusers: %s\n", + printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\n", i, config.realmtable[i].hostname, config.realmtable[i].lisportnum, - config.realmtable[i].manportnum, - config.realmtable[i].users); + config.realmtable[i].manportnum); exit(1); } + /* checking type of the realm */ if (!TYPE_IS_SET(config.realmtable[i].type)) { - printf("Unrecognized type of the realm... exiting\n"); - exit(1); - } - if ((( config.realmtable[i].usernum = strtol(config.realmtable[i].users, &znak, 10)) == LONG_MAX) || (config.realmtable[i].usernum == LONG_MIN)) { - printf("Invalid user amount - %s\n", config.realmtable[i].users); - exit(1); + TYPE_SET_TCP(config.realmtable[i].type); } - if (((*(config.realmtable[i].users)) == '\0') || (*znak != '\0')) { - printf("Invalid user amount - %s\n", config.realmtable[i].users); - exit(1); - } - + /* checking users amount */ + if (config.realmtable[i].users == NULL) { + config.realmtable[i].users = "5"; + } + check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount"); + /* checking clients amount */ + if (config.realmtable[i].clients == NULL) { + config.realmtable[i].clients = "1"; + } + check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount"); + /* checking usrpcli value */ + if (config.realmtable[i].usrpcli == NULL) { + config.realmtable[i].usrpcli = config.realmtable[i].users; + } + check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value"); + /* checking timeout value */ + if (config.realmtable[i].timeout == NULL) { + config.realmtable[i].timeout = "5"; + } + check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value"); + /* checking climode value */ + if (config.realmtable[i].clim == NULL) { + config.realmtable[i].clim = "1"; + } + check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value"); + /* allocating memory*/ config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT)); if (config.realmtable[i].contable == NULL) { printf("Calloc error - try define smaller amount of users\n"); exit(1); } + config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT)); + if (config.realmtable[i].clitable == NULL) { + printf("Calloc error - try define smaller amount of clients\n"); + exit(1); + } ipfam = 0x01; if (TYPE_IS_IPV4(config.realmtable[i].type)) { ipfam |= 0x02; @@ -343,21 +408,35 @@ main(int argc, char **argv) } config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); - config.realmtable[i].cliconn.ssl = SSL_new(ctx); - if (config.realmtable[i].cliconn.ssl == NULL) { - printf("Creating of ssl object failed... exiting\n"); - exit(1); - } + for (j=0; j (config.realmtable[i].managefd+1)) ? maxfdp1 : (config.realmtable[i].managefd+1); maxfdp1 = (maxfdp1 > (config.realmtable[i].listenfd+1)) ? maxfdp1 : (config.realmtable[i].listenfd+1); config.realmtable[i].usercon = 0; - config.realmtable[i].ready = 0; - config.realmtable[i].tv.tv_sec = 5; - config.realmtable[i].tv.tv_usec = 0; - } + config.realmtable[i].clicon = 0; + for (j=0; jselect, maxfdp1: %d", maxfdp1); if (manconnecting) { /* find out, in what realm client is trying to connect */ - for (i = 0; i < config.size; ++i) { - if ((config.realmtable[i].ready == 1) || (config.realmtable[i].ready == 2)) { - break; /* so i points to first good realm */ - } + for (k = 0; k < config.size; ++k) { + for (j=0; j < config.realmtable[k].clinum; ++j) { + if ((config.realmtable[k].clitable[j].ready == 1) || (config.realmtable[k].clitable[j].ready == 2)) { + i = k; + k = config.size; + break; /* so i points to first good realm and j to good client */ + } + } } - if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].tv))) == 0) { - close (config.realmtable[i].cliconn.commfd); - FD_CLR(config.realmtable[i].cliconn.commfd, &allset); + if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].clitable[j].tv))) == 0) { + close (config.realmtable[i].clitable[j].cliconn.commfd); + FD_CLR(config.realmtable[i].clitable[j].cliconn.commfd, &allset); FD_SET(config.realmtable[i].managefd, &allset); - config.realmtable[i].ready = 0; + SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl); + config.realmtable[i].clitable[j].ready = 0; manconnecting--; - aflog(1, " realm[%d]: SSL_accept failed (timeout)", i); + config.realmtable[i].clicon--; + aflog(1, " realm[%d]: client[%d]: SSL_accept failed (timeout)", i, j); } } else { @@ -397,125 +482,131 @@ main(int argc, char **argv) for (j = 0; j < config.size; ++j) { pointer = (&(config.realmtable[j])); for (i = 0; i usernum; ++i) { - if ((pointer->contable[i].state == S_STATE_OPEN) || - (pointer->contable[i].state == S_STATE_STOPPED)) - if (FD_ISSET(pointer->contable[i].connfd, &rset)) { - aflog(3, " realm[%d]: user[%d]: FD_ISSET", j, i); - if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ - n = read(pointer->contable[i].connfd, &buff[5], 8091); - if (n == -1) - n = 0; - if (n) { - aflog(2, " realm[%d]: FROM user[%d]: MESSAGE length=%d", j, i, n); - if ((buff[5] == AF_S_MESSAGE) && - (buff[6] == AF_S_LOGIN) && - (buff[7] == AF_S_MESSAGE)) { - aflog(2, " WARNING: got packet similiar to udp"); - } - buff[0] = AF_S_MESSAGE; /* sending message */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->cliconn, buff, n+5); - } - else { - aflog(1, " realm[%d]: user[%d]: CLOSED", j, i); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, + if ((pointer->contable[i].state == S_STATE_OPEN) || (pointer->contable[i].state == S_STATE_STOPPED)) + if (FD_ISSET(pointer->contable[i].connfd, &rset)) { + k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); + aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET", j, pointer->contable[i].whatcli, k); + if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ + n = read(pointer->contable[i].connfd, &buff[5], 8091); + if (n == -1) { + aflog(3, " realm[%d]: client[%d]: user[%d]: READ ERROR (%d)", j, + pointer->contable[i].whatcli, k, errno); + n = 0; + } + if (n) { + aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, + pointer->contable[i].whatcli, k, n); + if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { + aflog(2, " WARNING: got packet similiar to udp"); + } + buff[0] = AF_S_MESSAGE; /* sending message */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5); + } + else { + aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, 5); - } - } - else { /* when forwarding udp packets */ - n = readn(pointer->contable[i].connfd, buff, 5 ); - if (n != 5) { - n = 0; - } - if (n) { - if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) - && (buff[2] == AF_S_MESSAGE)) { - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { - aflog(2, " realm[%d]: FROM user[%d]: MESSAGE length=%d", j, i, n); - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, n+5); - } - } - else { - n = 0; - } - } - - if (n == 0) { - aflog(1, " realm[%d]: user[%d]: CLOSED", j, i); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, + close(pointer->contable[i].connfd); + FD_CLR(pointer->contable[i].connfd, &allset); + FD_CLR(pointer->contable[i].connfd, &wset); + pointer->contable[i].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + } + else { /* when forwarding udp packets */ + n = readn(pointer->contable[i].connfd, buff, 5 ); + if (n != 5) { + n = 0; + } + if (n) { + if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { + aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, + pointer->contable[i].whatcli, k, n); + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, + buff, n+5); + } + } + else { + n = 0; + } + } + + if (n == 0) { + aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED (udp mode)", j, + pointer->contable[i].whatcli, k); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, 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); + } + + } + } + } /* ------------------------------------ */ for (i = 0; i usernum; ++i) { - if (pointer->contable[i].state == S_STATE_STOPPED) - if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { - aflog(3, " realm[%d]: user[%d]: FD_ISSET - WRITE", j, 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; - } - else if ((sent == -1) && (errno == EAGAIN)) { - } - else if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED", j, i); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, - pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, 5); - } - else { - deleteblnode(&pointer->contable[i].head); - if (pointer->contable[i].head == NULL) { - pointer->contable[i].state = S_STATE_OPEN; - FD_CLR(pointer->contable[i].connfd, &wset); - buff[0] = AF_S_CAN_SEND; /* stopping transfer */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j, i); - send_message(pointer->type, pointer->cliconn, buff, 5); - } - } - } - } + if (pointer->contable[i].state == S_STATE_STOPPED) + if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { + k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); + aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET - WRITE", j, pointer->contable[i].whatcli, + k); + n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr; + sent = write(pointer->contable[i].connfd, + &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n); + if ((sent > 0) && (sent != n)) { + pointer->contable[i].head->actptr+=sent; + } + else if ((sent == -1) && (errno == EAGAIN)) { + } + else if (sent == -1) { + aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); + aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); + close(pointer->contable[i].connfd); + FD_CLR(pointer->contable[i].connfd, &allset); + FD_CLR(pointer->contable[i].connfd, &wset); + pointer->contable[i].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[i].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + else { + deleteblnode(&pointer->contable[i].head); + if (pointer->contable[i].head == NULL) { + pointer->contable[i].state = S_STATE_OPEN; + FD_CLR(pointer->contable[i].connfd, &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + aflog(3, " realm[%d]: client[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j, + pointer->contable[i].whatcli, k); + send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); + } + } + } + } /* ------------------------------------ */ if (FD_ISSET(pointer->listenfd, &rset)) { len = pointer->addrlen; @@ -523,49 +614,59 @@ main(int argc, char **argv) flags = fcntl(sent, F_GETFL, 0); fcntl(sent, F_SETFL, flags | O_NONBLOCK); aflog(3, " realm[%d]: listenfd: FD_ISSET", j); - if (pointer->ready == 3) { + k = find_client(pointer, pointer->climode); + if (pointer->clitable[k].ready == 3) { if (pointer->usercon == pointer->usernum) { close(sent); - aflog(3, " realm[%d]: user limit EXCEEDED", j); - } - else { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state == S_STATE_CLEAR) { - aflog(2, " realm[%d]: new user[%d]: CONNECTING", j, i); - pointer->contable[i].connfd = sent; - pointer->contable[i].state = S_STATE_OPENING; - pointer->usercon++; - aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len, - pointer->contable[i].namebuf, pointer->contable[i].portbuf)); - memcpy(&buff[5], pointer->contable[i].namebuf, 128); - memcpy(&buff[133], pointer->contable[i].portbuf, 7); - n = 135; - 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->cliconn, buff, n+5); - break; - } - } - } - } - else { - close(sent); - aflog(3, " realm[%d]: client is NOT CONNECTED", j); - } - } - if (pointer->ready != 0) /* Command file descriptor */ - if (FD_ISSET(pointer->cliconn.commfd, &rset)) { - if (pointer->ready == 1) { - if (SSL_set_fd(pointer->cliconn.ssl, pointer->cliconn.commfd) != 1) { + aflog(3, " realm[%d]: user limit EXCEEDED", j); + } + else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) { + close(sent); + aflog(3, " realm[%d]: client[%d]: usrpcli limit EXCEEDED", j, k); + } + else { + for (i = 0; i < pointer->usernum; ++i) { + if (pointer->contable[i].state == S_STATE_CLEAR) { + aflog(2, " realm[%d]: client[%d]: new user: CONNECTING", j, k); + pointer->contable[i].connfd = sent; + pointer->contable[i].state = S_STATE_OPENING; + pointer->contable[i].whatcli = k; + pointer->usercon++; + pointer->clitable[k].usercon++; + aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len, + pointer->contable[i].namebuf, pointer->contable[i].portbuf)); + memcpy(&buff[5], pointer->contable[i].namebuf, 128); + memcpy(&buff[133], pointer->contable[i].portbuf, 7); + n = 135; + i = find_usernum(&(pointer->clitable[k]), i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); + break; + } + } + } + } + else { + close(sent); + aflog(3, " realm[%d]: client[%d] is NOT CONNECTED", j, k); + } + } + /* ------------------------------------ */ + for (k = 0; k < pointer->clinum; ++k) + if (pointer->clitable[k].ready != 0) /* Command file descriptor */ + if (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset)) { + if (pointer->clitable[k].ready == 1) { + if (SSL_set_fd(pointer->clitable[k].cliconn.ssl, pointer->clitable[k].cliconn.commfd) != 1) { aflog(0, "Problem with initializing ssl... exiting"); exit(1); } aflog(2, " realm[%d]: new client: SSL_accept", j); - if ((n = SSL_accept(pointer->cliconn.ssl)) != 1) { - flags = SSL_get_error(pointer->cliconn.ssl, n); + if ((n = SSL_accept(pointer->clitable[k].cliconn.ssl)) != 1) { + flags = SSL_get_error(pointer->clitable[k].cliconn.ssl, n); switch (flags) { case SSL_ERROR_NONE : { aflog(2, " SSL_accept has failed(%d)...none", n); @@ -604,349 +705,290 @@ main(int argc, char **argv) } if (flags == SSL_ERROR_WANT_READ) continue; - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); + close (pointer->clitable[k].cliconn.commfd); + FD_CLR(pointer->clitable[k].cliconn.commfd, &allset); FD_SET(pointer->managefd, &allset); - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; + SSL_clear(pointer->clitable[k].cliconn.ssl); + pointer->clitable[k].ready = 0; manconnecting--; - aflog(1, " realm[%d]: new client: DENIED by SSL_accept", j); + pointer->clicon--; + aflog(1, " realm[%d]: new client[%d]: DENIED by SSL_accept", j, k); } else { - aflog(1, " realm[%d]: new client: ACCEPTED by SSL_accept", j); - pointer->ready = 2; + aflog(1, " realm[%d]: new client[%d]: ACCEPTED by SSL_accept", j, k); + pointer->clitable[k].ready = 2; } continue; /* in the case this is not our client */ } - aflog(3, " realm[%d]: commfd: FD_ISSET", j); - if (pointer->ready == 2) { - n = get_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, -5); + aflog(3, " realm[%d]: client[%d]: commfd: FD_ISSET", j, k); + if (pointer->clitable[k].ready == 2) { + n = get_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, -5); } else { - n = get_message(pointer->type, pointer->cliconn, buff, -5); + n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5); } if (n == -1) { if (errno == EAGAIN) { + aflog(4, " realm[%d]: client[%d]: commfd: EAGAIN", j, k); continue; } else { + aflog(4, " realm[%d]: client[%d]: commfd: ERROR: %d", j, k, errno); n = 0; } } else if (n != 5) { n = 0; } - if (n==0) { - close(pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - maxfdp1 = (maxfdp1 > (pointer->managefd+1)) ? maxfdp1 : (pointer->managefd+1); - if (pointer->ready == 3) { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state != S_STATE_CLEAR) { - pointer->contable[i].state = S_STATE_CLEAR; - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - close(pointer->contable[i].connfd); - } - } - } - pointer->usercon = 0; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - aflog(1, " realm[%d]: commfd: CLOSED", j); + if (n==0) { + remove_client(pointer, k, &allset, &wset, &manconnecting); + aflog(1, " realm[%d]: client[%d]: commfd: CLOSED", j, k); continue; } - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + switch (buff[0]) { case AF_S_CONCLOSED : { - if ((numofcon>=0) && - (numofcon<=(pointer->usernum)) && - ((pointer->ready)==3)) { - (pointer->usercon)--; - if (pointer->contable[numofcon].state == - S_STATE_CLOSING) { - pointer->contable[numofcon].state = - S_STATE_CLEAR; - } - else if ((pointer->contable[numofcon].state == S_STATE_OPEN) || - (pointer->contable[numofcon].state == S_STATE_STOPPED)) { - aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, 5); - } - } - else { - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - if (pointer->ready == 2) - manconnecting--; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - } - break; - } + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + pointer->usercon--; + pointer->clitable[k].usercon--; + pointer->clitable[k].users[n] = -1; + if (pointer->contable[numofcon].state == S_STATE_CLOSING) { + pointer->contable[numofcon].state = S_STATE_CLEAR; + } + else if ((pointer->contable[numofcon].state == S_STATE_OPEN) || + (pointer->contable[numofcon].state == S_STATE_STOPPED)) { + aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLEAR; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } case AF_S_CONOPEN : { - if ((numofcon>=0) && - (numofcon<=(pointer->usernum)) && - ((pointer->ready)==3)) { - if (pointer->contable[numofcon].state == - S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon); - FD_SET(pointer->contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? - maxfdp1 : (pointer->contable[numofcon].connfd+1); - pointer->contable[numofcon].state = - S_STATE_OPEN; - } - } - else { - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - if (pointer->ready == 2) - manconnecting--; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - } - break; - } - + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + if (pointer->contable[numofcon].state == S_STATE_OPENING) { + aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon); + FD_SET(pointer->contable[numofcon].connfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? + maxfdp1 : (pointer->contable[numofcon].connfd+1); + pointer->contable[numofcon].state = S_STATE_OPEN; + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } case AF_S_CANT_OPEN : { - if ((numofcon>=0) && - (numofcon<=(pointer->usernum)) && - ((pointer->ready)==3)) { - if (pointer->contable[numofcon].state == - S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: DROPPED",j, numofcon); - (pointer->usercon)--; - close(pointer->contable[numofcon].connfd); - pointer->contable[numofcon].state = - S_STATE_CLEAR; - } - } - else { - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - if (pointer->ready == 2) - manconnecting--; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - } - break; - } - - - + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { + if (pointer->contable[numofcon].state == S_STATE_OPENING) { + aflog(2, " realm[%d]: user[%d]: DROPPED", j, numofcon); + pointer->usercon--; + pointer->clitable[k].usercon--; + pointer->clitable[k].users[n] = -1; + close(pointer->contable[numofcon].connfd); + pointer->contable[numofcon].state = S_STATE_CLEAR; + } + } + else { + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } case AF_S_MESSAGE : { - if ((pointer->ready) != 3) { - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - manconnecting--; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; + if ((pointer->clitable[k].ready) != 3) { + remove_client(pointer, k, &allset, &wset, &manconnecting); break; - } - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - n = get_message(pointer->type, pointer->cliconn, &buff[5], length); - } - else { - n = get_message(pointer->type, pointer->cliconn, buff, length); - } - if ((numofcon>=0) && - (numofcon<=(pointer->usernum))) { - if (pointer->contable[numofcon].state == - S_STATE_OPEN) { - aflog(2, " realm[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - sent = write(pointer->contable[numofcon].connfd, buff, n+5); - if ((sent > 0) && (sent != n)) { - insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon); - send_message(pointer->type, pointer->cliconn, buff, 5); - } - else if ((sent == -1) && (errno == EAGAIN)) { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon); - send_message(pointer->type, pointer->cliconn, buff, 5); - } - else if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, 5); - } - } - else { /* tcp */ - sent = write(pointer->contable[numofcon].connfd, buff, n); - if ((sent > 0) && (sent != n)) { - insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon); - send_message(pointer->type, pointer->cliconn, buff, 5); - } - else if ((sent == -1) && (errno == EAGAIN)) { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED", j, numofcon); - send_message(pointer->type, pointer->cliconn, buff, 5); - } - else if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->cliconn, buff, 5); - } - } - } - else if (pointer->contable[numofcon].state == - S_STATE_STOPPED) { - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE", j, numofcon); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); - } - else { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - } - } - } - break; - } + } + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + n = get_message(pointer->type, pointer->clitable[k].cliconn, &buff[5], length); + } + else { + n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length); + } + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(pointer->usernum))) { + if (pointer->contable[numofcon].state == S_STATE_OPEN) { + aflog(2, " realm[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + sent = write(pointer->contable[numofcon].connfd, buff, n+5); + if ((sent > 0) && (sent != n)) { + insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, + sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if ((sent == -1) && (errno == EAGAIN)) { + insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, + sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if (sent == -1) { + aflog(1, " realm[%d]: user[%d]: CLOSED (write-udp)", j, numofcon); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + else { /* tcp */ + sent = write(pointer->contable[numofcon].connfd, buff, n); + if ((sent > 0) && (sent != n)) { + insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, + sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if ((sent == -1) && (errno == EAGAIN)) { + insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + pointer->contable[numofcon].state = S_STATE_STOPPED; + FD_SET(pointer->contable[numofcon].connfd, &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, + sent, n); + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + else if (sent == -1) { + aflog(1, " realm[%d]: user[%d]: CLOSED (write-tcp)", j, numofcon); + aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, + pointer->contable[numofcon].portbuf); + close(pointer->contable[numofcon].connfd); + FD_CLR(pointer->contable[numofcon].connfd, &allset); + FD_CLR(pointer->contable[numofcon].connfd, &wset); + pointer->contable[numofcon].state = S_STATE_CLOSING; + freebuflist(&pointer->contable[numofcon].head); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); + } + } + } + else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { + aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE (%d)", j, numofcon, n); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); + } + else { + insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); + } + } + } + break; + } case AF_S_LOGIN : { - if ((pointer->ready == 2)&& - (numofcon==(pointer->pass[0]*256+pointer->pass[1]))&& - (length==(pointer->pass[2]*256+pointer->pass[3]))) { - pointer->ready = 3; - aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j); - buff[0] = AF_S_LOGIN; /* sending message */ - buff[1] = pointer->usernum >> 8;/* high bits of user number */ - buff[2] = pointer->usernum; /* low bits of user number */ - buff[3] = pointer->type; /* type of connection */ - send_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, 5); - manconnecting--; - } - else { - aflog(1, " realm[%d]: Wrong password - CLOSING", j); - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - if (pointer->ready == 2) - manconnecting--; - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - } - break; - } - case AF_S_DONT_SEND: { - FD_CLR(pointer->contable[numofcon].connfd, &allset); - break; - } - case AF_S_CAN_SEND: { - FD_SET(pointer->contable[numofcon].connfd, &allset); - break; - } - + if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && + (length==(pointer->pass[2]*256+pointer->pass[3]))) { + pointer->clitable[k].ready = 3; + aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j); + buff[0] = AF_S_LOGIN; /* sending message */ + buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */ + buff[2] = pointer->clitable[k].usernum; /* low bits of user number */ + buff[3] = pointer->type; /* type of connection */ + send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5); + manconnecting--; + } + else { + aflog(1, " realm[%d]: Wrong password - CLOSING", j); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + break; + } + case AF_S_DONT_SEND: { + FD_CLR(pointer->contable[numofcon].connfd, &allset); + break; + } + case AF_S_CAN_SEND: { + FD_SET(pointer->contable[numofcon].connfd, &allset); + break; + } default : { - aflog(1, " realm[%d]: Unrecognized message - CLOSING", j); - close (pointer->cliconn.commfd); - FD_CLR(pointer->cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - if (pointer->ready == 2) - manconnecting--; - if (pointer->ready == 3) { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state != S_STATE_CLEAR) { - pointer->contable[i].state = S_STATE_CLEAR; - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - close(pointer->contable[i].connfd); - } - } - } - SSL_clear(pointer->cliconn.ssl); - pointer->ready = 0; - } - } - } - - if (FD_ISSET(pointer->managefd, &rset)) { - aflog(3, " realm[%d]: managefd: FD_ISSET", j); - len = pointer->addrlen; - if (!(pointer->ready)) { - aflog(2, " realm[%d]: new client: CONNECTING", j); - pointer->cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len); - flags = fcntl(pointer->cliconn.commfd, F_GETFL, 0); - fcntl(pointer->cliconn.commfd, F_SETFL, flags | O_NONBLOCK); - aflog(1, " realm[%d]: Client IP:%s", j, sock_ntop(pointer->cliaddr, len, NULL, NULL)); - FD_SET(pointer->cliconn.commfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->cliconn.commfd+1)) ? maxfdp1 : (pointer->cliconn.commfd+1); - FD_CLR(pointer->managefd, &allset); - pointer->tv.tv_sec = 5; - manconnecting++; - pointer->ready = 1; - } - } - } /* realms loop */ - } + aflog(1, " realm[%d]: Unrecognized message - CLOSING", j); + remove_client(pointer, k, &allset, &wset, &manconnecting); + } + } + } + if (FD_ISSET(pointer->managefd, &rset)) { + aflog(3, " realm[%d]: managefd: FD_ISSET", j); + len = pointer->addrlen; + for (k = 0; k < pointer->clinum; ++k) + if (!(pointer->clitable[k].ready)) { + aflog(2, " realm[%d]: new client[%d]: CONNECTING", j, k); + pointer->clitable[k].cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len); + flags = fcntl(pointer->clitable[k].cliconn.commfd, F_GETFL, 0); + fcntl(pointer->clitable[k].cliconn.commfd, F_SETFL, flags | O_NONBLOCK); + aflog(1, " realm[%d]: Client[%d] IP:%s", j, k, sock_ntop(pointer->cliaddr, len, NULL, NULL)); + FD_SET(pointer->clitable[k].cliconn.commfd, &allset); + maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ? + maxfdp1 : (pointer->clitable[k].cliconn.commfd+1); + pointer->clicon++; + if (pointer->clicon == pointer->clinum) + FD_CLR(pointer->managefd, &allset); + pointer->clitable[k].tv.tv_sec = pointer->tmout; + manconnecting++; + pointer->clitable[k].ready = 1; + break; + } + } + } /* realms loop */ + } } static void @@ -954,15 +996,22 @@ usage(char* info) { printf("\n%s\n\n", info); printf(" Options:\n"); - printf(" -h, --help - prints this help\n"); printf(" -n, --hostname - it's used when creating listening sockets\n"); printf(" (default: name returned by hostname function)\n"); printf(" -l, --listenport - listening port number - users connect\n"); printf(" to it (default: 50127)\n"); printf(" -m, --manageport - manage port number - second part of the active\n"); printf(" port forwarder connects to it (default: 50126)\n"); + printf(" -t, --timeout - the timeout value for the client's connection\n"); + printf(" (default: 5)\n"); printf(" -u, --users - the amount of users allowed to use this server\n"); printf(" (default: 5)\n"); + printf(" -C, --clients - the number of allowed clients to use this server\n"); + printf(" (default: 1)\n"); + printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n"); + printf(" -M, --climode - strategy used for connecting users with clients (default: 1)\n"); + printf(" Available strategies:\n"); + printf(" 1. fill first client before go to next\n\n"); printf(" -c, --cerfile - the name of the file with certificate\n"); printf(" (default: cacert.pem)\n"); printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n"); @@ -973,28 +1022,136 @@ usage(char* info) printf(" -O, --heavylog - logging everything to a logfile\n"); printf(" -o, --lightlog - logging some data to a logfile\n"); printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); - printf(" (use several times for greater effect)\n"); + printf(" (use several times for greater effect)\n\n"); printf(" --nossl - ssl is not used for transfering data (but it's still\n"); printf(" used to establish a connection) (default: ssl is used)\n"); printf(" --nozlib - zlib is not used for compressing data (default:\n"); printf(" zlib is used)\n"); printf(" --pass - set the password used for client identification\n"); - printf(" (default: no password)\n"); + printf(" (default: no password)\n\n"); printf(" -4, --ipv4 - use ipv4 only\n"); printf(" -6, --ipv6 - use ipv6 only\n\n"); + printf(" -h, --help - prints this help\n\n"); exit(0); } static void sig_int(int signo) { - int j; + int i, j; unsigned char buff[5]; for (j = 0; j < config.size; ++j) { buff[0] = AF_S_CLOSING; /* closing */ - send_message(config.realmtable[j].type, config.realmtable[j].cliconn, buff, 5); + for (i = 0; i < config.realmtable[j].clinum; ++i) { + if (config.realmtable[j].clitable[i].ready == 3) { + send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5); + } + } } aflog(1, "SERVER CLOSED cg: %ld bytes", getcg()); exit(0); } +static void +remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) +{ + int i; + if (ptr->clitable[client].ready == 3) { + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->contable[i].whatcli == client) { + if (ptr->contable[i].state != S_STATE_CLEAR) { + ptr->contable[i].state = S_STATE_CLEAR; + FD_CLR(ptr->contable[i].connfd, set); + FD_CLR(ptr->contable[i].connfd, wset); + close(ptr->contable[i].connfd); + ptr->usercon--; + } + } + } + } + ptr->clitable[client].usercon = 0; + close(ptr->clitable[client].cliconn.commfd); + FD_CLR(ptr->clitable[client].cliconn.commfd, set); + FD_SET(ptr->managefd, set); + if (ptr->clitable[client].ready == 2) + (*con)--; + SSL_clear(ptr->clitable[client].cliconn.ssl); + ptr->clitable[client].ready = 0; + ptr->clicon--; +} + +static int +find_client(RealmT* ptr, char mode) +{ + int i; + switch(mode) { + case 1: { /* fill first client before go to next */ + for (i = 0; i < ptr->clinum; ++i) { + if (ptr->clitable[i].ready == 3) { + if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) { + return i; + } + } + } + break; + } + default: { + return 0; + } + } + return 0; +} + +static int +eval_numofcon(RealmT* ptr, int client, int numofcon) +{ + if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) { + numofcon = ptr->clitable[client].users[numofcon]; + } + else { + numofcon = -1; + } + return numofcon; +} + +static int +eval_usernum(ConnectclientT* ptr, int usernum) +{ + int i; + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->users[i] == usernum) + return i; + } + return -1; +} + +static int +find_usernum(ConnectclientT* ptr, int usernum) +{ + int i; + for (i = 0; i < ptr->usernum; ++i) { + if (ptr->users[i] == -1) { + ptr->users[i] = usernum; + return i; + } + } + return -1; +} + +static void +check_value(int* where, char* what, char* info) +{ + char* znak; + if ((( (*where) = strtol(what, &znak, 10)) == LONG_MAX) || ((*where) == LONG_MIN)) { + printf("%s: %s\n", info, what); + exit(1); + } + if (((*what) == '\0') || (*znak != '\0')) { + printf("%s: %s\n", info, what); + exit(1); + } + if ((*where) <= 0) { + printf("%s: %d\n", info, *where); + exit(1); + } +} diff --git a/buflist.c b/buflist.c index b128249..d25a0ea 100644 --- a/buflist.c +++ b/buflist.c @@ -26,20 +26,20 @@ int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff) { - blnodeT* newnode, *lastnode; + blnodeT* newnode, *lastnode; lastnode = newnode = *headRef; while (newnode) { lastnode = newnode; newnode = newnode->next; } - newnode = calloc(1, sizeof(blnodeT)); - newnode->next = NULL; + newnode = calloc(1, sizeof(blnodeT)); + newnode->next = NULL; newnode->actptr = 0; newnode->msglen = msglen - actptr; newnode->buff = calloc(1, newnode->msglen); if (newnode->buff == NULL) return 1; - strncpy(newnode->buff, buff, newnode->msglen); + strncpy(newnode->buff, buff+actptr, newnode->msglen); if (lastnode) lastnode->next = newnode; else @@ -53,9 +53,10 @@ deleteblnode(blnodeT** headRef) blnodeT* node = *headRef; if (*headRef == NULL) return 1; - *headRef = node->next; - free(node->buff); - free(node); + *headRef = node->next; + if (node->buff != NULL) + free(node->buff); + free(node); return 0; } diff --git a/config b/config index 8230abc..8d82f1d 100644 --- a/config +++ b/config @@ -23,18 +23,20 @@ newrealm #options values -hostname #this is a name of the server (it's using it for choosing interface) -listen 50127 #portnumber on which server is listening for users -manage 50126 #portnumber on which server is listening for afclient -users 5 #amount of users we are allowing to connect -proto tcp #type of the realm (which protocol it will forward (tcp|udp) -#pass mypassword #this is a password used for client identification +hostname #this is a name of the server (it's using it for choosing interface) +listen 50127 #portnumber on which server is listening for users +manage 50126 #portnumber on which server is listening for afclient +#users 5 #amount of users we are allowing to connect (>0) (default: 5) +#timeout 5 #timeout value for the client's connection (>0) (default: 5) +#clients 1 #number of allowed clients for this realm (>0) (default: 1) +#usrpcli $users #allowed users per client for this realm (>0) (default: $users) +#climode 1 #strategy used for connecting users with clients (1) (default: 1) +#proto tcp #type of the realm (which protocol it will forward (tcp|udp) (default: tcp) +#pass mypassword #this is a password used for client identification # and now the second realm newrealm -hostname -listen 50125 -manage 50124 -users 5 -proto tcp +hostname +listen 50125 +manage 50124 diff --git a/docs/ru/ru_README b/docs/ru/ru_README new file mode 100644 index 0000000..4e825f7 --- /dev/null +++ b/docs/ru/ru_README @@ -0,0 +1,294 @@ +AF - Active Port Forwarder v0.5.4 - README +Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm> +=================== + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +========================== + + Программа Active Port Forwarder является частью проекта Gray-World.net. + + Наша команда Gray-World представляет на сайте http://gray-world.net проекты и + публикации, над которыми мы работаем, относящиеся к области исследования + NACS (Систем Контроля Сетевого Доступа), а также к теме компьютерной и + сетевой безопасности. + +================================================================================ + +========== +СОДЕРЖАНИЕ +========== + +ОПИСАНИЕ + +1. УСТАНОВКА + 1.1 Инструкции + 1.2 Необходимые библиотеки + 1.3 Тестовые платформы +2. ИСПОЛЬЗОВАНИЕ + 2.1 afserver + 2.2 afclient +3. ПРИМЕРЫ + 3.1 tcp-режим + 3.2 обратный udp-режим +4. ИЗВЕСТНЫЕ ОШИБКИ/ПРОБЛЕМЫ + +ЗАМЕЧАНИЯ + +БЛАГОДАРНОСТИ + +================================================================================ + +======== +ОПИСАНИЕ +======== + +Active port forwarder это программный инструмент для безопасного тунелирования +данных. Он использует SSL для защиты соединения между клиентом и сервером. +Изначально, программа была разработана для простой пересылки данных от точки к +точке. Однако необходимость обхода брандмауэра с целью сделать компьютеры +локальной сети доступными извне, повлияла на дальнейшее развитие проекта. + +AF предназначен для людей, не имеющих внешнего IP адреса и которые хотят сделать +некоторые локальные сервисы доступными в сети. + +В программе использована библиотека zlib для сжатия передаваемых данных. + +Использование единого канала для передачи данных и команд управления в сочетании +с буферизацией пересылаемых пакетов обеспечивает хорошую производительность и +малое время отклика системы. + +Для запуска afserver не требуется привилегий root, также он не использует +thread-ы или другие процессы. + +================================================================================ + +============ +1. УСТАНОВКА +============ + + 1.1 Инструкции + -------------- + +1. Загрузите упакованный исходный код с http://www.gray-world.net/pr_af.shtml +2. Распакуйте - tar zxvf +3. Выполните команду "make". +4. Если что-то пошло не так - напишите письмо автору или оставьте сообщение на + http://gray-world.net/board/ + + 1.2 Необходимые библиотеки + -------------------------- + +1. openssl - http://www.openssl.org/ +2. zlib - http://www.gzip.org/zlib/ + + 1.3 Тестовые платформы + ---------------------- + +1. Linux: + Gentoo, Slackware, Mandrake - было собрано без каких-либо проблем +2. Freebsd: + 4.4, 4.9 - Необходим patch с домашней страницы проекта +3. Windows: + win32 - Версия с cygwin доступна на домашней странице проекта + +================================================================================ + +================ +2. ИСПОЛЬЗОВАНИЕ +================ + + 2.1 afserver + ------------ + + Параметры: + -h, --help - печатает эту справку + -n, --hostname - используется при создании "слушающих" сокетов + (по умолчанию: имя возвращаемое функцией hostname) + -l, --listenport - порт сервера - пользователи соединяются + с ним (по умолчанию: 50127) + -m, --manageport - порт для управления - другая часть active + port forwarder соединяется с ним (по умолчанию: 50126) + -u, --users - количество пользователей, использующих сервер + (по умолчанию: 5) + -c, --cerfile - имя файла с сертификатом + (по умолчанию: cacert.pem) + -k, --keyfile - имя файла с ключом RSA (по умолчанию: server.rsa) + -f, --cfgfile - имя файла с конфигурацией для active forwarder (сервер) + -p, --proto - тип сервера (tcp|udp) - с каким протоколом он будет + работать (по умолчанию: tcp) + -O, --heavylog - писать все сообщения в logfile + -o, --lightlog - писать некоторые сообщения в logfile + -v, --verbose - вывод сообщений в консоль - програма не будет работать + как daemon. + --nossl - протокол ssl не будет использован для передачи данных (но + будет использован для установки соединений) (по умолчанию: + ssl используется всегда) + --nozlib - zlib не будет использоваться для сжатия данных + (по умолчанию: zlib используется) + --pass - задать пароль для идентификации клиента + (по умолчанию: нет пароля) + -4, --ipv4 - использовать только ipv4 + -6, --ipv6 - использовать только ipv6 + + 2.2 afclient + ------------ + + Options: + -h, --help - печатает эту справку + -n, --servername - где работает вторая часть active port + forwarder (необходимо) + -m, --manageport - порт для управления - сервер соединяется с ним + (по умолчанию: 50126) + -d, --hostname - имя локального/удаленного сервера - данные будут тунелированы + на него (по умолчанию: имя возвращаемое фунцией hostname) + -p, --portnum - порт на который будут тунелированы данные (необходимо) + -k, --keyfile - имя файла с ключом RSA (по умолчанию: client.rsa) + -u, --udpmode - udp-режим - клиент будет использовать udp протокол для + коммуникации с hostname + -U, --reverseudp - обратный udp-режим. Udp пакеты будут перенаправляться + с hostname:portnum (-p) на сервер name:portnum (-m) + -O, --heavylog - писать все сообщения в logfile + -o, --lightlog - писать некоторые сообщения в logfile + -v, --verbose - вывод сообщений в консоль - програма не будет работать + как daemon. + --pass - задать пароль для идентификации клиента + (по умолчанию: нет пароля) + -4, --ipv4 - использовать только ipv4 + -6, --ipv6 - использовать только ipv6 + -l, --load - загрузить модуль для фильтрации пакетов + +================================================================================ + +========== +3. ПРИМЕРЫ +========== + + 3.1 tcp-режим + ------------- + + local network |FireWall| Internet + || + || User 1 + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | \(tcp) + /(tcp) || (tcp)| User 2 + / || \ + Http server || User 3 + || + + +Использование этого режима черезвычано простое. Давайте предположим, что мы +хотим создат http сервер на нашем компьютере, находящемся в локальной сети за +брандмауэром: + +1) Мы должны найти машину с внешним IP адресом и доступом к shell. + +2) Использовать "make" чтобы скомпилировать AF на ней. (вы можете спокойно + удалять файлы afclient и client.rsa) + +3) Вы можете отредактировать конфигурационный файл или передать программе все + параметры из консоли (для использования файла наберите -f ) : + $ ./afserver + Это будет работать, если вы хотите использовать настройки по умолчанию: + - hostname будет взят из функции hostname (это работает замечательно, если + есть соответствующая запись в /etc/hosts) + - сервер будет ждать пользователей на порту 50127 + - сервер будет ждать клиента на порту 50126 + - сервер будет обслуживать макимум 5 пользователей + - сервер будет перенаправлять tcp соединения + - отладочных сообщений не будет + - идентификаций по паролю не будет + - версия протокола ip не будет задана + +4) Мы используем "make" на нашей машине (можно удалить все кроме afclient и + client.rsa) + +5) Набираем в консоли: + $ ./afclient -n <имя сервера> -p 80 + Где <имя сервера> строка типа: 'bastion.univ.gda.pl' или '153.19.7.200' + +6) Теперь в браузере мы можем набрать: <имя сервера>:50127 и попадем на наш + компьютер. + + 3.2 обратный udp-режим + ---------------------- + + local network |FireWall| Internet + || (udp) + || User 1-------AF Client + || /(tcp) + AF Client <---Encrypted/Compressed channel---> AF Server + / || | + /(udp) || (tcp)| + / || / + Game server || AF Client-------User 2 + || (udp) + + +Давайте теперь посмотрим как мы можем использовать af для перенаправления udp +пакетов. Предположим, что мы хотим создать игровой сервер на нашем компьютере +(udp порт 27960): + +1) - 4) тоже самое, что и в первом примере. (но добавляем параметр: -p udp) + +5) Набираем в консоли: + $ ./afclient -u -n <имя сервера> -p 27960 + Где <имя сервера> это имя (или ip) компютера где работает наш сервер. + +6) Процесс соединения с игровым сервером более сложный. Пользователь должен + запустить fclient чтобы сделать это. Он должен указать сервер с которым он + будет соединяться и порт, на котором его программа будет слушать: + $ ./afclient -U -d -p <порт> -n <имя сервера> \ + -m <порт сервера> + + Где имя машины пользователя (который соединяется с игровым + сервером), <порт> - локальный порт, <имя сервера> - имя сервера, <порт + сервера> - порт на котором сервер ждет пользователей.Теперь, чтобы попасть на + игровой сервер, пользователь должен соединятся с :<порт>. + +================================================================================ + +============================ +4. ИЗВЕСТНЫЕ ОШИБКИ/ПРОБЛЕМЫ +============================ + +На данный момент, нет никаких известных проблем. + +================================================================================ + +========= +ЗАМЕЧАНИЯ +========= + +Active port forwarder находится в разработке, так что пожалуйста, присылайте +свои комментарии, замечания об ошибках и предложения на jeremian [at] poczta.fm + +Если у вас есть какие-либо проблемы с использованием программы или вы хотите +поделиться своим мнением о ней, пожалйста оставляйте свои сообщения на: +http://gray-world.net/board/ + +================================================================================ + +============= +БЛАГОДАРНОСТИ +============= + + Большое спасибо команде GW: + + Alex + и Simon за тестирование AF и множество советов. + + Спасибо Ilia Perevezentsev за корректировку английской + версии этого файла. + + И спасибо за использование AF! + +ЛИЦЕНЗИЯ +-------- + + Active Port Forwarder is distributed under the terms of the GNU General + Public License v2.0 and is copyright (c) 2003,2004 jeremian . See the file COPYING for details. diff --git a/exmodule.c b/exmodule.c index 133609c..09141c4 100644 --- a/exmodule.c +++ b/exmodule.c @@ -18,10 +18,8 @@ * */ -/* This example module put IP of the connected user into a body of the message */ -#include -/* There is no required headers for module to work. - * We just need string.h for memcpy and strlen functions. +/* This example module scan the message for specified string and perform + * appropriate action */ /* info @@ -32,7 +30,7 @@ char* info(void) { - return "An example module"; + return "Module tester v0.1"; } /* allow @@ -52,15 +50,32 @@ allow(char* host, char* port) * 0 - allow to transfer * 1 - drop the packet * 2 - drop the connection + * 3 - release the module + * 4 - drop the packet and release the module + * 5 - drop the connection and release the module */ int filter(char* host, unsigned char* message, int* length) { - int n; - n = strlen(host); - message[*length] = '|'; - memcpy(&message[*length+1], host, n); - *length += n+1; - return 0; /* allow to transfer */ + int i; + for (i = 0; i < *length; ++i) { + if ((message[i] == 'M') && (message[i+1] == '1')) { + return 1; /* ignored */ + } + if ((message[i] == 'M') && (message[i+1] == '2')) { + return 2; /* dropped */ + } + if ((message[i] == 'M') && (message[i+1] == '3')) { + return 3; /* release */ + } + if ((message[i] == 'M') && (message[i+1] == '4')) { + return 4; /* ignored + release */ + } + if ((message[i] == 'M') && (message[i+1] == '5')) { + return 5; /* dropped + release */ + } + } + return 0; /* allow to transfer */ + } diff --git a/file.c b/file.c index d3712ea..59ff7ba 100644 --- a/file.c +++ b/file.c @@ -158,6 +158,22 @@ parsefile(char* name, int* status) cfg.realmtable[cfg.size-1].users = calloc(strlen(helpbuf2)+1, sizeof(char)); strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2); } + else if (strcmp(helpbuf1, "timeout")==0) { + cfg.realmtable[cfg.size-1].timeout = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(cfg.realmtable[cfg.size-1].timeout, helpbuf2); + } + else if (strcmp(helpbuf1, "clients")==0) { + cfg.realmtable[cfg.size-1].clients = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(cfg.realmtable[cfg.size-1].clients, helpbuf2); + } + else if (strcmp(helpbuf1, "usrpcli")==0) { + cfg.realmtable[cfg.size-1].usrpcli = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(cfg.realmtable[cfg.size-1].usrpcli, helpbuf2); + } + else if (strcmp(helpbuf1, "climode")==0) { + cfg.realmtable[cfg.size-1].clim = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(cfg.realmtable[cfg.size-1].clim, helpbuf2); + } else if (strcmp(helpbuf1, "proto")==0) { if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) { return cfg; diff --git a/file.h b/file.h index c0e752b..9132caa 100644 --- a/file.h +++ b/file.h @@ -36,17 +36,24 @@ typedef struct { char* lisportnum; char* manportnum; char* users; + char* clients; + char* usrpcli; + char* clim; + char* timeout; unsigned char pass[4]; int usercon; int usernum; + int clicon; + int clinum; + int upcnum; + int tmout; int listenfd; int managefd; - char ready; + int climode; char type; socklen_t addrlen; struct sockaddr* cliaddr; - struct timeval tv; - clifd cliconn; + ConnectclientT* clitable; ConnectuserT* contable; } RealmT; diff --git a/modules.c b/modules.c new file mode 100644 index 0000000..75c2a08 --- /dev/null +++ b/modules.c @@ -0,0 +1,63 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "modules.h" + +#include +#include + +int +loadmodule(moduleT* module) +{ + if (module->name) { + module->handle = dlopen(module->name, RTLD_NOW); + if (!module->handle) { + return 1; + } + dlerror(); + *(void**) (&module->info) = dlsym(module->handle, "info"); + *(void**) (&module->allow) = dlsym(module->handle, "allow"); + *(void**) (&module->filter) = dlsym(module->handle, "filter"); + if (dlerror() != NULL) { + return 2; + } + module->loaded = 1; + } + return 0; +} + +int +releasemodule(moduleT* module) +{ + if (ismloaded(module)) { + module->loaded = 0; + module->info = NULL; + module->allow = NULL; + module->filter = NULL; + return dlclose(module->handle); + } + return 0; +} + +int +ismloaded(moduleT* module) +{ + return module->loaded; +} diff --git a/modules.h b/modules.h new file mode 100644 index 0000000..7527114 --- /dev/null +++ b/modules.h @@ -0,0 +1,37 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_MODULES_H +#define _JS_MODULES_H + +typedef struct { + char loaded; + char* name; + void* handle; + char* (*info)(void); + int (*allow)(char*, char*); + int (*filter)(char*, unsigned char*, int*); +} moduleT; + +int loadmodule(moduleT* module); +int releasemodule(moduleT* module); +int ismloaded(moduleT* module); + +#endif -- cgit v1.1