diff options
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | Changelog | 16 | ||||
-rw-r--r-- | Makefile | 50 | ||||
-rw-r--r-- | README | 89 | ||||
-rw-r--r-- | activefor.h | 41 | ||||
-rw-r--r-- | afclient.c | 537 | ||||
-rw-r--r-- | afserver.c | 680 | ||||
-rw-r--r-- | config | 39 | ||||
-rw-r--r-- | file.c | 159 | ||||
-rw-r--r-- | file.h | 65 | ||||
-rw-r--r-- | network.c | 257 | ||||
-rw-r--r-- | network.h | 45 | ||||
-rw-r--r-- | stats.c | 79 | ||||
-rw-r--r-- | stats.h | 28 |
14 files changed, 2425 insertions, 0 deletions
@@ -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) @@ -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, ¬sent)) { + 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, ¬sent)) { + 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, ¬sent)) { + 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, ¬sent)) { + 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); +} + @@ -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 @@ -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; +} + @@ -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 @@ -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); +} @@ -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 + |