bug-wget
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-wget] [PATCH] Disable automatic wget headers.


From: adham elkarn
Subject: [Bug-wget] [PATCH] Disable automatic wget headers.
Date: Fri, 3 May 2019 23:44:26 +0000

From: sulfastor <address@hidden>

Hi,
This our update for the disable-header feature [bug #54769 
(https://savannah.gnu.org/bugs/?54769)].
We took in account Dale Worley's comment to avoid regression since a header can 
be sent empty, although is rare.

        * doc/wget.texi: Added --disable-header documentation.
        * fuzz/wget_options_fuzzer.dict: Update with --disable-header inputs.
        * src/http.c: removed disabled headers before its creation
        * src/init.c: added new functions to check user disabled headers, 
disable headers, remove user headers
        * src/main.c: added new option disable-header, added help description
        * src/options.h: added new option disable-header
        * testenv/Makefile.am: Added new test files
        * testenv/server/http/http_server.py: Added new rule RejectHeaderField
        * testenv/conf/reject_header_field.py: Added new rule RejectHeaderField
        * testenv/README: Added help description for new rule
        * testenv/Test-disable-default-headers.py: Test without using --header
        * testenv/Test-disable-headers-after.py: Test using --header before 
--disable-header
        * testenv/Test-disable-headers-before.py: Test using --header after 
--disable-header

Signed-off-by: sulfastor <address@hidden>, adham elkarn <address@hidden>
---
 doc/wget.texi                           |  19 ++++
 fuzz/wget_options_fuzzer.dict           |  17 +++
 src/http.c                              | 140 ++++++++++++++++--------
 src/init.c                              |  88 +++++++++++++++
 src/main.c                              |   4 +
 src/options.h                           |   1 +
 testenv/Makefile.am                     |   3 +
 testenv/README                          |   4 +
 testenv/Test-disable-default-headers.py |  73 ++++++++++++
 testenv/Test-disable-headers-after.py   |  77 +++++++++++++
 testenv/Test-disable-headers-before.py  |  77 +++++++++++++
 testenv/conf/reject_header_field.py     |  12 ++
 testenv/server/http/http_server.py      |   8 ++
 13 files changed, 476 insertions(+), 47 deletions(-)
 create mode 100644 testenv/Test-disable-default-headers.py
 create mode 100644 testenv/Test-disable-headers-after.py
 create mode 100644 testenv/Test-disable-headers-before.py
 create mode 100644 testenv/conf/reject_header_field.py

diff --git a/doc/wget.texi b/doc/wget.texi
index 7eada2dd..7a194bb2 100644
--- a/doc/wget.texi
+++ b/doc/wget.texi
@@ -1542,6 +1542,25 @@ wget --header="Host: foo.bar" http://localhost/
 In versions of Wget prior to 1.10 such use of @samp{--header} caused
 sending of duplicate headers.
 
address@hidden disable header, choose
address@hidden address@hidden
+Remove @var{header-field} among the headers in each @sc{http} request.
+
+You may define more than one additional header field by specifying
address@hidden more than once as in @samp{--header}.
+
address@hidden
address@hidden
+wget --disable-header='Accept'          \
+     --disable-header='User-Agent'      \
+     --disable-header='Accept-Encoding' \
+       http://fly.srk.fer.hr/
address@hidden group
address@hidden example
+
+Specificating a header field with @samp{--header} after disabling it
+will override it and include it in the @sc{http} request headers.
+
 @cindex Content-Encoding, choose
 @item address@hidden
 Choose the type of compression to be used.  Legal values are
diff --git a/fuzz/wget_options_fuzzer.dict b/fuzz/wget_options_fuzzer.dict
index 9a2dbd8e..12d54d60 100644
--- a/fuzz/wget_options_fuzzer.dict
+++ b/fuzz/wget_options_fuzzer.dict
@@ -30,6 +30,22 @@
 "human"
 "csv"
 "json"
+"Authorization"
+"User-Agent"
+"Referer"
+"Cache-Control"
+"Pragma"
+"If-Modified-Since"
+"Range"
+"Accept"
+"Accept-Encoding"
+"Host"
+"Connection"
+"Proxy-Connection"
+"Content-Type"
+"Content-Length"
+"Proxy-Authorization"
+"Cookie"
 "accept="
 "accept-regex="
 "adjust-extension="
@@ -66,6 +82,7 @@
 "delete-after="
 "directories="
 "directory-prefix="
+"disable-header="
 "dns-caching="
 "dns-timeout="
 "domains="
diff --git a/src/http.c b/src/http.c
index 289d1101..0ccba4bf 100644
--- a/src/http.c
+++ b/src/http.c
@@ -88,6 +88,7 @@ static char *basic_authentication_encode (const char *, const 
char *);
 static bool known_authentication_scheme_p (const char *, const char *);
 static void ensure_extension (struct http_stat *, const char *, int *);
 static void load_cookies (void);
+static bool disabled_header (char*);
 
 static bool cookies_loaded_p;
 static struct cookie_jar *wget_cookie_jar;
@@ -152,6 +153,8 @@ struct request {
   int hcount, hcapacity;
 };
 
+/* Forward decls. */
+static bool request_remove_header (struct request*, const char*);
 
 /* Create a new, empty request. Set the request's method and its
    arguments.  METHOD should be a literal string (or it should outlive
@@ -436,7 +439,7 @@ maybe_send_basic_creds (const char *hostname, const char 
*user,
       DEBUGP (("Host %s has not issued a general basic challenge.\n",
               quote (hostname)));
     }
-  if (do_challenge)
+  if (!disabled_header ("Authorization") && do_challenge)
     {
       request_set_header (req, "Authorization",
                           basic_authentication_encode (user, passwd),
@@ -1770,23 +1773,29 @@ read_response_body (struct http_stat *hs, int sock, 
FILE *fp, wgint contlen,
 
 #ifdef __VMS
 #define SET_USER_AGENT(req) do {                                         \
-  if (!opt.useragent)                                                    \
-    request_set_header (req, "User-Agent",                               \
-                        aprintf ("Wget/%s (VMS %s %s)",                  \
-                        version_string, vms_arch(), vms_vers()),         \
-                        rel_value);                                      \
-  else if (*opt.useragent)                                               \
-    request_set_header (req, "User-Agent", opt.useragent, rel_none);     \
+  if (!disabled_header ("User-Agent"))                                  \
+    {                                                                    \
+      if (!opt.useragent)                                               \
+       request_set_header (req, "User-Agent",                           \
+                           aprintf ("Wget/%s (VMS %s %s)",              \
+                           version_string, vms_arch(), vms_vers()),     \
+                           rel_value);                                  \
+      else if (*opt.useragent)                                           \
+       request_set_header (req, "User-Agent", opt.useragent, rel_none); \
+    }                                                                   \
 } while (0)
 #else /* def __VMS */
 #define SET_USER_AGENT(req) do {                                         \
-  if (!opt.useragent)                                                    \
-    request_set_header (req, "User-Agent",                               \
-                        aprintf ("Wget/%s (%s)",                         \
-                        version_string, OS_TYPE),                        \
-                        rel_value);                                      \
-  else if (*opt.useragent)                                               \
-    request_set_header (req, "User-Agent", opt.useragent, rel_none);     \
+  if (!disabled_header ("User-Agent"))                                     \
+    {                                                                    \
+      if (!opt.useragent)                                                \
+       request_set_header (req, "User-Agent",                           \
+                           aprintf ("Wget/%s (%s)",                     \
+                           version_string, OS_TYPE),                    \
+                           rel_value);                                  \
+      else if (*opt.useragent)                                           \
+       request_set_header (req, "User-Agent", opt.useragent, rel_none); \
+    }                                                                    \
 } while (0)
 #endif /* def __VMS [else] */
 
@@ -1842,6 +1851,26 @@ time_to_rfc1123 (time_t time, char *buf, size_t bufsize)
   return RETROK;
 }
 
+static bool
+disabled_header (char* header_name)
+{
+  char** p = opt.disabled_headers;
+  char *s;
+  size_t n;
+
+  if (!p)
+    return 0;
+
+  for (; *p; ++p) {
+    s = strchrnul (header_name, ':');
+    n = (size_t) (s - header_name);
+    if (n == strlen (*p) && 0 == strncmp (header_name, *p, n))
+      return 1;
+  }
+
+  return 0;
+}
+
 static struct request *
 initialize_request (const struct url *u, struct http_stat *hs, int *dt, struct 
url *proxy,
                     bool inhibit_keep_alive, bool *basic_auth_finished,
@@ -1874,15 +1903,17 @@ initialize_request (const struct url *u, struct 
http_stat *hs, int *dt, struct u
       meth_arg = url_full_path (u);
     req = request_new (meth, meth_arg);
   }
-
-  request_set_header (req, "Referer", (char *) hs->referer, rel_none);
+  if (!disabled_header ("Referer"))
+    request_set_header (req, "Referer", (char *) hs->referer, rel_none);
   if (*dt & SEND_NOCACHE)
     {
       /* Cache-Control MUST be obeyed by all HTTP/1.1 caching mechanisms...  */
-      request_set_header (req, "Cache-Control", "no-cache", rel_none);
+      if (!disabled_header ("Cache-Control"))
+       request_set_header (req, "Cache-Control", "no-cache", rel_none);
 
       /* ... but some HTTP/1.0 caches doesn't implement Cache-Control.  */
-      request_set_header (req, "Pragma", "no-cache", rel_none);
+      if (!disabled_header ("Pragma"))
+       request_set_header (req, "Pragma", "no-cache", rel_none);
     }
   if (*dt & IF_MODIFIED_SINCE)
     {
@@ -1896,21 +1927,27 @@ initialize_request (const struct url *u, struct 
http_stat *hs, int *dt, struct u
                                   "time.\n"));
           strcpy (strtime, "Thu, 01 Jan 1970 00:00:00 GMT");
         }
-      request_set_header (req, "If-Modified-Since", xstrdup (strtime), 
rel_value);
+      if (!disabled_header ("If-Modified-Since"))
+       request_set_header (req, "If-Modified-Since", xstrdup (strtime), 
rel_value);
     }
-  if (hs->restval)
+  if (!disabled_header ("Range") && hs->restval)
     request_set_header (req, "Range",
                         aprintf ("bytes=%s-",
                                  number_to_static_string (hs->restval)),
                         rel_value);
+
   SET_USER_AGENT (req);
-  request_set_header (req, "Accept", "*/*", rel_none);
+
+  if (!disabled_header ("Accept"))    
+    request_set_header (req, "Accept", "*/*", rel_none);
+  
 #ifdef HAVE_LIBZ
-  if (opt.compression != compression_none)
+  if (!disabled_header ("Accept-Encoding") && opt.compression != 
compression_none)
     request_set_header (req, "Accept-Encoding", "gzip", rel_none);
   else
 #endif
-    request_set_header (req, "Accept-Encoding", "identity", rel_none);
+    if (!disabled_header ("Accept-Encoding"))
+      request_set_header (req, "Accept-Encoding", "identity", rel_none);
 
   /* Find the username with priority */
   if (u->user)
@@ -1966,17 +2003,19 @@ initialize_request (const struct url *u, struct 
http_stat *hs, int *dt, struct u
     };
     int add_port = u->port != scheme_default_port (u->scheme);
     int add_squares = strchr (u->host, ':') != NULL;
-    request_set_header (req, "Host",
-                        aprintf (hfmt[add_port][add_squares], u->host, 
u->port),
-                        rel_value);
+    if (!disabled_header ("Host"))
+      request_set_header (req, "Host",
+                         aprintf (hfmt[add_port][add_squares], u->host, 
u->port),
+                         rel_value);
   }
 
-  if (inhibit_keep_alive)
+  if (!disabled_header ("Connection") && inhibit_keep_alive)
     request_set_header (req, "Connection", "Close", rel_none);
   else
     {
-      request_set_header (req, "Connection", "Keep-Alive", rel_none);
-      if (proxy)
+      if (!disabled_header ("Connection"))
+       request_set_header (req, "Connection", "Keep-Alive", rel_none);
+      if (!disabled_header ("Proxy-Connection") && proxy)
         request_set_header (req, "Proxy-Connection", "Keep-Alive", rel_none);
     }
 
@@ -1985,8 +2024,9 @@ initialize_request (const struct url *u, struct http_stat 
*hs, int *dt, struct u
 
       if (opt.body_data || opt.body_file)
         {
-          request_set_header (req, "Content-Type",
-                              "application/x-www-form-urlencoded", rel_none);
+         if (!disabled_header ("Content-Type"))
+           request_set_header (req, "Content-Type",
+                               "application/x-www-form-urlencoded", rel_none);
 
           if (opt.body_data)
             *body_data_size = strlen (opt.body_data);
@@ -2002,13 +2042,15 @@ initialize_request (const struct url *u, struct 
http_stat *hs, int *dt, struct u
                   return NULL;
                 }
             }
-          request_set_header (req, "Content-Length",
-                              xstrdup (number_to_static_string 
(*body_data_size)),
-                              rel_value);
+         if (!disabled_header ("Content-Length"))
+           request_set_header (req, "Content-Length",
+                               xstrdup (number_to_static_string 
(*body_data_size)),
+                               rel_value);
         }
-      else if (c_strcasecmp (opt.method, "post") == 0
-               || c_strcasecmp (opt.method, "put") == 0
-               || c_strcasecmp (opt.method, "patch") == 0)
+      else if (!disabled_header ("Content-Length")
+              && (c_strcasecmp (opt.method, "post") == 0
+                  || c_strcasecmp (opt.method, "put") == 0
+                  || c_strcasecmp (opt.method, "patch") == 0))
         request_set_header (req, "Content-Length", "0", rel_none);
     }
   return req;
@@ -2043,7 +2085,8 @@ initialize_proxy_configuration (const struct url *u, 
struct request *req,
 #ifdef HAVE_SSL
   if (u->scheme != SCHEME_HTTPS)
 #endif
-    request_set_header (req, "Proxy-Authorization", *proxyauth, rel_value);
+    if (!disabled_header ("Proxy-Authorization"))
+      request_set_header (req, "Proxy-Authorization", *proxyauth, rel_value);
 }
 
 static uerr_t
@@ -2133,8 +2176,9 @@ establish_connection (const struct url *u, const struct 
url **conn_ref,
              CONNECT method to request passthrough.  */
           struct request *connreq = request_new ("CONNECT",
                               aprintf ("%s:%d", u->host, u->port));
+
           SET_USER_AGENT (connreq);
-          if (proxyauth)
+          if (!disabled_header ("Proxy-Authorization") && proxyauth)
             {
               request_set_header (connreq, "Proxy-Authorization",
                                   *proxyauth, rel_value);
@@ -2143,9 +2187,10 @@ establish_connection (const struct url *u, const struct 
url **conn_ref,
                  the regular request below.  */
               *proxyauth = NULL;
             }
-          request_set_header (connreq, "Host",
-                              aprintf ("%s:%d", u->host, u->port),
-                              rel_value);
+         if (!disabled_header ("Host"))
+           request_set_header (connreq, "Host",
+                               aprintf ("%s:%d", u->host, u->port),
+                               rel_value);
 
           write_error = request_send (connreq, sock, 0);
           request_free (&connreq);
@@ -2456,7 +2501,7 @@ check_auth (const struct url *u, char *user, char 
*passwd, struct response *resp
           auth_err = *auth_stat;
           xfree (auth_stat);
           xfree (pth);
-          if (auth_err == RETROK)
+          if (!disabled_header ("Authorization") && auth_err == RETROK)
             {
               request_set_header (req, "Authorization", value, rel_value);
 
@@ -3248,9 +3293,10 @@ gethttp (const struct url *u, struct url *original_url, 
struct http_stat *hs,
      for the Digest authorization scheme.)  */
 
   if (opt.cookies)
-    request_set_header (req, "Cookie",
-                        cookie_header (wget_cookie_jar,
-                                       u->host, u->port, u->path,
+    if (!disabled_header ("Cookie"))
+      request_set_header (req, "Cookie",
+                         cookie_header (wget_cookie_jar,
+                                        u->host, u->port, u->path,
 #ifdef HAVE_SSL
                                        u->scheme == SCHEME_HTTPS
 #else
diff --git a/src/init.c b/src/init.c
index 9b6665a6..aaf99ba6 100644
--- a/src/init.c
+++ b/src/init.c
@@ -101,6 +101,7 @@ CMD_DECLARE (cmd_spec_compression);
 #endif
 CMD_DECLARE (cmd_spec_dirstruct);
 CMD_DECLARE (cmd_spec_header);
+CMD_DECLARE (cmd_dis_header);
 CMD_DECLARE (cmd_spec_warc_header);
 CMD_DECLARE (cmd_spec_htmlify);
 CMD_DECLARE (cmd_spec_mirror);
@@ -183,6 +184,7 @@ static const struct {
   { "deleteafter",      &opt.delete_after,      cmd_boolean },
   { "dirprefix",        &opt.dir_prefix,        cmd_directory },
   { "dirstruct",        NULL,                   cmd_spec_dirstruct },
+  { "disableheader",    NULL,                   cmd_dis_header},
   { "dnscache",         &opt.dns_cache,         cmd_boolean },
 #ifdef HAVE_LIBCARES
   { "dnsservers",       &opt.dns_servers,       cmd_string },
@@ -398,6 +400,7 @@ defaults (void)
   opt.metalink_index = -1;
 #endif
 
+  opt.disabled_headers = NULL;
   opt.cookies = true;
   opt.verbose = -1;
   opt.ntry = 20;
@@ -990,6 +993,7 @@ struct decode_item {
 static bool decode_string (const char *, const struct decode_item *, int, int 
*);
 static bool simple_atof (const char *, const char *, double *);
 
+
 #define CMP1(p, c0) (c_tolower((p)[0]) == (c0) && (p)[1] == '\0')
 
 #define CMP2(p, c0, c1) (c_tolower((p)[0]) == (c0)        \
@@ -1459,6 +1463,8 @@ cmd_cert_type (const char *com, const char *val, void 
*place)
    options specially.  */
 
 static bool check_user_specified_header (const char *);
+static bool check_user_disabled_header (const char *);
+static char ** vec_remove_header (char **, const char *);
 
 #ifdef HAVE_LIBZ
 static bool
@@ -1493,6 +1499,29 @@ cmd_spec_dirstruct (const char *com, const char *val, 
void *place_ignored _GL_UN
   return true;
 }
 
+static bool
+cmd_dis_header (const char *com, const char *val, void *place_ignored 
_GL_UNUSED)
+{
+  /* Empty value means reset the list of headers. */
+  if (*val == '\0')
+    {
+      free_vec (opt.disabled_headers);
+      opt.disabled_headers = NULL;
+      return true;
+    }
+
+  if (!check_user_disabled_header (val))
+    {
+      fprintf (stderr, _("%s: %s: Invalid header %s.\n"),
+               exec_name, com, quote (val));
+      return false;
+    }
+  /* Removes disabled headers from user defined headers */
+  opt.user_headers = vec_remove_header (opt.user_headers, val);
+  opt.disabled_headers = vec_append (opt.disabled_headers, val);
+  return true;
+}
+
 static bool
 cmd_spec_header (const char *com, const char *val, void *place_ignored 
_GL_UNUSED)
 {
@@ -1850,6 +1879,23 @@ simple_atof (const char *beg, const char *end, double 
*dest)
    contain a colon preceded by non-white-space characters and must not
    contain newlines.  */
 
+
+static bool
+check_user_disabled_header (const char* s)
+{
+  const char *p;
+
+  for (p = s; *p && !c_isspace (*p); p++)
+    ;
+
+  if (p == s)
+    return false;
+  /* The header MUST NOT contain newlines.  */
+  if (strchr (s, '\n'))
+    return false;
+  return true;
+}
+
 static bool
 check_user_specified_header (const char *s)
 {
@@ -1867,6 +1913,47 @@ check_user_specified_header (const char *s)
   return true;
 }
 
+/* Removes a header from a request headers vector */
+
+static char **
+vec_remove_header (char **vec, const char *str)
+{
+  char* s;
+  int i, cnt;                   /* count of vector elements */
+  size_t n;
+
+  if (vec != NULL)
+    {
+      for (cnt = 0; vec[cnt]; cnt++)
+       ;
+      /* remove all duplicates */
+      i = 0;
+      while (vec[i])
+       {
+         s = strchrnul (vec[i], ':');
+         n = (size_t) (s - vec[i]);
+         if (n == strlen (str) && 0 == strncmp (vec[i], str, n))
+           {
+             if (cnt == 1)
+               {
+                 vec[i] = NULL;
+                 return vec;
+               }
+             else
+               {
+                 vec[i] = xstrdup (vec[cnt - 1]);
+                 vec = xrealloc (vec, (cnt + 1) * sizeof (char *));
+                 vec[cnt] = NULL;
+                 --cnt;
+               }
+           }
+         else
+           ++i;
+       }
+    }
+  return vec;
+}
+
 /* Decode VAL into a number, according to ITEMS. */
 
 static bool
@@ -1977,6 +2064,7 @@ cleanup (void)
   xfree (opt.http_passwd);
   xfree (opt.dot_style);
   free_vec (opt.user_headers);
+  free_vec (opt.disabled_headers);
   free_vec (opt.warc_user_headers);
 # ifdef HAVE_SSL
   xfree (opt.cert_file);
diff --git a/src/main.c b/src/main.c
index 65b7f3f3..a73b39d9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -304,6 +304,7 @@ static struct cmdline_option option_data[] =
     { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
     { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
     { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
+    { "disable-header", 0, OPT_VALUE, "disableheader", -1 },
     { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
 #ifdef HAVE_LIBCARES
     { "dns-servers", 0, OPT_VALUE, "dnsservers", -1 },
@@ -544,6 +545,7 @@ init_switches (void)
              identical to "--foo", except it has opposite meaning and
              it doesn't allow an argument.  */
           longopt = &long_options[o++];
+
           longopt->name = no_prefix (cmdopt->long_name);
           longopt->has_arg = no_argument;
           /* Mask the value so we'll be able to recognize that we're
@@ -792,6 +794,8 @@ HTTP options:\n"),
        --ignore-length             ignore 'Content-Length' header field\n"),
     N_("\
        --header=STRING             insert STRING among the headers\n"),
+    N_("\
+       --disable-header=STRING     disable STRING among the headers\n"),
 #ifdef HAVE_LIBZ
     N_("\
        --compression=TYPE          choose compression, one of auto, gzip and 
none. (default: none)\n"),
diff --git a/src/options.h b/src/options.h
index 881e2b2e..5559c6fa 100644
--- a/src/options.h
+++ b/src/options.h
@@ -147,6 +147,7 @@ struct options
   char *http_user;              /* HTTP username. */
   char *http_passwd;            /* HTTP password. */
   char **user_headers;          /* User-defined header(s). */
+  char **disabled_headers;       /* User-disabled header(s) */
   bool http_keep_alive;         /* whether we use keep-alive */
 
   bool use_proxy;               /* Do we use proxy? */
diff --git a/testenv/Makefile.am b/testenv/Makefile.am
index b5a39ad2..4b3e2d08 100644
--- a/testenv/Makefile.am
+++ b/testenv/Makefile.am
@@ -95,6 +95,9 @@ if HAVE_PYTHON3
     Test-cookie-domain-mismatch.py                  \
     Test-cookie-expires.py                          \
     Test-cookie.py                                  \
+    Test-disable-default-headers.py                 \
+    Test-disable-headers-after.py                   \
+    Test-disable-headers-before.py                  \
     Test-Head.py                                    \
     Test-hsts.py                                    \
     Test--https.py                                  \
diff --git a/testenv/README b/testenv/README
index 6580bc99..d2f38a67 100644
--- a/testenv/README
+++ b/testenv/README
@@ -182,6 +182,10 @@ This section lists the currently supported File Rules and 
their structure.
     * RejectHeader  : This list of Headers must NEVER occur in a request. It
     uses the same value format as ExpectHeader.
 
+    * RejectHeaderField  : This list of Headers Fields must NOT appear in a 
request.
+    The value for this key is a list of strings where each header field is 
represented as:
+    |-->Header Field: <Header Field Name>
+
     * SendHeader    : This list of Headers will be sent in EVERY response to a
     request for the respective file. It follows the same value format as
     ExpectHeader. Additionally you can specify a list of strings as <Header 
Data>
diff --git a/testenv/Test-disable-default-headers.py 
b/testenv/Test-disable-default-headers.py
new file mode 100644
index 00000000..22ea54ad
--- /dev/null
+++ b/testenv/Test-disable-default-headers.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+from sys import exit
+from test.http_test import HTTPTest
+from test.base_test import HTTP, HTTPS
+from misc.wget_file import WgetFile
+
+"""
+    This is test ensures that the --disable-header option removes default 
request
+    headers. There aren't any user defined header.
+"""
+############# File Definitions ###############################################
+file_content = """Les paroles de la bouche d'un homme sont des eaux profondes; 
+La source de la sagesse est un torrent qui jaillit."""
+
+Headers = {
+    'Authorization',
+    'User-Agent',
+    'Referer',
+    'Cache-Control',
+    'Pragma',
+    'If-Modified-Since',
+    'Range',
+    'Accept',
+    'Accept-Encoding',
+    'Host',
+    'Connection',
+    'Proxy-Connection',
+    'Content-Type',
+    'Content-Length',
+    'Proxy-Authorization',
+    'Cookie',
+    'MyHeader',
+}
+
+WGET_OPTIONS = ''
+WGET_URLS = [[]]
+Files = [[]]
+
+for index, header in enumerate(Headers, start=1):
+    File_rules = {
+        "RejectHeaderField"    : {
+            header
+        }
+    }
+    file_name = "File" + str(index)
+    Files[0].append (WgetFile(file_name, file_content, rules=File_rules))
+    WGET_OPTIONS += ' --disable-header="' + header + '"'
+    WGET_URLS[0].append (file_name)
+
+Servers = [HTTP]
+
+ExpectedReturnCode = 0
+
+################ Pre and Post Test Hooks #####################################
+pre_test = {
+    "ServerFiles"       : Files
+}
+test_options = {
+    "WgetCommands"      : WGET_OPTIONS,
+    "Urls"              : WGET_URLS
+}
+post_test = {
+    "ExpectedRetcode"   : ExpectedReturnCode
+}
+
+err = HTTPTest (
+                pre_hook=pre_test,
+                test_params=test_options,
+                post_hook=post_test,
+                protocols=Servers
+).begin ()
+
+exit (err)
diff --git a/testenv/Test-disable-headers-after.py 
b/testenv/Test-disable-headers-after.py
new file mode 100644
index 00000000..44d03cb5
--- /dev/null
+++ b/testenv/Test-disable-headers-after.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+from sys import exit
+from test.http_test import HTTPTest
+from test.base_test import HTTP, HTTPS
+from misc.wget_file import WgetFile
+
+"""
+    This is test ensures that the --disable-header option removes user headers
+    from the HTTP request when it's placed after --header="header: value".
+"""
+############# File Definitions ###############################################
+file_content = """Les paroles de la bouche d'un homme sont des eaux profondes; 
+La source de la sagesse est un torrent qui jaillit."""
+
+Headers = {
+    'Authorization',
+    'User-Agent',
+    'Referer',
+    'Cache-Control',
+    'Pragma',
+    'If-Modified-Since',
+    'Range',
+    'Accept',
+    'Accept-Encoding',
+    'Host',
+    'Connection',
+    'Proxy-Connection',
+    'Content-Type',
+    'Content-Length',
+    'Proxy-Authorization',
+    'Cookie',
+    'MyHeader',
+}
+
+WGET_OPTIONS = ''
+WGET_URLS = [[]]
+Files = [[]]
+
+# Define user defined headers
+for header in Headers:
+    WGET_OPTIONS += ' --header="' + header + ': any"'
+
+for index, header in enumerate(Headers, start=1):
+    File_rules = {
+        "RejectHeader"    : {
+            header : 'any'
+        }
+    }
+    file_name = "File" + str(index)
+    Files[0].append(WgetFile(file_name, file_content, rules=File_rules))
+    WGET_OPTIONS += ' --disable-header="' + header + '"'
+    WGET_URLS[0].append(file_name)
+
+Servers = [HTTP]
+
+ExpectedReturnCode = 0
+
+################ Pre and Post Test Hooks #####################################
+pre_test = {
+    "ServerFiles"       : Files
+}
+test_options = {
+    "WgetCommands"      : WGET_OPTIONS,
+    "Urls"              : WGET_URLS
+}
+post_test = {
+    "ExpectedRetcode"   : ExpectedReturnCode
+}
+
+err = HTTPTest (
+                pre_hook=pre_test,
+                test_params=test_options,
+                post_hook=post_test,
+                protocols=Servers
+).begin ()
+
+exit (err)
diff --git a/testenv/Test-disable-headers-before.py 
b/testenv/Test-disable-headers-before.py
new file mode 100644
index 00000000..4356b4c1
--- /dev/null
+++ b/testenv/Test-disable-headers-before.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+from sys import exit
+from test.http_test import HTTPTest
+from test.base_test import HTTP, HTTPS
+from misc.wget_file import WgetFile
+
+"""
+    This is test ensures that the --disable-header option doesn't remove user 
headers
+    from the HTTP request when it's placed before --header="header: value".
+"""
+############# File Definitions ###############################################
+file_content = """Les paroles de la bouche d'un homme sont des eaux profondes; 
+La source de la sagesse est un torrent qui jaillit."""
+
+Headers = {
+    'Authorization',
+    'User-Agent',
+    'Referer',
+    'Cache-Control',
+    'Pragma',
+    'If-Modified-Since',
+    'Range',
+    'Accept',
+    'Accept-Encoding',
+    'Host',
+    'Connection',
+    'Proxy-Connection',
+    'Content-Type',
+    'Content-Length',
+    'Proxy-Authorization',
+    'Cookie',
+    'MyHeader',
+}
+
+WGET_OPTIONS = ''
+WGET_URLS = [[]]
+Files = [[]]
+
+for index, header in enumerate(Headers, start=1):
+    File_rules = {
+        "ExpectHeader"    : {
+            header : 'any'
+        }
+    }
+    file_name = "File" + str(index)
+    Files[0].append (WgetFile(file_name, file_content, rules=File_rules))
+    WGET_OPTIONS += ' --disable-header="' + header + '"'
+    WGET_URLS[0].append (file_name)
+
+# Define user defined headers
+for header in Headers:
+    WGET_OPTIONS += ' --header="' + header + ': any"'
+
+Servers = [HTTP]
+
+ExpectedReturnCode = 0
+
+################ Pre and Post Test Hooks #####################################
+pre_test = {
+    "ServerFiles"       : Files
+}
+test_options = {
+    "WgetCommands"      : WGET_OPTIONS,
+    "Urls"              : WGET_URLS
+}
+post_test = {
+    "ExpectedRetcode"   : ExpectedReturnCode
+}
+
+err = HTTPTest (
+                pre_hook=pre_test,
+                test_params=test_options,
+                post_hook=post_test,
+                protocols=Servers
+).begin ()
+
+exit (err)
diff --git a/testenv/conf/reject_header_field.py 
b/testenv/conf/reject_header_field.py
new file mode 100644
index 00000000..e1009cdd
--- /dev/null
+++ b/testenv/conf/reject_header_field.py
@@ -0,0 +1,12 @@
+from conf import rule
+
+""" Rule: RejectHeaderField
+This is a server side rule which expects a string list of Header Fields
+which should be blacklisted by the server for a particular file's requests.
+"""
+
+
address@hidden()
+class RejectHeaderField:
+    def __init__(self, header_fields):
+        self.header_fields = header_fields
diff --git a/testenv/server/http/http_server.py 
b/testenv/server/http/http_server.py
index 2cc82fb9..6f358335 100644
--- a/testenv/server/http/http_server.py
+++ b/testenv/server/http/http_server.py
@@ -370,6 +370,14 @@ class _Handler(BaseHTTPRequestHandler):
                                 header_line)
                 raise ServerError("Header " + header_line + ' received')
 
+    def RejectHeaderField(self, header_fields_obj):
+        rej_header_fields = header_fields_obj.header_fields
+        for field in rej_header_fields:
+            if field in self.headers:
+                self.send_error(400, 'Blacklisted Header Field %s received' %
+                                field)
+                raise ServerError('Header Field %s received' % field)
+
     def __log_request(self, method):
         req = method + " " + self.path
         self.server.request_headers.append(req)
-- 
2.21.0


reply via email to

[Prev in Thread] Current Thread [Next in Thread]