summaryrefslogtreecommitdiff
path: root/src/http_proxy_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/http_proxy_server.c')
-rw-r--r--src/http_proxy_server.c585
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