diff options
Diffstat (limited to 'src/http_proxy_server.c')
-rw-r--r-- | src/http_proxy_server.c | 585 |
1 files changed, 0 insertions, 585 deletions
diff --git a/src/http_proxy_server.c b/src/http_proxy_server.c deleted file mode 100644 index 17baf5a..0000000 --- a/src/http_proxy_server.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * active port forwarder - software for secure forwarding - * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include <config.h> - -#include "make_ssl_handshake.h" -#include "http_proxy_server.h" -#include "thread_management.h" -#include "stats.h" -#include "logging.h" -#include "network.h" - -#ifdef HAVE_LIBPTHREAD - -typedef struct { - int sockfd; - char *host; - char *serv; - socklen_t *addrlenp; - char type; - int limit; - char https; - SSL_CTX* ctx; -} sproxy_argT; - -/* - * Function name: afserver_connect - * Description: Connects new http proxy connection to the afserver. - * Arguments: sockfd - the file descriptor which will be used for communication with afserver - * afserverfd - the afserver's file descriptor - * cliaddr - pointer to sockaddr structure - * addrlenp - pointer to the length of the sockaddr structure - * type - the type of the connection - */ - -int -afserver_connect(int* sockfd, int afserverfd, struct sockaddr* cliaddr, socklen_t* addrlenp, char type) -{ - int sockets[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { - return 1; - } - if (write(afserverfd, &sockets[0], 4) != 4) { - return 2; - } - if (write(afserverfd, &type, 1) != 1) { - return 3; - } - if (write(afserverfd, addrlenp, 4) != 4) { - return 4; - } - if (write(afserverfd, cliaddr, *addrlenp) != *addrlenp) { - return 5; - } - (*sockfd) = sockets[1]; - return 0; -} - -/* - * Function name: http_proxy_server - * Description: Function responsible for the server part of the http proxy connection. - * Arguments: vptr - the structure with all the information needed for http proxy tunnel. - */ - -void* -http_proxy_server(void *vptr) -{ - int listenfd, afserverfd; - SslFd* connFd; - struct sockaddr* cliaddr; - char tab[9000]; - connection* table; - header hdr; - int i, n, maxfdp1; - fd_set rset, allset; - struct timeval tv; - int maxclients, tmp; - int timeout = 5; - socklen_t *addrlenp; - socklen_t addrlen; - char type, nothttp, https; - char *host, *serv, *name = ""; - SSL_CTX* ctx; - sproxy_argT *proxy_argptr; - - start_critical_section(); - proxy_argptr = (sproxy_argT *) vptr; - - afserverfd = proxy_argptr->sockfd; - host = proxy_argptr->host; - serv = proxy_argptr->serv; - addrlenp = proxy_argptr->addrlenp; - type = proxy_argptr->type; - maxclients = proxy_argptr->limit+1; - https = proxy_argptr->https; - ctx = proxy_argptr->ctx; - - if (https) { - name = "s"; - } - - table = calloc(maxclients, sizeof(connection)); - if (table == NULL) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't allocate memory... exiting.", name); - exit(1); - } - for (i = 0; i < maxclients; ++i) { - table[i].postFd = SslFd_new(); - table[i].getFd = SslFd_new(); - table[i].tmpFd = SslFd_new(); - if ((table[i].postFd == NULL) || (table[i].getFd == NULL) || (table[i].tmpFd == NULL)) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't allocate memory... exiting.", name); - exit(1); - } - if (https) { - SslFd_set_ssl(table[i].postFd, SSL_new(ctx)); - SslFd_set_ssl(table[i].getFd, SSL_new(ctx)); - SslFd_set_ssl(table[i].tmpFd, SSL_new(ctx)); - if ((SslFd_get_ssl(table[i].postFd) == NULL) || - (SslFd_get_ssl(table[i].getFd) == NULL) || - (SslFd_get_ssl(table[i].tmpFd) == NULL)) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't allocate memory... exiting.", name); - exit(1); - } - } - } - connFd = SslFd_new(); - if (connFd == NULL) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't allocate memory... exiting.", name); - exit(1); - } - if (https) { - SslFd_set_ssl(connFd, SSL_new(ctx)); - if (SslFd_get_ssl(connFd) == NULL) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't allocate memory... exiting.", name); - exit(1); - } - } - - if (ip_listen(&listenfd, host, serv, addrlenp, type)) { - aflog(LOG_T_INIT, LOG_I_CRIT, - "http%s proxy: Can't listen on %s:%s", name, host, serv); - exit(1); - } - cliaddr = malloc(*addrlenp); - addrlen = (*addrlenp); - addrlenp = &addrlen; - - broadcast_condition(); - end_critical_section(); - - FD_ZERO(&allset); - FD_SET(listenfd, &allset); - maxfdp1 = listenfd + 1; - tv.tv_usec = 0; - tv.tv_sec = timeout; - - while (1) { - rset = allset; - - if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: timeout", name); - tv.tv_sec = timeout; - for (i = 0; i < maxclients; ++i) { - if ((table[i].state == C_CLOSED) || (table[i].state & C_GET_WAIT) || (table[i].type == 1)) { - continue; - } - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: send T to table[%d].getfd", name, i); - if (table[i].sent_ptr+1 >= 90000) { - http_write(https, table[i].getFd, (unsigned char*) "T", 1); - table[i].sent_ptr = 0; - clear_sslFd(table[i].getFd, &allset); - FD_CLR(table[i].sockfd, &allset); - table[i].state |= C_GET_WAIT; - } - else { - http_write(https, table[i].getFd, (unsigned char*) "T", 1); - table[i].sent_ptr += 1; - } - } - continue; - } - - /* http proxy tunnels */ - for (i = 0; i < maxclients; ++i) { - if ((table[i].state == C_CLOSED) || (table[i].type == 1)) { - continue; - } - - /* sockfd */ - if ((!(table[i].state & C_GET_WAIT)) && (FD_ISSET(table[i].sockfd, &rset))) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: FD_ISSET(table[%d].sockfd)", name, i); - n = read(table[i].sockfd, table[i].buf+5, 8995); - if (n <= 0) { - http_write(https, table[i].getFd, (unsigned char*) "Q", 1); - delete_user(table, i, &allset); - continue; - } - table[i].buf[0] = 'M'; - tmp = htonl(n); - memcpy(&table[i].buf[1], &tmp, 4); - if (table[i].sent_ptr+5 + n >= 90000) { - http_write(https, table[i].getFd, (unsigned char*) table[i].buf, 90000 - table[i].sent_ptr); - table[i].ptr = 90000 - table[i].sent_ptr; - table[i].length = 5+n - table[i].ptr; - table[i].sent_ptr = 0; - clear_sslFd(table[i].getFd, &allset); - FD_CLR(table[i].sockfd, &allset); - table[i].state |= C_GET_WAIT; - continue; - } - else { - http_write(https, table[i].getFd, (unsigned char*) table[i].buf, n+5); - table[i].sent_ptr += n+5; - } - } - - /* getfd */ - if (FD_ISSET(SslFd_get_fd(table[i].getFd), &rset)) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: FD_ISSET(table[%d].getfd)", name, i); - delete_user(table, i, &allset); - continue; - } - - /* postfd */ - if (FD_ISSET(SslFd_get_fd(table[i].postFd), &rset)) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: FD_ISSET(table[%d].postfd)", name, i); - n = http_read(https, table[i].postFd, (unsigned char*) tab, 9000); - if (n != 0) { - table[i].received += n; - if (read_message(table[i].sockfd, n, &table[i], tab, 0)) { - delete_user(table, i, &allset); - } - } - if ((n == 0) || (table[i].received == 90000)) { - table[i].received = 0; - clear_sslFd(table[i].postFd, &allset); - table[i].state |= C_POST_WAIT; - - if (!(table[i].state & C_GET_WAIT)) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: send A to table[%d].getfd", name, i); - if (table[i].sent_ptr+1 >= 90000) { - http_write(https, table[i].getFd, (unsigned char*) "A", 1); - table[i].sent_ptr = 0; - clear_sslFd(table[i].getFd, &allset); - FD_CLR(table[i].sockfd, &allset); - table[i].state |= C_GET_WAIT; - } - else { - http_write(https, table[i].getFd, (unsigned char*) "A", 1); - table[i].sent_ptr += 1; - } - } - else { - table[i].state |= C_DELAYED_A; - } - - if (table[i].tmpstate == 1) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: get old POST request...", name); - table[i].state &= ~C_POST_WAIT; - SslFd_swap_content(table[i].postFd, table[i].tmpFd); - set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); - table[i].tmpstate = 0; - if (table[i].tmpheader.length) { - table[i].received += table[i].tmpheader.length; - if (read_message(table[i].sockfd, table[i].tmpheader.length, &table[i], - table[i].tmpbuf, table[i].tmpheader.ptr)) { - delete_user(table, i, &allset); - } - } - } - continue; - } - } - } - - /* direct tunnels */ - for (i = 0; i < maxclients; ++i) { - if ((table[i].state == C_OPEN) && (table[i].type == 1)) { - - if (FD_ISSET(table[i].sockfd, &rset)) { - n = read(table[i].sockfd, table[i].buf, 9000); - if (n > 0) { - writen(SslFd_get_fd(table[i].postFd), (unsigned char*) table[i].buf, n); - } - else { - delete_user(table, i, &allset); - continue; - } - } - - if (FD_ISSET(SslFd_get_fd(table[i].postFd), &rset)) { - n = read(SslFd_get_fd(table[i].postFd), tab, 9000); - if (n > 0) { - writen(table[i].sockfd, (unsigned char*) tab, n); - } - else { - delete_user(table, i, &allset); - continue; - } - } - - } - } - - /* listen */ - if (FD_ISSET(listenfd, &rset)) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: FD_ISSET(listenfd)", name); - tmp = accept(listenfd, cliaddr, addrlenp); - if (tmp != -1) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: New connection...", name); - SslFd_set_fd(connFd, tmp); - if (https) { - make_ssl_initialize(connFd); - if (make_ssl_accept(connFd)) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "https proxy: DENIED by SSL_accept"); - close(SslFd_get_fd(connFd)); - SSL_clear(SslFd_get_ssl(connFd)); - continue; - } - } - } - else { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: New connection --> EAGAIN", name); - continue; - } - memset(tab, 0, 9000); - nothttp = 0; - if (parse_header(connFd, tab, &hdr, https)) { - nothttp = 1; - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: no http header...", name); - } - n = -1; - for (i = 0; i < maxclients; ++i) { - if (table[i].state == C_CLOSED) { - if (n == -1) - n = i; - } - else { - if ((!nothttp) && (strcmp(table[i].id, hdr.id) == 0)) { - break; - } - } - } - if (i < maxclients) { /* the client exists */ - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: the client exist...", name); - if (hdr.type == H_TYPE_GET) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: type GET...", name); - if (!(table[i].state & C_GET_WAIT)) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: not waiting for GET...", name); - table[i].sent_ptr = 0; - FD_CLR(table[i].sockfd, &allset); - clear_sslFd(table[i].getFd, &allset); - table[i].state |= C_GET_WAIT; - } - if (!(table[i].state & C_OPEN)) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: not opened...", name); - if (afserver_connect(&table[i].sockfd, afserverfd, cliaddr, addrlenp, 1)) { - memset(tab, 0, 9000); - sprintf(tab,"HTTP/1.1 400 Bad Request\r\n\r\n"); - n = strlen (tab); - http_write(https, connFd, (unsigned char*) tab, n); - close_fd((&(connFd->fd))); - SSL_clear(SslFd_get_ssl(connFd)); - clear_sslFd(table[i].postFd, &allset); - table[i].state = C_CLOSED; - continue; - } - table[i].state |= C_OPEN; - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: OPEN...", name); - } - table[i].state &= ~C_GET_WAIT; - table[i].sent_ptr = 0; - SslFd_swap_content(table[i].getFd, connFd); - set_fd(table[i].sockfd, &maxfdp1, &allset); - set_fd(SslFd_get_fd(table[i].getFd), &maxfdp1, &allset); - memset(tab, 0, 9000); - sprintf(tab, - "HTTP/1.1 200 OK\r\n" - "Content-Length: 90000\r\n" - "Connection: close\r\n" - "Pragma: no-cache\r\n" - "Cache-Control: no-cache, no-store, must-revalidate\r\n" - "Expires: 0\r\n" - "Content-Type: text/html\r\n\r\n"); - n = strlen(tab); - if (writen(SslFd_get_fd(table[i].getFd), (unsigned char*) tab, n) <= 0) { - delete_user(table, i, &allset); - continue; - } - if (table[i].length) { - if (writen(SslFd_get_fd(table[i].getFd), - (unsigned char*) (table[i].buf+table[i].ptr), table[i].length) <= 0) { - delete_user(table, i, &allset); - continue; - } - } - table[i].sent_ptr = table[i].length; - table[i].ptr = 0; - table[i].length = 0; - if (table[i].state & C_DELAYED_A) { - aflog(LOG_T_MAIN, LOG_I_DDEBUG, - "http%s proxy: send A to table[%d].getfd", name, i); - http_write(https, table[i].getFd, (unsigned char*) "A", 1); - table[i].sent_ptr += 1; - table[i].state &= ~C_DELAYED_A; - } - } - else if (hdr.type == H_TYPE_POST) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: type POST...", name); - if (!(table[i].state & C_POST_WAIT)) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: unexpected POST request...", name); - if (table[i].tmpstate == 0) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: buffering POST request...", name); - table[i].tmpstate = 1; - SslFd_swap_content(table[i].tmpFd, connFd); - memcpy(table[i].tmpbuf, tab, 9000); - table[i].tmpheader = hdr; - } - else { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: no space to buffer POST request (received from first postfd: %d)", name, - table[i].received); - delete_user(table, i, &allset); - } - } - else { - if (hdr.length) { - table[i].received += hdr.length; - if (read_message(table[i].sockfd, hdr.length, &table[i], tab, hdr.ptr)) { - delete_user(table, i, &allset); - } - } - table[i].state &= ~C_POST_WAIT; - SslFd_swap_content(table[i].postFd, connFd); - set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); - } - } - else { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: unrecognized type...", name); - delete_user(table, i, &allset); - } - } - else if (n != -1) { /* there are free slots */ - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: there are free slots...", name); - if (!nothttp) { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: http header...", name); - if (hdr.type == H_TYPE_POST) { /* POST request must be first */ - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: type POST...", name); - table[n].state = C_GET_WAIT; - memcpy(table[n].id,hdr.id, 9); - SslFd_swap_content(table[n].postFd, connFd); - set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); - } - else { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: closing this connection... (not POST type)", name); - close_fd((&(connFd->fd))); - if (https) { - SSL_clear(SslFd_get_ssl(connFd)); - } - continue; - } - } - else { - table[n].state = C_OPEN; - SslFd_set_fd(table[n].postFd, SslFd_get_fd(connFd)); - table[n].type = 1; - set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); - if (afserver_connect(&table[n].sockfd, afserverfd, cliaddr, addrlenp, 0)) { - clear_sslFd(table[n].postFd, &allset); - table[n].state = C_CLOSED; - continue; - } - set_fd(table[n].sockfd, &maxfdp1, &allset); - write(table[n].sockfd, tab, hdr.allreaded); - } - } - else { - aflog(LOG_T_MAIN, LOG_I_DEBUG, - "http%s proxy: closing this connection... (no free slots)", name); - close_fd((&(connFd->fd))); - continue; - } - } - } - - return 0; -} - -/* - * Function name: initialize_http_proxy_server - * Description: Initializes the thread responsible for http proxy connection. - * Arguments: sockfd - the new connection descriptor will be stored here - * host - the name of the host on which we will be listening on - * serv - the port on which we will be listening on - * addrlenp - pointer to the length of the sockaddr structure - * type - the type of the connection - * limit - the limit for user's connections - * https - if the connection should be https instead of http - * ctx - the pointer to SSL_CTX structure - * Returns: 0 - success, - * !0 - failure. - */ - -int -initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit, char https, SSL_CTX* ctx) -{ - int retval; - int sockets[2]; - pthread_t proxy_thread; - static sproxy_argT arg; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { - return 1; - } - (*sockfd) = sockets[0]; - - start_critical_section(); - - arg.host = (char*) host; - arg.serv = (char*) serv; - arg.addrlenp = addrlenp; - arg.limit = limit; - arg.type = (char) type; - arg.sockfd = sockets[1]; - arg.https = https; - arg.ctx = ctx; - - retval = pthread_create(&proxy_thread, NULL, &http_proxy_server, &arg); - - wait_for_condition(); - - end_critical_section(); - - return retval; -} - -#endif |