summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am7
-rw-r--r--src/activefor.h162
-rw-r--r--src/afclient.c1000
-rw-r--r--src/afclient.h50
-rw-r--r--src/afserver.c1720
-rw-r--r--src/afserver.h51
-rw-r--r--src/buflist.c70
-rw-r--r--src/buflist.h35
-rw-r--r--src/clientnames.c129
-rw-r--r--src/clientnames.h35
-rw-r--r--src/file.c373
-rw-r--r--src/file.h37
-rw-r--r--src/first_run.c156
-rw-r--r--src/first_run.h29
-rw-r--r--src/inet_ntop.c227
-rw-r--r--src/inet_ntop.h36
-rw-r--r--src/make_ssl_handshake.c103
-rw-r--r--src/make_ssl_handshake.h31
-rw-r--r--src/modules.c69
-rw-r--r--src/modules.h43
-rw-r--r--src/network.c484
-rw-r--r--src/network.h54
-rw-r--r--src/realmnames.c62
-rw-r--r--src/realmnames.h30
-rw-r--r--src/remoteadmin.c503
-rw-r--r--src/remoteadmin.h49
-rw-r--r--src/server_check.c61
-rw-r--r--src/server_check.h28
-rw-r--r--src/server_eval.c44
-rw-r--r--src/server_eval.h31
-rw-r--r--src/server_find.c56
-rw-r--r--src/server_find.h31
-rw-r--r--src/server_remove.c84
-rw-r--r--src/server_remove.h30
-rw-r--r--src/server_set.c34
-rw-r--r--src/server_set.h27
-rw-r--r--src/stats.c127
-rw-r--r--src/stats.h36
-rw-r--r--src/usernames.c41
-rw-r--r--src/usernames.h30
40 files changed, 6205 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..a6ccd11
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,7 @@
+bin_PROGRAMS = afserver afclient
+afserver_SOURCES = afserver.c network.c file.c stats.c buflist.c remoteadmin.c \
+ server_check.c server_set.c server_eval.c server_find.c server_remove.c \
+ make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c
+afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB}
+afclient_SOURCES = afclient.c network.c stats.c buflist.c modules.c remoteadmin.c \
+ make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c clientnames.c usernames.c
diff --git a/src/activefor.h b/src/activefor.h
new file mode 100644
index 0000000..8d07c8b
--- /dev/null
+++ b/src/activefor.h
@@ -0,0 +1,162 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_ACTIVEFOR_H
+#define _JS_ACTIVEFOR_H
+
+#include "network.h"
+#include "buflist.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 AF_S_DONT_SEND 9
+#define AF_S_CAN_SEND 10
+#define AF_S_CANT_OPEN 12
+
+#define AF_S_WRONG 13
+#define AF_S_ADMIN_LOGIN 14
+#define AF_S_ADMIN_CMD 15
+
+#define S_STATE_CLEAR 0
+#define S_STATE_CLOSING 5
+#define S_STATE_OPENING 6
+#define S_STATE_OPEN 7
+#define S_STATE_STOPPED 11
+
+#define AF_VER(info) info" v0.6"
+
+#define TYPE_TCP 1
+#define TYPE_UDP 3
+#define TYPE_SSL 4
+#define TYPE_ZLIB 8
+#define TYPE_IPV4 16
+#define TYPE_IPV6 32
+#define TYPE_COMP 0x4000
+
+#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_IPV4(type) (type|=TYPE_IPV4)
+#define TYPE_UNSET_IPV4(type) (type&=(~TYPE_IPV4))
+#define TYPE_IS_IPV4(type) (type&TYPE_IPV4)
+#define TYPE_SET_IPV6(type) (type|=TYPE_IPV6)
+#define TYPE_UNSET_IPV6(type) (type&=(~TYPE_IPV6))
+#define TYPE_IS_IPV6(type) (type&TYPE_IPV6)
+#define TYPE_SET_UNSPEC(type) (type&=(~(TYPE_IPV4|TYPE_IPV6)))
+#define TYPE_IS_UNSPEC(type) (!(type&(TYPE_IPV4|TYPE_IPV6)))
+
+#define TYPE_SET_COMP(type) (type|=TYPE_COMP)
+#define TYPE_IS_COMP(type) (type&TYPE_COMP)
+
+typedef struct {
+ char* lisportnum;
+ char* manportnum;
+ int listenfd;
+ int managefd;
+} UsrCliT;
+
+typedef struct {
+ char state;
+ int connfd;
+ int whatcli;
+ int userid;
+ time_t connecttime;
+ char namebuf[128];
+ char portbuf[7];
+ blnodeT* head;
+} ConnectuserT;
+
+typedef struct {
+ char ready;
+ clifd cliconn;
+ struct timeval tv;
+ int* users;
+ int usercon;
+ int usernum;
+ int listenfd;
+ int whatusrcli;
+ int clientnum;
+ time_t connecttime;
+ char* clientid;
+ char namebuf[128];
+ char portbuf[7];
+} ConnectclientT;
+
+typedef struct {
+ char* hostname;
+ char* users;
+ char* clients;
+ char* raclients;
+ char* usrpcli;
+ char* clim;
+ char* timeout;
+ char* realmname;
+ unsigned char pass[4];
+ int usercon;
+ int usernum;
+ int clicon;
+ int clinum;
+ int raclicon;
+ int raclinum;
+ int upcnum;
+ int tmout;
+ int climode;
+ int usrclinum;
+ int clientcounter;
+ int usercounter;
+ char type;
+ char dnslookups;
+ char baseport;
+ socklen_t addrlen;
+ struct sockaddr* cliaddr;
+ ConnectuserT* contable;
+ ConnectclientT* clitable;
+ ConnectclientT* raclitable;
+ UsrCliT* usrclitable;
+} RealmT;
+
+typedef struct {
+ char* certif;
+ char* keys;
+ char* logfnam;
+ char* logsport;
+ char* dateformat;
+ char logging;
+ char socklogging;
+ int size;
+ time_t starttime;
+ RealmT* realmtable;
+} ConfigurationT;
+
+#endif
+
diff --git a/src/afclient.c b/src/afclient.c
new file mode 100644
index 0000000..cc3c0c8
--- /dev/null
+++ b/src/afclient.c
@@ -0,0 +1,1000 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#include "afclient.h"
+
+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'},
+ {"heavysocklog", 1, 0, 'S'},
+ {"lightsocklog", 1, 0, 's'},
+ {"pass", 1, 0, 301},
+#ifdef AF_INET6
+ {"ipv4", 0, 0, '4'},
+ {"ipv6", 0, 0, '6'},
+#endif
+#ifdef HAVE_LIBDL
+ {"load", 1, 0, 'l'},
+ {"Load", 1, 0, 'L'},
+#endif
+ {"id", 1, 0, 'i'},
+ {"dateformat", 1, 0, 'D'},
+ {"remoteadmin", 0, 0, 'r'},
+ {0, 0, 0, 0}
+};
+
+int
+main(int argc, char **argv)
+{
+ int i, n, numofcon, length, buflength, notsent, temp2;
+ ConnectuserT* contable = NULL;
+ clifd master;
+ unsigned char buff[9000];
+ char hostname[100];
+ int maxfdp1, usernum, usercon;
+ socklen_t len, addrlen;
+ struct sockaddr* cliaddr;
+ fd_set rset, allset, wset, tmpset;
+ char verbose = 0;
+ char remote = 0;
+ char logging = 0;
+ char socklogging = 0;
+ char* name = NULL;
+ char* id = NULL;
+ char* manage = NULL;
+ char* desnam = NULL;
+ char* despor = NULL;
+ char* keys = NULL;
+ char* logfname = NULL;
+ char* logsport = NULL;
+ char* dateformat = NULL;
+ char ipfam = 0;
+ unsigned char pass[4] = {1, 2, 3, 4};
+ char udp = 0;
+ char reverse = 0;
+ char type = 0;
+ struct sigaction act;
+#ifdef HAVE_LIBDL
+ moduleT module = {0, NULL, NULL, NULL, NULL}, secmodule = {0, NULL, NULL, NULL, NULL};
+#endif
+
+ SSL_METHOD* method;
+ SSL_CTX* ctx;
+
+ sigfillset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, NULL);
+
+#ifdef AF_INET6
+# ifdef HAVE_LIBDL
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46l:L:i:D:S:s:r", long_options, 0)) != -1) {
+# else
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:46i:D:S:s:r", long_options, 0)) != -1) {
+# endif
+#else
+# ifdef HAVE_LIBDL
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:l:L:i:D:S:s:r", long_options, 0)) != -1) {
+# else
+ while ((n = getopt_long(argc, argv, "huUn:m:d:p:vk:O:o:i:D:S:s:r", long_options, 0)) != -1) {
+# endif
+#endif
+ switch (n) {
+ case 'h': {
+ usage(AF_VER("Active port forwarder (client)"));
+ break;
+ }
+ case 'n': {
+ name = optarg;
+ break;
+ }
+ case 'i': {
+ id = optarg;
+ break;
+ }
+ case 'm': {
+ manage = optarg;
+ break;
+ }
+ case 'd': {
+ desnam = optarg;
+ break;
+ }
+ case 'p': {
+ despor = optarg;
+ break;
+ }
+ case 'v': {
+ ++verbose;
+ break;
+ }
+ case 'u': {
+ udp = 1;
+ break;
+ }
+ case 'U': {
+ reverse = 1;
+ break;
+ }
+ case 'k': {
+ keys = optarg;
+ break;
+ }
+ case 'O': {
+ logfname = optarg;
+ logging = 3;
+ break;
+ }
+ case 'o': {
+ logfname = optarg;
+ logging = 1;
+ break;
+ }
+ case 'S': {
+ logsport = optarg;
+ socklogging = 3;
+ break;
+ }
+ case 's': {
+ logsport = optarg;
+ socklogging = 1;
+ break;
+ }
+ case 301: {
+ n = strlen(optarg);
+ memset(pass, 0, 4);
+ for (i = 0; i < n; ++i) {
+ pass[i%4] += optarg[i];
+ }
+ break;
+ }
+#ifdef AF_INET6
+ case '4': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 4;
+ }
+ break;
+ }
+ case '6': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 6;
+ }
+ break;
+ }
+#endif
+#ifdef HAVE_LIBDL
+ case 'l': {
+ module.name = optarg;
+ break;
+ }
+ case 'L': {
+ secmodule.name = optarg;
+ break;
+ }
+#endif
+ case 'D': {
+ dateformat = optarg;
+ break;
+ }
+ case 'r': {
+ remote = 1;
+ break;
+ }
+ case '?': {
+ usage("");
+ break;
+ }
+ }
+ }
+
+ if (optind < argc) {
+ usage("Unrecognized non-option elements");
+ }
+
+ if (name == NULL) {
+ usage("Name of the server is required");
+ }
+ if (manage == NULL) {
+ manage = "50126";
+ if (reverse)
+ usage("Port on the server is required in reverse mode");
+ }
+ if (keys == NULL) {
+ keys = "client.rsa";
+ }
+ if ((reverse == 0) && (remote == 0) && (desnam == NULL)) {
+ gethostname(hostname, 100);
+ desnam = hostname;
+ }
+ if ((!remote) && (despor == NULL)) {
+ usage("Destination port number is required");
+ }
+
+ if ((temp2 = loginit(verbose, logging, socklogging, logfname, logsport, dateformat))) {
+ switch (temp2) {
+ case 1:
+ printf("Can't open file to log to... exiting\n");
+ break;
+ case 2:
+ printf("Can't connect to localhost:%s... exiting\n", logsport);
+ break;
+ case 3:
+ printf("Can't open socket to log to... exiting\n");
+ break;
+ }
+ exit(1);
+ }
+
+#ifdef HAVE_LIBDL
+ if (loadmodule(&module)) {
+ aflog(0, "Loading a module %s failed!", module.name);
+ exit(1);
+ }
+ if (loadmodule(&secmodule)) {
+ aflog(0, "Loading a module %s failed!", secmodule.name);
+ exit(1);
+ }
+#endif
+
+ TYPE_SET_SSL(type);
+ TYPE_SET_ZLIB(type);
+
+#ifdef AF_INET6
+ if (ipfam == -1) {
+ aflog(0, "Conflicting types of ip protocol family... exiting");
+ exit(1);
+ }
+ else if (ipfam == 4) {
+ TYPE_SET_IPV4(type);
+ }
+ else if (ipfam == 6) {
+ TYPE_SET_IPV6(type);
+ }
+#endif
+ ipfam = 0x01;
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+#endif
+
+ if (!reverse) {
+ SSL_library_init();
+ method = SSLv3_client_method();
+ ctx = SSL_CTX_new(method);
+ if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
+ aflog(0, "Setting cipher list failed... exiting");
+ exit(1);
+ }
+ if ((temp2 = create_apf_dir())) {
+ aflog(1, "Warning: Creating ~/.apf directory failed (%d)", temp2);
+ }
+ if ((temp2 = generate_rsa_key(&keys))) {
+ aflog(1, "Warning: Something bad happened when generating rsa keys... (%d)", temp2);
+ }
+ if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) {
+ aflog(0, "Setting rsa key failed (%s)... exiting", keys);
+ exit(1);
+ }
+
+ if (remote) {
+ temp2 = -1;
+ if (despor) {
+ if (ip_listen(&n, desnam, despor, &addrlen, ipfam)) {
+#ifdef AF_INET6
+ aflog(0, "tcp_listen_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor);
+#else
+ aflog(0, "tcp_listen error for %s, %s", desnam, despor);
+#endif
+ exit(1);
+ }
+ if (!verbose)
+ daemon(0, 0);
+ cliaddr = malloc(addrlen);
+ temp2 = accept(n, cliaddr, &addrlen);
+ }
+ }
+
+ if (ip_connect(&(master.commfd), name, manage, ipfam)) {
+#ifdef AF_INET6
+ aflog(0, "tcp_connect_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage);
+#else
+ aflog(0, "tcp_connect error for %s, %s", name, manage);
+#endif
+ exit(1);
+ }
+ master.ssl = SSL_new(ctx);
+ if (SSL_set_fd(master.ssl, master.commfd) != 1) {
+ aflog(0, "Problem with initializing ssl... exiting");
+ exit(1);
+ }
+
+ aflog(1, "Trying SSL_connect");
+ if ((n = SSL_connect(master.ssl)) == 1) {
+ aflog(1, "SSL_connect successfull");
+ }
+ else {
+ aflog(0, "SSL_connect has failed (%d)... exiting", n);
+ exit(1);
+ }
+
+ buff[0] = AF_S_LOGIN;
+ buff[1] = pass[0];
+ buff[2] = pass[1];
+ buff[3] = pass[2];
+ buff[4] = pass[3];
+
+ if (remote) {
+ return client_admin(type, master, buff, temp2, id);
+ }
+
+ send_message(type, master, buff, 5);
+ buff[0] = 0;
+ get_message(type, master, buff, -5);
+
+ if ( buff[0] == 0 ) {
+ aflog(0, "Wrong password");
+ exit(1);
+ }
+ if ( buff[0] == AF_S_CANT_OPEN ) {
+ aflog(0, "Server is full");
+ exit(1);
+ }
+ if ( buff[0] != AF_S_LOGIN ) {
+ aflog(0, "Incompatible server type or server full");
+ exit(1);
+ }
+
+ type = buff[3];
+ usernum = buff[1];
+ usernum = usernum << 8;
+ usernum += buff[2];
+ } /* !reverse */
+ else {
+ usernum = 1;
+ if (ip_connect(&(master.commfd), name, manage, ipfam)) {
+#ifdef AF_INET6
+ aflog(0, "tcp_connect_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", name, manage);
+#else
+ aflog(0, "tcp_connect error for %s, %s", name, manage);
+#endif
+ exit(1);
+ }
+ master.ssl = NULL;
+ }
+
+ contable = calloc( usernum, sizeof(ConnectuserT));
+ if (contable == NULL) {
+ aflog(0, "Calloc error - unable to succesfully communicate with server");
+ exit(1);
+ }
+
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) {
+ aflog(0, "Can't get socket send buffer size - exiting...");
+ exit(1);
+ }
+
+ if (!verbose)
+ daemon(0, 0);
+
+ FD_ZERO(&allset);
+ FD_ZERO(&wset);
+
+ FD_SET(master.commfd, &allset);
+ maxfdp1 = master.commfd + 1;
+
+ /* UDP REVERSE MODE */
+
+ if (reverse) {
+ ipfam = 0;
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+#endif
+ if (ip_listen(&(contable[0].connfd), desnam, despor, &addrlen, ipfam)) {
+#ifdef AF_INET6
+ aflog(0, "udp_listen_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", desnam, despor);
+#else
+ aflog(0, "udp_listen error for %s, %s", desnam, despor);
+#endif
+ exit(1);
+ }
+ cliaddr = malloc(addrlen);
+ maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1;
+ FD_SET(contable[0].connfd, &allset);
+ aflog(1, "CLIENT STARTED mode: udp reverse");
+ for ( ; ; ) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ len = addrlen;
+ rset = allset;
+ aflog(3, ">select");
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+ aflog(3, " >>after select...");
+
+ if (FD_ISSET(contable[0].connfd, &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/
+ n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len);
+#ifdef HAVE_LINUX_SOCKIOS_H
+# ifdef SIOCOUTQ
+ if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (buflength <= notsent + n + 5) { /* when we can't do this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength);
+# else
+ if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (notsent <= n + 5) { /* when we can't do this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength);
+# endif
+ }
+ else {
+#endif
+ if (n > 0) {
+#ifdef HAVE_LINUX_SOCKIOS_H
+ aflog(2, "Sending %d bytes to service (w:%d/%d) (FROM:%s)", n,
+# ifdef SIOCOUTQ
+ notsent
+# else
+ buflength - notsent
+# endif
+ , buflength, sock_ntop(cliaddr, len, NULL, NULL, 0));
+#else
+ aflog(2, "Sending %d bytes to service (FROM:%s)", n, sock_ntop(cliaddr, len, NULL, NULL, 0));
+#endif
+ buff[0] = AF_S_MESSAGE;
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8;
+ buff[4] = n;
+ writen(master.commfd, buff, n + 5);
+ }
+#ifdef HAVE_LINUX_SOCKIOS_H
+ }
+#endif
+ } /* - FD_ISSET CONTABLE[0].CONNFD RSET */
+
+ if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */
+ n = readn(master.commfd, buff, 5);
+ if (n == 5) {
+ if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) {
+ aflog(0, "Incompatible server type (not udp?) or data corruption -> exiting...");
+ exit(1);
+ }
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+ n = readn(master.commfd, buff, length);
+ }
+ else {
+ n = 0;
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ aflog(0, "premature quit of the server -> exiting...");
+ exit(1);
+ }
+ aflog(2, "Sending %d bytes to user (TO:%s)", n, sock_ntop(cliaddr, addrlen, NULL, NULL, 0));
+ sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen);
+ } /* - FD_ISSET MASTER.COMMFD RSET */
+ }
+ exit(0); /* we shouldn't get here */
+ }
+
+ /* NORMAL MODE */
+
+ aflog(1, "CLIENT STARTED mode: %s", (udp)?"udp":"tcp");
+ aflog(1, "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(type))?"yes":"no",
+ (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));
+#ifdef HAVE_LIBDL
+ 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());
+ }
+#endif
+ if (id != NULL) {
+ buff[0] = AF_S_LOGIN;
+ buff[1] = buff[2] = 0;
+ n = strlen(id);
+ memcpy(&buff[5], id, n);
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(type, master, buff, n+5);
+ aflog(1, "ID SENT: %s", id);
+ }
+
+ for ( ; ; ) {
+ rset = allset;
+ tmpset = wset;
+ aflog(3, ">select");
+ select(maxfdp1, &rset, &tmpset, NULL, NULL);
+ aflog(3, " >>after select...");
+
+ for (i = 0; i < usernum; ++i) {
+ if ((contable[i].state == S_STATE_OPEN)||(contable[i].state == S_STATE_STOPPED)) {
+ if (FD_ISSET(contable[i].connfd, &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */
+ aflog(3, " user[%d]: FD_ISSET", i);
+ n = read(contable[i].connfd, &buff[5], 8091);
+ if (n == -1) {
+ aflog(0, " error (%d): while reading from service", n);
+ n = 0;
+ }
+#ifdef HAVE_LINUX_SOCKIOS_H
+# ifdef SIOCOUTQ
+ if (ioctl(master.commfd, SIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ if (buflength <= notsent + n + 5) { /* when we can't send this */
+ aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, notsent, buflength);
+# else
+ if (ioctl(master.commfd, TIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffer size changed...");
+ }
+ }
+ if (notsent <= n + 5) { /* when we can't send this */
+ aflog(2, " user[%d]: DROP size:%d, buf:%d, w:%d/%d",
+ i, n+5, buflength, buflength-notsent, buflength);
+# endif
+ continue; /* drop this packet */
+ }
+ }
+#endif
+ if (n) {
+#ifdef HAVE_LIBDL
+ 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;
+ }
+ }
+ }
+#endif
+ 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 */
+#ifdef HAVE_LINUX_SOCKIOS_H
+ aflog(2, " user[%d]: TO msglen: %d [%d/%d]", i, n,
+# ifdef SIOCOUTQ
+ notsent
+# else
+ buflength - notsent
+# endif
+ , buflength);
+#else
+ aflog(2, " user[%d]: TO msglen: %d", i, n);
+#endif
+ send_message(type, master, buff, n+5);
+ }
+ else if (!udp) {
+ aflog(2, " user[%d]: CLOSING", i);
+ close(contable[i].connfd);
+ FD_CLR(contable[i].connfd, &allset);
+ FD_CLR(contable[i].connfd, &wset);
+ contable[i].state = S_STATE_CLOSING;
+ freebuflist(&contable[i].head);
+ 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);
+ }
+ } /* - FD_ISSET CONTABLE[i].CONNFD RSET */
+ }
+ }
+ for (i = 0; i < usernum; ++i) {
+ if (contable[i].state == S_STATE_STOPPED) {
+ if (FD_ISSET(contable[i].connfd, &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */
+ aflog(3, " user[%d]: FD_ISSET - WRITE", i);
+ n = contable[i].head->msglen - contable[i].head->actptr;
+ temp2 = write(contable[i].connfd, &(contable[i].head->buff[contable[i].head->actptr]), n);
+ if ((temp2 > 0) && (temp2 != n)) {
+ contable[i].head->actptr+=temp2;
+ }
+ else if ((temp2 == -1) && (errno == EAGAIN)) {
+ aflog(3, " user[%d]: Couldn't write?", i);
+ }
+ else if (temp2 == -1) {
+ close(contable[i].connfd);
+ FD_CLR(contable[i].connfd, &allset);
+ FD_CLR(contable[i].connfd, &wset);
+ contable[i].state = S_STATE_CLOSING;
+ 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);
+ }
+ else {
+ deleteblnode(&contable[i].head);
+ if (contable[i].head == NULL) {
+ contable[i].state = S_STATE_OPEN;
+ FD_CLR(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, " FROM user[%d]: BUFFERING MESSAGE ENDED", i);
+ send_message(type, master, buff, 5);
+ }
+ }
+ } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */
+ }
+ }
+ if (FD_ISSET(master.commfd, &rset)) { /* FD_ISSET MASTER.COMMFD RSET */
+ aflog(3, " masterfd: FD_ISSET");
+ n = get_message(type, master, buff, 5);
+ if (n != 5) {
+ aflog(2, " FATAL ERROR! (%d)", n);
+ if (n == -1) {
+ if (TYPE_IS_SSL(type)) {
+ get_ssl_error(&master, "FE", n);
+ continue; /* what happened? */
+ }
+ }
+ if (n != 0)
+ exit(1);
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ aflog(0, " SERVER: premature quit -> exiting...");
+ exit(1);
+ }
+ 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 : {
+ aflog(4, " user[%d]: AF_S_CONCLOSED", numofcon);
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ usercon--;
+ if (contable[numofcon].state == S_STATE_CLOSING) {
+ contable[numofcon].state = S_STATE_CLEAR;
+ aflog(1, " user[%d]: CLOSED", numofcon);
+ }
+ else if ((contable[numofcon].state==S_STATE_OPEN) || (contable[numofcon].state==S_STATE_STOPPED)){
+ aflog(1, " user[%d]: CLOSED", numofcon);
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ FD_CLR(contable[numofcon].connfd, &wset);
+ contable[numofcon].state = S_STATE_CLEAR;
+ freebuflist(&contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ }
+ }
+ break;
+ }
+ case AF_S_CONOPEN : {
+ aflog(4, " user[%d]: AF_S_CONOPEN", numofcon);
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ usercon++;
+ if (contable[numofcon].state == S_STATE_CLEAR) {
+ n = get_message(type, master, buff, length);
+ memcpy(contable[numofcon].namebuf, buff, 128);
+ memcpy(contable[numofcon].portbuf,&buff[128],7);
+ aflog(2, " user[%d]: OPENING", numofcon);
+ aflog(1, "user[%d]: IP:%s PORT:%s", numofcon,
+ contable[numofcon].namebuf, contable[numofcon].portbuf);
+#ifdef HAVE_LIBDL
+ if (ismloaded(&module) && module.allow(contable[numofcon].namebuf, contable[numofcon].portbuf)) {
+ aflog(2, " IT'S NOT ALLOWED - DROPPING", numofcon);
+ buff[0] = AF_S_CANT_OPEN; /* not opening connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ usercon--;
+ continue;
+ }
+#endif
+ if (udp) {
+ ipfam = 0;
+ }
+ else {
+ ipfam = 0x01;
+ }
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(type)) {
+ ipfam |= 0x04;
+ }
+#endif
+ if (ip_connect(&(contable[numofcon].connfd), desnam, despor, ipfam)) {
+ aflog(2, " CAN'T OPEN - DROPPING", numofcon);
+ buff[0] = AF_S_CANT_OPEN; /* not opening connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ usercon--;
+ continue;
+ }
+ temp2 = fcntl(contable[numofcon].connfd, F_GETFL, 0);
+ fcntl(contable[numofcon].connfd, F_SETFL, temp2 | O_NONBLOCK);
+ FD_SET(contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ contable[numofcon].state = S_STATE_OPEN;
+ }
+ }
+ break;
+ }
+ case AF_S_MESSAGE : {
+ aflog(4, " user[%d]: AF_S_MESSAGE", numofcon);
+ 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) {
+#ifdef HAVE_LIBDL
+ 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 5:{
+ aflog(2, " user[%d]: DROPPED BY MODULE", numofcon);
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ FD_CLR(contable[numofcon].connfd, &wset);
+ contable[numofcon].state = S_STATE_CLOSING;
+ freebuflist(&contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ 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;
+ }
+ }
+ }
+#endif
+ aflog(2, " user[%d]: FROM msglen: %d SENT", numofcon, n);
+ temp2 = write(contable[numofcon].connfd, buff, n);
+ if ((temp2 > 0) && (temp2 != n)) {
+ insertblnode(&(contable[numofcon].head), temp2, n, buff);
+ contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(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, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon);
+ send_message(type, master, buff, 5);
+ }
+ else if ((temp2 == -1) && (errno == EAGAIN)) {
+ insertblnode(&(contable[numofcon].head), 0, n, buff);
+ contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon);
+ send_message(type, master, buff, 5);
+ }
+ else if (temp2 == -1) {
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ FD_CLR(contable[numofcon].connfd, &wset);
+ contable[numofcon].state = S_STATE_CLOSING;
+ freebuflist(&contable[numofcon].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ send_message(type, master, buff, 5);
+ }
+ }
+ else if (contable[numofcon].state == S_STATE_STOPPED) {
+ aflog(3, " FROM user[%d]: BUFFERING MESSAGE", numofcon);
+ insertblnode(&(contable[numofcon].head), 0, n, buff);
+ }
+ }
+ break;
+ }
+ case AF_S_CLOSING : { /* server shut down -> exiting... */
+ aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg());
+ exit(1);
+ break;
+ }
+ case AF_S_DONT_SEND: {
+ aflog(4, " user[%d]: AF_S_DONT_SEND", numofcon);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ break;
+ }
+ case AF_S_CAN_SEND: {
+ aflog(4, " user[%d]: AF_S_CAN_SEND", numofcon);
+ FD_SET(contable[numofcon].connfd, &allset);
+ break;
+ }
+ default : { /* unrecognized type of message -> exiting... */
+ aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg());
+ exit(1);
+ break;
+ }
+ }
+ } /* - FD_ISSET MASTER.COMMFD RSET */
+ }
+}
+
+static void
+usage(char* info)
+{
+ printf("\n%s\n\n\n", info);
+ printf(" Basic options:\n\n");
+ printf(" -n, --servername - where the second part of the active\n");
+ printf(" port forwarder is running (required)\n");
+ printf(" -m, --manageport - manage port number - server must be\n");
+ printf(" listening on it (default: 50126)\n");
+ printf(" -d, --hostname - the name of this host/remote host - the final\n");
+ printf(" destination of the packets (default: the name\n");
+ printf(" returned by hostname function)\n");
+ printf(" -p, --portnum - the port we are forwarding connection to (required)\n");
+ printf(" -h, --help - prints this help\n\n");
+ printf(" Authorization:\n\n");
+ printf(" -i, --id - sends the id string to afserver\n");
+ printf(" --pass - set the password used for client identification\n");
+ printf(" (default: no password)\n\n");
+ printf(" Configuration:\n\n");
+ printf(" -k, --keyfile - the name of the file with RSA key (default: client.rsa)\n");
+ printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n");
+ printf(" for details) (default: %%d.%%m.%%Y %%H:%%M:%%S)\n\n");
+ printf(" Modes:\n\n");
+ printf(" -u, --udpmode - udp mode - client will use udp protocol to\n");
+ printf(" communicate with the hostname:portnum (-p)\n");
+ printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n");
+ printf(" from hostname:portnum (-p) to the server name:portnum\n");
+ printf(" (-m)\n");
+ printf(" -r, --remoteadmin - remote administration mode. (using '-p #port' will\n");
+ printf(" force afclient to use port rather then stdin-stdout)\n\n");
+ printf(" Logging:\n\n");
+ printf(" -O, --heavylog - logging everything to a logfile\n");
+ printf(" -o, --lightlog - logging some data to a logfile\n");
+ printf(" -S, --heavysocklog - logging everything to a localport\n");
+ printf(" -s, --lightsocklog - logging some data to a localport\n");
+ printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n");
+ printf(" (use several times for greater effect)\n\n");
+#ifdef AF_INET6
+ printf(" IP family:\n\n");
+ printf(" -4, --ipv4 - use ipv4 only\n");
+ printf(" -6, --ipv6 - use ipv6 only\n\n");
+#endif
+#ifdef HAVE_LIBDL
+ printf(" Modules:\n\n");
+ printf(" -l, --load - load a module for user's packets filtering\n");
+ printf(" -L, --Load - load a module for service's packets filtering\n\n");
+#endif
+
+ exit(0);
+}
+
+static void
+sig_int(int signo)
+{
+ aflog(1, "CLIENT CLOSED cg: %ld bytes", getcg());
+ exit(0);
+}
+
diff --git a/src/afclient.h b/src/afclient.h
new file mode 100644
index 0000000..108751b
--- /dev/null
+++ b/src/afclient.h
@@ -0,0 +1,50 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+#include "network.h"
+#include "stats.h"
+#include "modules.h"
+#include "remoteadmin.h"
+#include "make_ssl_handshake.h"
+#include "first_run.h"
+
+#include <openssl/rsa.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h>
+#endif
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <getopt.h>
+
+#ifndef _JS_AFCLIENT_H
+#define _JS_AFCLIENT_H
+
+static void usage(char* info);
+static void sig_int(int);
+
+#endif
+
diff --git a/src/afserver.c b/src/afserver.c
new file mode 100644
index 0000000..d1e11b7
--- /dev/null
+++ b/src/afserver.c
@@ -0,0 +1,1720 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#include "afserver.h"
+
+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'},
+ {"realm", 1, 0, 'r'},
+ {"raclients", 1, 0, 'R'},
+ {"usrpcli", 1, 0, 'U'},
+ {"climode", 1, 0, 'M'},
+ {"cerfile", 1, 0, 'c'},
+ {"keyfile", 1, 0, 'k'},
+ {"cfgfile", 1, 0, 'f'},
+ {"proto", 1, 0, 'p'},
+ {"lightlog", 1, 0, 'o'},
+ {"heavylog", 1, 0, 'O'},
+ {"heavysocklog", 1, 0, 'S'},
+ {"lightsocklog", 1, 0, 's'},
+ {"nossl", 0, 0, 301},
+ {"nozlib", 0, 0, 302},
+ {"pass", 1, 0, 303},
+#ifdef AF_INET6
+ {"ipv4", 0, 0, '4'},
+ {"ipv6", 0, 0, '6'},
+#endif
+ {"baseport", 0, 0, 'b'},
+ {"dnslookups", 0, 0, 311},
+ {"dateformat", 1, 0, 'D'},
+ {0, 0, 0, 0}
+};
+
+static ConfigurationT config;
+
+int
+main(int argc, char **argv)
+{
+ int i, j=0, k, l, n, flags, sent = 0;
+ socklen_t len;
+ unsigned char buff[9000];
+ int maxfdp1;
+ fd_set rset, allset, wset, tmpset;
+ int manconnecting, numofcon, length;
+ char* name = NULL;
+ char** listen = NULL;
+ int listencount = 0;
+ char** manage = NULL;
+ int managecount = 0;
+ char* amount = NULL;
+ char* clients = NULL;
+ char* raclients = NULL;
+ char* usrpcli = NULL;
+ char* clim = NULL;
+ char* filenam = NULL;
+ char* type = NULL;
+ char* timeout = NULL;
+ char* realmname = NULL;
+ unsigned char pass[4] = {1, 2, 3, 4};
+ char verbose = 0;
+ char mode = 0;
+ char ipfam = 0;
+ char baseport = 0;
+ char dnslookups = 0;
+ RealmT* pointer = NULL;
+ struct sigaction act;
+
+ char* certif = NULL;
+ char* keys = NULL;
+ char* logfnam = NULL;
+ char* logsport = NULL;
+ char* dateformat = NULL;
+ char logging = 0;
+ char socklogging = 0;
+
+ SSL_METHOD* method;
+ SSL_CTX* ctx;
+ SSL* tmp_ssl;
+
+ sigfillset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, NULL);
+
+ TYPE_SET_SSL(mode);
+ TYPE_SET_ZLIB(mode);
+
+ config.certif = NULL;
+ config.keys = NULL;
+ config.size = 0;
+ config.realmtable = NULL;
+ config.logging = 0;
+ config.socklogging = 0;
+ config.logfnam = NULL;
+ config.logsport = NULL;
+ config.dateformat = NULL;
+
+#ifdef AF_INET6
+ while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:bD:S:s:R:r:", long_options, 0)) != -1) {
+#else
+ while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:t:C:U:M:bD:S:s:R:r:", long_options, 0)) != -1) {
+#endif
+ switch (n) {
+ case 'h': {
+ usage(AF_VER("Active port forwarder (server)"));
+ break;
+ }
+ case 'n': {
+ name = optarg;
+ break;
+ }
+ case 'l': {
+ ++listencount;
+ listen = realloc(listen, sizeof(char*));
+ listen[listencount-1] = optarg;
+ break;
+ }
+ case 'm': {
+ ++managecount;
+ manage = realloc(manage, sizeof(char*));
+ manage[managecount-1] = optarg;
+ break;
+ }
+ case 't': {
+ timeout = optarg;
+ break;
+ }
+ case 'v': {
+ ++verbose;
+ break;
+ }
+ case 'u': {
+ amount = optarg;
+ break;
+ }
+ case 'C': {
+ clients = optarg;
+ break;
+ }
+ case 'r': {
+ realmname = optarg;
+ break;
+ }
+ case 'R': {
+ raclients = optarg;
+ break;
+ }
+ case 'U': {
+ usrpcli = optarg;
+ break;
+ }
+ case 'M': {
+ clim = optarg;
+ break;
+ }
+ case 'c': {
+ certif = optarg;
+ break;
+ }
+ case 'k': {
+ keys = optarg;
+ break;
+ }
+ case 'p': {
+ type = optarg;
+ break;
+ }
+ case 'f': {
+ filenam = optarg;
+ break;
+ }
+ case 'O': {
+ logfnam = optarg;
+ logging = 3;
+ break;
+ }
+ case 'o': {
+ logfnam = optarg;
+ logging = 1;
+ break;
+ }
+ case 'S': {
+ logsport = optarg;
+ socklogging = 3;
+ break;
+ }
+ case 's': {
+ logsport = optarg;
+ socklogging = 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];
+ }
+ sent = 1;
+ break;
+ }
+#ifdef AF_INET6
+ case '4': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 4;
+ }
+ break;
+ }
+ case '6': {
+ if (ipfam != 0) {
+ ipfam = -1;
+ }
+ else {
+ ipfam = 6;
+ }
+ break;
+ }
+#endif
+ case 'b': {
+ baseport = 1;
+ break;
+ }
+ case 311: {
+ dnslookups = 1;
+ break;
+ }
+ case 'D': {
+ dateformat = optarg;
+ break;
+ }
+ case '?': {
+ usage("");
+ break;
+ }
+ }
+ }
+
+ if (optind < argc) {
+ usage("Unrecognized non-option elements");
+ }
+
+ if (filenam != NULL) {
+ config = parsefile(filenam, &n);
+ if (n) {
+ printf("parsing failed! line:%d\n", n);
+ exit(1);
+ }
+ else {
+ if (certif == NULL) {
+ config.certif = "cacert.pem";
+ }
+ else {
+ config.certif = certif;
+ }
+ if (keys == NULL) {
+ config.keys = "server.rsa";
+ }
+ else {
+ config.keys = keys;
+ }
+ if (logfnam != NULL) {
+ config.logfnam = logfnam;
+ }
+ if (logsport != NULL) {
+ config.logsport = logsport;
+ }
+ if (dateformat != NULL) {
+ config.dateformat = dateformat;
+ }
+ if (logging != 0) {
+ config.logging = logging;
+ }
+ if (socklogging != 0) {
+ config.socklogging = socklogging;
+ }
+
+ if ((k = loginit(verbose, config.logging, config.socklogging,
+ config.logfnam, config.logsport, config.dateformat))) {
+ switch (k) {
+ case 1:
+ printf("Can't open file to log to... exiting\n");
+ break;
+ case 2:
+ printf("Can't connect to localhost:%s... exiting\n", logsport);
+ break;
+ case 3:
+ printf("Can't open socket to log to... exiting\n");
+ break;
+ }
+ exit(1);
+ }
+
+ aflog(1, "cfg file OK! (readed realms: %d)", config.size);
+ if (name != NULL)
+ aflog(1, "Warning: hostname=%s will be ignored", name);
+ if (listen != NULL)
+ aflog(1, "Warning: listenport will be ignored");
+ if (manage != NULL)
+ aflog(1, "Warning: manageport will be ignored");
+ if (realmname != NULL)
+ aflog(1, "Warning: realmname=%s will be ignored", realmname);
+ if (sent == 1)
+ aflog(1, "Warning: password from command line will be ignored");
+ }
+ }
+ else {
+ config.certif = certif;
+ config.keys = keys;
+ config.logfnam = logfnam;
+ config.logsport = logsport;
+ config.dateformat = dateformat;
+ config.logging = logging;
+ config.socklogging = socklogging;
+
+ if ((k = loginit(verbose, config.logging, config.socklogging,
+ config.logfnam, config.logsport, config.dateformat))) {
+ switch (k) {
+ case 1:
+ printf("Can't open file to log to... exiting\n");
+ break;
+ case 2:
+ printf("Can't connect to localhost:%s... exiting\n", logsport);
+ break;
+ case 3:
+ printf("Can't open socket to log to... exiting\n");
+ break;
+ }
+ exit(1);
+ }
+
+ if (listen == NULL) {
+ listencount = 1;
+ listen = calloc(1, sizeof(char*));
+ listen[0] = "50127";
+ }
+ if (manage == NULL) {
+ managecount = 1;
+ manage = calloc(1, sizeof(char*));
+ manage[0] = "50126";
+ }
+ if (managecount != listencount) {
+ aflog(0, "Number of listen and manage options are not the same... exiting");
+ exit(1);
+ }
+ if (config.certif == NULL) {
+ config.certif = "cacert.pem";
+ }
+ if (config.keys == NULL) {
+ config.keys = "server.rsa";
+ }
+ if (type == NULL) {
+ type = "tcp";
+ }
+ config.size = 1;
+ config.realmtable = calloc(config.size, sizeof(RealmT));
+ config.realmtable[0].hostname = name;
+ config.realmtable[0].usrclinum = managecount;
+ config.realmtable[0].usrclitable = calloc(managecount, sizeof(UsrCliT));
+ for (i = 0; i < config.realmtable[0].usrclinum; ++i) {
+ config.realmtable[0].usrclitable[i].lisportnum = listen[i];
+ config.realmtable[0].usrclitable[i].manportnum = manage[i];
+ }
+ config.realmtable[0].users = amount;
+ config.realmtable[0].clients = clients;
+ config.realmtable[0].raclients = raclients;
+ config.realmtable[0].timeout = timeout;
+ config.realmtable[0].usrpcli = usrpcli;
+ config.realmtable[0].clim = clim;
+ config.realmtable[0].baseport = baseport;
+ config.realmtable[0].dnslookups = dnslookups;
+ config.realmtable[0].realmname = realmname;
+ memcpy(config.realmtable[0].pass, pass, 4);
+ if (strcmp(type, "tcp") == 0) {
+ TYPE_SET_TCP(config.realmtable[0].type);
+ }
+ else if (strcmp(type, "udp") == 0) {
+ TYPE_SET_UDP(config.realmtable[0].type);
+ }
+ else {
+ TYPE_SET_ZERO(config.realmtable[0].type);
+ }
+#ifdef AF_INET6
+ if (ipfam == -1) {
+ aflog(0, "Conflicting types of ip protocol family... exiting");
+ exit(1);
+ }
+ else if (ipfam == 4) {
+ TYPE_SET_IPV4(config.realmtable[0].type);
+ }
+ else if (ipfam == 6) {
+ TYPE_SET_IPV6(config.realmtable[0].type);
+ }
+#endif
+ config.realmtable[0].type |= mode;
+ }
+
+ maxfdp1 = manconnecting = 0;
+
+ SSL_library_init();
+ method = SSLv3_server_method();
+ ctx = SSL_CTX_new(method);
+ if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
+ aflog(0, "Setting ciphers list failed... exiting");
+ exit(1);
+ }
+ if ((flags = create_apf_dir())) {
+ aflog(1, "Warning: Creating ~/.apf directory failed (%d)", flags);
+ }
+ if ((flags = generate_rsa_key(&config.keys))) {
+ aflog(1, "Warning: Something bad happened when generating rsa keys... (%d)", flags);
+ }
+ if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) {
+ aflog(0, "Setting rsa key failed (%s)... exiting", config.keys);
+ exit(1);
+ }
+ if ((flags = generate_certificate(&config.certif, config.keys))) {
+ aflog(1, "Warning: Something bad happened when generating certificate... (%d)", flags);
+ }
+ if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) {
+ aflog(0, "Setting certificate failed (%s)... exiting", config.certif);
+ exit(1);
+ }
+
+ if (config.size == 0) {
+ aflog(0, "Working without sense is really without sense...");
+ exit(1);
+ }
+
+ FD_ZERO(&allset);
+ FD_ZERO(&wset);
+
+ for (i = 0; i < config.size; ++i) {
+ if (config.realmtable[i].usrclinum == 0) {
+ aflog(0, "You have to specify at least one listen port and one manage port in each realm");
+ exit(1);
+ }
+ for (j = 0; j < config.realmtable[i].usrclinum; ++j) {
+ if ((config.realmtable[i].usrclitable[j].lisportnum == NULL) ||
+ (config.realmtable[i].usrclitable[j].manportnum == NULL)) {
+ aflog(0, "Missing some of the variables...\nRealm: %d\nlistenport[%d]: %s\nmanageport[%d]: %s",
+ i, j, config.realmtable[i].usrclitable[j].lisportnum,
+ j, config.realmtable[i].usrclitable[j].manportnum);
+ exit(1);
+ }
+ }
+ /* checking type of the realm */
+ if (!TYPE_IS_SET(config.realmtable[i].type)) {
+ if (type != NULL) {
+ if (strcmp(type, "tcp") == 0) {
+ TYPE_SET_TCP(config.realmtable[i].type);
+ }
+ else if (strcmp(type, "udp") == 0) {
+ TYPE_SET_UDP(config.realmtable[i].type);
+ }
+ else {
+ TYPE_SET_TCP(config.realmtable[i].type);
+ }
+ }
+ else {
+ TYPE_SET_TCP(config.realmtable[i].type);
+ }
+ }
+#ifdef AF_INET6
+ /* using user's value for ipfam*/
+ if (TYPE_IS_UNSPEC(config.realmtable[i].type)) {
+ if (ipfam == -1) {
+ aflog(0, "Conflicting types of ip protocol family... exiting");
+ exit(1);
+ }
+ else if (ipfam == 4) {
+ TYPE_SET_IPV4(config.realmtable[i].type);
+ }
+ else if (ipfam == 6) {
+ TYPE_SET_IPV6(config.realmtable[i].type);
+ }
+ }
+#endif
+ /* using user's values for zlib and ssl mode*/
+ if (!TYPE_IS_SSL(mode)) {
+ TYPE_UNSET_SSL(config.realmtable[i].type);
+ }
+ if (!TYPE_IS_ZLIB(mode)) {
+ TYPE_UNSET_ZLIB(config.realmtable[i].type);
+ }
+ /* using user's baseport value*/
+ if (config.realmtable[i].baseport == 0) {
+ config.realmtable[i].baseport = baseport;
+ }
+ /* using user's dnslookups value*/
+ if (config.realmtable[i].dnslookups == 0) {
+ config.realmtable[i].dnslookups = dnslookups;
+ }
+ /* checking users amount */
+ set_value(&(config.realmtable[i].users), amount, "5");
+ check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount");
+ /* checking clients amount */
+ set_value(&(config.realmtable[i].clients), clients, "1");
+ check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount");
+ /* checking raclients amount */
+ set_value(&(config.realmtable[i].raclients), raclients, "1");
+ check_value(&(config.realmtable[i].raclinum), config.realmtable[i].raclients, "Invalid raclients amount");
+ /* checking usrpcli value */
+ set_value(&(config.realmtable[i].usrpcli), usrpcli, config.realmtable[i].users);
+ check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value");
+ /* checking timeout value */
+ set_value(&(config.realmtable[i].timeout), timeout, "5");
+ check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value");
+ /* checking climode value */
+ set_value(&(config.realmtable[i].clim), clim, "1");
+ check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value");
+ /* allocating memory*/
+ config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT));
+ if (config.realmtable[i].contable == NULL) {
+ aflog(0, "Calloc error - try define smaller amount of users");
+ exit(1);
+ }
+ config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT));
+ if (config.realmtable[i].clitable == NULL) {
+ aflog(0, "Calloc error - try define smaller amount of clients");
+ exit(1);
+ }
+ config.realmtable[i].raclitable = calloc( config.realmtable[i].raclinum, sizeof(ConnectclientT));
+ if (config.realmtable[i].raclitable == NULL) {
+ aflog(0, "Calloc error - try define smaller amount of raclients");
+ exit(1);
+ }
+ ipfam = 0x01;
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(config.realmtable[i].type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(config.realmtable[i].type)) {
+ ipfam |= 0x04;
+ }
+#endif
+ if (config.realmtable[i].baseport == 0) {
+ for (j = 0; j < config.realmtable[i].usrclinum; ++j) {
+ if (ip_listen(&(config.realmtable[i].usrclitable[j].listenfd), config.realmtable[i].hostname,
+ config.realmtable[i].usrclitable[j].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) {
+ aflog(0,
+#ifdef AF_INET6
+ "tcp_listen_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
+#else
+ "tcp_listen error for %s, %s",
+#endif
+ config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].lisportnum);
+ exit(1);
+ }
+ }
+ }
+ for (j = 0; j < config.realmtable[i].usrclinum; ++j) {
+ if (ip_listen(&(config.realmtable[i].usrclitable[j].managefd), config.realmtable[i].hostname,
+ config.realmtable[i].usrclitable[j].manportnum, (&(config.realmtable[i].addrlen)), ipfam)) {
+ aflog(0,
+#ifdef AF_INET6
+ "tcp_listen_%s error for %s, %s",
+ (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec",
+#else
+ "tcp_listen error for %s, %s",
+#endif
+ config.realmtable[i].hostname, config.realmtable[i].usrclitable[j].manportnum);
+ exit(1);
+ }
+ }
+ config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen);
+
+ 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) {
+ aflog(0, "Creating of ssl object failed... exiting");
+ exit(1);
+ }
+ }
+
+ for (j=0; j<config.realmtable[i].raclinum; ++j) {
+ config.realmtable[i].raclitable[j].cliconn.ssl = SSL_new(ctx);
+ if (config.realmtable[i].raclitable[j].cliconn.ssl == NULL) {
+ aflog(0, "Creating of ssl object failed... exiting");
+ exit(1);
+ }
+ }
+
+ for (j = 0; j < config.realmtable[i].usrclinum; ++j) {
+ FD_SET(config.realmtable[i].usrclitable[j].managefd, &allset);
+ maxfdp1 = (maxfdp1 > (config.realmtable[i].usrclitable[j].managefd+1)) ?
+ maxfdp1 : (config.realmtable[i].usrclitable[j].managefd+1);
+ }
+ if (config.realmtable[i].baseport == 0) {
+ for (j = 0; j < config.realmtable[i].usrclinum; ++j) {
+ FD_SET(config.realmtable[i].usrclitable[j].listenfd, &allset);
+ maxfdp1 = (maxfdp1 > (config.realmtable[i].usrclitable[j].listenfd+1)) ?
+ maxfdp1 : (config.realmtable[i].usrclitable[j].listenfd+1);
+ }
+ }
+ config.realmtable[i].usercon = 0;
+ config.realmtable[i].clicon = 0;
+ config.realmtable[i].raclicon = 0;
+ for (j=0; j<config.realmtable[i].clinum; ++j) {
+ config.realmtable[i].clitable[j].tv.tv_sec = config.realmtable[i].tmout;
+ 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) {
+ aflog(0, "Calloc error - try define smaller amount of usrpcli (or users)");
+ exit(1);
+ }
+ for (k=0; k<config.realmtable[i].clitable[j].usernum; ++k) {
+ config.realmtable[i].clitable[j].users[k] = -1;
+ }
+ }
+ for (j=0; j<config.realmtable[i].raclinum; ++j) {
+ config.realmtable[i].raclitable[j].tv.tv_sec = config.realmtable[i].tmout;
+ }
+ }
+
+ if (!verbose)
+ daemon(0, 0);
+
+ aflog(1, "SERVER STARTED realms: %d", config.size);
+ time(&config.starttime);
+
+ for ( ; ; ) {
+ rset = allset;
+ tmpset = wset;
+ aflog(3, ">select, maxfdp1: %d", maxfdp1);
+ if (manconnecting) {
+ /* find out, in what realm client is trying to connect */
+ l = -1;
+ 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;
+ l = 0;
+ break; /* so i points to first good realm and j to good client */
+ }
+ }
+ if (l == -1) {
+ for (j=0; j < config.realmtable[k].raclinum; ++j) {
+ if ((config.realmtable[k].raclitable[j].ready==1) || (config.realmtable[k].raclitable[j].ready==2)) {
+ i = k;
+ k = config.size;
+ l = 1;
+ break; /* so i points to first good realm and j to good client */
+ }
+ }
+ }
+ }
+ if (!l) {
+ 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);
+ SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl);
+ config.realmtable[i].clitable[j].ready = 0;
+ manconnecting--;
+ config.realmtable[i].clicon--;
+ aflog(1, " realm[%s]: Client[%s]: SSL_accept failed (timeout)",
+ get_realmname(&config, i), get_clientname(pointer, j));
+ }
+ }
+ else {
+ if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].raclitable[j].tv))) == 0) {
+ close (config.realmtable[i].raclitable[j].cliconn.commfd);
+ FD_CLR(config.realmtable[i].raclitable[j].cliconn.commfd, &allset);
+ SSL_clear(config.realmtable[i].raclitable[j].cliconn.ssl);
+ config.realmtable[i].raclitable[j].ready = 0;
+ manconnecting--;
+ config.realmtable[i].clicon--;
+ aflog(1, " realm[%s]: Client[%s] (ra): SSL_accept failed (timeout)",
+ get_realmname(&config, i), get_raclientname(pointer, j));
+ }
+ }
+ }
+ else {
+ select(maxfdp1, &rset, &tmpset, NULL, NULL);
+ }
+ aflog(3, " >>after select...");
+
+ 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)) {
+ k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i);
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */
+ n = read(pointer->contable[i].connfd, &buff[5], 8091);
+ if (n == -1) {
+ if (errno == EAGAIN) {
+ continue;
+ }
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), errno);
+ n = 0;
+ }
+ if (n) {
+ aflog(2, " realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), n);
+ 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[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
+ pointer->contable[i].portbuf);
+ 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[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d",
+ get_realmname(&config, j), get_clientname(pointer, pointer->contable[i].whatcli),
+ get_username(pointer, k), n);
+ 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[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf,
+ pointer->contable[i].portbuf);
+ 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)) {
+ k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i);
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr;
+ sent = write(pointer->contable[i].connfd,
+ &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n);
+ if ((sent > 0) && (sent != n)) {
+ pointer->contable[i].head->actptr+=sent;
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), sent, n);
+ }
+ else if ((sent == -1) && (errno == EAGAIN)) {
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ }
+ else if (sent == -1) {
+ aflog(1, " realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k));
+ aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf);
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ FD_CLR(pointer->contable[i].connfd, &wset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ freebuflist(&pointer->contable[i].head);
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = k >> 8; /* high bits of user number */
+ buff[2] = k; /* low bits of user number */
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+ else {
+ aflog(3, " realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(&config, j),
+ get_clientname(pointer, pointer->contable[i].whatcli), get_username(pointer, k), sent, n);
+ 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[%s]: Client[%s]: TO user[%d]: BUFFERING MESSAGE ENDED",
+ get_realmname(&config, j), get_clientname(pointer, pointer->contable[i].whatcli),
+ get_username(pointer, k));
+ send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5);
+ }
+ }
+ }
+ }
+ /* ------------------------------------ */
+ if (pointer->baseport == 0) {
+ for (l = 0; l < pointer->usrclinum; ++l) {
+ if (FD_ISSET(pointer->usrclitable[l].listenfd, &rset)) {
+ len = pointer->addrlen;
+ sent = accept(pointer->usrclitable[l].listenfd, pointer->cliaddr, &len);
+ flags = fcntl(sent, F_GETFL, 0);
+ fcntl(sent, F_SETFL, flags | O_NONBLOCK);
+ aflog(3, " realm[%s]: listenfd: FD_ISSET", get_realmname(&config, j));
+ k = find_client(pointer, pointer->climode, l);
+ if (pointer->clitable[k].ready == 3) {
+ if (pointer->usercon == pointer->usernum) {
+ close(sent);
+ aflog(3, " realm[%s]: user limit EXCEEDED", get_realmname(&config, j));
+ }
+ else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) {
+ close(sent);
+ aflog(3, " realm[%s]: Client[%s]: usrpcli limit EXCEEDED",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ }
+ else {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state == S_STATE_CLEAR) {
+ pointer->contable[i].userid = pointer->usercounter;
+ ++(pointer->usercounter);
+ aflog(1, " realm[%s]: Client[%s]: new user: CONNECTING from IP: %s",
+ get_realmname(&config, j), get_clientname(pointer, k),
+ sock_ntop(pointer->cliaddr, len, pointer->contable[i].namebuf,
+ pointer->contable[i].portbuf, pointer->dnslookups));
+ pointer->contable[i].connfd = sent;
+ pointer->contable[i].state = S_STATE_OPENING;
+ pointer->contable[i].whatcli = k;
+ time(&pointer->contable[i].connecttime);
+ pointer->usercon++;
+ pointer->clitable[k].usercon++;
+ memcpy(&buff[5], pointer->contable[i].namebuf, 128);
+ memcpy(&buff[133], pointer->contable[i].portbuf, 7);
+ n = 135;
+ i = find_usernum(&(pointer->clitable[k]), i);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ close(sent);
+ aflog(3, " realm[%s]: Client(%d) is NOT CONNECTED",
+ get_realmname(&config, j), k);
+ }
+ }
+ }
+ }
+ /* ------------------------------------ */
+ if (pointer->baseport == 1)
+ for (k = 0; k < pointer->clinum; ++k)
+ if (pointer->clitable[k].ready == 3) /* Command file descriptor */
+ if (FD_ISSET(pointer->clitable[k].listenfd, &rset)) {
+ len = pointer->addrlen;
+ sent = accept(pointer->clitable[k].listenfd, pointer->cliaddr, &len);
+ flags = fcntl(sent, F_GETFL, 0);
+ fcntl(sent, F_SETFL, flags | O_NONBLOCK);
+ aflog(3, " realm[%s]: Client[%s]: listenfd: FD_ISSET",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ if (pointer->clitable[k].ready == 3) {
+ if (pointer->usercon == pointer->usernum) {
+ close(sent);
+ aflog(3, " realm[%s]: user limit EXCEEDED", get_realmname(&config, j));
+ }
+ else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) {
+ close(sent);
+ aflog(3, " realm[%s]: Client[%s]: usrpcli limit EXCEEDED",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ }
+ else {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state == S_STATE_CLEAR) {
+ pointer->contable[i].userid = pointer->usercounter;
+ ++(pointer->usercounter);
+ aflog(1, " realm[%s]: Client[%s]: new user: CONNECTING from IP: %s",
+ get_realmname(&config, j), get_clientname(pointer, k),
+ sock_ntop(pointer->cliaddr, len, pointer->contable[i].namebuf, pointer->contable[i].portbuf, pointer->dnslookups));
+ pointer->contable[i].connfd = sent;
+ pointer->contable[i].state = S_STATE_OPENING;
+ pointer->contable[i].whatcli = k;
+ time(&pointer->contable[i].connecttime);
+ pointer->usercon++;
+ pointer->clitable[k].usercon++;
+ memcpy(&buff[5], pointer->contable[i].namebuf, 128);
+ memcpy(&buff[133], pointer->contable[i].portbuf, 7);
+ n = 135;
+ i = find_usernum(&(pointer->clitable[k]), i);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5);
+ break;
+ }
+ }
+ }
+ }
+ }
+ /* ------------------------------------ */
+ for (k = 0; k < pointer->clinum; ++k)
+ if ((pointer->clitable[k].ready != 0) && (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset))) {
+ if (pointer->clitable[k].ready == 1) {
+ make_ssl_initialize(&(pointer->clitable[k].cliconn));
+ aflog(2, " realm[%s]: new Client[%s]: SSL_accept",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ switch (make_ssl_accept(&(pointer->clitable[k].cliconn))) {
+ case 2: {
+ close (pointer->clitable[k].cliconn.commfd);
+ FD_CLR(pointer->clitable[k].cliconn.commfd, &allset);
+ SSL_clear(pointer->clitable[k].cliconn.ssl);
+ pointer->clitable[k].ready = 0;
+ manconnecting--;
+ pointer->clicon--;
+ aflog(1, " realm[%s]: new Client[%s]: DENIED by SSL_accept",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ }
+ case 1: {
+ continue;
+ }
+ default: {
+ aflog(1, " realm[%s]: new Client[%s]: ACCEPTED by SSL_accept",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ pointer->clitable[k].ready = 2;
+ continue;
+ }
+ }
+ }
+ aflog(3, " realm[%s]: Client[%s]: commfd: FD_ISSET",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ if (pointer->clitable[k].ready == 2) {
+ n = get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, -5);
+ }
+ else {
+ n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5);
+ }
+ if (n == -1) {
+ if (errno == EAGAIN) {
+ aflog(4, " realm[%s]: Client[%s]: commfd: EAGAIN",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ continue;
+ }
+ else {
+ aflog(4, " realm[%s]: Client[%s]: commfd: ERROR: %d",
+ get_realmname(&config, j), get_clientname(pointer, k), errno);
+ n = 0;
+ }
+ }
+ else if (n != 5) {
+ if (n != 0) {
+ aflog(4, " realm[%s]: Client[%s]: header length = %d --> closing client",
+ get_realmname(&config, j), get_clientname(pointer, k), n);
+ }
+ n = 0;
+ }
+ if (n==0) {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ aflog(1, " realm[%s]: Client[%s]: commfd: CLOSED",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ continue;
+ }
+
+ numofcon = buff[1];
+ numofcon = numofcon << 8;
+ numofcon += buff[2]; /* this is id of user */
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+
+ if ((k == pointer->clinum) && (buff[0] != AF_S_LOGIN) &&
+ (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) {
+ buff[0] = AF_S_WRONG;
+ }
+ if (pointer->clitable[k].ready<2) {
+ aflog(1, " realm[%s]: Client[%s]: Impossible behaviour --> ignoring",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ continue;
+ }
+ if ((pointer->clitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
+ buff[0] = AF_S_WRONG;
+ }
+
+ switch (buff[0]) {
+ case AF_S_CONCLOSED : {
+ n = numofcon;
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ pointer->usercon--;
+ pointer->clitable[k].usercon--;
+ pointer->clitable[k].users[n] = -1;
+ if (pointer->contable[numofcon].state == S_STATE_CLOSING) {
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ aflog(3, " realm[%s]: user[%d]: CLOSE CONFIRMED",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ }
+ else if ((pointer->contable[numofcon].state == S_STATE_OPEN) ||
+ (pointer->contable[numofcon].state == S_STATE_STOPPED)) {
+ aflog(1, " realm[%s]: user[%d]: KICKED",
+ get_realmname(&config, j), get_username(pointer, 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 : {
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ if (pointer->contable[numofcon].state == S_STATE_OPENING) {
+ aflog(2, " realm[%s]: user[%d]: NEW",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ FD_SET(pointer->contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ?
+ maxfdp1 : (pointer->contable[numofcon].connfd+1);
+ pointer->contable[numofcon].state = S_STATE_OPEN;
+ }
+ }
+ else {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ case AF_S_CANT_OPEN : {
+ n = numofcon;
+ numofcon = eval_numofcon(pointer, k, numofcon);
+ if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) {
+ if (pointer->contable[numofcon].state == S_STATE_OPENING) {
+ aflog(2, " realm[%s]: user[%d]: DROPPED",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ pointer->usercon--;
+ pointer->clitable[k].usercon--;
+ pointer->clitable[k].users[n] = -1;
+ close(pointer->contable[numofcon].connfd);
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ }
+ }
+ else {
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ case AF_S_MESSAGE : {
+ 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->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[%s]: TO user[%d]: MESSAGE length=%d",
+ get_realmname(&config, j), get_username(pointer, numofcon), n);
+ if (TYPE_IS_UDP(pointer->type)) { /* udp */
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ sent = write(pointer->contable[numofcon].connfd, buff, n+5);
+ if (sent == -1) {
+ aflog(1, " realm[%s]: user[%d]: CLOSED (write-udp)",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf,
+ pointer->contable[numofcon].portbuf);
+ 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[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)",
+ get_realmname(&config, j), get_username(pointer, numofcon), sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if ((sent == -1) && (errno == EAGAIN)) {
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
+ pointer->contable[numofcon].state = S_STATE_STOPPED;
+ FD_SET(pointer->contable[numofcon].connfd, &wset);
+ buff[0] = AF_S_DONT_SEND; /* stopping transfer */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ aflog(3, " realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)",
+ get_realmname(&config, j), get_username(pointer, numofcon), sent, n);
+ send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5);
+ }
+ else if (sent == -1) {
+ aflog(1, " realm[%s]: user[%d]: CLOSED (write-tcp)",
+ get_realmname(&config, j), get_username(pointer, 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[%s]: TO user[%d]: BUFFERING MESSAGE (%d)",
+ get_realmname(&config, j), get_username(pointer, numofcon), n);
+ if (TYPE_IS_UDP(pointer->type)) { /* udp */
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff);
+ }
+ else {
+ insertblnode(&(pointer->contable[numofcon].head), 0, n, buff);
+ }
+ }
+ else if (pointer->contable[numofcon].state == S_STATE_CLOSING) {
+ aflog(3, " realm[%s]: TO user[%d]: IGNORED message length=%d",
+ get_realmname(&config, j), get_username(pointer, numofcon), n);
+ }
+ }
+ break;
+ }
+ case AF_S_LOGIN : {
+ if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) &&
+ (length==(pointer->pass[2]*256+pointer->pass[3]))) {
+ if (k != pointer->clinum) {
+ pointer->clitable[k].ready = 3;
+ aflog(1, " realm[%s]: Client[%s]: pass ok - ACCESS GRANTED",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ buff[0] = AF_S_LOGIN; /* sending message */
+ buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */
+ buff[2] = pointer->clitable[k].usernum; /* low bits of user number */
+ buff[3] = pointer->type; /* type of connection */
+ send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, 5);
+ manconnecting--;
+ if (pointer->baseport == 1) {
+ long tmp_val;
+ char tmp_tab[6];
+ if (check_long(pointer->usrclitable[pointer->clitable[k].whatusrcli].lisportnum, &tmp_val)) {
+ aflog(1, " realm[%s]: INVALID listenport - removing Client[%s]",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ break;
+ }
+ tmp_val = tmp_val%65536;
+ memset(tmp_tab, 0, 6);
+ sprintf(tmp_tab, "%d", (int)tmp_val);
+ ipfam = 0x01;
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(pointer->type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(pointer->type)) {
+ ipfam |= 0x04;
+ }
+#endif
+ while (ip_listen(&(pointer->clitable[k].listenfd), pointer->hostname,
+ tmp_tab, (&(pointer->addrlen)), ipfam)) {
+ tmp_val = (tmp_val+1)%65536;
+ memset(tmp_tab, 0, 6);
+ sprintf(tmp_tab, "%d", (int)tmp_val);
+ }
+ FD_SET(pointer->clitable[k].listenfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->clitable[k].listenfd+1)) ?
+ maxfdp1 : (pointer->clitable[k].listenfd+1);
+ aflog(1, " realm[%s]: Client[%s]: listenport=%s",
+ get_realmname(&config, j), get_clientname(pointer, k), tmp_tab);
+ }
+ }
+ else {
+ aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j));
+ buff[0] = AF_S_CANT_OPEN; /* sending message */
+ send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5);
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ else if ((pointer->clitable[k].ready == 3) && (numofcon == 0)) {
+ n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, length);
+ buff[n] = 0;
+ aflog(1, " realm[%s]: Client[%s]: ID received: %s",
+ get_realmname(&config, j), get_clientname(pointer, k), buff);
+ if (pointer->clitable[k].clientid) {
+ free(pointer->clitable[k].clientid);
+ }
+ pointer->clitable[k].clientid = malloc(n+1);
+ if (pointer->clitable[k].clientid) {
+ memcpy(pointer->clitable[k].clientid, buff, n+1);
+ }
+ }
+ else {
+ aflog(1, " realm[%s]: Client[%s]: Wrong password - CLOSING",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ case AF_S_DONT_SEND: {
+ aflog(3, " realm[%s]: user[%d]: STOP READING",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ break;
+ }
+ case AF_S_CAN_SEND: {
+ aflog(3, " realm[%s]: user[%d]: START READING",
+ get_realmname(&config, j), get_username(pointer, numofcon));
+ FD_SET(pointer->contable[numofcon].connfd, &allset);
+ break;
+ }
+ case AF_S_WRONG: {
+ aflog(1, " realm[%s]: Client[%s]: Wrong message - CLOSING",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ break;
+ }
+ case AF_S_ADMIN_LOGIN: {
+ if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) &&
+ (length==(pointer->pass[2]*256+pointer->pass[3]))) {
+ aflog(1, " realm[%s]: Client[%s]: NEW remote admin -- pass OK",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ for (l = 0; l < pointer->raclinum; ++l) {
+ if (pointer->raclitable[l].ready == 0) {
+ pointer->raclitable[l].cliconn.commfd = pointer->clitable[k].cliconn.commfd;
+ pointer->raclitable[l].connecttime = pointer->clitable[k].connecttime;
+ pointer->raclitable[l].clientnum = pointer->clitable[k].clientnum;
+ memcpy(pointer->raclitable[l].namebuf, pointer->clitable[k].namebuf, 128);
+ memcpy(pointer->raclitable[l].portbuf, pointer->clitable[k].portbuf, 7);
+ tmp_ssl = pointer->raclitable[l].cliconn.ssl;
+ pointer->raclitable[l].cliconn.ssl = pointer->clitable[k].cliconn.ssl;
+ pointer->clitable[k].cliconn.ssl = tmp_ssl;
+ pointer->clitable[k].ready = 0;
+ break;
+ }
+ }
+ if (l != pointer->raclinum) {
+ pointer->raclitable[l].ready = 3;
+ pointer->raclicon++;
+ manconnecting--;
+ sprintf((char*) &buff[5], AF_VER("AFSERVER"));
+ n = strlen((char*) &buff[5]);
+ buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
+ buff[1] = pointer->type; /* type of connection */
+ buff[2] = AF_RA_UNDEFINED;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type | TYPE_SSL, pointer->raclitable[l].cliconn, buff, n+5);
+ }
+ else {
+ aflog(1, " realm[%s]: Client[%s]: remote admin -- limit EXCEEDED",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ buff[0] = AF_S_CANT_OPEN; /* sending message */
+ send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[k].cliconn, buff, 5);
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ break;
+ }
+ default : {
+ aflog(1, " realm[%s]: Client[%s]: Unrecognized message - CLOSING",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ remove_client(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ }
+ /* ------------------------------------ */
+ for (k = 0; k < pointer->raclinum; ++k)
+ if ((pointer->raclitable[k].ready != 0) && (FD_ISSET(pointer->raclitable[k].cliconn.commfd, &rset))) {
+ if (pointer->raclitable[k].ready == 1) {
+ make_ssl_initialize(&(pointer->raclitable[k].cliconn));
+ aflog(2, " realm[%s]: new Client[%s] (ra): SSL_accept",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ switch (make_ssl_accept(&(pointer->raclitable[k].cliconn))) {
+ case 2: {
+ close (pointer->raclitable[k].cliconn.commfd);
+ FD_CLR(pointer->raclitable[k].cliconn.commfd, &allset);
+ SSL_clear(pointer->raclitable[k].cliconn.ssl);
+ pointer->raclitable[k].ready = 0;
+ manconnecting--;
+ pointer->clicon--;
+ aflog(1, " realm[%s]: new Client[%s] (ra): DENIED by SSL_accept",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ }
+ case 1: {
+ continue;
+ }
+ default: {
+ aflog(1, " realm[%s]: new Client[%s] (ra): ACCEPTED by SSL_accept",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ pointer->raclitable[k].ready = 2;
+ continue;
+ }
+ }
+ }
+ aflog(3, " realm[%s]: Client[%s] (ra): commfd: FD_ISSET",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ n = get_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, -5);
+ if (n == -1) {
+ if (errno == EAGAIN) {
+ aflog(4, " realm[%s]: Client[%s] (ra): commfd: EAGAIN",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ continue;
+ }
+ else {
+ aflog(4, " realm[%s]: Client[%s] (ra): commfd: ERROR: %d",
+ get_realmname(&config, j), get_raclientname(pointer, k), errno);
+ n = 0;
+ }
+ }
+ else if (n != 5) {
+ if (n != 0) {
+ aflog(4, " realm[%s]: Client[%s] (ra): header length = %d --> closing client",
+ get_realmname(&config, j), get_raclientname(pointer, k), n);
+ }
+ n = 0;
+ }
+ if (n==0) {
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ aflog(1, " realm[%s]: Client[%s] (ra): commfd: CLOSED",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ continue;
+ }
+
+ numofcon = buff[1];
+ numofcon = numofcon << 8;
+ numofcon += buff[2]; /* this is id of user */
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+
+ if (pointer->raclitable[k].ready<2) {
+ aflog(1, " realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ continue;
+ }
+ if ((pointer->raclitable[k].ready == 2) && (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) {
+ buff[0] = AF_S_WRONG;
+ }
+
+ switch (buff[0]) {
+ case AF_S_LOGIN : {
+ if ((pointer->raclitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) &&
+ (length==(pointer->pass[2]*256+pointer->pass[3]))) {
+ for (l = 0; l < pointer->clinum; ++l) {
+ if (!(pointer->clitable[l].ready)) {
+ aflog(1, " realm[%s]: Client[%s] (ra) --> Client[%s]",
+ get_realmname(&config, j), get_raclientname(pointer, k), get_clientname(pointer, l));
+ pointer->clitable[l].cliconn.commfd = pointer->raclitable[k].cliconn.commfd;
+ pointer->clitable[l].connecttime = pointer->raclitable[k].connecttime;
+ pointer->clitable[l].clientnum = pointer->raclitable[k].clientnum;
+ memcpy(pointer->clitable[l].namebuf, pointer->raclitable[k].namebuf, 128);
+ memcpy(pointer->clitable[l].portbuf, pointer->raclitable[k].portbuf, 7);
+ tmp_ssl = pointer->clitable[l].cliconn.ssl;
+ pointer->clitable[l].cliconn.ssl = pointer->raclitable[k].cliconn.ssl;
+ pointer->raclitable[k].cliconn.ssl = tmp_ssl;
+ pointer->clitable[l].whatusrcli = pointer->raclitable[k].whatusrcli;
+ pointer->raclitable[k].ready = 0;
+ break;
+ }
+ }
+ if (l != pointer->clinum) {
+ pointer->clitable[l].ready = 3;
+ aflog(1, " realm[%s]: Client[%s]: pass ok - ACCESS GRANTED",
+ get_realmname(&config, j), get_clientname(pointer, l));
+ buff[0] = AF_S_LOGIN; /* sending message */
+ buff[1] = pointer->clitable[l].usernum >> 8;/* high bits of user number */
+ buff[2] = pointer->clitable[l].usernum; /* low bits of user number */
+ buff[3] = pointer->type; /* type of connection */
+ send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->clitable[l].cliconn, buff, 5);
+ manconnecting--;
+ if (pointer->baseport == 1) {
+ long tmp_val;
+ char tmp_tab[6];
+ if (check_long(pointer->usrclitable[pointer->clitable[l].whatusrcli].lisportnum, &tmp_val)) {
+ aflog(1, " realm[%s]: INVALID listenport - removing Client[%s]",
+ get_realmname(&config, j), get_clientname(pointer, l));
+ remove_client(pointer, l, &allset, &wset, &manconnecting);
+ break;
+ }
+ tmp_val = tmp_val%65536;
+ memset(tmp_tab, 0, 6);
+ sprintf(tmp_tab, "%d", (int)tmp_val);
+ ipfam = 0x01;
+#ifdef AF_INET6
+ if (TYPE_IS_IPV4(pointer->type)) {
+ ipfam |= 0x02;
+ }
+ else if (TYPE_IS_IPV6(pointer->type)) {
+ ipfam |= 0x04;
+ }
+#endif
+ while (ip_listen(&(pointer->clitable[l].listenfd), pointer->hostname,
+ tmp_tab, (&(pointer->addrlen)), ipfam)) {
+ tmp_val = (tmp_val+1)%65536;
+ memset(tmp_tab, 0, 6);
+ sprintf(tmp_tab, "%d", (int)tmp_val);
+ }
+ FD_SET(pointer->clitable[l].listenfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->clitable[l].listenfd+1)) ?
+ maxfdp1 : (pointer->clitable[l].listenfd+1);
+ aflog(1, " realm[%s]: Client[%s]: listenport=%s",
+ get_realmname(&config, j), get_clientname(pointer, l), tmp_tab);
+ }
+ }
+ else {
+ aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j));
+ buff[0] = AF_S_CANT_OPEN; /* sending message */
+ send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, 5);
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ else if ((pointer->raclitable[k].ready == 3) && (numofcon == 0)) {
+ n = get_message(pointer->type, pointer->raclitable[k].cliconn, buff, length);
+ buff[n] = 0;
+ aflog(1, " realm[%s]: Client[%s] (ra): ID received: %s",
+ get_realmname(&config, j), get_raclientname(pointer, k), buff);
+ if (pointer->raclitable[k].clientid) {
+ free(pointer->raclitable[k].clientid);
+ }
+ pointer->raclitable[k].clientid = malloc(n+1);
+ if (pointer->raclitable[k].clientid) {
+ memcpy(pointer->raclitable[k].clientid, buff, n+1);
+ }
+ }
+ else {
+ aflog(1, " realm[%s]: Client[%s] (ra): Wrong password - CLOSING",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ case AF_S_WRONG: {
+ aflog(1, " realm[%s]: Client[%s] (ra): Wrong message - CLOSING",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ break;
+ }
+ case AF_S_ADMIN_LOGIN: {
+ if ((pointer->raclitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) &&
+ (length==(pointer->pass[2]*256+pointer->pass[3]))) {
+ aflog(1, " realm[%s]: Client[%s] (ra): NEW remote admin -- pass OK",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ pointer->raclitable[k].ready = 3;
+ pointer->raclicon++;
+ manconnecting--;
+ sprintf((char*) &buff[5], AF_VER("AFSERVER"));
+ n = strlen((char*) &buff[5]);
+ buff[0] = AF_S_ADMIN_LOGIN; /* sending message */
+ buff[1] = pointer->type; /* type of connection */
+ buff[2] = AF_RA_UNDEFINED;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(pointer->type | TYPE_SSL | TYPE_ZLIB, pointer->raclitable[k].cliconn, buff, n+5);
+ }
+ break;
+ }
+ case AF_S_ADMIN_CMD: {
+ if (pointer->raclitable[k].ready == 3) {
+ if (serve_admin(&config, j, k, buff)) {
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ else {
+ aflog(1, " realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ }
+ break;
+ }
+ default : {
+ aflog(1, " realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ remove_raclient(pointer, k, &allset, &wset, &manconnecting);
+ }
+ }
+ }
+ /* ------------------------------------ */
+ for (l = 0; l < pointer->usrclinum; ++l) {
+ if (FD_ISSET(pointer->usrclitable[l].managefd, &rset)) {
+ aflog(3, " realm[%s]: managefd: FD_ISSET", get_realmname(&config, j));
+ len = pointer->addrlen;
+ sent = accept(pointer->usrclitable[l].managefd,pointer->cliaddr,&len);
+ flags = fcntl(sent, F_GETFL, 0);
+ fcntl(sent, F_SETFL, flags | O_NONBLOCK);
+ for (k = 0; k < pointer->clinum; ++k) {
+ if (!(pointer->clitable[k].ready)) {
+ pointer->clitable[k].clientnum = pointer->clientcounter;
+ ++(pointer->clientcounter);
+ aflog(2, " realm[%s]: new Client[%s]: CONNECTING",
+ get_realmname(&config, j), get_clientname(pointer, k));
+ pointer->clitable[k].cliconn.commfd = sent;
+ pointer->clitable[k].whatusrcli = l;
+ time(&pointer->clitable[k].connecttime);
+ aflog(1, " realm[%s]: new Client[%s] IP:%s", get_realmname(&config, j), get_clientname(pointer, k),
+ sock_ntop(pointer->cliaddr, len, pointer->clitable[k].namebuf,
+ pointer->clitable[k].portbuf, pointer->dnslookups));
+ FD_SET(pointer->clitable[k].cliconn.commfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ?
+ maxfdp1 : (pointer->clitable[k].cliconn.commfd+1);
+ pointer->clicon++;
+ pointer->clitable[k].tv.tv_sec = pointer->tmout;
+ manconnecting++;
+ pointer->clitable[k].ready = 1;
+ break;
+ }
+ }
+ if (k == pointer->clinum) {
+ for (k = 0; k < pointer->raclinum; ++k) {
+ if ((!pointer->raclitable[k].ready)) {
+ pointer->raclitable[k].clientnum = pointer->clientcounter;
+ ++(pointer->clientcounter);
+ aflog(2, " realm[%s]: new Client[%s] (ra): CONNECTING",
+ get_realmname(&config, j), get_raclientname(pointer, k));
+ pointer->raclitable[k].cliconn.commfd = sent;
+ pointer->raclitable[k].whatusrcli = l;
+ time(&pointer->raclitable[k].connecttime);
+ aflog(1, " realm[%s]: new Client[%s] (ra) IP:%s",
+ get_realmname(&config, j), get_raclientname(pointer, k),
+ sock_ntop(pointer->cliaddr, len, pointer->raclitable[k].namebuf,
+ pointer->raclitable[k].portbuf, pointer->dnslookups));
+ FD_SET(pointer->raclitable[k].cliconn.commfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->raclitable[k].cliconn.commfd+1)) ?
+ maxfdp1 : (pointer->raclitable[k].cliconn.commfd+1);
+ pointer->clicon++;
+ pointer->raclitable[k].tv.tv_sec = pointer->tmout;
+ manconnecting++;
+ pointer->raclitable[k].ready = 1;
+ break;
+ }
+ }
+ if (k == pointer->raclinum) {
+ aflog(3, " realm[%s]: client limit EXCEEDED", get_realmname(&config, j));
+ close(sent);
+ }
+ }
+ }
+ }
+ } /* realms loop */
+ }
+}
+
+static void
+usage(char* info)
+{
+ printf("\n%s\n\n\n", info);
+ printf(" Basic options:\n\n");
+ printf(" -n, --hostname - it's used when creating listening sockets\n");
+ printf(" (default: '')\n");
+ printf(" -l, --listenport - listening port number - users connect\n");
+ printf(" to it (default: 50127)\n");
+ printf(" -m, --manageport - manage port number - second part of the active\n");
+ printf(" port forwarder connects to it (default: 50126)\n");
+ printf(" -h, --help - prints this help\n\n");
+ printf(" Authorization:\n\n");
+ printf(" --pass - set the password used for client identification\n");
+ printf(" (default: no password)\n\n");
+ printf(" Configuration:\n\n");
+ printf(" -c, --cerfile - the name of the file with certificate\n");
+ printf(" (default: cacert.pem)\n");
+ printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n");
+ printf(" -f, --cfgfile - the name of the file with the configuration for the\n");
+ printf(" active forwarder (server)\n");
+ printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n");
+ printf(" for details) (default: %%d.%%m.%%Y %%H:%%M:%%S)\n\n");
+ printf(" -t, --timeout - the timeout value for the client's connection\n");
+ printf(" (default: 5)\n");
+ printf(" -u, --users - the amount of users allowed to use this server\n");
+ printf(" (default: 5)\n");
+ printf(" -C, --clients - the number of allowed clients to use this server\n");
+ printf(" (default: 1)\n");
+ printf(" -r, --realm - set the realm name (default: none)\n");
+ printf(" -R, --raclients - the number of allowed clients in remote administration\n");
+ printf(" mode to use this server (default: 1)\n");
+ printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n");
+ printf(" -M, --climode - strategy used to connect users with clients (default: 1)\n");
+ printf(" Available strategies:\n");
+ printf(" 1. fill first client before go to next\n\n");
+ printf(" -p, --proto - type of server (tcp|udp) - what protocol it will be\n");
+ printf(" operating for (default: tcp)\n");
+ printf(" -b, --baseport - listenports are temporary and differ for each client\n");
+ printf(" --nossl - ssl is not used to transfer data (but it's still used\n");
+ printf(" to establish a connection) (default: ssl is used)\n");
+ printf(" --nozlib - zlib is not used to compress data (default: zlib is\n");
+ printf(" used)\n");
+ printf(" --dnslookups - try to obtain dns names of the computers rather than\n");
+ printf(" their numeric IP\n\n");
+ printf(" Logging:\n\n");
+ printf(" -O, --heavylog - logging everything to a logfile\n");
+ printf(" -o, --lightlog - logging some data to a logfile\n");
+ printf(" -S, --heavysocklog - logging everything to a localport\n");
+ printf(" -s, --lightsocklog - logging some data to a localport\n");
+ printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n");
+ printf(" (use several times for greater effect)\n\n");
+#ifdef AF_INET6
+ printf(" IP family:\n\n");
+ printf(" -4, --ipv4 - use ipv4 only\n");
+ printf(" -6, --ipv6 - use ipv6 only\n\n");
+#endif
+ exit(0);
+}
+
+static void
+sig_int(int signo)
+{
+ int i, j;
+ unsigned char buff[5];
+ for (j = 0; j < config.size; ++j) {
+ buff[0] = AF_S_CLOSING; /* closing */
+ for (i = 0; i < config.realmtable[j].clinum+1; ++i) {
+ if (config.realmtable[j].clitable[i].ready == 3) {
+ if (config.realmtable[j].clinum == i) {
+ send_message(config.realmtable[j].type | TYPE_SSL, config.realmtable[j].clitable[i].cliconn, buff, 5);
+ }
+ else {
+ send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5);
+ }
+ }
+ }
+ }
+ aflog(1, "SERVER CLOSED cg: %ld bytes", getcg());
+ exit(0);
+}
+
diff --git a/src/afserver.h b/src/afserver.h
new file mode 100644
index 0000000..6975af4
--- /dev/null
+++ b/src/afserver.h
@@ -0,0 +1,51 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+#include "network.h"
+#include "file.h"
+#include "stats.h"
+#include "remoteadmin.h"
+#include "server_check.h"
+#include "server_set.h"
+#include "server_eval.h"
+#include "server_find.h"
+#include "server_remove.h"
+#include "make_ssl_handshake.h"
+#include "first_run.h"
+#include "realmnames.h"
+#include "clientnames.h"
+#include "usernames.h"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+
+#ifndef _JS_AFSERVER_H
+#define _JS_AFSERVER_H
+
+static void usage(char* info);
+static void sig_int(int);
+
+#endif
+
diff --git a/src/buflist.c b/src/buflist.c
new file mode 100644
index 0000000..7ee5ede
--- /dev/null
+++ b/src/buflist.c
@@ -0,0 +1,70 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <stdlib.h>
+#include <string.h>
+
+#include "buflist.h"
+
+int
+insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff)
+{
+ blnodeT* newnode, *lastnode;
+ lastnode = newnode = *headRef;
+ while (newnode) {
+ lastnode = newnode;
+ newnode = newnode->next;
+ }
+ newnode = calloc(1, sizeof(blnodeT));
+ newnode->next = NULL;
+ newnode->actptr = 0;
+ newnode->msglen = msglen - actptr;
+ newnode->buff = calloc(1, newnode->msglen);
+ if (newnode->buff == NULL)
+ return 1;
+ memcpy((char*)newnode->buff, (char*)buff+actptr, newnode->msglen);
+ if (lastnode)
+ lastnode->next = newnode;
+ else
+ *headRef = newnode;
+ return 0;
+}
+
+int
+deleteblnode(blnodeT** headRef)
+{
+ blnodeT* node = *headRef;
+ if (*headRef == NULL)
+ return 1;
+ *headRef = node->next;
+ if (node->buff != NULL)
+ free(node->buff);
+ free(node);
+ return 0;
+}
+
+int
+freebuflist(blnodeT** headRef)
+{
+ while (*headRef) {
+ deleteblnode(headRef);
+ }
+ return 0;
+}
diff --git a/src/buflist.h b/src/buflist.h
new file mode 100644
index 0000000..bc96e73
--- /dev/null
+++ b/src/buflist.h
@@ -0,0 +1,35 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_BUFLIST_H
+#define _JS_BUFLIST_H
+
+typedef struct blnode {
+ int actptr;
+ int msglen;
+ unsigned char* buff;
+ struct blnode* next;
+} blnodeT;
+
+int insertblnode(blnodeT** headRef, int actptr, int msglen, unsigned char* buff);
+int deleteblnode(blnodeT** headRef);
+int freebuflist(blnodeT** headRef);
+
+#endif
diff --git a/src/clientnames.c b/src/clientnames.c
new file mode 100644
index 0000000..9658903
--- /dev/null
+++ b/src/clientnames.c
@@ -0,0 +1,129 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <stdio.h>
+#include <string.h>
+#include "clientnames.h"
+
+char*
+get_clientname(RealmT* pointer, int client)
+{
+ static char clientname[10];
+
+ if (pointer->clitable[client].clientid == NULL) {
+ memset(clientname, 0, 10);
+ sprintf(clientname, "%d", pointer->clitable[client].clientnum);
+ return clientname;
+ }
+
+ return pointer->clitable[client].clientid;
+}
+
+int
+get_clientid(RealmT* pointer, char* clientname)
+{
+ int i, n;
+ char guard;
+
+ for (i = 0; i < pointer->clinum; ++i) {
+ if (pointer->clitable[i].clientid != NULL) {
+ if (strcmp(clientname, pointer->clitable[i].clientid) == 0) {
+ return pointer->clitable[i].clientnum;
+ }
+ }
+ }
+
+ if (sscanf(clientname, "%d%c", &i, &guard) == 1) {
+ n = get_clientnumber(pointer, i);
+ if ((n >= 0) && (n < pointer->clinum)) {
+ if (pointer->clitable[n].clientid == NULL) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+get_clientnumber(RealmT* pointer, int clientid)
+{
+ int i;
+ for (i = 0; i < pointer->clinum; ++i) {
+ if (pointer->clitable[i].clientnum == clientid) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+char*
+get_raclientname(RealmT* pointer, int client)
+{
+ static char clientname[10];
+
+ if (pointer->raclitable[client].clientid == NULL) {
+ memset(clientname, 0, 10);
+ sprintf(clientname, "%d", pointer->raclitable[client].clientnum);
+ return clientname;
+ }
+
+ return pointer->raclitable[client].clientid;
+}
+
+int
+get_raclientid(RealmT* pointer, char* clientname)
+{
+ int i, n;
+ char guard;
+
+ for (i = 0; i < pointer->raclinum; ++i) {
+ if (pointer->raclitable[i].clientid != NULL) {
+ if (strcmp(clientname, pointer->raclitable[i].clientid) == 0) {
+ return pointer->raclitable[i].clientnum;
+ }
+ }
+ }
+
+ if (sscanf(clientname, "%d%c", &i, &guard) == 1) {
+ n = get_raclientnumber(pointer, i);
+ if ((n >= 0) && (n < pointer->raclinum)) {
+ if (pointer->raclitable[n].clientid == NULL) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+get_raclientnumber(RealmT* pointer, int clientid)
+{
+ int i;
+ for (i = 0; i < pointer->raclinum; ++i) {
+ if (pointer->raclitable[i].clientnum == clientid) {
+ return i;
+ }
+ }
+
+ return -1;
+}
diff --git a/src/clientnames.h b/src/clientnames.h
new file mode 100644
index 0000000..c93a2dc
--- /dev/null
+++ b/src/clientnames.h
@@ -0,0 +1,35 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+
+#ifndef _JS_CLIENTNAMES_H
+#define _JS_CLIENTNAMES_H
+
+char* get_clientname(RealmT*, int);
+int get_clientid(RealmT*, char*);
+int get_clientnumber(RealmT*, int);
+
+char* get_raclientname(RealmT*, int);
+int get_raclientid(RealmT*, char*);
+int get_raclientnumber(RealmT*, int);
+
+#endif
+
diff --git a/src/file.c b/src/file.c
new file mode 100644
index 0000000..e4cde62
--- /dev/null
+++ b/src/file.c
@@ -0,0 +1,373 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "file.h"
+#include "activefor.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+
+int
+parse_line(char* buff, char* tab1, char* tab2)
+{
+ int state, i, j, lastDot;
+ state = i = j = 0;
+ lastDot = -1;
+ while (buff[i] != 0) {
+ if (buff[i] == '#') {
+ if ((i > 0) && (buff[i-1] == '\\')) {
+ --j;
+ }
+ else {
+ break;
+ }
+ }
+ switch (state) {
+ case 0: { /* before option name */
+ if (!isspace(buff[i])) {
+ tab1[j] = buff[i];
+ j = 1;
+ state = 1;
+ }
+ break;
+ }
+ case 1: { /* option */
+ if (isspace(buff[i])) {
+ tab1[j] = 0;
+ state = 2;
+ j = 0;
+ }
+ else {
+ tab1[j] = buff[i];
+ ++j;
+ }
+ break;
+ }
+ case 2: { /* before option value */
+ if (!isspace(buff[i])) {
+ if (buff[i] != '.') {
+ tab2[j] = buff[i];
+ j = 1;
+ }
+ state = 3;
+ }
+ break;
+ }
+ case 3: { /* option value */
+ if (buff[i] == '.') {
+ lastDot = j;
+ }
+ else if (!isspace(buff[i])) {
+ lastDot = -1;
+ }
+ else if (lastDot == -1) {
+ lastDot = j;
+ }
+ tab2[j] = buff[i];
+ ++j;
+ break;
+ }
+ }
+ ++i;
+ }
+ if (lastDot != -1) {
+ tab2[lastDot] = 0;
+ }
+ if (state == 3) {
+ return 2;
+ }
+ if (state == 0) {
+ return 0;
+ }
+ return 1;
+}
+
+ConfigurationT
+parsefile(char* name, int* status)
+{
+ static ConfigurationT cfg;
+ FILE* file = NULL;
+ int state, i, n, listencount, managecount;
+ char buff[256];
+ char helpbuf1[256];
+ char helpbuf2[256];
+
+ *status = 1;
+
+ memset(buff, 0, 256);
+
+ cfg.certif = NULL;
+ cfg.keys = NULL;
+ cfg.size = 0;
+ cfg.realmtable = NULL;
+ cfg.logging = 0;
+ cfg.socklogging = 0;
+ cfg.logfnam = NULL;
+ cfg.logsport = NULL;
+ cfg.dateformat = NULL;
+
+ state = F_UNKNOWN;
+
+ file = fopen(name, "r");
+ if (file == NULL) {
+ return cfg;
+ }
+
+ while (fgets(buff, 256, file) != NULL) { /* first loop - counting realm */
+ helpbuf1[0] = 0;
+ parse_line(buff, helpbuf1, helpbuf2);
+ if (strcmp(helpbuf1, "realm")==0) {
+ ++cfg.size;
+ }
+ }
+ rewind(file);
+
+ cfg.realmtable = calloc(cfg.size, sizeof(RealmT));
+ for (i=0; i<cfg.size; ++i) {
+ cfg.realmtable[i].pass[0] = 1;
+ cfg.realmtable[i].pass[1] = 2;
+ cfg.realmtable[i].pass[2] = 3;
+ cfg.realmtable[i].pass[3] = 4;
+ }
+ cfg.size = 0;
+ *status = 0;
+
+ listencount = managecount = 0;
+
+
+ while (fgets(buff, 256, file) != NULL) { /* second loop - counting listen */
+ (*status)++;
+ state = parse_line(buff, helpbuf1, helpbuf2);
+ if (state) {
+ if (strcmp(helpbuf1, "realm")==0) {
+ ++cfg.size;
+ if (listencount != managecount) {
+ return cfg;
+ }
+ listencount = managecount = 0;
+ }
+ else if (strcmp(helpbuf1, "listen")==0) {
+ if (cfg.size == 0) {
+ return cfg;
+ }
+ ++cfg.realmtable[cfg.size-1].usrclinum;
+ ++listencount;
+ }
+ else if (strcmp(helpbuf1, "manage")==0) {
+ if (cfg.size == 0) {
+ return cfg;
+ }
+ ++managecount;
+ }
+ }
+ }
+ rewind(file);
+
+ if (listencount != managecount) {
+ return cfg;
+ }
+
+ for (i=0; i<cfg.size; ++i) {
+ cfg.realmtable[i].usrclitable = calloc(cfg.realmtable[i].usrclinum, sizeof(UsrCliT));
+ }
+
+ cfg.size = 0;
+ *status = 0;
+
+
+ while (fgets(buff, 256, file) != NULL) { /* third loop - parsing file */
+ (*status)++;
+ state = parse_line(buff, helpbuf1, helpbuf2);
+ if (helpbuf1[0] == '#') {
+ memset(buff, 0, 256);
+ continue;
+ }
+ if (state == 1) {
+ if (strcmp(helpbuf1, "realm")==0) {
+ ++cfg.size;
+ TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type);
+ TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type);
+ listencount = managecount = 0;
+ }
+ 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 if (strcmp(helpbuf1, "baseport")==0) {
+ cfg.realmtable[cfg.size-1].baseport = 1;
+ }
+ else if (strcmp(helpbuf1, "dnslookups")==0) {
+ cfg.realmtable[cfg.size-1].dnslookups = 1;
+ }
+ else if (strcmp(helpbuf1, "ipv4")==0) {
+ if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) {
+ TYPE_SET_IPV4(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else if (strcmp(helpbuf1, "ipv6")==0) {
+ if (TYPE_IS_UNSPEC(cfg.realmtable[cfg.size-1].type)) {
+ TYPE_SET_IPV6(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else {
+ return cfg;
+ }
+ }
+ else if (state == 2) {
+ if (strcmp(helpbuf1, "realm")==0) {
+ ++cfg.size;
+ TYPE_SET_SSL(cfg.realmtable[cfg.size-1].type);
+ TYPE_SET_ZLIB(cfg.realmtable[cfg.size-1].type);
+ listencount = managecount = 0;
+ cfg.realmtable[cfg.size-1].realmname = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].realmname, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "certificate")==0) {
+ cfg.certif = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.certif, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "key")==0) {
+ cfg.keys = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.keys, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "heavylog")==0) {
+ if (cfg.logging) {
+ return cfg;
+ }
+ cfg.logging = 3;
+ cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logfnam, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "lightlog")==0) {
+ if (cfg.logging) {
+ return cfg;
+ }
+ cfg.logging = 1;
+ cfg.logfnam = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logfnam, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "heavysocklog")==0) {
+ if (cfg.socklogging) {
+ return cfg;
+ }
+ cfg.socklogging = 3;
+ cfg.logsport = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logsport, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "lightsocklog")==0) {
+ if (cfg.socklogging) {
+ return cfg;
+ }
+ cfg.socklogging = 1;
+ cfg.logsport = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.logsport, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "dateformat")==0) {
+ cfg.dateformat = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.dateformat, helpbuf2);
+ }
+ else if (cfg.size == 0) {
+ return cfg;
+ }
+ else if (strcmp(helpbuf1, "hostname")==0) {
+ cfg.realmtable[cfg.size-1].hostname = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].hostname, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "listen")==0) {
+ cfg.realmtable[cfg.size-1].usrclitable[listencount].lisportnum=calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].usrclitable[listencount].lisportnum, helpbuf2);
+ ++listencount;
+ }
+ else if (strcmp(helpbuf1, "pass")==0) {
+ n = strlen(helpbuf2);
+ memset(cfg.realmtable[cfg.size-1].pass, 0, 4);
+ 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].usrclitable[managecount].manportnum=calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].usrclitable[managecount].manportnum, helpbuf2);
+ ++managecount;
+ }
+ else if (strcmp(helpbuf1, "users")==0) {
+ 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, "raclients")==0) {
+ cfg.realmtable[cfg.size-1].raclients = calloc(strlen(helpbuf2)+1, sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].raclients, 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;
+ }
+ if (strcmp(helpbuf2, "tcp")==0) {
+ TYPE_SET_TCP(cfg.realmtable[cfg.size-1].type);
+ }
+ else if (strcmp(helpbuf2, "udp")==0) {
+ TYPE_SET_UDP(cfg.realmtable[cfg.size-1].type);
+ }
+ else {
+ return cfg;
+ }
+ }
+ else {
+ return cfg;
+ }
+ }
+ memset(buff, 0, 256);
+ }
+
+ fclose(file);
+
+ *status = 0;
+ return cfg;
+}
+
diff --git a/src/file.h b/src/file.h
new file mode 100644
index 0000000..7738df6
--- /dev/null
+++ b/src/file.h
@@ -0,0 +1,37 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+#include "network.h"
+#include <openssl/ssl.h>
+
+#ifndef _JS_FILE_H
+#define _JS_FILE_H
+
+#define F_UNKNOWN 1
+#define F_IGNORE 2
+#define F_ROPTION 3
+#define F_RVALUE 4
+#define F_MIDDLE 5
+
+ConfigurationT parsefile(char*, int*); /* parse the cfg file */
+
+#endif
+
diff --git a/src/first_run.c b/src/first_run.c
new file mode 100644
index 0000000..842a3e0
--- /dev/null
+++ b/src/first_run.c
@@ -0,0 +1,156 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <pwd.h>
+
+static char* home_dir = NULL;
+static char* home_dir_key = NULL;
+static char* home_dir_cer = NULL;
+
+int
+create_apf_dir()
+{
+ int length;
+ struct stat buf;
+ struct passwd *user = getpwuid(getuid());
+ if (user == NULL) {
+ return 1; /* some problems witch fetching user info*/
+ }
+ if (user->pw_dir == NULL) {
+ return 2; /* home directory is not set? */
+ }
+ if (home_dir) {
+ free(home_dir);
+ home_dir = NULL;
+ }
+ length = strlen(user->pw_dir);
+ home_dir = calloc(1, length + 6);
+ if (home_dir == NULL) {
+ return 3; /* calloc failed */
+ }
+ strcpy(home_dir, user->pw_dir);
+ if (home_dir[length] == '/') {
+ strcpy(&home_dir[length], ".apf");
+ }
+ else {
+ strcpy(&home_dir[length], "/.apf");
+ }
+ if (stat(home_dir, &buf)) {
+ if (mkdir(home_dir, 0700)) {
+ return 4; /* creating directory failed */
+ }
+ }
+ return 0;
+}
+
+int
+generate_rsa_key(char** keyfile)
+{
+ int key_length, home_length, status;
+ char openssl_cmd[101];
+ struct stat buf;
+ /* check in local directory first */
+ if (stat(*keyfile, &buf) == 0) {
+ return 0;
+ }
+ /* check in home_dir */
+ key_length = strlen(*keyfile);
+ home_length = strlen(home_dir);
+ if (home_dir_key) {
+ free(home_dir_key);
+ home_dir_key = NULL;
+ }
+ home_dir_key = calloc(1, home_length + key_length + 2);
+ if (home_dir_key == NULL) {
+ return 1; /* calloc failed */
+ }
+ strcpy(home_dir_key, home_dir);
+ home_dir_key[home_length] = '/';
+ strcpy(&home_dir_key[home_length+1], *keyfile);
+ *keyfile = home_dir_key;
+ if (stat(home_dir_key, &buf) == 0) {
+ return 0;
+ }
+ /* have to generate the key */
+ if (snprintf(openssl_cmd, 101, "openssl genrsa -out %s 2048", home_dir_key) > 100) {
+ return 2; /* string is too long */
+ }
+ status = system(openssl_cmd);
+ if (status == -1) {
+ return -1;
+ }
+ return WEXITSTATUS(status);
+}
+
+int
+generate_certificate(char** cerfile, char* keyfile)
+{
+ int cer_length, home_length, status, tmp_fd1, tmp_fd2;
+ char openssl_cmd[301];
+ struct stat buf;
+ /* check in local directory first */
+ if (stat(*cerfile, &buf) == 0) {
+ return 0;
+ }
+ /* check in home_dir */
+ cer_length = strlen(*cerfile);
+ home_length = strlen(home_dir);
+ if (home_dir_cer) {
+ free(home_dir_cer);
+ home_dir_cer = NULL;
+ }
+ home_dir_cer = calloc(1, home_length + cer_length + 2);
+ if (home_dir_cer == NULL) {
+ return 1; /* calloc failed */
+ }
+ strcpy(home_dir_cer, home_dir);
+ home_dir_cer[home_length] = '/';
+ strcpy(&home_dir_cer[home_length+1], *cerfile);
+ *cerfile = home_dir_cer;
+ if (stat(home_dir_cer, &buf) == 0) {
+ return 0;
+ }
+ /* have to generate the certificate */
+ if (snprintf(openssl_cmd, 201, "echo -e \"pl\nWar-Maz\nOlsztyn\nSHEG\nUtils productions\njeremian\njeremian@poczta.fm\" | openssl req -new -x509 -key %s -out %s -days 1095", keyfile, home_dir_cer) > 300) {
+ return 2; /* string is too long */
+ }
+ tmp_fd1 = dup(STDOUT_FILENO);
+ tmp_fd2 = dup(STDERR_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ status = system(openssl_cmd);
+ dup2(tmp_fd1, STDOUT_FILENO);
+ dup2(tmp_fd2, STDERR_FILENO);
+ close(tmp_fd1);
+ close(tmp_fd2);
+ if (status == -1) {
+ return -1;
+ }
+ return WEXITSTATUS(status);
+}
diff --git a/src/first_run.h b/src/first_run.h
new file mode 100644
index 0000000..5a36ff6
--- /dev/null
+++ b/src/first_run.h
@@ -0,0 +1,29 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_FIRST_RUN_H
+#define _JS_FIRST_RUN_H
+
+int create_apf_dir();
+int generate_rsa_key(char**);
+int generate_certificate(char**, char*);
+
+#endif
+
diff --git a/src/inet_ntop.c b/src/inet_ntop.c
new file mode 100644
index 0000000..6d37620
--- /dev/null
+++ b/src/inet_ntop.c
@@ -0,0 +1,227 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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.
+ *
+ */
+
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "inet_ntop.h"
+
+#ifndef HAVE_THIS_INET_NTOP
+#define HAVE_THIS_INET_NTOP
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: inet_ntop.c,v 8.5 1996/05/22 04:56:30 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#define IN6ADDRSZ 16
+#define INT16SZ 2
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
+#ifdef AF_INET6
+static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
+#endif
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+ int af;
+ const void *src;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+#ifdef AF_INET6
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
+ if (strlen(tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+#ifdef AF_INET6
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[IN6ADDRSZ / INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, 0, sizeof words);
+ for (i = 0; i < IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ sprintf(tp, "%x", words[i]);
+ tp += strlen(tp);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+#endif
+
+#endif
diff --git a/src/inet_ntop.h b/src/inet_ntop.h
new file mode 100644
index 0000000..9e49f1f
--- /dev/null
+++ b/src/inet_ntop.h
@@ -0,0 +1,36 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef HAVE_INET_NTOP
+
+#include <sys/types.h>
+
+# ifndef _JS_INET_NTOP_H
+# define _JS_INET_NTOP_H
+
+const char* inet_ntop(int af, const void *src, char *dst, size_t size);
+
+# endif
+
+#endif
diff --git a/src/make_ssl_handshake.c b/src/make_ssl_handshake.c
new file mode 100644
index 0000000..a5c97eb
--- /dev/null
+++ b/src/make_ssl_handshake.c
@@ -0,0 +1,103 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "make_ssl_handshake.h"
+#include "stats.h"
+
+#include <config.h>
+
+#include <errno.h>
+#include <openssl/err.h>
+
+void
+make_ssl_initialize(clifd *cliconn)
+{
+ if (SSL_set_fd(cliconn->ssl, cliconn->commfd) != 1) {
+ aflog(0, "Problem with initializing ssl... exiting");
+ exit(1);
+ }
+}
+
+int
+make_ssl_accept(clifd *cliconn)
+{
+ int result;
+ if ((result = SSL_accept(cliconn->ssl)) != 1) {
+ return get_ssl_error(cliconn, " SSL_accept has failed", result);
+ }
+ return 0;
+}
+
+int
+get_ssl_error(clifd *cliconn, char* info, int result)
+{
+ int merror;
+#ifdef HAVE_ERR_ERROR_STRING
+ char err_buff[200];
+#endif
+ merror = SSL_get_error(cliconn->ssl, result);
+ switch (merror) {
+ case SSL_ERROR_NONE : {
+ aflog(2, "%s(%d): none", info, result);
+ break;
+ }
+ case SSL_ERROR_ZERO_RETURN : {
+ aflog(2, "%s(%d): zero", info, result);
+ break;
+ }
+ case SSL_ERROR_WANT_READ : {
+ aflog(2, "%s(%d): w_read", info, result);
+ break;
+ }
+ case SSL_ERROR_WANT_WRITE : {
+ aflog(2, "%s(%d): w_write", info, result);
+ break;
+ }
+ case SSL_ERROR_WANT_CONNECT : {
+ aflog(2, "%s(%d): w_connect", info, result);
+ break;
+ }
+ case SSL_ERROR_WANT_X509_LOOKUP : {
+ aflog(2, "%s(%d): w_x509_lookup", info, result);
+ break;
+ }
+ case SSL_ERROR_SYSCALL : {
+ aflog(2, "%s(%d): syscall", info, result);
+ break;
+ }
+ case SSL_ERROR_SSL : {
+ SSL_load_error_strings();
+#ifdef HAVE_ERR_ERROR_STRING
+ aflog(2, "%s(%d): ssl:%s", info, result,
+ ERR_error_string(ERR_get_error(), err_buff));
+#else
+ aflog(2, "%s(%d): ssl", info, result);
+#endif
+ break;
+ }
+ default: {
+ aflog(2, "%s(%d): unrecognized error (%d)", info, result, errno);
+ }
+ }
+ if (merror == SSL_ERROR_WANT_READ) {
+ return 1;
+ }
+ return 2;
+}
diff --git a/src/make_ssl_handshake.h b/src/make_ssl_handshake.h
new file mode 100644
index 0000000..674867a
--- /dev/null
+++ b/src/make_ssl_handshake.h
@@ -0,0 +1,31 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "network.h"
+
+#ifndef _JS_MAKE_SSL_HANDSHAKE_H
+#define _JS_MAKE_SSL_HANDSHAKE_H
+
+void make_ssl_initialize(clifd *cliconn);
+int make_ssl_accept(clifd *cliconn);
+int get_ssl_error(clifd *cliconn, char* info, int result);
+
+#endif
+
diff --git a/src/modules.c b/src/modules.c
new file mode 100644
index 0000000..0d153be
--- /dev/null
+++ b/src/modules.c
@@ -0,0 +1,69 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#ifdef HAVE_LIBDL
+
+#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;
+}
+
+#endif
diff --git a/src/modules.h b/src/modules.h
new file mode 100644
index 0000000..f6f8ea9
--- /dev/null
+++ b/src/modules.h
@@ -0,0 +1,43 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#ifdef HAVE_LIBDL
+
+# 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
+
+#endif
diff --git a/src/network.c b/src/network.c
new file mode 100644
index 0000000..7618c76
--- /dev/null
+++ b/src/network.c
@@ -0,0 +1,484 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <config.h>
+
+#include "inet_ntop.h"
+#include "network.h"
+#include "activefor.h"
+#include "stats.h"
+#include <string.h>
+#include <errno.h>
+#include <zlib.h>
+
+int
+ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type)
+{
+#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
+ int n;
+ const int on = 1;
+ struct addrinfo hints, *res, *ressave;
+
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE;
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
+
+ if (type & 0x01) {
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
+
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ return n;
+ }
+ ressave = res;
+
+ do {
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
+ continue; /* error, try next one */
+ }
+
+ if (type & 0x01) { /* tcp_listen */
+ setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ }
+ if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
+ break; /* success */
+ }
+
+ close((*sockfd)); /* bind error, close and try next one */
+ } while ( (res = res->ai_next) != NULL);
+
+ if (res == NULL) { /* errno from final socket() or bind() */
+ return 1;
+ }
+
+ if (type & 0x01) { /* tcp_listen */
+ listen((*sockfd), 1);
+ }
+
+ if (addrlenp) {
+ *addrlenp = res->ai_addrlen; /* return size of protocol address */
+ }
+
+ freeaddrinfo(ressave);
+#else
+ struct sockaddr_in servaddr;
+ struct hostent* hostaddr;
+ int port;
+
+ if (type & 0x01) {
+ (*sockfd) = socket(AF_INET, SOCK_STREAM, 0);
+ }
+ else {
+ (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0);
+ }
+
+ if ((*sockfd) == -1) {
+ return 1;
+ }
+ port = atoi(serv);
+
+ if (host) {
+ hostaddr = gethostbyname(host);
+ if (hostaddr == NULL) {
+ return 2;
+ }
+ }
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ if (host) {
+ memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length);
+ }
+ else {
+ servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ servaddr.sin_port = htons(port);
+
+ if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){
+ return 4;
+ }
+
+ if (listen((*sockfd), 5)){
+ return 5;
+ }
+#endif
+
+ return(0);
+}
+
+int
+ip_connect(int* sockfd, const char *host, const char *serv, const char type)
+{
+#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
+ int n;
+ struct addrinfo hints, *res, *ressave;
+
+ bzero(&hints, sizeof(struct addrinfo));
+ if (type & 0x02) {
+ hints.ai_family = AF_INET;
+ }
+ else if (type & 0x04) {
+ hints.ai_family = AF_INET6;
+ }
+ else {
+ hints.ai_family = AF_UNSPEC;
+ }
+ if (type & 0x01) {
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
+
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ return n;
+ }
+ ressave = res;
+
+ do {
+ (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if ((*sockfd) < 0) {
+ continue; /* ignore this one */
+ }
+
+ if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) {
+ break; /* success */
+ }
+
+ close((*sockfd)); /* ignore this one */
+ } while ( (res = res->ai_next) != NULL);
+
+ if (res == NULL) { /* errno set from final connect() */
+ return 1;
+ }
+
+ freeaddrinfo(ressave);
+#else
+ struct sockaddr_in servaddr;
+ struct hostent* hostaddr;
+ int port;
+
+ if (type & 0x01) {
+ (*sockfd) = socket(AF_INET, SOCK_STREAM, 0);
+ }
+ else {
+ (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0);
+ }
+
+ if ((*sockfd) == -1) {
+ return 1;
+ }
+ port = atoi(serv);
+
+ hostaddr = gethostbyname(host);
+ if (hostaddr == NULL) {
+ return 2;
+ }
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(port);
+ memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length);
+
+ if (connect((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){
+ return 3;
+ }
+#endif
+
+ return(0);
+}
+
+char *
+sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf, char type)
+{
+ char portstr[7];
+ static char str[136]; /* Unix domain is largest */
+
+ switch (sa->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+
+ if (type) {
+#ifdef HAVE_GETNAMEINFO
+ if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
+ return NULL;
+ }
+#else
+ struct hostent* hostname;
+ if ((hostname = gethostbyaddr(&sin->sin_addr, sizeof(struct in_addr), AF_INET))) {
+ strncpy(str, hostname->h_name, 127);
+ str[127] = 0;
+ }
+ else {
+ if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+#endif
+
+ }
+ else {
+ if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+ if (namebuf) {
+ memcpy(namebuf, str, 128);
+ }
+ if (ntohs(sin->sin_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin->sin_port));
+ }
+ strcat(str, portstr);
+ }
+ return(str);
+ }
+#ifdef AF_INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+
+ if (type) {
+#ifdef HAVE_GETNAMEINFO
+ if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) {
+ return NULL;
+ }
+#else
+ struct hostent* hostname;
+ if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) {
+ strncpy(str, hostname->h_name, 127);
+ str[127] = 0;
+ }
+ else {
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+#endif
+
+ }
+ else {
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) {
+ return NULL;
+ }
+ }
+ if (namebuf) {
+ memcpy(namebuf, str, 128);
+ }
+ if (ntohs(sin6->sin6_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port));
+ if (portbuf) {
+ snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port));
+ }
+ strcat(str, portstr);
+ }
+ return(str);
+ }
+#endif
+ default: {
+ snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen);
+ return(str);
+ }
+ }
+ return NULL;
+}
+
+int
+SSL_writen(SSL* fd, unsigned char* buf, int amount)
+{
+ int sent, n;
+ sent = 0;
+ while (sent < amount) {
+ n = SSL_write(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
+}
+
+int
+SSL_readn(SSL* fd, unsigned char* buf, int amount)
+{
+ int sent, n;
+ sent = 0;
+ while (sent < amount) {
+ n = SSL_read(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == 0)
+ return 0;
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
+}
+
+int
+writen(int fd, unsigned char* buf, int amount)
+{
+ int sent, n;
+ sent = 0;
+ while (sent < amount) {
+ n = write(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
+}
+
+int
+readn(int fd, unsigned char* buf, int amount)
+{
+ int sent, n;
+ sent = 0;
+ while (sent < amount) {
+ n = read(fd, buf+sent, amount - sent);
+ if (n != -1) {
+ sent += n;
+ }
+ if (n == 0)
+ return 0;
+ if (n == -1) {
+ if (errno != EAGAIN)
+ return 0;
+ }
+ }
+ return amount;
+
+}
+
+int
+send_message(char type, clifd fd, unsigned char* buf, int amount)
+{
+ unsigned long clen;
+ int length;
+ static unsigned char bufor[9000];
+ aflog(4, " send_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no",
+ (TYPE_IS_ZLIB(type))?"yes":"no", amount);
+ clen = 8995;
+ length = amount - 5;
+ if (TYPE_IS_ZLIB(type)) {
+ memcpy(bufor, buf, 5);
+ if (amount > 5) {
+ compress(&bufor[5], &clen, &buf[5], length);
+ if (clen < length) {
+ length = clen;
+ TYPE_SET_COMP(length);
+ bufor[3] = length >> 8; /* high bits of message length */
+ bufor[4] = length; /* low bits of message length */
+ addtocg(amount-5 - clen);
+ }
+ }
+ if (TYPE_IS_SSL(type)) {
+ if (TYPE_IS_COMP(length)) {
+ return SSL_writen(fd.ssl, bufor, clen+5);
+ }
+ else {
+ return SSL_writen(fd.ssl, buf, amount);
+ }
+ }
+ else {
+ if (TYPE_IS_COMP(length)) {
+ return writen(fd.commfd, bufor, clen+5);
+ }
+ else {
+ return writen(fd.commfd, buf, amount);
+ }
+ }
+ }
+ else {
+ if (TYPE_IS_SSL(type)) {
+ return SSL_writen(fd.ssl, buf, amount);
+ }
+ else {
+ return writen(fd.commfd, buf, amount);
+ }
+ }
+}
+
+int
+get_message(char type, clifd fd, unsigned char* buf, int amount)
+{
+ int length;
+ unsigned long elen;
+ static unsigned char bufor[9000];
+ aflog(4, " get_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no",
+ (TYPE_IS_ZLIB(type))?"yes":"no", amount);
+ if (amount == -5) {
+ if (TYPE_IS_SSL(type)) {
+ return SSL_read(fd.ssl, buf, 5);
+ }
+ else {
+ return read(fd.commfd, buf, 5);
+ }
+ }
+ if (TYPE_IS_ZLIB(type)) {
+ if (TYPE_IS_SSL(type)) {
+ length = SSL_readn(fd.ssl, bufor, amount&0xBFFF);
+ }
+ else {
+ length = readn(fd.commfd, bufor, amount&0xBFFF);
+ }
+ if (length <= 0) return length;
+ elen = 8096;
+ if (TYPE_IS_COMP(amount)) {
+ uncompress(buf, &elen, bufor, length);
+ }
+ else {
+ memcpy(buf, bufor, length);
+ elen = length;
+ }
+ return elen;
+ }
+ else
+ {
+ if (TYPE_IS_SSL(type)) {
+ return SSL_readn(fd.ssl, buf, amount);
+ }
+ else {
+ return readn(fd.commfd, buf, amount);
+ }
+ }
+}
diff --git a/src/network.h b/src/network.h
new file mode 100644
index 0000000..401a627
--- /dev/null
+++ b/src/network.h
@@ -0,0 +1,54 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_NETWORK_H
+#define _JS_NETWORK_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <netdb.h>
+#include <openssl/ssl.h>
+
+typedef struct {
+ int commfd;
+ SSL* ssl;
+} clifd;
+
+int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */
+int ip_connect(int* sockfd, const char *host, const char *serv, const char type); /* socket, connect... */
+char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf, char type); /* return the IP of connected user */
+
+int send_message(char type, clifd fd, unsigned char* buf, int amount);
+int get_message(char type, clifd fd, unsigned char* buf, int amount);
+
+int SSL_writen(SSL* fd, unsigned char* buf, int amount);
+int SSL_readn(SSL* fd, unsigned char* buf, int amount);
+int writen(int fd, unsigned char* buf, int amount);
+int readn(int fd, unsigned char* buf, int amount);
+
+#endif
diff --git a/src/realmnames.c b/src/realmnames.c
new file mode 100644
index 0000000..84d9f53
--- /dev/null
+++ b/src/realmnames.c
@@ -0,0 +1,62 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <stdio.h>
+#include <string.h>
+#include "realmnames.h"
+
+char*
+get_realmname(ConfigurationT* config, int realm)
+{
+ static char realmname[10];
+
+ if (config->realmtable[realm].realmname == NULL) {
+ memset(realmname, 0, 10);
+ sprintf(realmname, "%d", realm);
+ return realmname;
+ }
+
+ return config->realmtable[realm].realmname;
+}
+
+int
+get_realmnumber(ConfigurationT* config, char* realmname)
+{
+ int i;
+ char guard;
+
+ for (i = 0; i < config->size; ++i) {
+ if (config->realmtable[i].realmname != NULL) {
+ if (strcmp(realmname, config->realmtable[i].realmname) == 0) {
+ return i;
+ }
+ }
+ }
+
+ if (sscanf(realmname, "%d%c", &i, &guard) == 1) {
+ if ((i >= 0) && (i < config->size)) {
+ if (config->realmtable[i].realmname == NULL) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
diff --git a/src/realmnames.h b/src/realmnames.h
new file mode 100644
index 0000000..70ad46f
--- /dev/null
+++ b/src/realmnames.h
@@ -0,0 +1,30 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+
+#ifndef _JS_REALMNAMES_H
+#define _JS_REALMNAMES_H
+
+char* get_realmname(ConfigurationT*, int);
+int get_realmnumber(ConfigurationT*, char*);
+
+#endif
+
diff --git a/src/remoteadmin.c b/src/remoteadmin.c
new file mode 100644
index 0000000..4e777c1
--- /dev/null
+++ b/src/remoteadmin.c
@@ -0,0 +1,503 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "remoteadmin.h"
+
+static char newmessage;
+
+static int
+parse_cmd(unsigned char* buff, int* ret)
+{
+ int i, j, state;
+ char cmd[31];
+
+ i = j = state = 0;
+ newmessage = 1;
+ while (buff[i] != 0) {
+ if (state == 1) {
+ if (isspace(buff[i])) {
+ break;
+ }
+ else {
+ if (j == 30) {
+ return 0;
+ }
+ cmd[j] = buff[i];
+ ++j;
+ }
+ }
+ if (state == 0) {
+ if (!isspace(buff[i])) {
+ cmd[j] = buff[i];
+ j = 1;
+ state = 1;
+ }
+ }
+ ++i;
+ }
+ if (state == 0) {
+ return 0;
+ }
+ while (isspace(buff[i])) {
+ ++i;
+ }
+ if (buff[i] == '.') {
+ ++i;
+ }
+ (*ret) = i;
+ cmd[j] = 0;
+ if (strcmp(cmd, "help") == 0) { return 1; }
+ if (strcmp(cmd, "lcmd") == 0) { return 2; }
+ if (strcmp(cmd, "info") == 0) { return 3; }
+ if (strcmp(cmd, "rshow") == 0) { return 4; }
+ if (strcmp(cmd, "cshow") == 0) { return 5; }
+ if (strcmp(cmd, "ushow") == 0) { return 6; }
+ if (strcmp(cmd, "quit") == 0) { return 7; }
+ return 0;
+}
+
+static void
+send_adm_message(char type, clifd master, unsigned char* buff, unsigned char st)
+{
+ int n;
+ if (!newmessage) {
+ n = strlen((char*) &buff[5]);
+ }
+ else {
+ n = 0;
+ }
+ buff[0] = AF_S_ADMIN_CMD;
+ buff[1] = st;
+ buff[2] = AF_RA_UNDEFINED;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(type, master, buff, n+5);
+}
+
+static void
+add_to_message(unsigned char* buff, const char* format, ...)
+{
+ va_list ap;
+ int n;
+ if (!newmessage) {
+ n = strlen((char*) &buff[5]);
+ }
+ else {
+ n = 0;
+ }
+ newmessage = 0;
+ va_start(ap, format);
+
+ vsprintf((char*) &buff[5+n], format, ap);
+ n = strlen((char*) &buff[5]);
+ sprintf((char*) &buff[5+n], "\n");
+
+ va_end(ap);
+}
+
+static void
+add_uptime_to_message(unsigned char* buff, char* info, time_t period)
+{
+ int hours, minutes, seconds;
+
+ hours = period/3600;
+ minutes = (period/60)%60;
+ seconds = period%60;
+
+ if (hours) {
+ add_to_message(buff, "%s: %d:%02d:%02d", info, hours, minutes, seconds);
+ }
+ else {
+ add_to_message(buff, "%s: %d:%02d", info, minutes, seconds);
+ }
+}
+
+int
+serve_admin(ConfigurationT* config, int realm, int client, unsigned char* buff)
+{
+ int length, n, i, j, ret;
+ time_t now, tmp;
+ char type = config->realmtable[realm].type | TYPE_SSL | TYPE_ZLIB;
+ clifd master = config->realmtable[realm].raclitable[client].cliconn;
+
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+
+ time(&now);
+
+ switch (buff[1]) {
+ case AF_RA_CMD: {
+ n = get_message(type, master, buff, length);
+ buff[n] = 0;
+ aflog(2, " realm[%s]: admin: message length = %d [%s]",
+ get_realmname(config, realm), n, buff);
+ switch (parse_cmd(buff, &ret)) {
+ case 1: { /* help */
+ add_to_message(buff, AF_VER("AFSERVER"));
+ add_to_message(buff, "\nValid commands are:");
+ add_to_message(buff, " help display help");
+ add_to_message(buff, " lcmd lists available commands");
+ add_to_message(buff, " info prints info about server");
+ add_to_message(buff, " rshow display realms");
+ add_to_message(buff, " cshow X display clients in X realm");
+ add_to_message(buff, " ushow X display users in X realm");
+ add_to_message(buff, " quit quit connection");
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ case 2: { /* lcmd */
+ add_to_message(buff, "help");
+ add_to_message(buff, "lcmd");
+ add_to_message(buff, "info");
+ add_to_message(buff, "rshow");
+ add_to_message(buff, "cshow");
+ add_to_message(buff, "ushow");
+ add_to_message(buff, "quit");
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ case 3: { /* info */
+ add_to_message(buff, AF_VER("Version:"));
+ add_to_message(buff, "Realms: %d", config->size);
+ add_to_message(buff, "Certificate: %s", config->certif);
+ add_to_message(buff, "Key: %s", config->keys);
+ if (config->logging) {
+ add_to_message(buff, "logfile: %s (verbosity:%d)",
+ config->logfnam, config->logging);
+ }
+ else {
+ add_to_message(buff, "no logfile");
+ }
+ if (config->socklogging) {
+ add_to_message(buff, "logsocket: %s (verbosity:%d)",
+ config->logsport, config->socklogging);
+ }
+ else {
+ add_to_message(buff, "no logsocket");
+ }
+ tmp = now - config->starttime;
+ add_uptime_to_message(buff, "Uptime", tmp);
+ add_to_message(buff, "Cg: %ld B", getcg());
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ case 4: { /* rshow */
+ for (i = 0; i < config->size; ++i) {
+ add_to_message(buff, "\nRealm[%s]:", get_realmname(config, i));
+ add_to_message(buff, "hostname: %s", config->realmtable[i].hostname);
+ add_to_message(buff, "users: %d (max: %d)",
+ config->realmtable[i].usercon, config->realmtable[i].usernum);
+ add_to_message(buff, "clients: %d (max: %d)",
+ config->realmtable[i].clicon-config->realmtable[i].raclicon,
+ config->realmtable[i].clinum);
+ add_to_message(buff, "raclients: %d (max: %d)",
+ config->realmtable[i].raclicon, config->realmtable[i].raclinum);
+ add_to_message(buff, "users per client: %s", config->realmtable[i].usrpcli);
+ add_to_message(buff, "user-client pairs: %d",
+ config->realmtable[i].usrclinum);
+ for (j = 0; j < config->realmtable[i].usrclinum; ++j) {
+ add_to_message(buff, " pair[%d]: listenport: %s, manageport: %s", j,
+ config->realmtable[i].usrclitable[j].lisportnum,
+ config->realmtable[i].usrclitable[j].manportnum);
+ }
+ add_to_message(buff, "climode: %s", config->realmtable[i].clim);
+ add_to_message(buff, "timeout: %s", config->realmtable[i].timeout);
+ add_to_message(buff, "baseport: %s", config->realmtable[i].baseport ?
+ "yes" : "no");
+ add_to_message(buff, "ssl: %s, zlib: %s, mode: %s",
+ (TYPE_IS_SSL(config->realmtable[i].type))?"yes":"no",
+ (TYPE_IS_ZLIB(config->realmtable[i].type))?"yes":"no",
+ (TYPE_IS_TCP(config->realmtable[i].type))?"tcp":"udp");
+ }
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ case 5: { /* cshow*/
+ n = get_realmnumber(config, (char*) &buff[ret]);
+ if ((n >= 0) && (n < config->size)) {
+ for (i = 0; i < config->realmtable[n].clinum; ++i) {
+ if (config->realmtable[n].clitable[i].ready) {
+ add_to_message(buff, "\nClient[%s]:",
+ get_clientname(&(config->realmtable[n]), i));
+ switch (config->realmtable[n].clitable[i].ready) {
+ case 1: {
+ add_to_message(buff, "state: ssl handshake");
+ break;
+ }
+ case 2: {
+ add_to_message(buff, "state: authorization");
+ break;
+ }
+ case 3: {
+ add_to_message(buff, "state: running");
+ break;
+ }
+ default: {
+ add_to_message(buff, "state: unknown");
+ }
+ }
+ add_to_message(buff, "users: %d (max: %d)",
+ config->realmtable[n].clitable[i].usercon,
+ config->realmtable[n].clitable[i].usernum);
+ add_to_message(buff, "user-client pair: %d",
+ config->realmtable[n].clitable[i].whatusrcli);
+ tmp = now - config->realmtable[n].clitable[i].connecttime;
+ add_uptime_to_message(buff, "Connection time", tmp);
+ add_to_message(buff, "Id: %s",
+ (config->realmtable[n].clitable[i].clientid == NULL)?"":
+ config->realmtable[n].clitable[i].clientid);
+ add_to_message(buff, "IP: %s, port: %s",
+ config->realmtable[n].clitable[i].namebuf,
+ config->realmtable[n].clitable[i].portbuf);
+ }
+ }
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ add_to_message(buff, "Wrong realm name");
+ send_adm_message(type, master, buff, AF_RA_FAILED);
+ break;
+ }
+ case 6: { /* ushow */
+ n = get_realmnumber(config, (char*) &buff[ret]);
+ if ((n >= 0) && (n < config->size)) {
+ for (i = 0; i < config->realmtable[n].usernum; ++i) {
+ if (config->realmtable[n].contable[i].state != S_STATE_CLEAR) {
+ add_to_message(buff, "\nUser[%d]:",
+ get_username(&(config->realmtable[n]), i));
+ switch (config->realmtable[n].contable[i].state) {
+ case S_STATE_CLOSING: {
+ add_to_message(buff, "state: closing");
+ break;
+ }
+ case S_STATE_OPENING: {
+ add_to_message(buff, "state: opening");
+ break;
+ }
+ case S_STATE_OPEN: {
+ add_to_message(buff, "state: running");
+ break;
+ }
+ case S_STATE_STOPPED: {
+ add_to_message(buff, "state: stopped");
+ break;
+ }
+ default: {
+ add_to_message(buff, "state: unknown");
+ }
+ }
+ add_to_message(buff, "connected to: Client[%s]",
+ get_clientname(&(config->realmtable[n]),
+ config->realmtable[n].contable[i].whatcli));
+ tmp = now - config->realmtable[n].contable[i].connecttime;
+ add_uptime_to_message(buff, "Connection time", tmp);
+ add_to_message(buff, "IP: %s, port: %s",
+ config->realmtable[n].contable[i].namebuf,
+ config->realmtable[n].contable[i].portbuf);
+ }
+ }
+ send_adm_message(type, master, buff, AF_RA_STATUS_OK);
+ break;
+ }
+ add_to_message(buff, "Wrong realm name");
+ send_adm_message(type, master, buff, AF_RA_FAILED);
+ break;
+ }
+ case 7: { /* quit */
+ aflog(1, " realm[%s]: Client[%s] (ra): commfd: CLOSED",
+ get_realmname(config, realm),
+ get_raclientname(&(config->realmtable[realm]), client));
+ send_adm_message(type, master, buff, AF_RA_KICKED);
+ return 1;
+ }
+ default: {
+ aflog(2, " realm[%s]: admin: cmd ignored", get_realmname(config, realm));
+ send_adm_message(type, master, buff, AF_RA_UNDEFINED);
+ }
+ }
+ break;
+ }
+ case AF_RA_REPEAT: {
+ break;
+ }
+ default: {
+ aflog(1, "Unrecognized message from remote admin --> closing");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+client_admin(char type, clifd master, unsigned char* buff, int connectfd, char* id)
+{
+ fd_set rset, allset;
+ int maxfdp1, n, length, infd;
+ FILE *outfp, *infp;
+
+ buff[0] = AF_S_ADMIN_LOGIN;
+ send_message(type, master, buff, 5);
+ buff[0] = 0;
+ get_message(type, master, buff, -5);
+
+ if ( buff[0] == 0 ) {
+ aflog(0, "Wrong password");
+ return 1;
+ }
+ if ( buff[0] == AF_S_CANT_OPEN ) {
+ aflog(0, "Server is full");
+ return 1;
+ }
+ if ( buff[0] != AF_S_ADMIN_LOGIN ) {
+ aflog(0, "Incompatible server type or server full");
+ return 1;
+ }
+
+ aflog(1, "CLIENT STARTED mode: remote administration");
+
+ if (connectfd > 0) {
+ outfp = fdopen(connectfd, "w");
+ if (outfp == NULL) {
+ aflog(0, "Error in opening file descriptor for writing");
+ return 1;
+ }
+ infd = connectfd;
+ }
+ else {
+ infd = STDIN_FILENO;
+ outfp = stdout;
+ }
+ infp = fdopen(infd, "r");
+ if (infp == NULL) {
+ aflog(0, "Error in opening file descriptor for reading");
+ return 1;
+ }
+
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+ n = get_message(type, master, buff, length);
+ buff[n] = 0;
+ fprintf(outfp, "%s\n", (char*) buff);
+ fflush(outfp);
+
+ FD_ZERO(&allset);
+
+ FD_SET(master.commfd, &allset);
+ FD_SET(infd, &allset);
+
+ maxfdp1 = (infd > master.commfd) ? infd+1: master.commfd+1;
+
+ if (id != NULL) {
+ buff[0] = AF_S_LOGIN;
+ buff[1] = buff[2] = 0;
+ n = strlen(id);
+ memcpy(&buff[5], id, n);
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(type, master, buff, n+5);
+ aflog(1, "ID SENT: %s", id);
+ }
+
+ while (1) {
+ rset = allset;
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+
+ if (FD_ISSET(master.commfd, &rset)) {
+ aflog(3, " masterfd: FD_ISSET");
+ n = get_message(type, master, buff, 5);
+ if (n != 5) {
+ aflog(2, " FATAL ERROR! (%d)", n);
+ if (n == -1) {
+ if (TYPE_IS_SSL(type)) {
+ get_ssl_error(&master, "FE", n);
+ continue; /* what happened? */
+ }
+ }
+ if (n != 0)
+ return 1;
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ aflog(0, " SERVER: premature quit --> exiting...");
+ return 1;
+ }
+ if (buff[0] == AF_S_CLOSING) {
+ aflog(0, " SERVER: CLOSED -> exiting... cg: %ld bytes", getcg());
+ return 0;
+ }
+ if (buff[0] != AF_S_ADMIN_CMD) {
+ aflog(0, " SERVER: wrong message --> exiting");
+ return 1;
+ }
+ length = buff[3];
+ length = length << 8;
+ length += buff[4]; /* this is length of message */
+
+ switch (buff[1]) {
+ case AF_RA_STATUS_OK: {
+ aflog(1, " SERVER: cmd successful");
+ }
+ case AF_RA_FAILED: {
+ if (buff[1] == AF_RA_FAILED) {
+ aflog(1, " SERVER: cmd failed");
+ }
+ }
+ case AF_RA_UNDEFINED: {
+ if (buff[1] == AF_RA_UNDEFINED) {
+ aflog(1, " SERVER: unknown cmd");
+ }
+ n = get_message(type, master, buff, length);
+ buff[n] = 0;
+ fprintf(outfp, "%s", (char*) buff);
+ fflush(outfp);
+ break;
+ }
+ case AF_RA_KICKED: {
+ aflog(0, " SERVER: kicked us -> exiting... cg: %ld bytes", getcg());
+ return 1;
+ break;
+ }
+ default: {
+ aflog(0, " SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg());
+ return 1;
+ }
+ }
+ }
+
+ if (FD_ISSET(infd, &rset)) {
+ aflog(3, " infd: FD_ISSET");
+ if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */
+ aflog(0, " CLIENT CLOSED cg: %ld bytes", getcg());
+ return 0;
+ }
+ n = strlen((char*) &buff[5]);
+ if ((n > 0) && (buff[n+4] == '\n')) {
+ --n;
+ }
+ buff[0] = AF_S_ADMIN_CMD;
+ buff[1] = AF_RA_CMD;
+ buff[2] = AF_RA_UNDEFINED;
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ send_message(type, master, buff, n+5);
+ }
+ }
+}
diff --git a/src/remoteadmin.h b/src/remoteadmin.h
new file mode 100644
index 0000000..cad9c76
--- /dev/null
+++ b/src/remoteadmin.h
@@ -0,0 +1,49 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "file.h"
+#include "stats.h"
+#include "activefor.h"
+#include "realmnames.h"
+#include "clientnames.h"
+#include "usernames.h"
+#include "make_ssl_handshake.h"
+
+#include <openssl/err.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifndef _JS_REMOTEADMIN_H
+#define _JS_REMOTEADMIN_H
+
+#define AF_RA_UNDEFINED 0
+#define AF_RA_CMD 1
+#define AF_RA_REPEAT 2
+#define AF_RA_STATUS_OK 3
+#define AF_RA_NOT_KNOWN 4
+#define AF_RA_FAILED 5
+#define AF_RA_KICKED 6
+
+int serve_admin(ConfigurationT*, int, int, unsigned char*);
+int client_admin(char, clifd, unsigned char*, int, char*);
+
+#endif
+
diff --git a/src/server_check.c b/src/server_check.c
new file mode 100644
index 0000000..94069cc
--- /dev/null
+++ b/src/server_check.c
@@ -0,0 +1,61 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "stats.h"
+
+void
+check_value(int* where, char* what, char* info)
+{
+ char* znak;
+ long tmp;
+ if ((tmp = strtol(what, &znak, 10)) >= INT_MAX) {
+ aflog(0, "%s: %s\n", info, what);
+ exit(1);
+ }
+ if (((*what) == '\0') || (*znak != '\0')) {
+ aflog(0, "%s: %s\n", info, what);
+ exit(1);
+ }
+ if (tmp <= 0) {
+ aflog(0, "%s: %d\n", info, *where);
+ exit(1);
+ }
+ (*where) = tmp;
+}
+
+int
+check_long(char* text, long* number)
+{
+ char* tmp;
+ if (((*number = strtol(text, &tmp, 10)) == LONG_MAX) || (*number == LONG_MIN)) {
+ return 1;
+ }
+ if ((*text != '\0') && (*tmp == '\0')) {
+ return 0;
+ }
+ else {
+ return 2;
+ }
+}
+
diff --git a/src/server_check.h b/src/server_check.h
new file mode 100644
index 0000000..3877426
--- /dev/null
+++ b/src/server_check.h
@@ -0,0 +1,28 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_SERVER_CHECK_H
+#define _JS_SERVER_CHECK_H
+
+void check_value(int* where, char* what, char* info);
+int check_long(char* text, long* number);
+
+#endif
+
diff --git a/src/server_eval.c b/src/server_eval.c
new file mode 100644
index 0000000..d487b01
--- /dev/null
+++ b/src/server_eval.c
@@ -0,0 +1,44 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "server_eval.h"
+
+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;
+}
+
+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;
+}
diff --git a/src/server_eval.h b/src/server_eval.h
new file mode 100644
index 0000000..ed09e84
--- /dev/null
+++ b/src/server_eval.h
@@ -0,0 +1,31 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "file.h"
+#include "activefor.h"
+
+#ifndef _JS_SERVER_EVAL_H
+#define _JS_SERVER_EVAL_H
+
+int eval_numofcon(RealmT*, int, int);
+int eval_usernum(ConnectclientT*, int);
+
+#endif
+
diff --git a/src/server_find.c b/src/server_find.c
new file mode 100644
index 0000000..1d67640
--- /dev/null
+++ b/src/server_find.c
@@ -0,0 +1,56 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "server_find.h"
+
+int
+find_client(RealmT* ptr, char mode, int usrclipair)
+{
+ 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) && (ptr->clitable[i].whatusrcli == usrclipair)) {
+ if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) {
+ return i;
+ }
+ }
+ }
+ break;
+ }
+ default: {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+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;
+}
diff --git a/src/server_find.h b/src/server_find.h
new file mode 100644
index 0000000..36642cc
--- /dev/null
+++ b/src/server_find.h
@@ -0,0 +1,31 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+#include "file.h"
+
+#ifndef _JS_SERVER_FIND_H
+#define _JS_SERVER_FIND_H
+
+int find_client(RealmT*, char, int);
+int find_usernum(ConnectclientT*, int);
+
+#endif
+
diff --git a/src/server_remove.c b/src/server_remove.c
new file mode 100644
index 0000000..de2df66
--- /dev/null
+++ b/src/server_remove.c
@@ -0,0 +1,84 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "server_remove.h"
+
+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--;
+ }
+ }
+ }
+ }
+ for (i=0; i<ptr->clitable[client].usernum; ++i) {
+ ptr->clitable[client].users[i] = -1;
+ }
+ if ((ptr->clinum != client) && (ptr->baseport == 1)) {
+ close(ptr->clitable[client].listenfd);
+ FD_CLR(ptr->clitable[client].listenfd, set);
+ }
+ if (ptr->clitable[client].clientid) {
+ free(ptr->clitable[client].clientid);
+ ptr->clitable[client].clientid = NULL;
+ }
+ ptr->clitable[client].usercon = 0;
+ close(ptr->clitable[client].cliconn.commfd);
+ FD_CLR(ptr->clitable[client].cliconn.commfd, set);
+ if (ptr->clitable[client].ready == 2)
+ (*con)--;
+ SSL_clear(ptr->clitable[client].cliconn.ssl);
+ ptr->clitable[client].ready = 0;
+ ptr->clicon--;
+}
+
+void
+remove_raclient(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con)
+{
+ int i;
+ for (i=0; i<ptr->raclitable[client].usernum; ++i) {
+ ptr->raclitable[client].users[i] = -1;
+ }
+ if (ptr->raclitable[client].clientid) {
+ free(ptr->raclitable[client].clientid);
+ ptr->raclitable[client].clientid = NULL;
+ }
+ ptr->raclitable[client].usercon = 0;
+ close(ptr->raclitable[client].cliconn.commfd);
+ FD_CLR(ptr->raclitable[client].cliconn.commfd, set);
+ if (ptr->raclitable[client].ready == 2) {
+ (*con)--;
+ }
+ SSL_clear(ptr->raclitable[client].cliconn.ssl);
+ ptr->clicon--;
+ if (ptr->raclitable[client].ready == 3) {
+ ptr->raclicon--;
+ }
+ ptr->raclitable[client].ready = 0;
+}
diff --git a/src/server_remove.h b/src/server_remove.h
new file mode 100644
index 0000000..363b1cc
--- /dev/null
+++ b/src/server_remove.h
@@ -0,0 +1,30 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "file.h"
+
+#ifndef _JS_SERVER_REMOVE_H
+#define _JS_SERVER_REMOVE_H
+
+void remove_client(RealmT*, int, fd_set*, fd_set*, int*);
+void remove_raclient(RealmT*, int, fd_set*, fd_set*, int*);
+
+#endif
+
diff --git a/src/server_set.c b/src/server_set.c
new file mode 100644
index 0000000..c3a0058
--- /dev/null
+++ b/src/server_set.c
@@ -0,0 +1,34 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 <stdlib.h>
+
+void
+set_value(char** dest, char* from, char* def)
+{
+ if ((*dest) == NULL) {
+ if (from != NULL) {
+ (*dest) = from;
+ }
+ else {
+ (*dest) = def;
+ }
+ }
+}
diff --git a/src/server_set.h b/src/server_set.h
new file mode 100644
index 0000000..5bd4de5
--- /dev/null
+++ b/src/server_set.h
@@ -0,0 +1,27 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_SERVER_SET_H
+#define _JS_SERVER_SET_H
+
+void set_value(char** dest, char* from, char* def);
+
+#endif
+
diff --git a/src/stats.c b/src/stats.c
new file mode 100644
index 0000000..82e90aa
--- /dev/null
+++ b/src/stats.c
@@ -0,0 +1,127 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "stats.h"
+#include "network.h"
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+
+static char verlev;
+static char loglev;
+static char logsocklev;
+static FILE* logfd;
+static FILE* logsockfd;
+static signed long compressgained;
+static char* format = "%d.%m.%Y %H:%M:%S";
+
+char*
+datum(void)
+{
+ time_t sec;
+ struct tm* tm;
+ static char timedat[31];
+ time(&sec);
+ tm = localtime(&sec);
+ memset(timedat, 0, 31);
+ strftime(timedat, 30, format, tm);
+ return timedat;
+}
+
+int
+loginit(char verl, char logl, char logsl, const char* logfname, const char* port, char* dateformat) {
+ int tmpfd;
+ verlev = loglev = 0;
+ if (logfd)
+ fclose(logfd);
+ logfd = NULL;
+ logsockfd = NULL;
+ verlev = verl;
+ loglev = logl;
+ logsocklev = logsl;
+ if (dateformat)
+ format = dateformat;
+ if (loglev) {
+ logfd = fopen(logfname, "a");
+ if (logfd == NULL)
+ return 1; /* logging to a non-opened file? */
+ }
+ if (logsocklev) {
+ if (ip_connect(&tmpfd, "localhost", port, 1))
+ return 2; /* can't connect to localhost:port */
+ logsockfd = fdopen(tmpfd, "a");
+ if (logsockfd == NULL)
+ return 3; /* can't create FILE* to log to */
+ }
+ return 0;
+}
+
+void
+aflog(char type, const char* format, ...)
+{
+ va_list ap;
+
+ if ((verlev) || (!type))
+ if (type <= verlev) {
+ printf("[%s] ", datum());
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+ printf("\n");
+ }
+ if (loglev)
+ if (type <= loglev) {
+ fprintf(logfd, "[%s] ", datum());
+ va_start(ap, format);
+ vfprintf(logfd, format, ap);
+ va_end(ap);
+ fprintf(logfd, "\n");
+ fflush(logfd);
+ }
+ if (logsocklev)
+ if (type <= logsocklev) {
+ fprintf(logsockfd, "[%s] ", datum());
+ va_start(ap, format);
+ vfprintf(logsockfd, format, ap);
+ va_end(ap);
+ fprintf(logsockfd, "\n");
+ fflush(logsockfd);
+ }
+
+}
+
+void
+addtocg(int amount)
+{
+ compressgained += amount;
+}
+
+signed long
+getcg(void)
+{
+ return compressgained;
+}
+
+void
+resetcg(void)
+{
+ compressgained = 0;
+}
diff --git a/src/stats.h b/src/stats.h
new file mode 100644
index 0000000..08838ad
--- /dev/null
+++ b/src/stats.h
@@ -0,0 +1,36 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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_STATS_H
+#define _JS_STATS_H
+
+ /* initializing logging routine */
+int loginit(char verlev, char loglev, char logsocklev, const char* logfname, const char* port, char* dateformat);
+ /* log to a file or|and screen */
+void aflog(char type, const char* format, ...);
+ /* add amount to compressgained value */
+void addtocg(int amount);
+ /* reset the compressgained value */
+void resetcg(void);
+ /* returns the compressgained value */
+signed long getcg(void);
+
+#endif
+
diff --git a/src/usernames.c b/src/usernames.c
new file mode 100644
index 0000000..3e4b24c
--- /dev/null
+++ b/src/usernames.c
@@ -0,0 +1,41 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "usernames.h"
+
+int
+get_username(RealmT* pointer, int user)
+{
+ return pointer->contable[user].userid;
+}
+
+int
+get_usernumber(RealmT* pointer, int userid)
+{
+ int i;
+
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (userid == pointer->contable[i].userid) {
+ return i;
+ }
+ }
+
+ return -1;
+}
diff --git a/src/usernames.h b/src/usernames.h
new file mode 100644
index 0000000..0d0cb21
--- /dev/null
+++ b/src/usernames.h
@@ -0,0 +1,30 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003,2004,2005 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 "activefor.h"
+
+#ifndef _JS_USERNAMES_H
+#define _JS_USERNAMES_H
+
+int get_username(RealmT*, int);
+int get_usernumber(RealmT*, int);
+
+#endif
+