From 367fff2ea59ebd3f78fed43968fc57f092df1ac2 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Mon, 14 Nov 2005 04:10:14 +0000 Subject: [PATCH] * Added an '-f' command line option to allow WebCit to follow the 'X-Forwarded-For:' HTTP header, if present. --- webcit/ChangeLog | 5 +++-- webcit/README.txt | 10 ++++++++-- webcit/webcit.c | 23 ++++++++++++++++++++--- webcit/webcit.h | 1 + webcit/webserver.c | 10 +++++++--- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/webcit/ChangeLog b/webcit/ChangeLog index 31bf3aa3c..a412bed4b 100644 --- a/webcit/ChangeLog +++ b/webcit/ChangeLog @@ -1,11 +1,12 @@ $Id$ +Sun Nov 13 23:08:58 EST 2005 ajc +* Added an '-f' command line option to allow WebCit to follow the + 'X-Forwarded-For:' HTTP header, if present. * Added missing HTTP headers for /listsub - * Discovered the style -moz-user-select:none and applied it to the mailbox summary table, to prevent text select from ruining the appearance of our beautiful drag and drop function. - * Strip prepended '/webcit' in requested url's. This may allow us to handle incoming proxy requests from a front end web server. * Don't require a session cookie for static content. diff --git a/webcit/README.txt b/webcit/README.txt index 8c5be237b..10d80d249 100644 --- a/webcit/README.txt +++ b/webcit/README.txt @@ -86,12 +86,12 @@ something like this: the "webserver" program: webserver [-i ip_addr] [-p http_port] [-s] [-t tracefile] - [-c] [remotehost [remoteport]] + [-c] [-f] [remotehost [remoteport]] *or* webserver [-i ip_addr] [-p http_port] [-s] [-t tracefile] - [-c] uds /your/citadel/directory + [-c] [-f] uds /your/citadel/directory Explained: @@ -120,6 +120,12 @@ the "webserver" program: -> The "-s" option causes WebCit to present an HTTPS (SSL-encrypted) web service. If you want to do both HTTP and HTTPS, you can simply run two instances of WebCit on two different ports. + + -> The "-f" option tells WebCit that it is allowed to follow the + "X-Forwarded-For:" HTTP headers which may be added if your WebCit service + is sitting behind a front end proxy. This will allow users in your "Who + is online?" list to appear as connecting from their actual host address + instead of the address of the proxy. -> remotehost: the name or IP address of the host on which your Citadel server is running. The default is "localhost". diff --git a/webcit/webcit.c b/webcit/webcit.c index bdda202f6..3644aca0f 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -896,8 +896,8 @@ void session_loop(struct httprequest *req) char *content = NULL; char *content_end = NULL; struct httprequest *hptr; - char browser_host[SIZ]; - char user_agent[SIZ]; + char browser_host[256]; + char user_agent[256]; int body_start = 0; int is_static = 0; @@ -918,6 +918,7 @@ void session_loop(struct httprequest *req) safestrncpy(c_httpauth_string, "", sizeof c_httpauth_string); safestrncpy(c_httpauth_user, DEFAULT_HTTPAUTH_USER, sizeof c_httpauth_user); safestrncpy(c_httpauth_pass, DEFAULT_HTTPAUTH_PASS, sizeof c_httpauth_pass); + strcpy(browser_host, ""); WC->upload_length = 0; WC->upload = NULL; @@ -1002,6 +1003,13 @@ void session_loop(struct httprequest *req) else if (!strncasecmp(buf, "Host: ", 6)) { safestrncpy(WC->http_host, &buf[6], sizeof WC->http_host); } + else if (!strncasecmp(buf, "X-Forwarded-For: ", 17)) { + safestrncpy(browser_host, &buf[17], sizeof browser_host); + while (num_tokens(browser_host, ',') > 1) { + remove_token(browser_host, 0, ','); + } + striplt(browser_host); + } /* Only WAP gateways explicitly name this content-type */ else if (strstr(buf, "text/vnd.wap.wml")) { WC->is_wap = 1; @@ -1095,7 +1103,16 @@ void session_loop(struct httprequest *req) else { WC->connected = 1; serv_getln(buf, sizeof buf); /* get the server welcome message */ - locate_host(browser_host, WC->http_sock); + + /* From what host is our user connecting? Go with + * the host at the other end of the HTTP socket, + * unless we are following X-Forwarded-For: headers + * and such a header has already turned up something. + */ + if ( (!follow_xff) || (strlen(browser_host) == 0) ) { + locate_host(browser_host, WC->http_sock); + } + get_serv_info(browser_host, user_agent); if (serv_info.serv_rev_level < MINIMUM_CIT_VERSION) { wprintf(_("You are connected to a Citadel " diff --git a/webcit/webcit.h b/webcit/webcit.h index 615bdeda4..8782a40bc 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -347,6 +347,7 @@ extern int is_https; extern int setup_wizard; extern char wizard_filename[]; extern time_t if_modified_since; +extern int follow_xff; void do_setup_wizard(void); void stuff_to_cookie(char *cookie, int session, diff --git a/webcit/webserver.c b/webcit/webserver.c index 16a0ca1ca..092236442 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -18,6 +18,7 @@ int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp); int verbosity = 9; /* Logging level */ int msock; /* master listening socket */ int is_https = 0; /* Nonzero if I am an HTTPS service */ +int follow_xff = 0; /* Follow X-Forwarded-For: header */ extern void *context_loop(int); extern void *housekeeping_loop(void); extern pthread_mutex_t SessionListMutex; @@ -392,9 +393,9 @@ int main(int argc, char **argv) /* Parse command line */ #ifdef HAVE_OPENSSL - while ((a = getopt(argc, argv, "h:i:p:t:x:cs")) != EOF) + while ((a = getopt(argc, argv, "h:i:p:t:x:cfs")) != EOF) #else - while ((a = getopt(argc, argv, "h:i:p:t:x:c")) != EOF) + while ((a = getopt(argc, argv, "h:i:p:t:x:cf")) != EOF) #endif switch (a) { case 'h': @@ -415,6 +416,9 @@ int main(int argc, char **argv) case 'x': verbosity = atoi(optarg); break; + case 'f': + follow_xff = 1; + break; case 'c': server_cookie = malloc(256); if (server_cookie != NULL) { @@ -436,7 +440,7 @@ int main(int argc, char **argv) default: fprintf(stderr, "usage: webserver " "[-i ip_addr] [-p http_port] " - "[-t tracefile] [-c] " + "[-t tracefile] [-c] [-f] " #ifdef HAVE_OPENSSL "[-s] " #endif -- 2.39.2