* Added an '-f' command line option to allow WebCit to follow the
authorArt Cancro <ajc@citadel.org>
Mon, 14 Nov 2005 04:10:14 +0000 (04:10 +0000)
committerArt Cancro <ajc@citadel.org>
Mon, 14 Nov 2005 04:10:14 +0000 (04:10 +0000)
  'X-Forwarded-For:' HTTP header, if present.

webcit/ChangeLog
webcit/README.txt
webcit/webcit.c
webcit/webcit.h
webcit/webserver.c

index 31bf3aa3c9ff53bfdb8b0ab3d37826b708787697..a412bed4b4e5a84426cca525e8237c33cf687c5a 100644 (file)
@@ -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.
index 8c5be237b8e804ac2e1197e6b67c1bedef3642fc..10d80d24918bfc1fd2fea10676764862efc81e15 100644 (file)
@@ -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".
index bdda202f69d3c7734ca518f4d7eae602e5883298..3644aca0f602c7d2ebe57cc85cfb79b1c3a9458b 100644 (file)
@@ -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 "
index 615bdeda401fa8bae1e701e3b264ec38f05c47de..8782a40bcea546349c1ced21a2e252656dc76ed5 100644 (file)
@@ -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,
index 16a0ca1ca339b6816633f77ba012645e297d66c3..092236442b6eb6365e6e397e89af784346c22d93 100644 (file)
@@ -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