From 5ea289d82ea412b59bbabd1ddfff70d3d5f1ecb2 Mon Sep 17 00:00:00 2001
From: Robert James Kaes <rjk@wormbytes.ca>
Date: Sun, 8 Jun 2008 18:50:23 -0400
Subject: Moved transparent proxy code into its own file

Extracted the transparent proxy logic from reqs.c and placed it into a
separate file.

Signed-off-by: Robert James Kaes <rjk@wormbytes.ca>
---
 src/Makefile.am         |   3 +-
 src/reqs.c              | 122 ++++--------------------------------------------
 src/reqs.h              |  22 +++++++++
 src/transparent-proxy.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++
 src/transparent-proxy.h |  39 ++++++++++++++++
 5 files changed, 193 insertions(+), 114 deletions(-)
 create mode 100644 src/transparent-proxy.c
 create mode 100644 src/transparent-proxy.h

(limited to 'src')

diff --git a/src/Makefile.am b/src/Makefile.am
index 3910e33..4b616e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@ tinyproxy_SOURCES = \
 	vector.c vector.h
 
 EXTRA_tinyproxy_SOURCES = filter.c filter.h \
-	reverse-proxy.c reverse-proxy.h
+	reverse-proxy.c reverse-proxy.h \
+	transparent-proxy.c transparent-proxy.h
 tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
 tinyproxy_LDADD = @ADDITIONAL_OBJECTS@
diff --git a/src/reqs.c b/src/reqs.c
index 5c5ff77..8d8cbe3 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -44,17 +44,13 @@
 #include "utils.h"
 #include "vector.h"
 #include "reverse-proxy.h"
+#include "transparent-proxy.h"
 
 /*
  * Maximum length of a HTTP line
  */
 #define HTTP_LINE_LENGTH (MAXBUFFSIZE / 6)
 
-/*
- * Port constants for HTTP (80) and SSL (443)
- */
-#define HTTP_PORT 80
-#define HTTP_PORT_SSL 443
 
 /*
  * Macro to help test if the Upstream proxy supported is compiled in and
@@ -79,18 +75,6 @@
  */
 static vector_t ports_allowed_by_connect = NULL;
 
-/*
- * This structure holds the information pulled from a URL request.
- */
-struct request_s {
-        char *method;
-        char *protocol;
-
-        char *host;
-        uint16_t port;
-
-        char *path;
-};
 
 /*
  * Now, this routine adds a "port" to the list.  It also creates the list if
@@ -316,28 +300,6 @@ extract_ssl_url(const char *url, struct request_s *request)
         return 0;
 }
 
-#ifdef TRANSPARENT_PROXY
-/*
- * Build a URL from parts.
- */
-static int
-build_url(char **url, const char *host, int port, const char *path)
-{
-        int len;
-
-        assert(url != NULL);
-        assert(host != NULL);
-        assert(port > 0 && port < 32768);
-        assert(path != NULL);
-
-        len = strlen(host) + strlen(path) + 14;
-        *url = safemalloc(len);
-        if (*url == NULL)
-                return -1;
-
-        return snprintf(*url, len, "http://%s:%d%s", host, port, path);
-}
-#endif                          /* TRANSPARENT_PROXY */
 
 #ifdef UPSTREAM_SUPPORT
 /*
@@ -692,88 +654,22 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
                 connptr->connect_method = TRUE;
         } else {
 #ifdef TRANSPARENT_PROXY
-                /*
-                 * This section of code is used for the transparent proxy
-                 * option.  You will need to configure your firewall to
-                 * redirect all connections for HTTP traffic to tinyproxy
-                 * for this to work properly.
-                 *
-                 * This code was written by Petr Lampa <lampa@fit.vutbr.cz>
-                 */
-                int length;
-                char *data;
-
-                length =
-                    hashmap_entry_by_key(hashofheaders, "host", (void **)&data);
-                if (length <= 0) {
-                        struct sockaddr_in dest_addr;
-
-                        if (getsockname
-                            (connptr->client_fd, (struct sockaddr *)&dest_addr,
-                             &length) < 0) {
-                                log_message(LOG_ERR,
-                                            "process_request: cannot get destination IP for %d",
-                                            connptr->client_fd);
-                                indicate_http_error(connptr, 400, "Bad Request",
-                                                    "detail",
-                                                    "Unknown destination",
-                                                    "url", url, NULL);
-                                safefree(url);
-                                free_request_struct(request);
-                                return NULL;
-                        }
-                        request->host = safemalloc(17);
-                        strcpy(request->host, inet_ntoa(dest_addr.sin_addr));
-                        request->port = ntohs(dest_addr.sin_port);
-                        request->path = safemalloc(strlen(url) + 1);
-                        strcpy(request->path, url);
-                        safefree(url);
-                        build_url(&url, request->host, request->port,
-                                  request->path);
-                        log_message(LOG_INFO,
-                                    "process_request: trans IP %s %s for %d",
-                                    request->method, url, connptr->client_fd);
-                } else {
-                        request->host = safemalloc(length + 1);
-                        if (sscanf
-                            (data, "%[^:]:%hu", request->host,
-                             &request->port) != 2) {
-                                strcpy(request->host, data);
-                                request->port = HTTP_PORT;
-                        }
-                        request->path = safemalloc(strlen(url) + 1);
-                        strcpy(request->path, url);
-                        safefree(url);
-                        build_url(&url, request->host, request->port,
-                                  request->path);
-                        log_message(LOG_INFO,
-                                    "process_request: trans Host %s %s for %d",
-                                    request->method, url, connptr->client_fd);
-                }
-                if (config.ipAddr && strcmp(request->host, config.ipAddr) == 0) {
-                        log_message(LOG_ERR,
-                                    "process_request: destination IP is localhost %d",
-                                    connptr->client_fd);
-                        indicate_http_error(connptr, 400, "Bad Request",
-                                            "detail",
-                                            "You tried to connect to the machine the proxy is running on",
-                                            "url", url, NULL);
+                if (!do_transparent_proxy(connptr, hashofheaders, request, &config, url)) {
                         safefree(url);
                         free_request_struct(request);
                         return NULL;
                 }
 #else
-                log_message(LOG_ERR,
-                            "process_request: Unknown URL type on file descriptor %d",
-                            connptr->client_fd);
-                indicate_http_error(connptr, 400, "Bad Request",
-                                    "detail", "Unknown URL type",
-                                    "url", url, NULL);
-
+                indicate_http_error(connptr, 501, "Not Implemented",
+                                "detail", "Unknown method or unsupported protocol.",
+                                "url", url, NULL);
+                log_message(LOG_INFO,
+                                "Unknown method (%s) or protocol (%s)",
+                                request->method, url);
                 safefree(url);
                 free_request_struct(request);
-
                 return NULL;
+                                
 #endif
         }
 
diff --git a/src/reqs.h b/src/reqs.h
index 2748bab..de8730e 100644
--- a/src/reqs.h
+++ b/src/reqs.h
@@ -22,6 +22,28 @@
 #ifndef _TINYPROXY_REQS_H_
 #define _TINYPROXY_REQS_H_
 
+#include "common.h"
+
+
+/*
+ * Port constants for HTTP (80) and SSL (443)
+ */
+#define HTTP_PORT 80
+#define HTTP_PORT_SSL 443
+
+/*
+ * This structure holds the information pulled from a URL request.
+ */
+struct request_s {
+        char *method;
+        char *protocol;
+
+        char *host;
+        uint16_t port;
+
+        char *path;
+};
+
 extern void handle_connection(int fd);
 extern void add_connect_port_allowed(int port);
 extern void upstream_add(const char *host, int port, const char *domain);
diff --git a/src/transparent-proxy.c b/src/transparent-proxy.c
new file mode 100644
index 0000000..5bffa31
--- /dev/null
+++ b/src/transparent-proxy.c
@@ -0,0 +1,121 @@
+/* tinyproxy - A fast light-weight HTTP proxy
+ * Copyright (C) 2002       Petr Lampa <lampa@fit.vutbr.cz>
+ * Copyright (C) 2008       Robert James Kaes <rjk@wormbytes.ca>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * This section of code is used for the transparent proxy option.  You will
+ * need to configure your firewall to redirect all connections for HTTP
+ * traffic to tinyproxy for this to work properly.
+ */
+
+#include "tinyproxy.h"
+
+#include "transparent-proxy.h"
+#include "conns.h"
+#include "heap.h"
+#include "html-error.h"
+#include "log.h"
+#include "reqs.h"
+
+/*
+ * Build a URL from parts.
+ */
+static int
+build_url(char **url, const char *host, int port, const char *path)
+{
+        int len;
+
+        assert(url != NULL);
+        assert(host != NULL);
+        assert(port > 0 && port < 32768);
+        assert(path != NULL);
+
+        len = strlen(host) + strlen(path) + 14;
+        *url = safemalloc(len);
+        if (*url == NULL)
+                return -1;
+
+        return snprintf(*url, len, "http://%s:%d%s", host, port, path);
+}
+
+
+int
+do_transparent_proxy(struct conn_s *connptr, hashmap_t hashofheaders,
+                struct request_s *request, struct config_s *conf, char *url)
+{
+        socklen_t length;
+        char *data;
+        
+        length =
+                hashmap_entry_by_key(hashofheaders, "host", (void **)&data);
+        if (length <= 0) {
+                struct sockaddr_in dest_addr;
+        
+                if (getsockname
+                        (connptr->client_fd, (struct sockaddr *)&dest_addr,
+                        &length) < 0) {
+                        log_message(LOG_ERR,
+                                        "process_request: cannot get destination IP for %d",
+                                        connptr->client_fd);
+                        indicate_http_error(connptr, 400, "Bad Request",
+                                                "detail",
+                                                "Unknown destination",
+                                                "url", url, NULL);
+                        return 0;
+                }
+                request->host = safemalloc(17);
+                strcpy(request->host, inet_ntoa(dest_addr.sin_addr));
+                request->port = ntohs(dest_addr.sin_port);
+                request->path = safemalloc(strlen(url) + 1);
+                strcpy(request->path, url);
+                safefree(url);
+                build_url(&url, request->host, request->port,
+                                request->path);
+                log_message(LOG_INFO,
+                                "process_request: trans IP %s %s for %d",
+                                request->method, url, connptr->client_fd);
+        } else {
+                request->host = safemalloc(length + 1);
+                if (sscanf
+                        (data, "%[^:]:%hu", request->host,
+                        &request->port) != 2) {
+                        strcpy(request->host, data);
+                        request->port = HTTP_PORT;
+                }
+                request->path = safemalloc(strlen(url) + 1);
+                strcpy(request->path, url);
+                safefree(url);
+                build_url(&url, request->host, request->port,
+                                request->path);
+                log_message(LOG_INFO,
+                                "process_request: trans Host %s %s for %d",
+                                request->method, url, connptr->client_fd);
+        }
+        if (conf->ipAddr && strcmp(request->host, conf->ipAddr) == 0) {
+                log_message(LOG_ERR,
+                                "process_request: destination IP is localhost %d",
+                                connptr->client_fd);
+                indicate_http_error(connptr, 400, "Bad Request",
+                                        "detail",
+                                        "You tried to connect to the machine the proxy is running on",
+                                        "url", url, NULL);
+                return 0;
+        }
+
+        return 1;
+}
diff --git a/src/transparent-proxy.h b/src/transparent-proxy.h
new file mode 100644
index 0000000..37cc54d
--- /dev/null
+++ b/src/transparent-proxy.h
@@ -0,0 +1,39 @@
+/* tinyproxy - A fast light-weight HTTP proxy
+ * Copyright (C) 2008 Robert James Kaes <rjk@wormbytes.ca>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* See 'transparent-proxy.c' for detailed information. */
+
+#ifndef TINYPROXY_TRANSPARENT_PROXY_H
+#define TINYPROXY_TRANSPARENT_PROXY_H
+
+#include "common.h"
+
+#ifdef TRANSPARENT_PROXY
+
+#include "conns.h"
+#include "hashmap.h"
+#include "reqs.h"
+
+extern int do_transparent_proxy(struct conn_s *connptr,
+                                hashmap_t hashofheaders, struct request_s *request,
+                                struct config_s *config, char *url);
+
+
+#endif
+
+#endif
-- 
cgit v1.2.3