155 lines
5.2 KiB
C
155 lines
5.2 KiB
C
|
/* $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;
|
||
|
}
|