diff options
| author | Jakub SЕ‚awiЕ„ski | 2004-10-12 00:07:33 +0200 | 
|---|---|---|
| committer | Joshua Judson Rosen | 2014-07-17 21:14:58 +0200 | 
| commit | 8a5f0141a346ad4b94d09313a2ec9a52efa7cf59 (patch) | |
| tree | 70af82a7af209cca2ecd6fb44388cf25dd9c785d | |
| parent | v0.5.4 (diff) | |
| download | apf-8a5f0141a346ad4b94d09313a2ec9a52efa7cf59.tar.gz | |
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
| -rw-r--r-- | AUTHORS | 7 | ||||
| -rw-r--r-- | Changelog | 72 | ||||
| -rw-r--r-- | Makefile | 12 | ||||
| -rw-r--r-- | README | 47 | ||||
| -rw-r--r-- | activefor.h | 12 | ||||
| -rw-r--r-- | afclient.c | 157 | ||||
| -rw-r--r-- | afserver.c | 1195 | ||||
| -rw-r--r-- | buflist.c | 15 | ||||
| -rw-r--r-- | config | 24 | ||||
| -rw-r--r-- | docs/ru/ru_README | 294 | ||||
| -rw-r--r-- | exmodule.c | 37 | ||||
| -rw-r--r-- | file.c | 16 | ||||
| -rw-r--r-- | file.h | 13 | ||||
| -rw-r--r-- | modules.c | 63 | ||||
| -rw-r--r-- | modules.h | 37 | 
15 files changed, 1357 insertions, 644 deletions
@@ -1,5 +1,8 @@  Author: -	o jeremian <jeremian [at] poczta.fm> +  o jeremian <jeremian [at] poczta.fm>  French translation: -        o Simon CASTRO <scastro [at] entreelibre.com> +  o Simon CASTRO <scastro [at] entreelibre.com> + +Russian translation: +  o Alex Dyatlov <alex [at] gray-world.net> @@ -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 @@ -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 @@ -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 - <jeremian [at] poczta.fm>  =================== @@ -7,10 +7,10 @@ Copyright (C) 2003,2004 jeremian - <jeremian [at] poczta.fm>  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 <cfgfile>) :          $ ./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 <name of the server> -p 27960 +  $ ./afclient -u -n <name of the server> -p 27960     Where <name of the server> 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  <jeremian  [at]    poczta.fm>. 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 @@ -21,7 +21,9 @@  #include "activefor.h"  #include "network.h"  #include "stats.h" +#include "modules.h" +#include <openssl/rsa.h>  #include <openssl/ssl.h>  #include <openssl/err.h>  #include <sys/time.h> @@ -30,12 +32,12 @@  #include <signal.h>  #include <string.h>  #include <fcntl.h> -#include <dlfcn.h>  #include <getopt.h>  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); +  } +} @@ -28,19 +28,29 @@  #include <fcntl.h>  #include <signal.h>  #include <string.h> - +#include <sys/time.h>  #include <getopt.h>  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].clinum; ++j) { +  		config.realmtable[i].clitable[j].cliconn.ssl = SSL_new(ctx); +  		if (config.realmtable[i].clitable[j].cliconn.ssl == NULL) { +  			printf("Creating of ssl object failed... exiting\n"); +  			exit(1); +  		} +    }  		FD_SET(config.realmtable[i].managefd, &allset);  		FD_SET(config.realmtable[i].listenfd, &allset);  		maxfdp1 = (maxfdp1 > (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; j<config.realmtable[i].clinum; ++j) { +		  config.realmtable[i].clitable[j].ready = 0; +      config.realmtable[i].clitable[j].tv.tv_sec = config.realmtable[i].tmout; +      config.realmtable[i].clitable[j].tv.tv_usec = 0; +      config.realmtable[i].clitable[j].usernum = config.realmtable[i].upcnum; +      config.realmtable[i].clitable[j].users = malloc( config.realmtable[i].clitable[j].usernum * sizeof(int)); +      if (config.realmtable[i].clitable[j].users == NULL) { +        printf("Calloc error - try define smaller amount of usrpcli (or users)\n"); +        exit(1); +      } +      for (k=0; k<config.realmtable[i].clitable[j].usernum; ++k) { +        config.realmtable[i].clitable[j].users[k] = -1; +      } +    } +  }  	if (loginit(verbose, config.logging, config.logfnam)) {  		printf("Can't open file to log to... exiting\n"); @@ -375,18 +454,24 @@ main(int argc, char **argv)  			aflog(3, ">select, 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 <pointer->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 <pointer->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); +  } +} @@ -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;  } @@ -23,18 +23,20 @@ newrealm  #options        values -hostname	<yourhostname> #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  <yourhostname> #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	<yourhostname> -listen		50125 -manage		50124 -users		5 -proto		tcp +hostname  <yourhostname> +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 <cfgfile>) : +        $ ./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 <hostname> -p <порт> -n <имя сервера>  \ +         -m <порт сервера> + +   Где  <hostname>  имя  машины  пользователя  (который  соединяется  с  игровым +   сервером),  <порт> -  локальный  порт,  <имя  сервера> -  имя сервера,  <порт +   сервера> - порт на котором сервер ждет пользователей.Теперь, чтобы попасть на +   игровой сервер, пользователь должен соединятся с <hostname>:<порт>. + +================================================================================ + +============================ +4. ИЗВЕСТНЫЕ ОШИБКИ/ПРОБЛЕМЫ +============================ + +На данный момент, нет никаких известных проблем. + +================================================================================ + +========= +ЗАМЕЧАНИЯ +========= + +Active port  forwarder  находится в разработке,  так что пожалуйста, присылайте +свои комментарии, замечания об ошибках и предложения на jeremian [at] poczta.fm + +Если у вас  есть какие-либо проблемы  с использованием  программы или вы хотите +поделиться своим мнением о ней, пожалйста оставляйте свои сообщения на: +http://gray-world.net/board/ + +================================================================================ + +============= +БЛАГОДАРНОСТИ +============= + + Большое спасибо команде GW: + + Alex <alex [at] gray-world.net> + и Simon <scastro [at] entreelibre.com> за тестирование AF и множество советов. + + Спасибо Ilia Perevezentsev <iliaper [at] mail.ru>  за корректировку английской + версии этого файла. + + И спасибо за использование AF! + +ЛИЦЕНЗИЯ +-------- + +  Active Port Forwarder is distributed	under  the  terms  of  the  GNU  General +  Public License v2.0 and is copyright (c)  2003,2004  jeremian  <jeremian  [at] +  poczta.fm>. See the file COPYING for details. @@ -18,10 +18,8 @@   *   */ -/* This example module put IP of the connected user into a body of the message */ -#include <string.h> -/* 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 */ +  } @@ -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; @@ -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 <jeremian [at] poczta.fm> + * + * 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 <stdlib.h> +#include <dlfcn.h> + +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 <jeremian [at] poczta.fm> + * + * 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  | 
