From 46f96ed5e3127394a0cd4dcb961404b792f743b4 Mon Sep 17 00:00:00 2001 From: Jakub Slawinski Date: Thu, 10 Jul 2014 10:24:59 +0200 Subject: Initial project structure based on Active Port Forwarder 0.8.4. --- src/client_reverse_udp.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/client_reverse_udp.c (limited to 'src/client_reverse_udp.c') diff --git a/src/client_reverse_udp.c b/src/client_reverse_udp.c new file mode 100644 index 0000000..882a6f9 --- /dev/null +++ b/src/client_reverse_udp.c @@ -0,0 +1,213 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "client_reverse_udp.h" + +#include + +/* + * Function name: initialize_client_reverse_udp + * Description: Initializes the realm for reverse udp connection. + * Arguments: cr - pointer to ClientRealm structure + * Returns: 0 - connection was initialized successfully, + * 1 - connection initialization failed. + */ + +int +initialize_client_reverse_udp(ClientRealm* cr) +{ + int tmp; + int wanttoexit = (ArOptions_get_arStart(ClientRealm_get_arOptions(cr)) == AR_OPTION_ENABLED) ? 0 : 1; + ClientRealm_set_usersLimit(cr, 1); + if (ip_connect(&tmp, ClientRealm_get_serverName(cr), + ClientRealm_get_managePort(cr), + ClientRealm_get_ipFamily(cr), NULL, NULL)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect_%s error for %s, %s", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4" : (ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect error for %s, %s", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + + } + SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); + SslFd_set_ssl(ClientRealm_get_masterSslFd(cr), NULL); + return 0; +} + +/* + * Function name: client_reverse_udp + * Description: This function is responsible for the client part of the reverse udp tunnel. + * Arguments: cr - pointer to ClientRealm structure + * buff - buffer which will be used for communication + * buflength - socket send buffer size + */ + +void +client_reverse_udp(ClientRealm* cr, unsigned char* buff, int buflength) +{ + socklen_t len, addrlen; + int maxfdp1, temp, n, length; +#ifdef HAVE_LINUX_SOCKIOS_H + int notsent; +#endif + struct sockaddr* cliaddr; + fd_set rset, allset; + + if (ip_listen(&temp, ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0)), &addrlen, + ClientRealm_get_ipFamily(cr) & 0xfe)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen_%s error for %s, %s", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0))); +#else + aflog(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen error for %s, %s", ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0))); +#endif + exit(1); + } + ConnectUser_set_connFd(ClientRealm_get_usersTable(cr)[0], temp); + cliaddr = malloc(addrlen); + FD_ZERO(&allset); + + FD_SET(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), &allset); + maxfdp1 = SslFd_get_fd(ClientRealm_get_masterSslFd(cr)) + 1; + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]) + 1); + FD_SET(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &allset); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "CLIENT STARTED mode: udp reverse"); + for ( ; ; ) { + len = 4; + if (getsockopt(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), SOL_SOCKET, SO_SNDBUF, &temp, &len) != -1) { + if (temp != buflength) { + buflength = temp; + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "Send buffer size changed..."); + } + } + len = addrlen; + rset = allset; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "select"); + select(maxfdp1, &rset, NULL, NULL, NULL); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "after select..."); + + if (FD_ISSET(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/ + n = recvfrom(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &buff[5], 8091, 0, cliaddr, &len); +#ifdef HAVE_LINUX_SOCKIOS_H +# ifdef SIOCOUTQ + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "SIOCOUTQ is defined"); + if (ioctl(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), SIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (buflength <= notsent + n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); +# else + aflog(LOG_T_MAIN< LOG_I_DDEBUG, + "TIOCOUTQ is defined"); + if (ioctl(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), TIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (notsent <= n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength); +# endif + } + else { +#endif + if (n > 0) { +#ifdef HAVE_LINUX_SOCKIOS_H + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to service (w:%d/%d) (FROM:%s)", n, +# ifdef SIOCOUTQ + notsent +# else + buflength - notsent +# endif + , buflength, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#else + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to service (FROM:%s)", n, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#endif + buff[0] = AF_S_MESSAGE; + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; + buff[4] = n; + writen(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, n + 5); + } +#ifdef HAVE_LINUX_SOCKIOS_H + } +#endif + } /* - FD_ISSET CONTABLE[0].CONNFD RSET */ + + if (FD_ISSET(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + n = readn(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, 5); + if (n == 5) { + if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "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(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, length); + } + else { + n = 0; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "premature quit of the server -> exiting..."); + exit(1); + } + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to user (TO:%s)", n, sock_ntop(cliaddr, addrlen, NULL, NULL, 0)); + sendto(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), buff, n, 0, cliaddr, addrlen); + } /* - FD_ISSET MASTER.COMMFD RSET */ + } + exit(0); /* we shouldn't get here */ +} -- cgit v1.1