/* $Id: reverse-proxy.c,v 1.1 2005-08-16 04:03:19 rjkaes Exp $ * * Allow tinyproxy to be used as a reverse proxy. * * Copyright (C) 1999-2005 Robert James Kaes (rjkaes@users.sourceforge.net) * * 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, 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. */ #include "tinyproxy.h" #include "reverse-proxy.h" #include "conns.h" #include "heap.h" #include "htmlerror.h" #include "log.h" /* * Add entry to the reversepath list */ void reversepath_add(const char *path, const char *url) { struct reversepath *reverse; if (url == NULL) { log_message(LOG_WARNING, "Illegal reverse proxy rule: missing url"); return; } if (!strstr(url, "://")) { log_message(LOG_WARNING, "Skipping reverse proxy rule: '%s' is not a valid url", url); return; } if (path && *path != '/') { log_message(LOG_WARNING, "Skipping reverse proxy rule: path '%s' doesn't start with a /", path); return; } if (!(reverse = safemalloc(sizeof(struct reversepath)))) { log_message(LOG_ERR, "Unable to allocate memory in reversepath_add()"); return; } if (!path) reverse->path = safestrdup("/"); else reverse->path = safestrdup(path); reverse->url = safestrdup(url); reverse->next = config.reversepath_list; config.reversepath_list = reverse; log_message(LOG_INFO, "Added reverse proxy rule: %s -> %s", reverse->path, reverse->url); } /* * Check if a request url is in the reversepath list */ struct reversepath * reversepath_get(char *url) { struct reversepath *reverse = config.reversepath_list; while (reverse) { if (strstr(url, reverse->path) == url) return reverse; reverse = reverse->next; } return NULL; } /* * Rewrite the URL for reverse proxying. */ char * reverse_rewrite_url(struct conn_s *connptr, hashmap_t hashofheaders, char *url) { char *rewrite_url = NULL; char *cookie = NULL; char *cookieval; struct reversepath *reverse; /* Reverse requests always start with a slash */ if (*url == '/') { /* First try locating the reverse mapping by request url */ reverse = reversepath_get(url); if (reverse) { rewrite_url = safemalloc(strlen(url) + strlen(reverse->url) + 1); strcpy(rewrite_url, reverse->url); strcat(rewrite_url, url + strlen(reverse->path)); } else if (config.reversemagic && hashmap_entry_by_key(hashofheaders, "cookie", (void **)&cookie) > 0) { /* No match - try the magical tracking cookie next */ if ((cookieval = strstr(cookie, REVERSE_COOKIE "=")) && (reverse = reversepath_get(cookieval + strlen(REVERSE_COOKIE) + 1))) { rewrite_url = safemalloc(strlen(url) + strlen (reverse->url) + 1); strcpy(rewrite_url, reverse->url); strcat(rewrite_url, url + 1); log_message(LOG_INFO, "Magical tracking cookie says: %s", reverse->path); } } } /* Forward proxy support off and no reverse path match found */ if (config.reverseonly && !rewrite_url) { log_message(LOG_ERR, "Bad request"); indicate_http_error(connptr, 400, "Bad Request", "detail", "Request has an invalid URL", "url", url, NULL); return NULL; } log_message(LOG_CONN, "Rewriting URL: %s -> %s", url, rewrite_url); /* Store reverse path so that the magical tracking cookie can be set */ if (config.reversemagic) connptr->reversepath = safestrdup(reverse->path); return rewrite_url; }