From c691251feaffa310a51e0c2255eefc6b42f0e728 Mon Sep 17 00:00:00 2001 From: Jakub SÅ‚awiÅ„ski Date: Fri, 9 Jan 2004 18:48:31 +0100 Subject: v0.5.3 - Added: client password identification (weak) - Added: sigint intercepting 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 --- AUTHORS | 5 + Changelog | 9 ++ Makefile | 8 +- README | 4 +- activefor.h | 28 ++++- afclient.c | 225 ++++++++++++++++++++++++--------------- afserver.c | 309 ++++++++++++++++++++++++++++++++++-------------------- config | 5 +- docs/en/README | 91 ++++++++++++++++ docs/fr/fr_README | 102 ++++++++++++++++++ file.c | 28 ++++- file.h | 4 +- network.c | 93 ++++++++++++++++ network.h | 9 ++ stats.c | 19 ++++ stats.h | 3 + 16 files changed, 726 insertions(+), 216 deletions(-) create mode 100644 AUTHORS create mode 100644 docs/en/README create mode 100644 docs/fr/fr_README diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..10c79d5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +Author: + o jeremian + +French translation: + o Simon CASTRO diff --git a/Changelog b/Changelog index 4c3dc15..4cb70d8 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,12 @@ +09.01.2004 (v0.5.3): + - Added: client password identification (weak) + - Added: sigint intercepting 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 diff --git a/Makefile b/Makefile index 21e5bb4..5e4463f 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ security=server.rsa client.rsa cacert.pem all: compi $(programs) ok1 secure afserver: afserver.c network.o file.o stats.o - $(CC) $(CFLAGS) -lssl afserver.c network.o file.o stats.o -o afserver + $(CC) $(CFLAGS) -lssl -lz afserver.c network.o file.o stats.o -o afserver afclient: afclient.c network.o stats.o - $(CC) $(CFLAGS) -lssl afclient.c network.o stats.o -o afclient + $(CC) $(CFLAGS) -lssl -lz afclient.c network.o stats.o -o afclient network.o: network.c network.h $(CC) $(CFLAGS) -c network.c @@ -23,10 +23,10 @@ stats.o: stats.c stats.h secure: crea $(security) ok2 server.rsa: - @openssl genrsa -out server.rsa 2048 + @openssl genrsa -rand Makefile -out server.rsa 2048 client.rsa: - @openssl genrsa -out client.rsa 2048 + @openssl genrsa -rand server.rsa -out client.rsa 2048 cacert.pem: @echo -e "\n Generating certificate...\n" diff --git a/README b/README index 7abf822..cbae3d7 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -AF - Active Port Forwarder v0.5.2 - README +AF - Active Port Forwarder v0.5.3 - README Copyright (C) 2003 jeremian - jeremian@poczta.fm =================== @@ -23,6 +23,7 @@ It uses ssl for increasing security of communication between server and client. Af is dedicated for people, who don't have external ip number and want to make some services available across the net. +Moreover, zlib is used to compress transfered data. EXAMPLE 1: @@ -44,6 +45,7 @@ our computer and we are behind masquerade or firewall: - server will be for maximum 5 users - server will forward tcp packets - there will be no logging and no verbose messages + - there will be no password identification 4) We use make on our machine (we can delete everything apart afclient and client.rsa) diff --git a/activefor.h b/activefor.h index 777f54f..01a29a6 100644 --- a/activefor.h +++ b/activefor.h @@ -21,17 +21,43 @@ #ifndef _JS_ACTIVEFOR_H #define _JS_ACTIVEFOR_H +#include "network.h" + #define AF_S_CONCLOSED 1 #define AF_S_CONOPEN 2 #define AF_S_MESSAGE 3 +#define AF_S_CLOSING 4 #define AF_S_LOGIN 8 #define S_STATE_CLEAR 0 -#define S_STATE_RUNNING 4 #define S_STATE_CLOSING 5 #define S_STATE_OPENING 6 #define S_STATE_OPEN 7 +#define AF_VER(info) info" v0.5.3" + +#define TYPE_TCP 1 +#define TYPE_UDP 3 +#define TYPE_SSL 4 +#define TYPE_ZLIB 8 +#define TYPE_COMP 0x4000 +#define TYPE_NOTCOMP (~TYPE_COMP) + +#define TYPE_SET_ZERO(type) (type=0) +#define TYPE_IS_SET(type) (type&1) +#define TYPE_IS_UDP(type) TYPE_IS_SET(type)&&(type&2) +#define TYPE_IS_TCP(type) TYPE_IS_SET(type)&&(!(type&2)) +#define TYPE_SET_UDP(type) (type|=TYPE_UDP) +#define TYPE_SET_TCP(type) (type|=TYPE_TCP) +#define TYPE_SET_SSL(type) (type|=TYPE_SSL) +#define TYPE_UNSET_SSL(type) (type&=(~TYPE_SSL)) +#define TYPE_IS_SSL(type) (type&TYPE_SSL) +#define TYPE_SET_ZLIB(type) (type|=TYPE_ZLIB) +#define TYPE_UNSET_ZLIB(type) (type&=(~TYPE_ZLIB)) +#define TYPE_IS_ZLIB(type) (type&TYPE_ZLIB) +#define TYPE_SET_COMP(type) (type|=TYPE_COMP) +#define TYPE_IS_COMP(type) (type&TYPE_COMP) + typedef struct { char state; int connfd; diff --git a/afclient.c b/afclient.c index e4d7c05..73f5fb6 100644 --- a/afclient.c +++ b/afclient.c @@ -28,15 +28,36 @@ #include #include #include +#include + +#include static void usage(char* info); +static void sig_int(int); + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"udpmode", 0, 0, 'u'}, + {"reverseudp", 0, 0, 'U'}, + {"servername", 1, 0, 'n'}, + {"manageport", 1, 0, 'm'}, + {"hostname", 1, 0, 'd'}, + {"portnum", 1, 0, 'p'}, + {"verbose", 0, 0, 'v'}, + {"keyfile", 1, 0, 'k'}, + {"heavylog", 1, 0, 'O'}, + {"lightlog", 1, 0, 'o'}, + {"pass", 1, 0, 301}, + {0, 0, 0, 0} +}; int main(int argc, char **argv) { - int masterfd, i, n, numofcon, length, buflength, notsent, temp2; /* !!! */ + int i, n, numofcon, length, buflength, notsent, temp2; /* !!! */ ConnectuserT* contable = NULL; - unsigned char buff[8096]; + clifd master; + unsigned char buff[9000]; char hostname[100]; struct timeval tv; int maxfdp1, usernum, usercon, merror; @@ -51,19 +72,21 @@ main(int argc, char **argv) char* despor = NULL; char* keys = NULL; char* logfname = NULL; + unsigned char pass[4]; char udp = 0; char reverse = 0; + char type; SSL_METHOD* method; SSL_CTX* ctx; - SSL* ssl; signal(SIGPIPE, SIG_IGN); + signal(SIGINT, sig_int); - while ((n = getopt(argc, argv, "huUn:m:d:p:vk:O:o:")) != -1) { + while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:", long_options, 0)) != -1) { switch (n) { case 'h': { - usage("Active port forwarder (client) v0.5.2"); + usage(AF_VER("Active port forwarder (client)")); break; } case 'n': { @@ -108,6 +131,14 @@ main(int argc, char **argv) logging = 1; break; } + case 301: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + break; + } case '?': { usage(""); break; @@ -115,6 +146,10 @@ main(int argc, char **argv) } } + if (optind < argc) { + usage("Unrecognized non-option elements"); + } + if (name == NULL) { usage("Name of the server is required"); } @@ -134,8 +169,11 @@ main(int argc, char **argv) keys = "client.rsa"; } + type = 0; + TYPE_SET_SSL(type); + TYPE_SET_ZLIB(type); - masterfd = ip_connect(name, manage, "tcp"); + master.commfd = ip_connect(name, manage, "tcp"); if (!reverse) { SSL_library_init(); @@ -149,14 +187,14 @@ main(int argc, char **argv) printf("Setting rsa key failed (%s)... exiting\n", keys); exit(1); } - ssl = SSL_new(ctx); - if (SSL_set_fd(ssl, masterfd) != 1) { + master.ssl = SSL_new(ctx); + if (SSL_set_fd(master.ssl, master.commfd) != 1) { printf("Problem with initializing ssl... exiting\n"); exit(1); } if (verbose>1) printf("Trying SSL_connect\n"); - if ((n = SSL_connect(ssl)) == 1) { + if ((n = SSL_connect(master.ssl)) == 1) { if (verbose) { printf("SSL_connect successfull\n"); } @@ -168,19 +206,24 @@ main(int argc, char **argv) buff[0] = AF_S_LOGIN; - buff[1] = 1; - buff[2] = 3; - buff[3] = 6; - buff[4] = 2; - SSL_write(ssl, buff, 5); + buff[1] = pass[0]; + buff[2] = pass[1]; + buff[3] = pass[2]; + buff[4] = pass[3]; + send_message(type, master, buff, 5); buff[0] = 0; - SSL_read(ssl, buff, 5); + get_message(type, master, buff, -5); + if ( buff[0] == 0 ) { + printf("Wrong password\n"); + exit(1); + } if ( buff[0] != AF_S_LOGIN ) { printf("Incompatible server type or server full\n"); exit(1); } + type = buff[3]; usernum = buff[1]; usernum = usernum << 8; usernum += buff[2]; @@ -188,7 +231,7 @@ main(int argc, char **argv) } /* !reverse */ else { usernum = 1; - ssl = NULL; + master.ssl = NULL; } contable = calloc( usernum, sizeof(ConnectuserT)); @@ -198,7 +241,7 @@ main(int argc, char **argv) } len = 4; - if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) { + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) { printf("Can't get socket send buffor size - exiting...\n"); exit(1); } @@ -213,18 +256,18 @@ main(int argc, char **argv) FD_ZERO(&allset); - FD_SET(masterfd, &allset); - maxfdp1 = masterfd + 1; + FD_SET(master.commfd, &allset); + maxfdp1 = master.commfd + 1; if (reverse) { contable[0].connfd=ip_listen(desnam, despor, &addrlen, "udp"); cliaddr = malloc(addrlen); maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1; FD_SET(contable[0].connfd, &allset); - aflog(1, "^^Started in udp reverse mode^^"); + aflog(1, "CLIENT STARTED mode: udp reverse"); for ( ; ; ) { len = 4; - if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; aflog(2, "Send buffor size changed..."); @@ -234,11 +277,11 @@ main(int argc, char **argv) rset = allset; aflog(2, ">select"); select(maxfdp1, &rset, NULL, NULL, NULL); - aflog(2, ">>after select..."); + aflog(2, " >>after select..."); if (FD_ISSET(contable[0].connfd, &rset)) { n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len); #ifdef SIOCOUTQ - if (ioctl(masterfd, SIOCOUTQ, ¬sent)) { + if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { aflog(0, "ioctl error -> exiting..."); exit(1); } @@ -246,7 +289,7 @@ main(int argc, char **argv) aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); #else - if (ioctl(masterfd, TIOCOUTQ, ¬sent)) { + if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { aflog(0, "ioctl error -> exiting..."); exit(1); } @@ -270,12 +313,12 @@ main(int argc, char **argv) buff[2] = AF_S_MESSAGE; buff[3] = n >> 8; buff[4] = n; - writen(masterfd, buff, n + 5); + writen(master.commfd, buff, n + 5); } } } - if (FD_ISSET(masterfd, &rset)) { - n = readn(masterfd, buff, 5); + if (FD_ISSET(master.commfd, &rset)) { + n = readn(master.commfd, buff, 5); if (n == 5) { if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) { @@ -285,7 +328,7 @@ main(int argc, char **argv) length = buff[3]; length = length << 8; length += buff[4]; /* this is length of message */ - n = readn(masterfd, buff, length); + n = readn(master.commfd, buff, length); } else { n = 0; @@ -302,55 +345,57 @@ main(int argc, char **argv) exit(0); /* we shouldn't get here */ } - aflog(1, "^^Started in normal mode^^ (%s)", (udp)?"udp":"tcp"); + aflog(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp"); + 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"); for ( ; ; ) { rset = allset; aflog(2, ">select"); select(maxfdp1, &rset, NULL, NULL, NULL); - aflog(2, ">>after select..."); + aflog(2, " >>after select..."); for (i = 0; i < usernum; ++i) { if (contable[i].state == S_STATE_OPEN) if (FD_ISSET(contable[i].connfd, &rset)) { - aflog(2, "FD_ISSET(contable[%d].connfd)", i); + aflog(2, " user[%d]: FD_ISSET", i); n = read(contable[i].connfd, &buff[5], 8091); if (n == -1) { - aflog(0, "FATAL ERROR! (%d) while reading from user", n); + aflog(0, " error (%d): while reading from service", n); n = 0; } #ifdef SIOCOUTQ - if (ioctl(masterfd, SIOCOUTQ, ¬sent)) { + if (ioctl(master.commfd, SIOCOUTQ, ¬sent)) { aflog(0, "ioctl error -> exiting..."); exit(1); } if (udp) { len = 4; - if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; aflog(2, "Send buffor size changed..."); } } if (buflength <= notsent + n + 5) { /* when we can't send this */ - aflog(2, "drop: size:%d, buf:%d, w:%d/%d", - n+5, buflength, notsent, buflength); + aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", + i, n+5, buflength, notsent, buflength); #else - if (ioctl(masterfd, TIOCOUTQ, ¬sent)) { + if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { aflog(0, "ioctl error -> exiting..."); exit(1); } if (udp) { len = 4; - if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { if (temp2 != buflength) { buflength = temp2; aflog(2, "Send buffor size changed..."); } } if (notsent <= n + 5) { /* when we can't send this */ - aflog(2, "drop: size:%d, buf:%d, w:%d/%d", - n+5, buflength, buflength-notsent, buflength); + aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", + i, n+5, buflength, buflength-notsent, buflength); #endif continue; /* drop this packet */ } @@ -361,15 +406,15 @@ main(int argc, char **argv) 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 */ - aflog(2, "Sending %d bytes to user (%d) [%d/%d]", - n, i, + aflog(2, " user[%d]: TO msglen: %d [%d/%d]", + i, n, #ifdef SIOCOUTQ notsent #else buflength - notsent #endif , buflength); - SSL_writen(ssl, buff, n+5); + send_message(type, master, buff, n+5); } else if (!udp) { close(contable[i].connfd); @@ -378,18 +423,19 @@ main(int argc, char **argv) buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - SSL_writen(ssl, buff, 5); + send_message(type, master, buff, 5); } } } - if (FD_ISSET(masterfd, &rset)) { - aflog(2, "FD_ISSET(masterfd)"); - n = SSL_readn(ssl, buff, 5); + if (FD_ISSET(master.commfd, &rset)) { + aflog(2, " masterfd: FD_ISSET"); + n = get_message(type, master, buff, 5); if (n != 5) { - aflog(2, "FATAL ERROR! (%d)", n); + aflog(2, " FATAL ERROR! (%d)", n); if (n == -1) { - merror = SSL_get_error(ssl, n); + if (TYPE_IS_SSL(type)) { + merror = SSL_get_error(master.ssl, n); switch (merror) { case SSL_ERROR_NONE : { aflog(2, "FE: none"); @@ -427,12 +473,13 @@ main(int argc, char **argv) } } continue; /* what happened? */ + } } if (n != 0) exit(1); } if (n == 0) { /* server quits -> we do the same... */ - aflog(0, "premature quit of the server -> exiting..."); + aflog(0, " SERVER: premature quit -> exiting..."); exit(1); } numofcon = buff[1]; @@ -455,7 +502,7 @@ main(int argc, char **argv) buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - SSL_writen(ssl, buff, 5); + send_message(type, master, buff, 5); } } break; @@ -465,43 +512,43 @@ main(int argc, char **argv) usercon++; if (contable[numofcon].state == S_STATE_CLEAR) { if (udp) { - contable[numofcon].connfd=ip_connect(desnam,despor,"udp"); + contable[numofcon].connfd=ip_connect(desnam,despor,"udp"); } else { - contable[numofcon].connfd=ip_connect(desnam,despor,"tcp"); + contable[numofcon].connfd=ip_connect(desnam,despor,"tcp"); } - FD_SET(contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1); + FD_SET(contable[numofcon].connfd, &allset); + maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1); buff[0] = AF_S_CONOPEN; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - SSL_writen(ssl, buff, 5); + send_message(type, master, buff, 5); contable[numofcon].state = S_STATE_OPEN; } } break; } case AF_S_MESSAGE : { - aflog(2, "Received msg for con[%d], length=%d", numofcon, length); - n = SSL_readn(ssl, buff, length); - if (n != length) { - aflog(2, "n(%d)!=length(%d)", n, length); - break; - } + aflog(2, " user[%d]: FROM msglen: %d", numofcon, length); + n = get_message(type, master, buff, length); if ((numofcon>=0) && (numofcon<=usernum)) { if (contable[numofcon].state == S_STATE_OPEN) { - aflog(2, "sent msg con[%d], length=%d", numofcon, n); - if (writen(contable[numofcon].connfd, buff, n)==-1) { + aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n); + if (writen(contable[numofcon].connfd, buff, n)==-1) { aflog(0, "Sending msg failed!"); - } + } } } break; } + case AF_S_CLOSING : { /* server shut down -> exiting... */ + aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + exit(1); + break; + } default : { /* unrecognized type of message -> exiting... */ - aflog(0, "Server sents unrecognized message -> exiting..."); + aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); exit(1); - break; } } @@ -514,24 +561,32 @@ usage(char* info) { printf("\n%s\n\n", info); printf(" Options:\n"); - printf(" -h - prints this help\n"); - printf(" -n [server name] - where the second part of the active\n"); - printf(" port forwarder is running (required)\n"); - printf(" -m [portnum] - the manage port number - server must\n"); - printf(" listening on it (default: 50126)\n"); - printf(" -d [hostname] - name of this host/remote host - the final\n"); - printf(" destination of the packets (default: name\n"); - printf(" returned by hostname function)\n"); - printf(" -p [portnum] - port we are forwarding connection to (required)\n"); - printf(" -k [keyfile] - name of the file with RSA key (default: client.rsa)\n"); - printf(" -u - udp mode - client will use udp protocol to\n"); - printf(" communicate with hostname\n"); - printf(" -U - reverse udp forwarding. Udp packets will be forwarded\n"); - printf(" from hostname:portnum (-p) to server name:portnum (-m)\n"); - printf(" -O [logfile] - logging everything to a logfile\n"); - printf(" -o [logfile] - logging some data to a logfile\n"); - printf(" -v - to be verbose - program won't enter into\n"); - printf(" the daemon mode (use twice for greater effect)\n\n"); + printf(" -h, --help - prints this help\n"); + printf(" -n, --servername - where the second part of the active\n"); + printf(" port forwarder is running (required)\n"); + printf(" -m, --manageport - the manage port number - server must\n"); + printf(" listening on it (default: 50126)\n"); + printf(" -d, --hostname - name of this host/remote host - the final\n"); + printf(" destination of the packets (default: name\n"); + printf(" returned by hostname function)\n"); + printf(" -p, --portnum - port we are forwarding connection to (required)\n"); + printf(" -k, --keyfile - name of the file with RSA key (default: client.rsa)\n"); + printf(" -u, --udpmode - udp mode - client will use udp protocol to\n"); + printf(" communicate with hostname\n"); + printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n"); + printf(" from hostname:portnum (-p) to server name:portnum (-m)\n"); + 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 into\n"); + printf(" the daemon mode (use twice for greater effect)\n"); + printf(" --pass - set the password used for client identification\n"); + printf(" (default: no password)\n\n"); exit(0); } +static void +sig_int(int signo) +{ + aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg()); + exit(0); +} diff --git a/afserver.c b/afserver.c index 947d001..17c2143 100644 --- a/afserver.c +++ b/afserver.c @@ -29,15 +29,38 @@ #include #include +#include + static void usage(char* info); +static void sig_int(int); + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"hostname", 1, 0, 'n'}, + {"listenport", 1, 0, 'l'}, + {"manageport", 1, 0, 'm'}, + {"verbose", 0, 0, 'v'}, + {"users", 1, 0, 'u'}, + {"cerfile", 1, 0, 'c'}, + {"keyfile", 1, 0, 'k'}, + {"cfgfile", 1, 0, 'f'}, + {"proto", 1, 0, 'p'}, + {"lightlog", 1, 0, 'o'}, + {"heavylog", 1, 0, 'O'}, + {"nossl", 0, 0, 301}, + {"nozlib", 0, 0, 302}, + {"pass", 1, 0, 303}, + {0, 0, 0, 0} +}; + +static ConfigurationT config; int main(int argc, char **argv) { int i, j, n, flags; - ConfigurationT config; socklen_t len; - unsigned char buff[8096]; + unsigned char buff[9000]; char hostname[100]; int maxfdp1; fd_set rset, allset; @@ -49,13 +72,19 @@ main(int argc, char **argv) char* filenam = NULL; char* type = NULL; char* znak; + unsigned char pass[4]; char verbose = 0; + char mode = 0; RealmT* pointer = NULL; SSL_METHOD* method; SSL_CTX* ctx; signal(SIGPIPE, SIG_IGN); + signal(SIGINT, sig_int); + + TYPE_SET_SSL(mode); + TYPE_SET_ZLIB(mode); config.certif = NULL; config.keys = NULL; @@ -64,10 +93,10 @@ main(int argc, char **argv) config.logging = 0; config.logfnam = NULL; - while ((n = getopt(argc, argv, "hn:l:m:vu:c:k:f:t:o:O:")) != -1) { + while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:", long_options, 0)) != -1) { switch (n) { case 'h': { - usage("Active port forwarder (server) v0.5.2"); + usage(AF_VER("Active port forwarder (server)")); break; } case 'n': { @@ -98,7 +127,7 @@ main(int argc, char **argv) config.keys = optarg; break; } - case 't': { + case 'p': { type = optarg; break; } @@ -116,6 +145,23 @@ main(int argc, char **argv) config.logging = 1; break; } + case 301: { + TYPE_UNSET_SSL(mode); + break; + } + case 302: { + TYPE_UNSET_ZLIB(mode); + break; + } + case 303: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + break; + } + case '?': { usage(""); break; @@ -123,6 +169,10 @@ main(int argc, char **argv) } } + if (optind < argc) { + usage("Unrecognized non-option elements"); + } + if (filenam != NULL) { config = parsefile(filenam, &n); if (n) { @@ -164,15 +214,17 @@ main(int argc, char **argv) config.realmtable[0].lisportnum = listen; config.realmtable[0].manportnum = manage; config.realmtable[0].users = amount; + memcpy(config.realmtable[0].pass, pass, 4); if (strcmp(type, "tcp") == 0) { - config.realmtable[0].type = 1; + TYPE_SET_TCP(config.realmtable[0].type); } else if (strcmp(type, "udp") == 0) { - config.realmtable[0].type = 2; + TYPE_SET_UDP(config.realmtable[0].type); } else { - config.realmtable[0].type = 0; + TYPE_SET_ZERO(config.realmtable[0].type); } + config.realmtable[0].type |= mode; } maxfdp1 = manconnecting = 0; @@ -212,7 +264,7 @@ main(int argc, char **argv) config.realmtable[i].users); exit(1); } - if (config.realmtable[i].type == 0) { + if (!TYPE_IS_SET(config.realmtable[i].type)) { printf("Unrecognized type of the realm... exiting\n"); exit(1); } @@ -237,8 +289,8 @@ main(int argc, char **argv) config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), "tcp"); config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); - config.realmtable[i].ssl = SSL_new(ctx); - if (config.realmtable[i].ssl == NULL) { + 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); } @@ -259,7 +311,7 @@ main(int argc, char **argv) if (!verbose) daemon(0, 0); - aflog(1, "Server started"); + aflog(1, "SERVER STARTED realms: %d", config.size); for ( ; ; ) { rset = allset; @@ -272,53 +324,53 @@ main(int argc, char **argv) } } if (select(maxfdp1, &rset, NULL, NULL, (&(config.realmtable[i].tv))) == 0) { - close (config.realmtable[i].commfd); - FD_CLR(config.realmtable[i].commfd, &allset); + close (config.realmtable[i].cliconn.commfd); + FD_CLR(config.realmtable[i].cliconn.commfd, &allset); FD_CLR(config.realmtable[i].listenfd, &allset); FD_SET(config.realmtable[i].managefd, &allset); config.realmtable[i].ready = 0; manconnecting--; - aflog(1, "SSL_accept failed (timeout) in realm[%d]", i); + aflog(1, " realm[%d]: SSL_accept failed (timeout)", i); } } else { select(maxfdp1, &rset, NULL, NULL, NULL); } - aflog(2, "<< >>after select..."); + aflog(2, " >>after select..."); for (j = 0; j < config.size; ++j) { pointer = (&(config.realmtable[j])); for (i = 0; i usernum; ++i) { if (pointer->contable[i].state == S_STATE_OPEN) if (FD_ISSET(pointer->contable[i].connfd, &rset)) { - aflog(2, "FD_ISSET(realm[%d].contable[%d].connfd)", j, i); - if (pointer->type == 1) { /* forwarding tcp packets */ + aflog(2, " 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, "message from realm[%d].con[%d], length=%d", j, i, 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"); + 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 */ - SSL_writen(pointer->ssl, buff, n+5); + send_message(pointer->type, pointer->cliconn, buff, n+5); } else { - aflog(1, "user closed: realm[%d].con[%d]", j, i); + aflog(1, " realm[%d]: user[%d]: CLOSED", j, i); close(pointer->contable[i].connfd); FD_CLR(pointer->contable[i].connfd, &allset); pointer->contable[i].state = S_STATE_CLOSING; buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - SSL_writen(pointer->ssl, buff, 5); + send_message(pointer->type, pointer->cliconn, buff, 5); } } else { /* when forwarding udp packets */ @@ -333,10 +385,10 @@ main(int argc, char **argv) length = length << 8; length += buff[4]; /* this is length of message */ if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { - aflog(2, "message from realm[%d].con[%d], length=%d", j, i, n); + 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 */ - SSL_writen(pointer->ssl, buff, n+5); + send_message(pointer->type, pointer->cliconn, buff, n+5); } } else { @@ -345,14 +397,14 @@ main(int argc, char **argv) } if (n == 0) { - aflog(1, "user closed: realm[%d].con[%d]", j, i); + aflog(1, " realm[%d]: user[%d]: CLOSED", j, i); close(pointer->contable[i].connfd); FD_CLR(pointer->contable[i].connfd, &allset); pointer->contable[i].state = S_STATE_CLOSING; buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - SSL_writen(pointer->ssl, buff, 5); + send_message(pointer->type, pointer->cliconn, buff, 5); } } @@ -360,92 +412,97 @@ main(int argc, char **argv) } if (pointer->ready == 3) if (FD_ISSET(pointer->listenfd, &rset)) { - aflog(2, "FD_ISSET(realm[%d].listenfd)", j); + aflog(2, " realm[%d]: listenfd: FD_ISSET", j); len = pointer->addrlen; if (pointer->ready == 3) { for (i = 0; i < pointer->usernum; ++i) { if (pointer->contable[i].state == S_STATE_CLEAR) { - aflog(2, "realm[%d].contable[%d].connfd = (realm[%d].listenfd)", j, i, j); + aflog(2, " realm[%d]: new user[%d]: CONNECTING", j, i); pointer->contable[i].connfd = accept(pointer->listenfd, pointer->cliaddr, &len); pointer->contable[i].state = S_STATE_OPENING; pointer->usercon++; - aflog(1, "user IP:%s",sock_ntop(pointer->cliaddr, len)); + aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len)); if (pointer->usercon == pointer->usernum) FD_CLR(pointer->listenfd, &allset); buff[0] = AF_S_CONOPEN; /* opening connection */ buff[1] = i >> 8; /* high bits of user number */ buff[2] = i; /* low bits of user number */ - SSL_writen(pointer->ssl, buff, 5); + send_message(pointer->type, pointer->cliconn, buff, 5); break; } } } } if (pointer->ready != 0) - if (FD_ISSET(pointer->commfd, &rset)) { + if (FD_ISSET(pointer->cliconn.commfd, &rset)) { if (pointer->ready == 1) { - if (SSL_set_fd(pointer->ssl, pointer->commfd) != 1) { + if (SSL_set_fd(pointer->cliconn.ssl, pointer->cliconn.commfd) != 1) { aflog(0, "Problem with initializing ssl... exiting"); exit(1); } - aflog(2, "Trying SSL_accept in realm[%d]", j); - if ((n = SSL_accept(pointer->ssl)) != 1) { - flags = SSL_get_error(pointer->ssl, n); + 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); switch (flags) { case SSL_ERROR_NONE : { - aflog(2, "SSL_accept has failed(%d)...none", n); + aflog(2, " SSL_accept has failed(%d)...none", n); break; } case SSL_ERROR_ZERO_RETURN : { - aflog(2, "SSL_accept has failed(%d)...zero", n); + aflog(2, " SSL_accept has failed(%d)...zero", n); break; } case SSL_ERROR_WANT_READ : { - aflog(2, "SSL_accept has failed(%d)...w_read", n); + aflog(2, " SSL_accept has failed(%d)...w_read", n); break; } case SSL_ERROR_WANT_WRITE : { - aflog(2, "SSL_accept has failed(%d)...w_write", n); + aflog(2, " SSL_accept has failed(%d)...w_write", n); break; } case SSL_ERROR_WANT_CONNECT : { - aflog(2, "SSL_accept has failed(%d)...w_connect", n); + aflog(2, " SSL_accept has failed(%d)...w_connect", n); break; } case SSL_ERROR_WANT_X509_LOOKUP : { - aflog(2, "SSL_accept has failed(%d)...w_x509_lookup", n); + aflog(2, " SSL_accept has failed(%d)...w_x509_lookup", n); break; } case SSL_ERROR_SYSCALL : { - aflog(2, "SSL_accept has failed(%d)...syscall", n); + aflog(2, " SSL_accept has failed(%d)...syscall", n); break; } case SSL_ERROR_SSL : { SSL_load_error_strings(); - aflog(2, "SSL_accept has failed(%d)...ssl:%s", + aflog(2, " SSL_accept has failed(%d)...ssl:%s", n, ERR_error_string(ERR_get_error(), (char*) buff)); break; } } if (flags == SSL_ERROR_WANT_READ) continue; - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_SET(pointer->managefd, &allset); - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; manconnecting--; - aflog(1, "SSL_accept failed (denied) in realm[%d]", j); + aflog(1, " realm[%d]: new client: DENIED by SSL_accept", j); } else { - aflog(1, "SSL_accept successfull in realm[%d]", j); + aflog(1, " realm[%d]: new client: ACCEPTED by SSL_accept", j); pointer->ready = 2; } continue; /* in the case this is not our client */ } - aflog(2, "FD_ISSET(realm[%d].commfd)", j); - n = SSL_read(pointer->ssl, buff, 5); + aflog(2, " realm[%d]: commfd: FD_ISSET", j); + if (pointer->ready == 2) { + n = get_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, -5); + } + else { + n = get_message(pointer->type, pointer->cliconn, buff, -5); + } if (n == -1) { if (errno == EAGAIN) { continue; @@ -458,8 +515,8 @@ main(int argc, char **argv) n = 0; } if (n==0) { - close(pointer->commfd); - FD_CLR(pointer->commfd, &allset); + close(pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); maxfdp1 = (maxfdp1 > (pointer->managefd+1)) ? maxfdp1 : (pointer->managefd+1); @@ -473,9 +530,9 @@ main(int argc, char **argv) } } pointer->usercon = 0; - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; - aflog(1, "realm[%d].commfd closed!", j); + aflog(1, " realm[%d]: commfd: CLOSED", j); continue; } numofcon = buff[1]; @@ -499,24 +556,24 @@ main(int argc, char **argv) } else if (pointer->contable[numofcon].state == S_STATE_OPEN) { - aflog(1, "user kicked: realm[%d].con[%d]", j, numofcon); + aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon); close(pointer->contable[numofcon].connfd); FD_CLR(pointer->contable[numofcon].connfd, &allset); pointer->contable[numofcon].state = S_STATE_CLEAR; buff[0] = AF_S_CONCLOSED; /* closing connection */ buff[1] = numofcon >> 8; /* high bits of user number */ buff[2] = numofcon; /* low bits of user number */ - SSL_writen(pointer->ssl, buff, 5); + send_message(pointer->type, pointer->cliconn, buff, 5); } } else { - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); if (pointer->ready == 2) manconnecting--; - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; } break; @@ -527,90 +584,91 @@ main(int argc, char **argv) ((pointer->ready)==3)) { if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(2, "realm[%d].con[%d]->ok",j,numofcon); + aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon); FD_SET(pointer->contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? + maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? maxfdp1 : (pointer->contable[numofcon].connfd+1); pointer->contable[numofcon].state = S_STATE_OPEN; } } else { - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); if (pointer->ready == 2) manconnecting--; - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; } break; } case AF_S_MESSAGE : { if ((pointer->ready) != 3) { - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); manconnecting--; - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; break; } - if (pointer->type==2) { /* udp */ - n = SSL_readn(pointer->ssl, &buff[5], length); + if (TYPE_IS_UDP(pointer->type)) { /* udp */ + n = get_message(pointer->type, pointer->cliconn, &buff[5], length); } else { - n = SSL_readn(pointer->ssl, buff, length); + n = get_message(pointer->type, pointer->cliconn, buff, length); } - if (n != length) { - aflog(2, "n(%d)!=length(%d)", n, length); - break; - } if ((numofcon>=0) && (numofcon<=(pointer->usernum))) { if (pointer->contable[numofcon].state == S_STATE_OPEN) { - aflog(2, "message to realm[%d].con[%d], length=%d",j, numofcon, n); - if (pointer->type==2) { /* udp */ + 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; - writen(pointer->contable[numofcon].connfd, buff, n+5); + writen(pointer->contable[numofcon].connfd, buff, n+5); } else { - writen(pointer->contable[numofcon].connfd, buff, n); + writen(pointer->contable[numofcon].connfd, buff, n); } } } break; } case AF_S_LOGIN : { - if ((pointer->ready == 2)&&(numofcon==259)&&(length==1538)) { + 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 */ - SSL_writen(pointer->ssl, buff, 5); + buff[3] = pointer->type; /* type of connection */ + send_message(pointer->type | TYPE_SSL, pointer->cliconn, buff, 5); FD_SET(pointer->listenfd, &allset); manconnecting--; } else { - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + aflog(1, " realm[%d]: Wrong password - CLOSING", j); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); if (pointer->ready == 2) manconnecting--; - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; } break; } default : { - aflog(1, "Unrecognized message - closing realm[%d]", j); - close (pointer->commfd); - FD_CLR(pointer->commfd, &allset); + aflog(1, " realm[%d]: Unrecognized message - CLOSING", j); + close (pointer->cliconn.commfd); + FD_CLR(pointer->cliconn.commfd, &allset); FD_CLR(pointer->listenfd, &allset); FD_SET(pointer->managefd, &allset); if (pointer->ready == 2) @@ -619,28 +677,28 @@ main(int argc, char **argv) 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, &allset); close(pointer->contable[i].connfd); } } } - SSL_clear(pointer->ssl); + SSL_clear(pointer->cliconn.ssl); pointer->ready = 0; } } } if (FD_ISSET(pointer->managefd, &rset)) { - aflog(2, "FD_ISSET(realm[%d].managefd)", j); + aflog(2, " realm[%d]: managefd: FD_ISSET", j); len = pointer->addrlen; if (!(pointer->ready)) { - aflog(2, "accept(realm[%d].managefd)", j); - pointer->commfd = accept(pointer->managefd, pointer->cliaddr, &len); - flags = fcntl(pointer->commfd, F_GETFL, 0); - fcntl(pointer->commfd, F_SETFL, flags | O_NONBLOCK); - aflog(1, " >> Client IP:%s", sock_ntop(pointer->cliaddr, len)); - FD_SET(pointer->commfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->commfd+1)) ? maxfdp1 : (pointer->commfd+1); + 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)); + 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++; @@ -656,25 +714,44 @@ usage(char* info) { printf("\n%s\n\n", info); printf(" Options:\n"); - printf(" -h - 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 [portnum] - the listening port number - users connect\n"); - printf(" to it (default: 50127)\n"); - printf(" -m [portnum] - the manage port number - second part of active\n"); - printf(" port forwarder connects to it (default: 50126)\n"); - printf(" -u [#users] - amount of users allowed to use this server\n"); - printf(" (default: 5)\n"); - printf(" -c [cerfile] - name of the file with certificate (default: cacert.pem)\n"); - printf(" -k [keyfile] - name of the file with RSA key (default: server.rsa)\n"); - printf(" -f [cfgfile] - name of the file with configuration for active\n"); - printf(" forwarder (server)\n"); - printf(" -t [type] - type of the server (tcp|udp) - for which protocol it\n"); - printf(" would be (default: tcp)\n"); - printf(" -O [logfile] - logging everything to a logfile\n"); - printf(" -o [logfile] - logging some data to a logfile\n"); - printf(" -v - to be verbose - program won't enter into\n"); - printf(" the daemon mode (use twice for greater effect)\n\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 - the listening port number - users connect\n"); + printf(" to it (default: 50127)\n"); + printf(" -m, --manageport - the manage port number - second part of active\n"); + printf(" port forwarder connects to it (default: 50126)\n"); + printf(" -u, --users - amount of users allowed to use this server\n"); + printf(" (default: 5)\n"); + printf(" -c, --cerfile - name of the file with certificate (default: cacert.pem)\n"); + printf(" -k, --keyfile - name of the file with RSA key (default: server.rsa)\n"); + printf(" -f, --cfgfile - name of the file with configuration for active\n"); + printf(" forwarder (server)\n"); + printf(" -p, --proto - type of the server (tcp|udp) - for which protocol it\n"); + printf(" would be (default: tcp)\n"); + 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 into\n"); + printf(" the daemon mode (use twice for greater effect)\n"); + printf(" --nossl - ssl is not used for transfering data (but it's still\n"); + printf(" used to establish 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\n"); exit(0); } +static void +sig_int(int signo) +{ + int 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); + } + aflog(1, "SERVER CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/config b/config index 4a3eb4e..8230abc 100644 --- a/config +++ b/config @@ -27,7 +27,8 @@ hostname #this is a name of the server (it's using it for choosin 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 -type tcp #type of the realm (which protocol it will forward (tcp|udp) +proto tcp #type of the realm (which protocol it will forward (tcp|udp) +#pass mypassword #this is a password used for client identification # and now the second realm @@ -36,4 +37,4 @@ hostname listen 50125 manage 50124 users 5 -type tcp +proto tcp diff --git a/docs/en/README b/docs/en/README new file mode 100644 index 0000000..cbae3d7 --- /dev/null +++ b/docs/en/README @@ -0,0 +1,91 @@ +AF - Active Port Forwarder v0.5.3 - README +Copyright (C) 2003 jeremian - jeremian@poczta.fm +=================== + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +========================== + + 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 + Access Control System) bypassing research field and to the computer and + network security topics. + +================================================================================ + + +Active port forwarder is a software for secure port forwarding. +It uses ssl for increasing security of communication between server and client. + +Af is dedicated for people, who don't have external ip number and want to +make some services available across the net. + +Moreover, zlib is used to compress transfered data. + +EXAMPLE 1: + +The use of it is extremely simple. Let's suppose we want to create http server on +our computer and we are behind masquerade or firewall: + +1) We have to find some machine on the net with external ip and shell account. + +2) Use make to compile everything on that machine. (you can freely remove afclient + and client.rsa files) + +3) You can edit config file or just type from the console: (to use config type -f ) + $ ./afserver + This will work, if you want to use default values: + - hostname will be taken from hostname function (it would be ideally, if 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 + - server will be for maximum 5 users + - server will forward tcp packets + - there will be no logging and no verbose messages + - there will be no password identification + +4) We use make on our machine (we can delete everything apart afclient and client.rsa) + +5) We are typing from the console: + $ ./afclient -n -p 80 + Where is a string like : 'bastion.univ.gda.pl' or '153.19.7.200' + +6) We can now enter with webbrowser to : :50127 and we will enter to our + computer in the fact. + +EXAMPLE 2: + +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: -t udp) + +5) We are typing from the console: + $ ./afclient -u -n -p 27960 + Where is a name (or ip) of a host where our server is running. + +6) Connecting to our game is more complicated. User must use afclient to do this. + He has to specify server he is connecting to and port which his program will be listening on: + $ ./afclient -U -d -p -n -m + Where is name of user machine (who wants to connect to our game). + is a port he will be connecting to. is a name of a host where our server + is running. is a port on which server is listening for users. + In order to connect to our game, user have to connect to :. + + +Active port forwarder is still under development, so please sent me any comments, bugs notices +and suggestions about it to jeremian@poczta.fm + + +And thanks for using this software! + +LICENSE +------- + + Active Port Forwarder is distributed under the terms of the GNU General Public License + v2.0 and is copyright (c) 2003 jeremian . + See the file COPYING for details. + diff --git a/docs/fr/fr_README b/docs/fr/fr_README new file mode 100644 index 0000000..56e87b1 --- /dev/null +++ b/docs/fr/fr_README @@ -0,0 +1,102 @@ +AF - Active Port Forwarder v0.5.2 - fr_README +Copyright (C) 2003 jeremian - jeremian@poczta.fm +================================================ + +================================================================================ + +GRAY-WORLD.NET / Active Port Forwarder +====================================== + + Le programme Active Port Forwarder est partie intégrante des projets + Gray-World.net. + + Notre équipe présente sur le site http://gray-world.net les projets et + publications sur lesquels nous travaillons. Ces projets et publications sont + relatifs au contournement des systèmes de contrôle d'accès réseau (NACS + bypassing) ainsi qu'à la sécurité des systèmes et réseaux. + +================================================================================ + +Active port forwarder est un programme permettant de réaliser du forwarding de +port sécurisé. +Il utilise le protocole SSL pour augmenter le niveau de sécurité des +communications entre serveur et client. + +Af est destiné aux personnes sans adresse IP publique externe qui désirent +offrir des services accessibles depuis le net. + +EXEMPLE 1: + +L'utilisation de Af est extrèmement simple. Supposons que nous voulons mettre en +place un serveur http sur notre station et que nous sommes masqueradés ou placé +derrière un firewall: + +1) Nous devons tout d'abord trouver une station sur internet avec une IP +publique et un shell. + +2) Utilisez ensuite make pour compiler Af sur cette machine. (Vous pouvez par la +suite supprimer les fichiers afclient et client.rsa) + +3) Editez le fichier de configuration ou entrez sur la console: (pour utiliser +la configuration, entrez type -f ) + $ ./afserver + Si vous voulez utiliser les valeurs par défaut: + - Le nom d'hôte sera pris en compte par la fonction hostname (Il serait idéal + qu'il soit référencé dans le fichier /etc/hosts) + - Le serveur sera en écoute pour les utilisateurs sur le port 50127 + - Le serveur sera en écoute pour le client sur le port 50126 + - Le serveur sera limité à 5 utilisateurs + - Le serveur retransmettra les paquets tcp + - Aucun log ou message verbeux ne sera activé + +4) Nous utilisons make sur notre propre station (Nous pouvons ensuite supprimer +tous les fichiers sauf afclient et client.rsa) + +5) Nous entrons sur la console: + $ ./afclient -n -p 80 + Où est une chaîne du type : 'bastion.univ.gda.pl' ou + '153.19.7.200' + +6) Nous pouvons ensuite utiliser notre navigateur web avec : + :50127 et nous atteindrons notre propre station. + +EXEMPLE 2: + +Regardons comment nous pouvons utiliser af pour forwarder des paquets udp. +Supposez que nous voulons mettre en place un serveur de jeu sur notre station +(port udp 27960 sur notre station): + +1) - 4) sont les mêmes que pour l'exemple 1. (mais nous utilisons l'option: +-t udp) + +5) Nous entrons sur la console: + $ ./afclient -u -n -p 27960 + Où est un nom (ou une ip) d'un hôte sur lequel notre + serveur tourne. + +6) Nous connecter à notre jeu est un peu plus compliqué. L'utilisateur doit se + servir de afclient pour cela. + Il doit spécifier le serveur auquel il veut se connecter et le port sur + lequel son programme sera en écoute: + $ ./afclient -U -d -p -n -m\ + + Où est le nom de la station utilisateur (qui veut se connecter à + notre jeu). est le port auquel il se connectera. est le nom de l'hôte sur lequel notre serveur tourne. + est le port sur lequel notre serveur est en écoute pour les utilisateurs. + Pour se connecter à notre jeu, l'utilisateur doit se connecter à : + . + +Active port forwarder est toujours en phase en développement, alors envoyez moi +vos commentaires, les bugs que vous rencontrez et vos suggestions à + + +Et merci pour votre utilisation de ce programme! + +LICENCE +------- + + Active Port Forwarder est distribué sous les termes de la licence GNU - + General Public Licence version 2.0 et est copyright (c) 2003 jeremian + . + Consultez le fichier COPYING pour plus de details. diff --git a/file.c b/file.c index b81e595..fcd41f8 100644 --- a/file.c +++ b/file.c @@ -19,6 +19,7 @@ */ #include "file.h" +#include "activefor.h" #include #include #include @@ -29,7 +30,7 @@ parsefile(char* name, int* status) { static ConfigurationT cfg; FILE* file = NULL; - int state; + int state, i, n; char buff[256]; char helpbuf1[256]; char helpbuf2[256]; @@ -75,6 +76,17 @@ parsefile(char* name, int* status) if (state == 1) { if (strcmp(helpbuf1, "newrealm")==0) { ++cfg.size; + TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type); + TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type); + } + else if (cfg.size == 0) { + return cfg; + } + else if (strcmp(helpbuf1, "nossl")==0) { + TYPE_UNSET_SSL(cfg.realmtable[cfg.size-1].type); + } + else if (strcmp(helpbuf1, "nozlib")==0) { + TYPE_UNSET_ZLIB(cfg.realmtable[cfg.size-1].type); } else { return cfg; @@ -120,6 +132,12 @@ parsefile(char* name, int* status) sizeof(char)); strcpy(cfg.realmtable[cfg.size-1].lisportnum, helpbuf2); } + else if (strcmp(helpbuf1, "pass")==0) { + n = strlen(helpbuf2); + for (i = 0; i < n; ++i) { + cfg.realmtable[cfg.size-1].pass[i%4] += helpbuf2[i]; + } + } else if (strcmp(helpbuf1, "manage")==0) { cfg.realmtable[cfg.size-1].manportnum = calloc(strlen(helpbuf2)+1, sizeof(char)); @@ -130,15 +148,15 @@ parsefile(char* name, int* status) sizeof(char)); strcpy(cfg.realmtable[cfg.size-1].users, helpbuf2); } - else if (strcmp(helpbuf1, "type")==0) { - if (cfg.realmtable[cfg.size-1].type != 0) { + else if (strcmp(helpbuf1, "proto")==0) { + if (TYPE_IS_SET(cfg.realmtable[cfg.size-1].type)) { return cfg; } if (strcmp(helpbuf2, "tcp")==0) { - cfg.realmtable[cfg.size-1].type = 1; + TYPE_SET_TCP(cfg.realmtable[cfg.size-1].type); } else if (strcmp(helpbuf2, "udp")==0) { - cfg.realmtable[cfg.size-1].type = 2; + TYPE_SET_UDP(cfg.realmtable[cfg.size-1].type); } else { return cfg; diff --git a/file.h b/file.h index 0a27894..041f3b0 100644 --- a/file.h +++ b/file.h @@ -36,17 +36,17 @@ typedef struct { char* lisportnum; char* manportnum; char* users; + unsigned char pass[4]; int usercon; int usernum; int listenfd; int managefd; - int commfd; char ready; char type; socklen_t addrlen; struct sockaddr* cliaddr; struct timeval tv; - SSL* ssl; + clifd cliconn; ConnectuserT* contable; } RealmT; diff --git a/network.c b/network.c index 59e14a9..2c7862b 100644 --- a/network.c +++ b/network.c @@ -19,9 +19,12 @@ */ #include "network.h" +#include "activefor.h" +#include "stats.h" #include #include #include +#include static void sig_alrm(int signo) @@ -255,3 +258,93 @@ readn(int fd, unsigned char* buf, int amount) return amount; } + +int +send_message(char type, clifd fd, unsigned char* buf, int amount) +{ + unsigned long clen; + int length; + static unsigned char bufor[9000]; + clen = 8995; + length = amount - 5; + if (TYPE_IS_ZLIB(type)) { + memcpy(bufor, buf, 5); + if (amount > 5) { + compress(&bufor[5], &clen, &buf[5], length); + if (clen < length) { + length = clen; + TYPE_SET_COMP(length); + bufor[3] = length >> 8; /* high bits of message length */ + bufor[4] = length; /* low bits of message length */ + addtocg(amount-5 - clen); + } + } + if (TYPE_IS_SSL(type)) { + if (TYPE_IS_COMP(length)) { + return SSL_writen(fd.ssl, bufor, clen+5); + } + else { + return SSL_writen(fd.ssl, buf, amount); + } + } + else { + if (TYPE_IS_COMP(length)) { + return writen(fd.commfd, bufor, clen+5); + } + else { + return writen(fd.commfd, buf, amount); + } + } + } + else { + if (TYPE_IS_SSL(type)) { + return SSL_writen(fd.ssl, buf, amount); + } + else { + return writen(fd.commfd, buf, amount); + } + } +} + +int +get_message(char type, clifd fd, unsigned char* buf, int amount) +{ + int length; + unsigned long elen; + static unsigned char bufor[9000]; + if (amount == -5) { + if (TYPE_IS_SSL(type)) { + return SSL_read(fd.ssl, buf, 5); + } + else { + return read(fd.commfd, buf, 5); + } + } + if (TYPE_IS_ZLIB(type)) { + if (TYPE_IS_SSL(type)) { + length = SSL_readn(fd.ssl, bufor, amount&0xBFFF); + } + else { + length = readn(fd.commfd, bufor, amount&0xBFFF); + } + if (length <= 0) return length; + elen = 8096; + if (TYPE_IS_COMP(amount)) { + uncompress(buf, &elen, bufor, length); + } + else { + memcpy(buf, bufor, length); + elen = length; + } + return elen; + } + else + { + if (TYPE_IS_SSL(type)) { + return SSL_readn(fd.ssl, buf, amount); + } + else { + return readn(fd.commfd, buf, amount); + } + } +} diff --git a/network.h b/network.h index c4d168c..930a842 100644 --- a/network.h +++ b/network.h @@ -34,9 +34,18 @@ #include #include +typedef struct { + int commfd; + SSL* ssl; +} clifd; + int ip_listen(const char *host, const char *serv, socklen_t *addrlenp, const char *type); /* socket, bind, listen... */ int ip_connect(const char *host, const char *serv, const char *type); /* socket, connect... */ char* sock_ntop(const struct sockaddr* sa, socklen_t salen); /* return the hostname of connected user */ + +int send_message(char type, clifd fd, unsigned char* buf, int amount); +int get_message(char type, clifd fd, unsigned char* buf, int amount); + int SSL_writen(SSL* fd, unsigned char* buf, int amount); int SSL_readn(SSL* fd, unsigned char* buf, int amount); int writen(int fd, unsigned char* buf, int amount); diff --git a/stats.c b/stats.c index 3eca5b9..48697cb 100644 --- a/stats.c +++ b/stats.c @@ -27,6 +27,7 @@ static char verlev; static char loglev; static FILE* logfd; +static signed long compressgained; char* datum(void) @@ -77,3 +78,21 @@ aflog(char type, const char* format, ...) } va_end(ap); } + +void +addtocg(int amount) +{ + compressgained += amount; +} + +signed long +getcg(void) +{ + return compressgained; +} + +void +resetcg(void) +{ + compressgained = 0; +} diff --git a/stats.h b/stats.h index 117899f..695b5f4 100644 --- a/stats.h +++ b/stats.h @@ -23,6 +23,9 @@ int loginit(char verlev, char loglev, const char* logfname); /* initializes logging routine */ void aflog(char type, const char* format, ...); /* log to a file or|and screen */ +void addtocg(int amount); /* add amount to compressgained value */ +void resetcg(void); /* reset the compressgained value */ +signed long getcg(void); /* returns the compressgained value */ #endif -- cgit v1.1