summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING340
-rw-r--r--Changelog16
-rw-r--r--Makefile50
-rw-r--r--README89
-rw-r--r--activefor.h41
-rw-r--r--afclient.c537
-rw-r--r--afserver.c680
-rw-r--r--config39
-rw-r--r--file.c159
-rw-r--r--file.h65
-rw-r--r--network.c257
-rw-r--r--network.h45
-rw-r--r--stats.c79
-rw-r--r--stats.h28
14 files changed, 2425 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..4c3dc15
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,16 @@
+06.12.2003 (v0.5.2):
+ - Added: types of realm
+ - Added: logging to a file
+ - Fixed: major bug in communication between server and client
+ - Fixed: deformed packets in udp protocol forwarding
+
+04.12.2003 (v0.5.1):
+ - Fixed: Some data transfer problems
+ - Added: udp protocol tunneling/forwarding
+ - Fixed: bug in parsing the config file
+ - Improved: making connection between server and client
+ - Lightly modified: verbose mode (added double v mode)
+
+23.11.2003 (v0.5):
+ - This is the first release
+ - There are no known major bugs
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..21e5bb4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,50 @@
+CC=gcc
+CFLAGS=-pedantic -Wall -O2
+programs=afserver afclient
+security=server.rsa client.rsa cacert.pem
+
+all: compi $(programs) ok1 secure
+
+afserver: afserver.c network.o file.o stats.o
+ $(CC) $(CFLAGS) -lssl afserver.c network.o file.o stats.o -o afserver
+
+afclient: afclient.c network.o stats.o
+ $(CC) $(CFLAGS) -lssl afclient.c network.o stats.o -o afclient
+
+network.o: network.c network.h
+ $(CC) $(CFLAGS) -c network.c
+
+file.o: file.c file.h
+ $(CC) $(CFLAGS) -c file.c
+
+stats.o: stats.c stats.h
+ $(CC) $(CFLAGS) -c stats.c
+
+secure: crea $(security) ok2
+
+server.rsa:
+ @openssl genrsa -out server.rsa 2048
+
+client.rsa:
+ @openssl genrsa -out client.rsa 2048
+
+cacert.pem:
+ @echo -e "\n Generating certificate...\n"
+ @echo -e "pl\nWar-Maz\nOlsztyn\nSHEG\nUtils productions\njeremian\njeremian@poczta.fm" | openssl req -new -x509 -key server.rsa -out cacert.pem -days 1095 > /dev/null 2>&1
+
+compi:
+ @echo -e "\nCompiling program...\n"
+
+crea:
+ @echo -e "\nCreating necessary files...\n"
+
+ok1:
+ @echo " OK!"
+
+ok2:
+ @echo " OK!"
+
+.PHONY: clean
+
+clean:
+ rm -rf a.out *~ *.o $(programs) $(security)
diff --git a/README b/README
new file mode 100644
index 0000000..7abf822
--- /dev/null
+++ b/README
@@ -0,0 +1,89 @@
+AF - Active Port Forwarder v0.5.2 - README
+Copyright (C) 2003 jeremian - jeremian@poczta.fm
+===================
+
+================================================================================
+
+GRAY-WORLD.NET / Active Port Forwarder
+==========================
+
+ The Active Port Forwarder program is part of the Gray-World.net projects.
+
+ Our Gray-World Team presents on the http://gray-world.net website the projects
+ and publications we are working on which are related to the NACS (Network
+ Access Control System) bypassing research field and to the computer and
+ network security topics.
+
+================================================================================
+
+
+Active port forwarder is a software for secure port forwarding.
+It uses ssl for increasing security of communication between server and client.
+
+Af is dedicated for people, who don't have external ip number and want to
+make some services available across the net.
+
+
+EXAMPLE 1:
+
+The use of it is extremely simple. Let's suppose we want to create http server on
+our computer and we are behind masquerade or firewall:
+
+1) We have to find some machine on the net with external ip and shell account.
+
+2) Use make to compile everything on that machine. (you can freely remove afclient
+ and client.rsa files)
+
+3) You can edit config file or just type from the console: (to use config type -f <cfgfile>)
+ $ ./afserver
+ This will work, if you want to use default values:
+ - hostname will be taken from hostname function (it would be ideally, if there is
+ appropriate registration in /etc/hosts)
+ - server will be listening for users on port 50127
+ - server will be listening for client on port 50126
+ - server will be for maximum 5 users
+ - server will forward tcp packets
+ - there will be no logging and no verbose messages
+
+4) We use make on our machine (we can delete everything apart afclient and client.rsa)
+
+5) We are typing from the console:
+ $ ./afclient -n <name of the server> -p 80
+ Where <name of the server> is a string like : 'bastion.univ.gda.pl' or '153.19.7.200'
+
+6) We can now enter with webbrowser to : <name of the server>:50127 and we will enter to our
+ computer in the fact.
+
+EXAMPLE 2:
+
+Let's see how to use af to forward udp packets. Suppose we want to create a game server
+on our computer (udp port 27960 on our machine):
+
+1) - 4) is the same like in example 1. (but we add option: -t udp)
+
+5) We are typing from the console:
+ $ ./afclient -u -n <name of the server> -p 27960
+ Where <name of the server> is a name (or ip) of a host where our server is running.
+
+6) Connecting to our game is more complicated. User must use afclient to do this.
+ He has to specify server he is connecting to and port which his program will be listening on:
+ $ ./afclient -U -d <hostname> -p <portnum> -n <name of the server> -m <server port>
+ Where <hostname> is name of user machine (who wants to connect to our game). <portnum>
+ is a port he will be connecting to. <name of the server> is a name of a host where our server
+ is running. <server port> is a port on which server is listening for users.
+ In order to connect to our game, user have to connect to <hostname>:<portnum>.
+
+
+Active port forwarder is still under development, so please sent me any comments, bugs notices
+and suggestions about it to jeremian@poczta.fm
+
+
+And thanks for using this software!
+
+LICENSE
+-------
+
+ Active Port Forwarder is distributed under the terms of the GNU General Public License
+ v2.0 and is copyright (c) 2003 jeremian <jeremian [at] poczta.fm>.
+ See the file COPYING for details.
+
diff --git a/activefor.h b/activefor.h
new file mode 100644
index 0000000..777f54f
--- /dev/null
+++ b/activefor.h
@@ -0,0 +1,41 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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
+
+#define AF_S_CONCLOSED 1
+#define AF_S_CONOPEN 2
+#define AF_S_MESSAGE 3
+#define AF_S_LOGIN 8
+
+#define S_STATE_CLEAR 0
+#define S_STATE_RUNNING 4
+#define S_STATE_CLOSING 5
+#define S_STATE_OPENING 6
+#define S_STATE_OPEN 7
+
+typedef struct {
+ char state;
+ int connfd;
+} ConnectuserT;
+
+#endif
+
diff --git a/afclient.c b/afclient.c
new file mode 100644
index 0000000..e4d7c05
--- /dev/null
+++ b/afclient.c
@@ -0,0 +1,537 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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 <openssl/ssl.h>
+#include <openssl/err.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+#include <signal.h>
+
+static void usage(char* info);
+
+int
+main(int argc, char **argv)
+{
+ int masterfd, i, n, numofcon, length, buflength, notsent, temp2; /* !!! */
+ ConnectuserT* contable = NULL;
+ unsigned char buff[8096];
+ char hostname[100];
+ struct timeval tv;
+ int maxfdp1, usernum, usercon, merror;
+ socklen_t len, addrlen;
+ struct sockaddr* cliaddr;
+ fd_set rset, allset;
+ char verbose = 0;
+ char logging = 0;
+ char* name = NULL;
+ char* manage = NULL;
+ char* desnam = NULL;
+ char* despor = NULL;
+ char* keys = NULL;
+ char* logfname = NULL;
+ char udp = 0;
+ char reverse = 0;
+
+ SSL_METHOD* method;
+ SSL_CTX* ctx;
+ SSL* ssl;
+
+ signal(SIGPIPE, SIG_IGN);
+
+ while ((n = getopt(argc, argv, "huUn:m:d:p:vk:O:o:")) != -1) {
+ switch (n) {
+ case 'h': {
+ usage("Active port forwarder (client) v0.5.2");
+ break;
+ }
+ case 'n': {
+ name = 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 = 2;
+ break;
+ }
+ case 'o': {
+ logfname = optarg;
+ logging = 1;
+ break;
+ }
+ case '?': {
+ usage("");
+ break;
+ }
+ }
+ }
+
+ 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 (desnam == NULL) {
+ gethostname(hostname, 100);
+ desnam = hostname;
+ }
+ if (despor == NULL) {
+ usage("Destination port number is required");
+ }
+ if (keys == NULL) {
+ keys = "client.rsa";
+ }
+
+
+ masterfd = ip_connect(name, manage, "tcp");
+
+ if (!reverse) {
+ SSL_library_init();
+ method = SSLv3_client_method();
+ ctx = SSL_CTX_new(method);
+ if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) {
+ printf("Setting cipher list failed... exiting\n");
+ exit(1);
+ }
+ if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) {
+ printf("Setting rsa key failed (%s)... exiting\n", keys);
+ exit(1);
+ }
+ ssl = SSL_new(ctx);
+ if (SSL_set_fd(ssl, masterfd) != 1) {
+ printf("Problem with initializing ssl... exiting\n");
+ exit(1);
+ }
+ if (verbose>1)
+ printf("Trying SSL_connect\n");
+ if ((n = SSL_connect(ssl)) == 1) {
+ if (verbose) {
+ printf("SSL_connect successfull\n");
+ }
+ }
+ else {
+ printf("SSL_connect has failed (%d)... exiting\n", n);
+ exit(1);
+ }
+
+
+ buff[0] = AF_S_LOGIN;
+ buff[1] = 1;
+ buff[2] = 3;
+ buff[3] = 6;
+ buff[4] = 2;
+ SSL_write(ssl, buff, 5);
+ buff[0] = 0;
+ SSL_read(ssl, buff, 5);
+
+ if ( buff[0] != AF_S_LOGIN ) {
+ printf("Incompatible server type or server full\n");
+ exit(1);
+ }
+
+ usernum = buff[1];
+ usernum = usernum << 8;
+ usernum += buff[2];
+
+ } /* !reverse */
+ else {
+ usernum = 1;
+ ssl = NULL;
+ }
+
+ contable = calloc( usernum, sizeof(ConnectuserT));
+ if (contable == NULL) {
+ printf("Calloc error - unable to succesfully comunicate with server\n");
+ exit(1);
+ }
+
+ len = 4;
+ if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &buflength, &len) == -1) {
+ printf("Can't get socket send buffor size - exiting...\n");
+ exit(1);
+ }
+
+ if (loginit(verbose, logging, logfname)) {
+ printf("Can't open file to log to... exiting\n");
+ exit(1);
+ }
+
+ if (!verbose)
+ daemon(0, 0);
+
+ FD_ZERO(&allset);
+
+ FD_SET(masterfd, &allset);
+ maxfdp1 = masterfd + 1;
+
+ if (reverse) {
+ contable[0].connfd=ip_listen(desnam, despor, &addrlen, "udp");
+ cliaddr = malloc(addrlen);
+ maxfdp1 = (maxfdp1>contable[0].connfd+1) ? maxfdp1 : contable[0].connfd+1;
+ FD_SET(contable[0].connfd, &allset);
+ aflog(1, "^^Started in udp reverse mode^^");
+ for ( ; ; ) {
+ len = 4;
+ if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffor size changed...");
+ }
+ }
+ len = addrlen;
+ rset = allset;
+ aflog(2, ">select");
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+ aflog(2, ">>after select...");
+ if (FD_ISSET(contable[0].connfd, &rset)) {
+ n = recvfrom(contable[0].connfd, &buff[5], 8091, 0, cliaddr, &len);
+#ifdef SIOCOUTQ
+ if (ioctl(masterfd, SIOCOUTQ, &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(masterfd, 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 {
+ if (n > 0) {
+ aflog(2, "Sending %d bytes to service (w:%d/%d)",
+ n,
+#ifdef SIOCOUTQ
+ notsent
+#else
+ buflength - notsent
+#endif
+ , buflength);
+ buff[0] = AF_S_MESSAGE;
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ buff[3] = n >> 8;
+ buff[4] = n;
+ writen(masterfd, buff, n + 5);
+ }
+ }
+ }
+ if (FD_ISSET(masterfd, &rset)) {
+ n = readn(masterfd, 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(masterfd, buff, length);
+ }
+ else {
+ n = 0;
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ gettimeofday(&tv, 0);
+ aflog(0, "premature quit of the server -> exiting...");
+ exit(1);
+ }
+ aflog(2, "Sending %d bytes to user", n);
+ sendto(contable[0].connfd, buff, n, 0, cliaddr, addrlen);
+ }
+ }
+ exit(0); /* we shouldn't get here */
+ }
+
+ aflog(1, "^^Started in normal mode^^ (%s)", (udp)?"udp":"tcp");
+
+ for ( ; ; ) {
+ rset = allset;
+ aflog(2, ">select");
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+ aflog(2, ">>after select...");
+
+ for (i = 0; i < usernum; ++i) {
+ if (contable[i].state == S_STATE_OPEN)
+ if (FD_ISSET(contable[i].connfd, &rset)) {
+ aflog(2, "FD_ISSET(contable[%d].connfd)", i);
+ n = read(contable[i].connfd, &buff[5], 8091);
+ if (n == -1) {
+ aflog(0, "FATAL ERROR! (%d) while reading from user", n);
+ n = 0;
+ }
+#ifdef SIOCOUTQ
+ if (ioctl(masterfd, SIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffor size changed...");
+ }
+ }
+ if (buflength <= notsent + n + 5) { /* when we can't send this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d",
+ n+5, buflength, notsent, buflength);
+#else
+ if (ioctl(masterfd, TIOCOUTQ, &notsent)) {
+ aflog(0, "ioctl error -> exiting...");
+ exit(1);
+ }
+ if (udp) {
+ len = 4;
+ if (getsockopt(masterfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) {
+ if (temp2 != buflength) {
+ buflength = temp2;
+ aflog(2, "Send buffor size changed...");
+ }
+ }
+ if (notsent <= n + 5) { /* when we can't send this */
+ aflog(2, "drop: size:%d, buf:%d, w:%d/%d",
+ n+5, buflength, buflength-notsent, buflength);
+#endif
+ continue; /* drop this packet */
+ }
+ }
+ if (n) {
+ 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 */
+ aflog(2, "Sending %d bytes to user (%d) [%d/%d]",
+ n, i,
+#ifdef SIOCOUTQ
+ notsent
+#else
+ buflength - notsent
+#endif
+ , buflength);
+ SSL_writen(ssl, buff, n+5);
+ }
+ else if (!udp) {
+ close(contable[i].connfd);
+ FD_CLR(contable[i].connfd, &allset);
+ contable[i].state = S_STATE_CLOSING;
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ SSL_writen(ssl, buff, 5);
+ }
+ }
+ }
+
+ if (FD_ISSET(masterfd, &rset)) {
+ aflog(2, "FD_ISSET(masterfd)");
+ n = SSL_readn(ssl, buff, 5);
+ if (n != 5) {
+ aflog(2, "FATAL ERROR! (%d)", n);
+ if (n == -1) {
+ merror = SSL_get_error(ssl, n);
+ switch (merror) {
+ case SSL_ERROR_NONE : {
+ aflog(2, "FE: none");
+ break;
+ }
+ case SSL_ERROR_ZERO_RETURN : {
+ aflog(2, "FE: zero");
+ break;
+ }
+ case SSL_ERROR_WANT_READ : {
+ aflog(2, "FE: w_read");
+ break;
+ }
+ case SSL_ERROR_WANT_WRITE : {
+ aflog(2, "FE: w_write");
+ break;
+ }
+ case SSL_ERROR_WANT_CONNECT : {
+ aflog(2, "FE: w_connect");
+ break;
+ }
+ case SSL_ERROR_WANT_X509_LOOKUP : {
+ aflog(2, "FE: w_x509_lookup");
+ break;
+ }
+ case SSL_ERROR_SYSCALL : {
+ aflog(2, "FE: syscall");
+ break;
+ }
+ case SSL_ERROR_SSL : {
+ SSL_load_error_strings();
+ aflog(2, "FE: ssl:%s",
+ ERR_error_string(ERR_get_error(), (char*) buff));
+ break;
+ }
+ }
+ continue; /* what happened? */
+ }
+ if (n != 0)
+ exit(1);
+ }
+ if (n == 0) { /* server quits -> we do the same... */
+ aflog(0, "premature quit of the server -> exiting...");
+ 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 : {
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ usercon--;
+ if (contable[numofcon].state == S_STATE_CLOSING) {
+ contable[numofcon].state = S_STATE_CLEAR;
+ }
+ else if (contable[numofcon].state==S_STATE_OPEN) {
+ close(contable[numofcon].connfd);
+ FD_CLR(contable[numofcon].connfd, &allset);
+ contable[numofcon].state = S_STATE_CLEAR;
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ SSL_writen(ssl, buff, 5);
+ }
+ }
+ break;
+ }
+ case AF_S_CONOPEN : {
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ usercon++;
+ if (contable[numofcon].state == S_STATE_CLEAR) {
+ if (udp) {
+ contable[numofcon].connfd=ip_connect(desnam,despor,"udp");
+ }
+ else {
+ contable[numofcon].connfd=ip_connect(desnam,despor,"tcp");
+ }
+ FD_SET(contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (contable[numofcon].connfd+1)) ? maxfdp1 : (contable[numofcon].connfd+1);
+ buff[0] = AF_S_CONOPEN; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ SSL_writen(ssl, buff, 5);
+ contable[numofcon].state = S_STATE_OPEN;
+ }
+ }
+ break;
+ }
+ case AF_S_MESSAGE : {
+ aflog(2, "Received msg for con[%d], length=%d", numofcon, length);
+ n = SSL_readn(ssl, buff, length);
+ if (n != length) {
+ aflog(2, "n(%d)!=length(%d)", n, length);
+ break;
+ }
+ if ((numofcon>=0) && (numofcon<=usernum)) {
+ if (contable[numofcon].state == S_STATE_OPEN) {
+ aflog(2, "sent msg con[%d], length=%d", numofcon, n);
+ if (writen(contable[numofcon].connfd, buff, n)==-1) {
+ aflog(0, "Sending msg failed!");
+ }
+ }
+ }
+ break;
+ }
+ default : { /* unrecognized type of message -> exiting... */
+ aflog(0, "Server sents unrecognized message -> exiting...");
+ exit(1);
+
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+usage(char* info)
+{
+ printf("\n%s\n\n", info);
+ printf(" Options:\n");
+ printf(" -h - prints this help\n");
+ printf(" -n [server name] - where the second part of the active\n");
+ printf(" port forwarder is running (required)\n");
+ printf(" -m [portnum] - the manage port number - server must\n");
+ printf(" listening on it (default: 50126)\n");
+ printf(" -d [hostname] - name of this host/remote host - the final\n");
+ printf(" destination of the packets (default: name\n");
+ printf(" returned by hostname function)\n");
+ printf(" -p [portnum] - port we are forwarding connection to (required)\n");
+ printf(" -k [keyfile] - name of the file with RSA key (default: client.rsa)\n");
+ printf(" -u - udp mode - client will use udp protocol to\n");
+ printf(" communicate with hostname\n");
+ printf(" -U - reverse udp forwarding. Udp packets will be forwarded\n");
+ printf(" from hostname:portnum (-p) to server name:portnum (-m)\n");
+ printf(" -O [logfile] - logging everything to a logfile\n");
+ printf(" -o [logfile] - logging some data to a logfile\n");
+ printf(" -v - to be verbose - program won't enter into\n");
+ printf(" the daemon mode (use twice for greater effect)\n\n");
+ exit(0);
+}
+
diff --git a/afserver.c b/afserver.c
new file mode 100644
index 0000000..947d001
--- /dev/null
+++ b/afserver.c
@@ -0,0 +1,680 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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 <openssl/ssl.h>
+#include <openssl/err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+
+static void usage(char* info);
+
+int
+main(int argc, char **argv)
+{
+ int i, j, n, flags;
+ ConfigurationT config;
+ socklen_t len;
+ unsigned char buff[8096];
+ char hostname[100];
+ int maxfdp1;
+ fd_set rset, allset;
+ int manconnecting, numofcon, length;
+ char* name = NULL;
+ char* listen = NULL;
+ char* manage = NULL;
+ char* amount = NULL;
+ char* filenam = NULL;
+ char* type = NULL;
+ char* znak;
+ char verbose = 0;
+ RealmT* pointer = NULL;
+
+ SSL_METHOD* method;
+ SSL_CTX* ctx;
+
+ signal(SIGPIPE, SIG_IGN);
+
+ config.certif = NULL;
+ config.keys = NULL;
+ config.size = 0;
+ config.realmtable = NULL;
+ config.logging = 0;
+ config.logfnam = NULL;
+
+ while ((n = getopt(argc, argv, "hn:l:m:vu:c:k:f:t:o:O:")) != -1) {
+ switch (n) {
+ case 'h': {
+ usage("Active port forwarder (server) v0.5.2");
+ break;
+ }
+ case 'n': {
+ name = optarg;
+ break;
+ }
+ case 'l': {
+ listen = optarg;
+ break;
+ }
+ case 'm': {
+ manage = optarg;
+ break;
+ }
+ case 'v': {
+ ++verbose;
+ break;
+ }
+ case 'u': {
+ amount = optarg;
+ break;
+ }
+ case 'c': {
+ config.certif = optarg;
+ break;
+ }
+ case 'k': {
+ config.keys = optarg;
+ break;
+ }
+ case 't': {
+ type = optarg;
+ break;
+ }
+ case 'f': {
+ filenam = optarg;
+ break;
+ }
+ case 'O': {
+ config.logfnam = optarg;
+ config.logging = 2;
+ break;
+ }
+ case 'o': {
+ config.logfnam = optarg;
+ config.logging = 1;
+ break;
+ }
+ case '?': {
+ usage("");
+ break;
+ }
+ }
+ }
+
+ 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 (amount == NULL) {
+ amount = "5";
+ }
+ 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;
+ if (strcmp(type, "tcp") == 0) {
+ config.realmtable[0].type = 1;
+ }
+ else if (strcmp(type, "udp") == 0) {
+ config.realmtable[0].type = 2;
+ }
+ else {
+ config.realmtable[0].type = 0;
+ }
+ }
+
+ 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);
+
+ for (i = 0; i < config.size; ++i) {
+ if ((config.realmtable[i].hostname == NULL) ||
+ (config.realmtable[i].lisportnum == NULL) ||
+ (config.realmtable[i].manportnum == NULL) ||
+ (config.realmtable[i].users == NULL)) {
+ printf("Missing some of configurable variables... exiting\n");
+ printf("%d) %s, %s, %s, %s\n", i, config.realmtable[i].hostname,
+ config.realmtable[i].lisportnum,
+ config.realmtable[i].manportnum,
+ config.realmtable[i].users);
+ exit(1);
+ }
+ if (config.realmtable[i].type == 0) {
+ printf("Unrecognized type of the realm... exiting\n");
+ exit(1);
+ }
+ if ((( config.realmtable[i].usernum = strtol(config.realmtable[i].users, &znak, 10)) == LONG_MAX) || (config.realmtable[i].usernum == LONG_MIN)) {
+ printf("Invalid user amount - %s\n", config.realmtable[i].users);
+ exit(1);
+ }
+ if (((*(config.realmtable[i].users)) == '\0') || (*znak != '\0')) {
+ printf("Invalid user amount - %s\n", config.realmtable[i].users);
+ exit(1);
+ }
+
+ 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].listenfd = ip_listen(config.realmtable[i].hostname,
+ config.realmtable[i].lisportnum, (&(config.realmtable[i].addrlen)), "tcp");
+ config.realmtable[i].managefd = ip_listen(config.realmtable[i].hostname,
+ config.realmtable[i].manportnum, (&(config.realmtable[i].addrlen)), "tcp");
+ config.realmtable[i].cliaddr = malloc(config.realmtable[i].addrlen);
+
+ config.realmtable[i].ssl = SSL_new(ctx);
+ if (config.realmtable[i].ssl == NULL) {
+ printf("Creating of ssl object failed... exiting\n");
+ exit(1);
+ }
+
+ FD_SET(config.realmtable[i].managefd, &allset);
+ maxfdp1 = (maxfdp1 > (config.realmtable[i].managefd+1)) ? maxfdp1 : (config.realmtable[i].managefd+1);
+ config.realmtable[i].usercon = 0;
+ config.realmtable[i].ready = 0;
+ config.realmtable[i].tv.tv_sec = 5;
+ config.realmtable[i].tv.tv_usec = 0;
+ }
+
+ if (loginit(verbose, config.logging, config.logfnam)) {
+ printf("Can't open file to log to... exiting\n");
+ exit(1);
+ }
+
+ if (!verbose)
+ daemon(0, 0);
+
+ aflog(1, "Server started");
+
+ for ( ; ; ) {
+ rset = allset;
+ aflog(2, ">select, maxfdp1: %d", maxfdp1);
+ if (manconnecting) {
+ /* find out, in what realm client is trying to connect */
+ for (i = 0; i < config.size; ++i) {
+ if ((config.realmtable[i].ready == 1) || (config.realmtable[i].ready == 2)) {
+ break; /* so i points to first good realm */
+ }
+ }
+ if (select(maxfdp1, &rset, NULL, NULL, (&(config.realmtable[i].tv))) == 0) {
+ close (config.realmtable[i].commfd);
+ FD_CLR(config.realmtable[i].commfd, &allset);
+ FD_CLR(config.realmtable[i].listenfd, &allset);
+ FD_SET(config.realmtable[i].managefd, &allset);
+ config.realmtable[i].ready = 0;
+ manconnecting--;
+ aflog(1, "SSL_accept failed (timeout) in realm[%d]", i);
+ }
+ }
+ else {
+ select(maxfdp1, &rset, NULL, NULL, NULL);
+ }
+ aflog(2, "<< >>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)
+ if (FD_ISSET(pointer->contable[i].connfd, &rset)) {
+ aflog(2, "FD_ISSET(realm[%d].contable[%d].connfd)", j, i);
+ if (pointer->type == 1) { /* forwarding tcp packets */
+ n = read(pointer->contable[i].connfd, &buff[5], 8091);
+ if (n == -1)
+ n = 0;
+ if (n) {
+ aflog(2, "message from realm[%d].con[%d], length=%d", j, i, n);
+ if ((buff[5] == AF_S_MESSAGE) &&
+ (buff[6] == AF_S_LOGIN) &&
+ (buff[7] == AF_S_MESSAGE)) {
+ aflog(2, "WARNING: got packet similiar to udp");
+ }
+ buff[0] = AF_S_MESSAGE; /* sending message */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ buff[3] = n >> 8; /* high bits of message length */
+ buff[4] = n; /* low bits of message length */
+ SSL_writen(pointer->ssl, buff, n+5);
+ }
+ else {
+ aflog(1, "user closed: realm[%d].con[%d]", j, i);
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, 5);
+ }
+ }
+ 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, "message from realm[%d].con[%d], length=%d", j, i, n);
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, n+5);
+ }
+ }
+ else {
+ n = 0;
+ }
+ }
+
+ if (n == 0) {
+ aflog(1, "user closed: realm[%d].con[%d]", j, i);
+ close(pointer->contable[i].connfd);
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ pointer->contable[i].state = S_STATE_CLOSING;
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, 5);
+ }
+
+ }
+ }
+ }
+ if (pointer->ready == 3)
+ if (FD_ISSET(pointer->listenfd, &rset)) {
+ aflog(2, "FD_ISSET(realm[%d].listenfd)", j);
+ len = pointer->addrlen;
+ if (pointer->ready == 3) {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state == S_STATE_CLEAR) {
+ aflog(2, "realm[%d].contable[%d].connfd = (realm[%d].listenfd)", j, i, j);
+ pointer->contable[i].connfd =
+ accept(pointer->listenfd, pointer->cliaddr, &len);
+ pointer->contable[i].state = S_STATE_OPENING;
+ pointer->usercon++;
+ aflog(1, "user IP:%s",sock_ntop(pointer->cliaddr, len));
+ if (pointer->usercon == pointer->usernum)
+ FD_CLR(pointer->listenfd, &allset);
+ buff[0] = AF_S_CONOPEN; /* opening connection */
+ buff[1] = i >> 8; /* high bits of user number */
+ buff[2] = i; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, 5);
+ break;
+ }
+ }
+ }
+ }
+ if (pointer->ready != 0)
+ if (FD_ISSET(pointer->commfd, &rset)) {
+ if (pointer->ready == 1) {
+ if (SSL_set_fd(pointer->ssl, pointer->commfd) != 1) {
+ aflog(0, "Problem with initializing ssl... exiting");
+ exit(1);
+ }
+ aflog(2, "Trying SSL_accept in realm[%d]", j);
+ if ((n = SSL_accept(pointer->ssl)) != 1) {
+ flags = SSL_get_error(pointer->ssl, n);
+ 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->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ manconnecting--;
+ aflog(1, "SSL_accept failed (denied) in realm[%d]", j);
+ }
+ else {
+ aflog(1, "SSL_accept successfull in realm[%d]", j);
+ pointer->ready = 2;
+ }
+ continue; /* in the case this is not our client */
+ }
+ aflog(2, "FD_ISSET(realm[%d].commfd)", j);
+ n = SSL_read(pointer->ssl, buff, 5);
+ if (n == -1) {
+ if (errno == EAGAIN) {
+ continue;
+ }
+ else {
+ n = 0;
+ }
+ }
+ else if (n != 5) {
+ n = 0;
+ }
+ if (n==0) {
+ close(pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->managefd+1)) ? maxfdp1 : (pointer->managefd+1);
+ if (pointer->ready == 3) {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state != S_STATE_CLEAR) {
+ pointer->contable[i].state = S_STATE_CLEAR;
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ close(pointer->contable[i].connfd);
+ }
+ }
+ }
+ pointer->usercon = 0;
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ aflog(1, "realm[%d].commfd closed!", j);
+ 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 : {
+ if ((numofcon>=0) &&
+ (numofcon<=(pointer->usernum)) &&
+ ((pointer->ready)==3)) {
+ (pointer->usercon)--;
+ if (pointer->usercon == pointer->usernum-1)
+ FD_SET(pointer->listenfd, &allset);
+ if (pointer->contable[numofcon].state ==
+ S_STATE_CLOSING) {
+ pointer->contable[numofcon].state =
+ S_STATE_CLEAR;
+ }
+ else if (pointer->contable[numofcon].state ==
+ S_STATE_OPEN) {
+ aflog(1, "user kicked: realm[%d].con[%d]", j, numofcon);
+ close(pointer->contable[numofcon].connfd);
+ FD_CLR(pointer->contable[numofcon].connfd, &allset);
+ pointer->contable[numofcon].state = S_STATE_CLEAR;
+ buff[0] = AF_S_CONCLOSED; /* closing connection */
+ buff[1] = numofcon >> 8; /* high bits of user number */
+ buff[2] = numofcon; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, 5);
+ }
+ }
+ else {
+ close (pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ if (pointer->ready == 2)
+ manconnecting--;
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ }
+ break;
+ }
+ case AF_S_CONOPEN : {
+ if ((numofcon>=0) &&
+ (numofcon<=(pointer->usernum)) &&
+ ((pointer->ready)==3)) {
+ if (pointer->contable[numofcon].state ==
+ S_STATE_OPENING) {
+ aflog(2, "realm[%d].con[%d]->ok",j,numofcon);
+ FD_SET(pointer->contable[numofcon].connfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->contable[numofcon].connfd+1)) ?
+ maxfdp1 : (pointer->contable[numofcon].connfd+1);
+ pointer->contable[numofcon].state =
+ S_STATE_OPEN;
+ }
+ }
+ else {
+ close (pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ if (pointer->ready == 2)
+ manconnecting--;
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ }
+ break;
+ }
+ case AF_S_MESSAGE : {
+ if ((pointer->ready) != 3) {
+ close (pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ manconnecting--;
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ break;
+ }
+ if (pointer->type==2) { /* udp */
+ n = SSL_readn(pointer->ssl, &buff[5], length);
+ }
+ else {
+ n = SSL_readn(pointer->ssl, buff, length);
+ }
+ if (n != length) {
+ aflog(2, "n(%d)!=length(%d)", n, length);
+ break;
+ }
+ if ((numofcon>=0) &&
+ (numofcon<=(pointer->usernum))) {
+ if (pointer->contable[numofcon].state ==
+ S_STATE_OPEN) {
+ aflog(2, "message to realm[%d].con[%d], length=%d",j, numofcon, n);
+ if (pointer->type==2) { /* udp */
+ buff[1] = AF_S_LOGIN;
+ buff[2] = AF_S_MESSAGE;
+ writen(pointer->contable[numofcon].connfd, buff, n+5);
+ }
+ else {
+ writen(pointer->contable[numofcon].connfd, buff, n);
+ }
+ }
+ }
+ break;
+ }
+ case AF_S_LOGIN : {
+ if ((pointer->ready == 2)&&(numofcon==259)&&(length==1538)) {
+ pointer->ready = 3;
+ buff[0] = AF_S_LOGIN; /* sending message */
+ buff[1] = pointer->usernum >> 8;/* high bits of user number */
+ buff[2] = pointer->usernum; /* low bits of user number */
+ SSL_writen(pointer->ssl, buff, 5);
+ FD_SET(pointer->listenfd, &allset);
+ manconnecting--;
+ }
+ else {
+ close (pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ if (pointer->ready == 2)
+ manconnecting--;
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ }
+ break;
+ }
+ default : {
+ aflog(1, "Unrecognized message - closing realm[%d]", j);
+ close (pointer->commfd);
+ FD_CLR(pointer->commfd, &allset);
+ FD_CLR(pointer->listenfd, &allset);
+ FD_SET(pointer->managefd, &allset);
+ if (pointer->ready == 2)
+ manconnecting--;
+ if (pointer->ready == 3) {
+ for (i = 0; i < pointer->usernum; ++i) {
+ if (pointer->contable[i].state != S_STATE_CLEAR) {
+ pointer->contable[i].state = S_STATE_CLEAR;
+ FD_CLR(pointer->contable[i].connfd, &allset);
+ close(pointer->contable[i].connfd);
+ }
+ }
+ }
+ SSL_clear(pointer->ssl);
+ pointer->ready = 0;
+ }
+ }
+ }
+
+ if (FD_ISSET(pointer->managefd, &rset)) {
+ aflog(2, "FD_ISSET(realm[%d].managefd)", j);
+ len = pointer->addrlen;
+ if (!(pointer->ready)) {
+ aflog(2, "accept(realm[%d].managefd)", j);
+ pointer->commfd = accept(pointer->managefd, pointer->cliaddr, &len);
+ flags = fcntl(pointer->commfd, F_GETFL, 0);
+ fcntl(pointer->commfd, F_SETFL, flags | O_NONBLOCK);
+ aflog(1, " >> Client IP:%s", sock_ntop(pointer->cliaddr, len));
+ FD_SET(pointer->commfd, &allset);
+ maxfdp1 = (maxfdp1 > (pointer->commfd+1)) ? maxfdp1 : (pointer->commfd+1);
+ FD_CLR(pointer->managefd, &allset);
+ pointer->tv.tv_sec = 5;
+ manconnecting++;
+ pointer->ready = 1;
+ }
+ }
+ } /* realms loop */
+ }
+}
+
+static void
+usage(char* info)
+{
+ printf("\n%s\n\n", info);
+ printf(" Options:\n");
+ printf(" -h - prints this help\n");
+ printf(" -n [hostname] - it's used when creating listening sockets\n");
+ printf(" (default: name returned by hostname function)\n");
+ printf(" -l [portnum] - the listening port number - users connect\n");
+ printf(" to it (default: 50127)\n");
+ printf(" -m [portnum] - the manage port number - second part of active\n");
+ printf(" port forwarder connects to it (default: 50126)\n");
+ printf(" -u [#users] - amount of users allowed to use this server\n");
+ printf(" (default: 5)\n");
+ printf(" -c [cerfile] - name of the file with certificate (default: cacert.pem)\n");
+ printf(" -k [keyfile] - name of the file with RSA key (default: server.rsa)\n");
+ printf(" -f [cfgfile] - name of the file with configuration for active\n");
+ printf(" forwarder (server)\n");
+ printf(" -t [type] - type of the server (tcp|udp) - for which protocol it\n");
+ printf(" would be (default: tcp)\n");
+ printf(" -O [logfile] - logging everything to a logfile\n");
+ printf(" -o [logfile] - logging some data to a logfile\n");
+ printf(" -v - to be verbose - program won't enter into\n");
+ printf(" the daemon mode (use twice for greater effect)\n\n");
+ exit(0);
+}
+
diff --git a/config b/config
new file mode 100644
index 0000000..4a3eb4e
--- /dev/null
+++ b/config
@@ -0,0 +1,39 @@
+# This is an example configuration file for active forwarder
+# Firstly, we have to declare our files with key and certificate
+
+certificate cacert.pem
+
+# Please note, that we can place only blank characters between words
+
+key server.rsa
+
+# when we want to log some information, we specify file for lightlog
+# when we want to log everything - we do this by using heavylog option
+
+# type name of file
+
+lightlog logfile
+#heavylog logfile
+
+
+# And it's time for create forwarding targets (named realms here)
+
+#newrealm indicates a new set of commands to a server
+newrealm
+
+#options values
+
+hostname <yourhostname> #this is a name of the server (it's using it for choosing interface)
+listen 50127 #portnumber on which server is listening for users
+manage 50126 #portnumber on which server is listening for afclient
+users 5 #amount of users we are allowing to connect
+type tcp #type of the realm (which protocol it will forward (tcp|udp)
+
+# and now the second realm
+
+newrealm
+hostname <yourhostname>
+listen 50125
+manage 50124
+users 5
+type tcp
diff --git a/file.c b/file.c
new file mode 100644
index 0000000..b81e595
--- /dev/null
+++ b/file.c
@@ -0,0 +1,159 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+ConfigurationT
+parsefile(char* name, int* status)
+{
+ static ConfigurationT cfg;
+ FILE* file = NULL;
+ int state;
+ 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.logfnam = NULL;
+
+ state = F_UNKNOWN;
+
+ file = fopen(name, "r");
+ if (file == NULL) {
+ return cfg;
+ }
+
+ while (fgets(buff, 256, file) != NULL) {
+ helpbuf1[0] = 0;
+ sscanf(buff, "%s", helpbuf1);
+ if (strcmp(helpbuf1, "newrealm")==0) {
+ ++cfg.size;
+ }
+ }
+ rewind(file);
+
+ cfg.realmtable = calloc(cfg.size, sizeof(RealmT));
+ cfg.size = 0;
+ *status = 0;
+
+ while (fgets(buff, 256, file) != NULL) {
+ (*status)++;
+ state = sscanf(buff, "%s %s", helpbuf1, helpbuf2);
+ if (helpbuf1[0] == '#') {
+ memset(buff, 0, 256);
+ continue;
+ }
+ if (state == 1) {
+ if (strcmp(helpbuf1, "newrealm")==0) {
+ ++cfg.size;
+ }
+ else {
+ return cfg;
+ }
+ }
+ else if (state == 2) {
+ 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 = 2;
+ 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 (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].lisportnum = calloc(strlen(helpbuf2)+1,
+ sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].lisportnum, helpbuf2);
+ }
+ else if (strcmp(helpbuf1, "manage")==0) {
+ cfg.realmtable[cfg.size-1].manportnum = calloc(strlen(helpbuf2)+1,
+ sizeof(char));
+ strcpy(cfg.realmtable[cfg.size-1].manportnum, helpbuf2);
+ }
+ 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, "type")==0) {
+ if (cfg.realmtable[cfg.size-1].type != 0) {
+ return cfg;
+ }
+ if (strcmp(helpbuf2, "tcp")==0) {
+ cfg.realmtable[cfg.size-1].type = 1;
+ }
+ else if (strcmp(helpbuf2, "udp")==0) {
+ cfg.realmtable[cfg.size-1].type = 2;
+ }
+ else {
+ return cfg;
+ }
+ }
+ else {
+ return cfg;
+ }
+ }
+ memset(buff, 0, 256);
+ }
+
+ fclose(file);
+
+ *status = 0;
+ return cfg;
+}
+
diff --git a/file.h b/file.h
new file mode 100644
index 0000000..0a27894
--- /dev/null
+++ b/file.h
@@ -0,0 +1,65 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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
+
+typedef struct {
+ char* hostname;
+ char* lisportnum;
+ char* manportnum;
+ char* users;
+ int usercon;
+ int usernum;
+ int listenfd;
+ int managefd;
+ int commfd;
+ char ready;
+ char type;
+ socklen_t addrlen;
+ struct sockaddr* cliaddr;
+ struct timeval tv;
+ SSL* ssl;
+ ConnectuserT* contable;
+} RealmT;
+
+typedef struct {
+ char* certif;
+ char* keys;
+ char* logfnam;
+ char logging;
+ int size;
+ RealmT* realmtable;
+} ConfigurationT;
+
+ConfigurationT parsefile(char*, int*); /* parse the cfg file */
+
+#endif
+
diff --git a/network.c b/network.c
new file mode 100644
index 0000000..59e14a9
--- /dev/null
+++ b/network.c
@@ -0,0 +1,257 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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"
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+static void
+sig_alrm(int signo)
+{
+ return;
+}
+
+int
+ip_listen(const char *host, const char *serv, socklen_t *addrlenp, const char *type)
+{
+ int listenfd, n, typ;
+ const int on = 1;
+ struct addrinfo hints, *res, *ressave;
+
+ if (strcmp(type, "udp") == 0)
+ typ = 0; /* this is udp_listen */
+ else
+ typ = 1; /* default: tcp_listen */
+
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_UNSPEC;
+
+ if (typ)
+ hints.ai_socktype = SOCK_STREAM;
+ else
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ printf("%s_listen error for %s, %s: %s\n",
+ (typ)?"tcp":"udp", host, serv, gai_strerror(n));
+ exit(1);
+ }
+ ressave = res;
+
+ do {
+ listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (listenfd < 0)
+ continue; /* error, try next one */
+
+ if (typ) /* tcp_listen */
+ setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
+ break; /* success */
+
+ close(listenfd); /* bind error, close and try next one */
+ } while ( (res = res->ai_next) != NULL);
+
+ if (res == NULL) { /* errno from final socket() or bind() */
+ printf("%s_listen error for %s, %s\n", (typ)?"tcp":"udp", host, serv);
+ exit(1);
+ }
+
+ if (typ) /* tcp_listen */
+ listen(listenfd, 1);
+
+ if (addrlenp)
+ *addrlenp = res->ai_addrlen; /* return size of protocol address */
+
+ freeaddrinfo(ressave);
+
+ return(listenfd);
+}
+
+int
+ip_connect(const char *host, const char *serv, const char* type)
+{
+ int sockfd, n, typ;
+ struct addrinfo hints, *res, *ressave;
+
+ if (strcmp(type, "udp") == 0)
+ typ = 0; /* this is udp_listen */
+ else
+ typ = 1; /* default: tcp_listen */
+
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ if (typ)
+ hints.ai_socktype = SOCK_STREAM;
+ else
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) {
+ printf("%s_connect error for %s, %s: %s\n",
+ (typ)?"tcp":"udp", host, serv, gai_strerror(n));
+ exit(1);
+ }
+ 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() */
+ printf("%s_connect error for %s, %s\n", (typ)?"tcp":"udp", host, serv);
+ exit(1);
+ }
+
+ freeaddrinfo(ressave);
+
+ return(sockfd);
+}
+
+char *
+sock_ntop(const struct sockaddr *sa, socklen_t salen)
+{
+ char portstr[7];
+ static char str[128]; /* Unix domain is largest */
+
+ switch (sa->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+
+ if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
+ return(NULL);
+ if (ntohs(sin->sin_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
+ strcat(str, portstr);
+ }
+ return(str);
+ }
+
+#ifdef IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL)
+ return(NULL);
+ if (ntohs(sin6->sin6_port) != 0) {
+ snprintf(portstr, sizeof(portstr), ".%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) {
+ signal(SIGALRM, sig_alrm);
+ alarm(5);
+ n = SSL_write(fd, buf+sent, amount - sent);
+ alarm(0);
+ 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) {
+ signal(SIGALRM, sig_alrm);
+ alarm(5);
+ n = write(fd, buf+sent, amount - sent);
+ alarm(0);
+ 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;
+
+}
diff --git a/network.h b/network.h
new file mode 100644
index 0000000..c4d168c
--- /dev/null
+++ b/network.h
@@ -0,0 +1,45 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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>
+
+int ip_listen(const char *host, const char *serv, socklen_t *addrlenp, const char *type); /* socket, bind, listen... */
+int ip_connect(const char *host, const char *serv, const char *type); /* socket, connect... */
+char* sock_ntop(const struct sockaddr* sa, socklen_t salen); /* return the hostname of connected user */
+int 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/stats.c b/stats.c
new file mode 100644
index 0000000..3eca5b9
--- /dev/null
+++ b/stats.c
@@ -0,0 +1,79 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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 <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+
+static char verlev;
+static char loglev;
+static FILE* logfd;
+
+char*
+datum(void)
+{
+ time_t sec;
+ struct tm* tm;
+ static char timedat[20];
+ time(&sec);
+ tm = localtime(&sec);
+ memset(timedat, 0, 20);
+ strftime(timedat, 20, "%d.%m.%Y %H:%M:%S", tm);
+ return timedat;
+}
+
+int
+loginit(char verl, char logl, const char* logfname) {
+ verlev = loglev = 0;
+ if (logfd)
+ fclose(logfd);
+ logfd = NULL;
+ verlev = verl;
+ loglev = logl;
+ if (loglev) {
+ logfd = fopen(logfname, "a");
+ if (logfd == NULL)
+ return 1; /* logging to a non-opened file? */
+ }
+ return 0;
+}
+
+void
+aflog(char type, const char* format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ if (verlev)
+ if (type <= verlev) {
+ printf("[%s] ", datum());
+ vfprintf(stdout, format, ap);
+ printf("\n");
+ }
+ if (loglev)
+ if (type <= loglev) {
+ fprintf(logfd, "[%s] ", datum());
+ vfprintf(logfd, format, ap);
+ fprintf(logfd, "\n");
+ fflush(logfd);
+ }
+ va_end(ap);
+}
diff --git a/stats.h b/stats.h
new file mode 100644
index 0000000..117899f
--- /dev/null
+++ b/stats.h
@@ -0,0 +1,28 @@
+/*
+ * active port forwarder - software for secure forwarding
+ * Copyright (C) 2003 jeremian <jeremian@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
+
+int loginit(char verlev, char loglev, const char* logfname); /* initializes logging routine */
+void aflog(char type, const char* format, ...); /* log to a file or|and screen */
+
+#endif
+