From 1adde65db245ec1fca752cfee4c198badf40fb5f Mon Sep 17 00:00:00 2001 From: Jakub Sławiński Date: Tue, 15 Mar 2005 01:22:55 +0100 Subject: v0.6 - Fixed: default password incompatibilities from config file - Added: "client's id" option - Lightly Modified: verbose mode - Added: temporary listen ports - Fixed: bug in printing "client's id" - Added: 'dateformat' option to set format of the date in the logs - Modified: command line option and config file behaviour - Added: logging to a socket - Fixed: parsing config file - Fixed: major bug in packet buffering - Added: several clients-users in one realm - Modified: default hostname used by afserver - Modified: server listening behaviour (for clients) - Fixed: bug in checking options values - Modified: verbose mode - Modified: client initial connection to server - Added: connection time / uptime statistics - Added: first version of remote administration (statistics only) - Fixed: major bug in remove_client routine - Added: 'raclients' option - Added: use of automake/autoconf - Added: creating ~/.apf directory - Modified: the way of creating/managing keys/certificates - Added: 'dnslookups' option - Modified: usage functions - Fixed: no handling of missing 'listen' option after 'newrealm' in config file - Added: 'quit' command in remote administration mode - Modified: logging error messages during initialization - Modified: 'newrealm' changed to 'realm' in config file - Added: realm names - Modified: connection time / uptime - Added: client names / unique numbers - Added: user unique numbers - Fixed: segmentation fault after 'quit' command --- afserver.c | 1134 ------------------------------------------------------------ 1 file changed, 1134 deletions(-) delete mode 100644 afserver.c (limited to 'afserver.c') diff --git a/afserver.c b/afserver.c deleted file mode 100644 index a8ca773..0000000 --- a/afserver.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003,2004 jeremian - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "activefor.h" -#include "network.h" -#include "file.h" -#include "stats.h" - -#include -#include -#include -#include -#include -#include - -static void usage(char* info); -static void sig_int(int); -static void remove_client(RealmT*, int, fd_set*, fd_set*, int*); -static int find_client(RealmT*, char); -static int eval_numofcon(RealmT*, int, int); -static int eval_usernum(ConnectclientT*, int); -static int find_usernum(ConnectclientT*, int); -static void check_value(int*, char*, char*); - -static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"hostname", 1, 0, 'n'}, - {"listenport", 1, 0, 'l'}, - {"manageport", 1, 0, 'm'}, - {"timeout", 1, 0, 't'}, - {"verbose", 0, 0, 'v'}, - {"users", 1, 0, 'u'}, - {"clients", 1, 0, 'C'}, - {"usrpcli", 1, 0, 'U'}, - {"climode", 1, 0, 'M'}, - {"cerfile", 1, 0, 'c'}, - {"keyfile", 1, 0, 'k'}, - {"cfgfile", 1, 0, 'f'}, - {"proto", 1, 0, 'p'}, - {"lightlog", 1, 0, 'o'}, - {"heavylog", 1, 0, 'O'}, - {"nossl", 0, 0, 301}, - {"nozlib", 0, 0, 302}, - {"pass", 1, 0, 303}, - {"ipv4", 0, 0, '4'}, - {"ipv6", 0, 0, '6'}, - {0, 0, 0, 0} -}; - -static ConfigurationT config; - -int -main(int argc, char **argv) -{ - int i, j=0, k, n, flags, sent; - socklen_t len; - unsigned char buff[9000]; - char hostname[100]; - int maxfdp1; - fd_set rset, allset, wset, tmpset; - int manconnecting, numofcon, length; - char* name = NULL; - char* listen = NULL; - char* manage = NULL; - char* amount = NULL; - char* clients = NULL; - char* usrpcli = NULL; - char* clim = NULL; - char* filenam = NULL; - char* type = NULL; - char* timeout = NULL; - unsigned char pass[4] = {1, 2, 3, 4}; - char verbose = 0; - char mode = 0; - char ipfam = 0; - RealmT* pointer = NULL; - struct sigaction act; - - 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); - - TYPE_SET_SSL(mode); - TYPE_SET_ZLIB(mode); - - config.certif = NULL; - config.keys = NULL; - config.size = 0; - config.realmtable = NULL; - config.logging = 0; - config.logfnam = NULL; - - while ((n = getopt_long(argc, argv, "hn:l:m:vu:c:k:f:p:o:O:46t:C:U:M:", long_options, 0)) != -1) { - switch (n) { - case 'h': { - usage(AF_VER("Active port forwarder (server)")); - break; - } - case 'n': { - name = optarg; - break; - } - case 'l': { - listen = optarg; - break; - } - case 'm': { - manage = optarg; - break; - } - case 't': { - timeout = optarg; - break; - } - case 'v': { - ++verbose; - break; - } - case 'u': { - amount = optarg; - break; - } - case 'C': { - clients = optarg; - break; - } - case 'U': { - usrpcli = optarg; - break; - } - case 'M': { - clim = optarg; - break; - } - case 'c': { - config.certif = optarg; - break; - } - case 'k': { - config.keys = optarg; - break; - } - case 'p': { - type = optarg; - break; - } - case 'f': { - filenam = optarg; - break; - } - case 'O': { - config.logfnam = optarg; - config.logging = 3; - break; - } - case 'o': { - config.logfnam = optarg; - config.logging = 1; - break; - } - case 301: { - TYPE_UNSET_SSL(mode); - break; - } - case 302: { - TYPE_UNSET_ZLIB(mode); - break; - } - case 303: { - n = strlen(optarg); - memset(pass, 0, 4); - for (i = 0; i < n; ++i) { - pass[i%4] += optarg[i]; - } - break; - } - case '4': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 4; - } - break; - } - case '6': { - if (ipfam != 0) { - ipfam = -1; - } - else { - ipfam = 6; - } - 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 (verbose) { - printf("cfg file OK! (readed realms: %d)\n", config.size); - } - } - } - else { - if (name == NULL) { - gethostname(hostname, 100); - name = hostname; - } - if (listen == NULL) { - listen = "50127"; - } - if (manage == NULL) { - manage = "50126"; - } - if (timeout == NULL) { - timeout = "5"; - } - if (amount == NULL) { - amount = "5"; - } - if (clients == NULL) { - clients = "1"; - } - if (usrpcli == NULL) { - usrpcli = amount; - } - if (clim == NULL) { - clim = "1"; - } - if (config.certif == NULL) { - config.certif = "cacert.pem"; - } - 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].lisportnum = listen; - config.realmtable[0].manportnum = manage; - config.realmtable[0].users = amount; - config.realmtable[0].clients = clients; - config.realmtable[0].timeout = timeout; - config.realmtable[0].usrpcli = usrpcli; - config.realmtable[0].clim = clim; - memcpy(config.realmtable[0].pass, pass, 4); - if (strcmp(type, "tcp") == 0) { - TYPE_SET_TCP(config.realmtable[0].type); - } - else if (strcmp(type, "udp") == 0) { - TYPE_SET_UDP(config.realmtable[0].type); - } - else { - TYPE_SET_ZERO(config.realmtable[0].type); - } - if (ipfam == -1) { - printf("Conflicting types of ip protocol family... exiting\n"); - exit(1); - } - else if (ipfam == 4) { - TYPE_SET_IPV4(config.realmtable[0].type); - } - else if (ipfam == 6) { - TYPE_SET_IPV6(config.realmtable[0].type); - } - 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) { - printf("Setting ciphers list failed... exiting\n"); - exit(1); - } - if (SSL_CTX_use_RSAPrivateKey_file(ctx, config.keys, SSL_FILETYPE_PEM) != 1) { - printf("Setting rsa key failed (%s)... exiting\n", config.keys); - exit(1); - } - if (SSL_CTX_use_certificate_file(ctx, config.certif, SSL_FILETYPE_PEM) != 1) { - printf("Setting certificate failed (%s)... exiting\n", config.certif); - exit(1); - } - - if (config.size == 0) { - printf("Working without sense is really without sense...\n"); - exit(1); - } - - FD_ZERO(&allset); - FD_ZERO(&wset); - - for (i = 0; i < config.size; ++i) { - if ((config.realmtable[i].hostname == NULL) || - (config.realmtable[i].lisportnum == NULL) || - (config.realmtable[i].manportnum == NULL)) { - printf("Missing some of the configurable variables...\n"); - printf("\nRealm: %d\nhostname: %s\nlistenport: %s\nmanageport: %s\n", - i, config.realmtable[i].hostname, - config.realmtable[i].lisportnum, - config.realmtable[i].manportnum); - exit(1); - } - /* checking type of the realm */ - if (!TYPE_IS_SET(config.realmtable[i].type)) { - TYPE_SET_TCP(config.realmtable[i].type); - } - /* checking users amount */ - if (config.realmtable[i].users == NULL) { - config.realmtable[i].users = "5"; - } - check_value(&(config.realmtable[i].usernum), config.realmtable[i].users, "Invalid users amount"); - /* checking clients amount */ - if (config.realmtable[i].clients == NULL) { - config.realmtable[i].clients = "1"; - } - check_value(&(config.realmtable[i].clinum), config.realmtable[i].clients, "Invalid clients amount"); - /* checking usrpcli value */ - if (config.realmtable[i].usrpcli == NULL) { - config.realmtable[i].usrpcli = config.realmtable[i].users; - } - check_value(&(config.realmtable[i].upcnum), config.realmtable[i].usrpcli, "Invalid usrpcli value"); - /* checking timeout value */ - if (config.realmtable[i].timeout == NULL) { - config.realmtable[i].timeout = "5"; - } - check_value(&(config.realmtable[i].tmout), config.realmtable[i].timeout, "Invalid timeout value"); - /* checking climode value */ - if (config.realmtable[i].clim == NULL) { - config.realmtable[i].clim = "1"; - } - check_value(&(config.realmtable[i].climode), config.realmtable[i].clim, "Invalid climode value"); - /* allocating memory*/ - config.realmtable[i].contable = calloc( config.realmtable[i].usernum, sizeof(ConnectuserT)); - if (config.realmtable[i].contable == NULL) { - printf("Calloc error - try define smaller amount of users\n"); - exit(1); - } - config.realmtable[i].clitable = calloc( config.realmtable[i].clinum, sizeof(ConnectclientT)); - if (config.realmtable[i].clitable == NULL) { - printf("Calloc error - try define smaller amount of clients\n"); - exit(1); - } - ipfam = 0x01; - if (TYPE_IS_IPV4(config.realmtable[i].type)) { - ipfam |= 0x02; - } - else if (TYPE_IS_IPV6(config.realmtable[i].type)) { - ipfam |= 0x04; - } - if (ip_listen(&(config.realmtable[i].listenfd), config.realmtable[i].hostname, - config.realmtable[i].lisportnum, (&(config.realmtable[i].addrlen)), ipfam)) { - printf("tcp_listen_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", - config.realmtable[i].hostname, config.realmtable[i].lisportnum); - exit(1); - } - if (ip_listen(&(config.realmtable[i].managefd), config.realmtable[i].hostname, - config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), ipfam)) { - printf("tcp_listen_%s error for %s, %s\n", - (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", - config.realmtable[i].hostname, config.realmtable[i].manportnum); - exit(1); - } - config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen); - - for (j=0; j (config.realmtable[i].managefd+1)) ? maxfdp1 : (config.realmtable[i].managefd+1); - maxfdp1 = (maxfdp1 > (config.realmtable[i].listenfd+1)) ? maxfdp1 : (config.realmtable[i].listenfd+1); - config.realmtable[i].usercon = 0; - config.realmtable[i].clicon = 0; - for (j=0; jselect, maxfdp1: %d", maxfdp1); - if (manconnecting) { - /* find out, in what realm client is trying to connect */ - for (k = 0; k < config.size; ++k) { - for (j=0; j < config.realmtable[k].clinum; ++j) { - if ((config.realmtable[k].clitable[j].ready == 1) || (config.realmtable[k].clitable[j].ready == 2)) { - i = k; - k = config.size; - break; /* so i points to first good realm and j to good client */ - } - } - } - if (select(maxfdp1, &rset, &tmpset, NULL, (&(config.realmtable[i].clitable[j].tv))) == 0) { - close (config.realmtable[i].clitable[j].cliconn.commfd); - FD_CLR(config.realmtable[i].clitable[j].cliconn.commfd, &allset); - FD_SET(config.realmtable[i].managefd, &allset); - SSL_clear(config.realmtable[i].clitable[j].cliconn.ssl); - config.realmtable[i].clitable[j].ready = 0; - manconnecting--; - config.realmtable[i].clicon--; - aflog(1, " realm[%d]: client[%d]: SSL_accept failed (timeout)", i, 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 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[%d]: client[%d]: user[%d]: FD_ISSET", j, pointer->contable[i].whatcli, k); - if (TYPE_IS_TCP(pointer->type)) { /* forwarding tcp packets */ - n = read(pointer->contable[i].connfd, &buff[5], 8091); - if (n == -1) { - aflog(3, " realm[%d]: client[%d]: user[%d]: READ ERROR (%d)", j, - pointer->contable[i].whatcli, k, errno); - n = 0; - } - if (n) { - aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, - pointer->contable[i].whatcli, k, n); - if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { - aflog(2, " WARNING: got packet similiar to udp"); - } - buff[0] = AF_S_MESSAGE; /* sending message */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, n+5); - } - else { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, - pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - else { /* when forwarding udp packets */ - n = readn(pointer->contable[i].connfd, buff, 5 ); - if (n != 5) { - n = 0; - } - if (n) { - if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - if ((n = readn(pointer->contable[i].connfd, &buff[5], length)) != 0) { - aflog(2, " realm[%d]: client[%d]: FROM user[%d]: MESSAGE length=%d", j, - pointer->contable[i].whatcli, k, n); - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, - buff, n+5); - } - } - else { - n = 0; - } - } - - if (n == 0) { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED (udp mode)", j, - pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, - pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - - } - } - } - /* ------------------------------------ */ - for (i = 0; i usernum; ++i) { - if (pointer->contable[i].state == S_STATE_STOPPED) - if (FD_ISSET(pointer->contable[i].connfd, &tmpset)) { - k = eval_usernum(&(pointer->clitable[pointer->contable[i].whatcli]), i); - aflog(3, " realm[%d]: client[%d]: user[%d]: FD_ISSET - WRITE", j, pointer->contable[i].whatcli, - k); - n = pointer->contable[i].head->msglen - pointer->contable[i].head->actptr; - sent = write(pointer->contable[i].connfd, - &(pointer->contable[i].head->buff[pointer->contable[i].head->actptr]), n); - if ((sent > 0) && (sent != n)) { - pointer->contable[i].head->actptr+=sent; - } - else if ((sent == -1) && (errno == EAGAIN)) { - } - else if (sent == -1) { - aflog(1, " realm[%d]: client[%d]: user[%d]: CLOSED", j, pointer->contable[i].whatcli, k); - aflog(2, " IP:%s PORT:%s", pointer->contable[i].namebuf, pointer->contable[i].portbuf); - close(pointer->contable[i].connfd); - FD_CLR(pointer->contable[i].connfd, &allset); - FD_CLR(pointer->contable[i].connfd, &wset); - pointer->contable[i].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[i].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - else { - deleteblnode(&pointer->contable[i].head); - if (pointer->contable[i].head == NULL) { - pointer->contable[i].state = S_STATE_OPEN; - FD_CLR(pointer->contable[i].connfd, &wset); - buff[0] = AF_S_CAN_SEND; /* stopping transfer */ - buff[1] = k >> 8; /* high bits of user number */ - buff[2] = k; /* low bits of user number */ - aflog(3, " realm[%d]: client[%d]: TO user[%d]: BUFFERING MESSAGE ENDED", j, - pointer->contable[i].whatcli, k); - send_message(pointer->type, pointer->clitable[pointer->contable[i].whatcli].cliconn, buff, 5); - } - } - } - } - /* ------------------------------------ */ - if (FD_ISSET(pointer->listenfd, &rset)) { - len = pointer->addrlen; - sent = accept(pointer->listenfd, pointer->cliaddr, &len); - flags = fcntl(sent, F_GETFL, 0); - fcntl(sent, F_SETFL, flags | O_NONBLOCK); - aflog(3, " realm[%d]: listenfd: FD_ISSET", j); - k = find_client(pointer, pointer->climode); - if (pointer->clitable[k].ready == 3) { - if (pointer->usercon == pointer->usernum) { - close(sent); - aflog(3, " realm[%d]: user limit EXCEEDED", j); - } - else if(pointer->clitable[k].usercon == pointer->clitable[k].usernum) { - close(sent); - aflog(3, " realm[%d]: client[%d]: usrpcli limit EXCEEDED", j, k); - } - else { - for (i = 0; i < pointer->usernum; ++i) { - if (pointer->contable[i].state == S_STATE_CLEAR) { - aflog(2, " realm[%d]: client[%d]: new user: CONNECTING", j, k); - pointer->contable[i].connfd = sent; - pointer->contable[i].state = S_STATE_OPENING; - pointer->contable[i].whatcli = k; - pointer->usercon++; - pointer->clitable[k].usercon++; - aflog(1, " user IP:%s",sock_ntop(pointer->cliaddr, len, - pointer->contable[i].namebuf, pointer->contable[i].portbuf)); - memcpy(&buff[5], pointer->contable[i].namebuf, 128); - memcpy(&buff[133], pointer->contable[i].portbuf, 7); - n = 135; - i = find_usernum(&(pointer->clitable[k]), i); - buff[0] = AF_S_CONOPEN; /* opening connection */ - buff[1] = i >> 8; /* high bits of user number */ - buff[2] = i; /* low bits of user number */ - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, n+5); - break; - } - } - } - } - else { - close(sent); - aflog(3, " realm[%d]: client[%d] is NOT CONNECTED", j, k); - } - } - /* ------------------------------------ */ - for (k = 0; k < pointer->clinum; ++k) - if (pointer->clitable[k].ready != 0) /* Command file descriptor */ - if (FD_ISSET(pointer->clitable[k].cliconn.commfd, &rset)) { - if (pointer->clitable[k].ready == 1) { - if (SSL_set_fd(pointer->clitable[k].cliconn.ssl, pointer->clitable[k].cliconn.commfd) != 1) { - aflog(0, "Problem with initializing ssl... exiting"); - exit(1); - } - aflog(2, " realm[%d]: new client: SSL_accept", j); - if ((n = SSL_accept(pointer->clitable[k].cliconn.ssl)) != 1) { - flags = SSL_get_error(pointer->clitable[k].cliconn.ssl, n); - switch (flags) { - case SSL_ERROR_NONE : { - aflog(2, " SSL_accept has failed(%d)...none", n); - break; - } - case SSL_ERROR_ZERO_RETURN : { - aflog(2, " SSL_accept has failed(%d)...zero", n); - break; - } - case SSL_ERROR_WANT_READ : { - aflog(2, " SSL_accept has failed(%d)...w_read", n); - break; - } - case SSL_ERROR_WANT_WRITE : { - aflog(2, " SSL_accept has failed(%d)...w_write", n); - break; - } - case SSL_ERROR_WANT_CONNECT : { - aflog(2, " SSL_accept has failed(%d)...w_connect", n); - break; - } - case SSL_ERROR_WANT_X509_LOOKUP : { - aflog(2, " SSL_accept has failed(%d)...w_x509_lookup", n); - break; - } - case SSL_ERROR_SYSCALL : { - aflog(2, " SSL_accept has failed(%d)...syscall", n); - break; - } - case SSL_ERROR_SSL : { - SSL_load_error_strings(); - aflog(2, " SSL_accept has failed(%d)...ssl:%s", - n, ERR_error_string(ERR_get_error(), (char*) buff)); - break; - } - } - if (flags == SSL_ERROR_WANT_READ) - continue; - close (pointer->clitable[k].cliconn.commfd); - FD_CLR(pointer->clitable[k].cliconn.commfd, &allset); - FD_SET(pointer->managefd, &allset); - SSL_clear(pointer->clitable[k].cliconn.ssl); - pointer->clitable[k].ready = 0; - manconnecting--; - pointer->clicon--; - aflog(1, " realm[%d]: new client[%d]: DENIED by SSL_accept", j, k); - } - else { - aflog(1, " realm[%d]: new client[%d]: ACCEPTED by SSL_accept", j, k); - pointer->clitable[k].ready = 2; - } - continue; /* in the case this is not our client */ - } - aflog(3, " realm[%d]: client[%d]: commfd: FD_ISSET", j, k); - if (pointer->clitable[k].ready == 2) { - n = get_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, -5); - } - else { - n = get_message(pointer->type, pointer->clitable[k].cliconn, buff, -5); - } - if (n == -1) { - if (errno == EAGAIN) { - aflog(4, " realm[%d]: client[%d]: commfd: EAGAIN", j, k); - continue; - } - else { - aflog(4, " realm[%d]: client[%d]: commfd: ERROR: %d", j, k, errno); - n = 0; - } - } - else if (n != 5) { - n = 0; - } - if (n==0) { - remove_client(pointer, k, &allset, &wset, &manconnecting); - aflog(1, " realm[%d]: client[%d]: commfd: CLOSED", j, k); - continue; - } - - numofcon = buff[1]; - numofcon = numofcon << 8; - numofcon += buff[2]; /* this is id of user */ - length = buff[3]; - length = length << 8; - length += buff[4]; /* this is length of message */ - - 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; - } - else if ((pointer->contable[numofcon].state == S_STATE_OPEN) || - (pointer->contable[numofcon].state == S_STATE_STOPPED)) { - aflog(1, " realm[%d]: user[%d]: KICKED", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLEAR; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CONOPEN : { - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: NEW", j, numofcon); - FD_SET(pointer->contable[numofcon].connfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ? - maxfdp1 : (pointer->contable[numofcon].connfd+1); - pointer->contable[numofcon].state = S_STATE_OPEN; - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_CANT_OPEN : { - n = numofcon; - numofcon = eval_numofcon(pointer, k, numofcon); - if ((numofcon>=0) && (numofcon<(pointer->usernum)) && ((pointer->clitable[k].ready)==3)) { - if (pointer->contable[numofcon].state == S_STATE_OPENING) { - aflog(2, " realm[%d]: user[%d]: DROPPED", j, numofcon); - pointer->usercon--; - pointer->clitable[k].usercon--; - pointer->clitable[k].users[n] = -1; - close(pointer->contable[numofcon].connfd); - pointer->contable[numofcon].state = S_STATE_CLEAR; - } - } - else { - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_MESSAGE : { - if ((pointer->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[%d]: TO user[%d]: MESSAGE length=%d", j, numofcon, n); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - sent = write(pointer->contable[numofcon].connfd, buff, n+5); - if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED (write-udp)", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - else { /* tcp */ - sent = write(pointer->contable[numofcon].connfd, buff, n); - if ((sent > 0) && (sent != n)) { - insertblnode(&(pointer->contable[numofcon].head), sent, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, - sent, n); - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - else if ((sent == -1) && (errno == EAGAIN)) { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - pointer->contable[numofcon].state = S_STATE_STOPPED; - FD_SET(pointer->contable[numofcon].connfd, &wset); - buff[0] = AF_S_DONT_SEND; /* stopping transfer */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", j, numofcon, - sent, n); - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - else if (sent == -1) { - aflog(1, " realm[%d]: user[%d]: CLOSED (write-tcp)", j, numofcon); - aflog(2, " IP:%s PORT:%s", pointer->contable[numofcon].namebuf, - pointer->contable[numofcon].portbuf); - close(pointer->contable[numofcon].connfd); - FD_CLR(pointer->contable[numofcon].connfd, &allset); - FD_CLR(pointer->contable[numofcon].connfd, &wset); - pointer->contable[numofcon].state = S_STATE_CLOSING; - freebuflist(&pointer->contable[numofcon].head); - buff[0] = AF_S_CONCLOSED; /* closing connection */ - buff[1] = numofcon >> 8; /* high bits of user number */ - buff[2] = numofcon; /* low bits of user number */ - send_message(pointer->type, pointer->clitable[k].cliconn, buff, 5); - } - } - } - else if (pointer->contable[numofcon].state == S_STATE_STOPPED) { - aflog(3, " realm[%d]: TO user[%d]: BUFFERING MESSAGE (%d)", j, numofcon, n); - if (TYPE_IS_UDP(pointer->type)) { /* udp */ - buff[1] = AF_S_LOGIN; - buff[2] = AF_S_MESSAGE; - buff[3] = n >> 8; /* high bits of message length */ - buff[4] = n; /* low bits of message length */ - insertblnode(&(pointer->contable[numofcon].head), 0, n+5, buff); - } - else { - insertblnode(&(pointer->contable[numofcon].head), 0, n, buff); - } - } - } - break; - } - case AF_S_LOGIN : { - if ((pointer->clitable[k].ready == 2) && (numofcon==(pointer->pass[0]*256+pointer->pass[1])) && - (length==(pointer->pass[2]*256+pointer->pass[3]))) { - pointer->clitable[k].ready = 3; - aflog(1, " realm[%d]: pass ok - ACCESS GRANTED", j); - buff[0] = AF_S_LOGIN; /* sending message */ - buff[1] = pointer->clitable[k].usernum >> 8;/* high bits of user number */ - buff[2] = pointer->clitable[k].usernum; /* low bits of user number */ - buff[3] = pointer->type; /* type of connection */ - send_message(pointer->type | TYPE_SSL, pointer->clitable[k].cliconn, buff, 5); - manconnecting--; - } - else { - aflog(1, " realm[%d]: Wrong password - CLOSING", j); - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - break; - } - case AF_S_DONT_SEND: { - FD_CLR(pointer->contable[numofcon].connfd, &allset); - break; - } - case AF_S_CAN_SEND: { - FD_SET(pointer->contable[numofcon].connfd, &allset); - break; - } - default : { - aflog(1, " realm[%d]: Unrecognized message - CLOSING", j); - remove_client(pointer, k, &allset, &wset, &manconnecting); - } - } - } - if (FD_ISSET(pointer->managefd, &rset)) { - aflog(3, " realm[%d]: managefd: FD_ISSET", j); - len = pointer->addrlen; - for (k = 0; k < pointer->clinum; ++k) - if (!(pointer->clitable[k].ready)) { - aflog(2, " realm[%d]: new client[%d]: CONNECTING", j, k); - pointer->clitable[k].cliconn.commfd = accept(pointer->managefd, pointer->cliaddr, &len); - flags = fcntl(pointer->clitable[k].cliconn.commfd, F_GETFL, 0); - fcntl(pointer->clitable[k].cliconn.commfd, F_SETFL, flags | O_NONBLOCK); - aflog(1, " realm[%d]: Client[%d] IP:%s", j, k, sock_ntop(pointer->cliaddr, len, NULL, NULL)); - FD_SET(pointer->clitable[k].cliconn.commfd, &allset); - maxfdp1 = (maxfdp1 > (pointer->clitable[k].cliconn.commfd+1)) ? - maxfdp1 : (pointer->clitable[k].cliconn.commfd+1); - pointer->clicon++; - if (pointer->clicon == pointer->clinum) - FD_CLR(pointer->managefd, &allset); - pointer->clitable[k].tv.tv_sec = pointer->tmout; - manconnecting++; - pointer->clitable[k].ready = 1; - break; - } - } - } /* realms loop */ - } -} - -static void -usage(char* info) -{ - printf("\n%s\n\n", info); - printf(" Options:\n"); - printf(" -n, --hostname - it's used when creating listening sockets\n"); - printf(" (default: name returned by hostname function)\n"); - printf(" -l, --listenport - listening port number - users connect\n"); - printf(" to it (default: 50127)\n"); - printf(" -m, --manageport - manage port number - second part of the active\n"); - printf(" port forwarder connects to it (default: 50126)\n"); - printf(" -t, --timeout - the timeout value for the client's connection\n"); - printf(" (default: 5)\n"); - printf(" -u, --users - the amount of users allowed to use this server\n"); - printf(" (default: 5)\n"); - printf(" -C, --clients - the number of allowed clients to use this server\n"); - printf(" (default: 1)\n"); - printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n"); - printf(" -M, --climode - strategy used for connecting users with clients (default: 1)\n"); - printf(" Available strategies:\n"); - printf(" 1. fill first client before go to next\n\n"); - printf(" -c, --cerfile - the name of the file with certificate\n"); - printf(" (default: cacert.pem)\n"); - printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n"); - printf(" -f, --cfgfile - the name of the file with the configuration for the\n"); - printf(" active forwarder (server)\n"); - printf(" -p, --proto - type of server (tcp|udp) - for which protocol it will be\n"); - printf(" operating (default: tcp)\n"); - printf(" -O, --heavylog - logging everything to a logfile\n"); - printf(" -o, --lightlog - logging some data to a logfile\n"); - printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); - printf(" (use several times for greater effect)\n\n"); - printf(" --nossl - ssl is not used for transfering data (but it's still\n"); - printf(" used to establish a connection) (default: ssl is used)\n"); - printf(" --nozlib - zlib is not used for compressing data (default:\n"); - printf(" zlib is used)\n"); - printf(" --pass - set the password used for client identification\n"); - printf(" (default: no password)\n\n"); - printf(" -4, --ipv4 - use ipv4 only\n"); - printf(" -6, --ipv6 - use ipv6 only\n\n"); - printf(" -h, --help - prints this help\n\n"); - exit(0); -} - -static void -sig_int(int signo) -{ - int 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; ++i) { - if (config.realmtable[j].clitable[i].ready == 3) { - send_message(config.realmtable[j].type, config.realmtable[j].clitable[i].cliconn, buff, 5); - } - } - } - aflog(1, "SERVER CLOSED cg: %ld bytes", getcg()); - exit(0); -} - -static void -remove_client(RealmT* ptr, int client, fd_set* set, fd_set* wset, int* con) -{ - int i; - if (ptr->clitable[client].ready == 3) { - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->contable[i].whatcli == client) { - if (ptr->contable[i].state != S_STATE_CLEAR) { - ptr->contable[i].state = S_STATE_CLEAR; - FD_CLR(ptr->contable[i].connfd, set); - FD_CLR(ptr->contable[i].connfd, wset); - close(ptr->contable[i].connfd); - ptr->usercon--; - } - } - } - } - ptr->clitable[client].usercon = 0; - close(ptr->clitable[client].cliconn.commfd); - FD_CLR(ptr->clitable[client].cliconn.commfd, set); - FD_SET(ptr->managefd, set); - if (ptr->clitable[client].ready == 2) - (*con)--; - SSL_clear(ptr->clitable[client].cliconn.ssl); - ptr->clitable[client].ready = 0; - ptr->clicon--; -} - -static int -find_client(RealmT* ptr, char mode) -{ - int i; - switch(mode) { - case 1: { /* fill first client before go to next */ - for (i = 0; i < ptr->clinum; ++i) { - if (ptr->clitable[i].ready == 3) { - if (ptr->clitable[i].usercon < ptr->clitable[i].usernum) { - return i; - } - } - } - break; - } - default: { - return 0; - } - } - return 0; -} - -static int -eval_numofcon(RealmT* ptr, int client, int numofcon) -{ - if ((numofcon >= 0) && (numofcon < ptr->clitable[client].usernum)) { - numofcon = ptr->clitable[client].users[numofcon]; - } - else { - numofcon = -1; - } - return numofcon; -} - -static int -eval_usernum(ConnectclientT* ptr, int usernum) -{ - int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == usernum) - return i; - } - return -1; -} - -static int -find_usernum(ConnectclientT* ptr, int usernum) -{ - int i; - for (i = 0; i < ptr->usernum; ++i) { - if (ptr->users[i] == -1) { - ptr->users[i] = usernum; - return i; - } - } - return -1; -} - -static void -check_value(int* where, char* what, char* info) -{ - char* znak; - if ((( (*where) = strtol(what, &znak, 10)) == LONG_MAX) || ((*where) == LONG_MIN)) { - printf("%s: %s\n", info, what); - exit(1); - } - if (((*what) == '\0') || (*znak != '\0')) { - printf("%s: %s\n", info, what); - exit(1); - } - if ((*where) <= 0) { - printf("%s: %d\n", info, *where); - exit(1); - } -} -- cgit v1.1