Implement --no-server-id
authorEmil Mikulic <emikulic@gmail.com>
Sun, 28 Apr 2013 14:55:08 +0000 (00:55 +1000)
committerEmil Mikulic <emikulic@gmail.com>
Sun, 28 Apr 2013 14:55:08 +0000 (00:55 +1000)
Suggested by: T.Ramirez

darkhttpd.c
devel/cover
devel/test.py
devel/test_server_id.py [new file with mode: 0755]

index 4648938..893782e 100644 (file)
@@ -271,7 +271,8 @@ static char *logfile_name = NULL;   /* NULL = no logging */
 static FILE *logfile = NULL;
 static char *pidfile_name = NULL;   /* NULL = no pidfile */
 static int want_chroot = 0, want_daemon = 0, want_accf = 0,
-           want_keepalive = 1;
+           want_keepalive = 1, want_server_id = 1;
+static char *server_hdr = NULL;
 static uint64_t num_requests = 0, total_in = 0, total_out = 0;
 
 static int running = 1; /* signal handler sets this to false */
@@ -888,6 +889,9 @@ static void usage(const char *argv0) {
     "\t\tRequests to the host are redirected to the corresponding url.\n"
     "\t\tThe option may be specified multiple times, in which case\n"
     "\t\tthe host is matched in order of appearance.\n\n");
+    printf("\t--no-server-id\n"
+    "\t\tDon't identify the server type in headers\n"
+    "\t\tor directory listings.\n");
 }
 
 /* Returns 1 if string is a number, 0 otherwise.  Set num to NULL if
@@ -1009,6 +1013,9 @@ static void parse_commandline(const int argc, char *argv[]) {
             url = argv[i];
             add_forward_mapping(host, url);
         }
+        else if (strcmp(argv[i], "--no-server-id") == 0) {
+            want_server_id = 0;
+        }
         else
             errx(1, "unknown argument `%s'", argv[i]);
     }
@@ -1285,6 +1292,19 @@ static const char *keep_alive(const struct connection *conn)
     return (conn->conn_close ? "Connection: close\r\n" : keep_alive_field);
 }
 
+/* "Generated by " + pkgname + " on " + date + "\n"
+ *  1234567890123               1234            2 ('\n' and '\0')
+ */
+static char _generated_on_buf[13 + sizeof(pkgname) - 1 + 4 + DATE_LEN + 2];
+static const char *generated_on(const char date[DATE_LEN]) {
+    if (!want_server_id)
+        return "";
+    snprintf(_generated_on_buf, sizeof(_generated_on_buf),
+            "Generated by %s on %s\n",
+            pkgname, date);
+    return _generated_on_buf;
+}
+
 /* A default reply for any (erroneous) occasion. */
 static void default_reply(struct connection *conn,
         const int errcode, const char *errname, const char *format, ...)
@@ -1306,21 +1326,21 @@ static void default_reply(struct connection *conn,
      "<h1>%s</h1>\n" /* errname */
      "%s\n" /* reason */
      "<hr>\n"
-     "Generated by %s on %s\n"
+     "%s" /* generated on */
      "</body></html>\n",
-     errcode, errname, errname, reason, pkgname, date);
+     errcode, errname, errname, reason, generated_on(date));
     free(reason);
 
     conn->header_length = xasprintf(&(conn->header),
      "HTTP/1.1 %d %s\r\n"
      "Date: %s\r\n"
-     "Server: %s\r\n"
+     "%s" /* server */
      "Accept-Ranges: bytes\r\n"
      "%s" /* keep-alive */
      "Content-Length: %llu\r\n"
      "Content-Type: text/html\r\n"
      "\r\n",
-     errcode, errname, date, pkgname, keep_alive(conn),
+     errcode, errname, date, server_hdr, keep_alive(conn),
      llu(conn->reply_length));
 
     conn->reply_type = REPLY_GENERATED;
@@ -1345,21 +1365,21 @@ static void redirect(struct connection *conn, const char *format, ...) {
      "<h1>Moved Permanently</h1>\n"
      "Moved to: <a href=\"%s\">%s</a>\n" /* where x 2 */
      "<hr>\n"
-     "Generated by %s on %s\n"
+     "%s" /* generated on */
      "</body></html>\n",
-     where, where, pkgname, date);
+     where, where, generated_on(date));
 
     conn->header_length = xasprintf(&(conn->header),
      "HTTP/1.1 301 Moved Permanently\r\n"
      "Date: %s\r\n"
-     "Server: %s\r\n"
+     "%s" /* server */
      /* "Accept-Ranges: bytes\r\n" - not relevant here */
      "Location: %s\r\n"
      "%s" /* keep-alive */
      "Content-Length: %llu\r\n"
      "Content-Type: text/html\r\n"
      "\r\n",
-     date, pkgname, where, keep_alive(conn), llu(conn->reply_length));
+     date, server_hdr, where, keep_alive(conn), llu(conn->reply_length));
 
     free(where);
     conn->reply_type = REPLY_GENERATED;
@@ -1693,15 +1713,13 @@ static void generate_dir_listing(struct connection *conn, const char *path) {
     free(list);
     free(spaces);
 
-    rfc1123_date(date, now);
     append(listing,
      "</pre></tt>\n"
-     "<hr>\n"
-     "Generated by ");
-    append(listing, pkgname);
-    append(listing, " on ");
-    append(listing, date);
-    append(listing, "\n</body>\n</html>\n");
+     "<hr>\n");
+
+    rfc1123_date(date, now);
+    append(listing, generated_on(date));
+    append(listing, "</body>\n</html>\n");
 
     conn->reply = listing->str;
     conn->reply_length = (off_t)listing->length;
@@ -1710,13 +1728,13 @@ static void generate_dir_listing(struct connection *conn, const char *path) {
     conn->header_length = xasprintf(&(conn->header),
      "HTTP/1.1 200 OK\r\n"
      "Date: %s\r\n"
-     "Server: %s\r\n"
+     "%s" /* server */
      "Accept-Ranges: bytes\r\n"
      "%s" /* keep-alive */
      "Content-Length: %llu\r\n"
      "Content-Type: text/html\r\n"
      "\r\n",
-     date, pkgname, keep_alive(conn), llu(conn->reply_length));
+     date, server_hdr, keep_alive(conn), llu(conn->reply_length));
 
     conn->reply_type = REPLY_GENERATED;
     conn->http_code = 200;
@@ -1833,11 +1851,11 @@ static void process_get(struct connection *conn) {
         conn->header_length = xasprintf(&(conn->header),
          "HTTP/1.1 304 Not Modified\r\n"
          "Date: %s\r\n"
-         "Server: %s\r\n"
+         "%s" /* server */
          "Accept-Ranges: bytes\r\n"
          "%s" /* keep-alive */
          "\r\n",
-         rfc1123_date(date, now), pkgname, keep_alive(conn));
+         rfc1123_date(date, now), server_hdr, keep_alive(conn));
         conn->reply_length = 0;
         conn->reply_type = REPLY_GENERATED;
         conn->header_only = 1;
@@ -1894,7 +1912,7 @@ static void process_get(struct connection *conn) {
         conn->header_length = xasprintf(&(conn->header),
             "HTTP/1.1 206 Partial Content\r\n"
             "Date: %s\r\n"
-            "Server: %s\r\n"
+            "%s" /* server */
             "Accept-Ranges: bytes\r\n"
             "%s" /* keep-alive */
             "Content-Length: %llu\r\n"
@@ -1903,7 +1921,7 @@ static void process_get(struct connection *conn) {
             "Last-Modified: %s\r\n"
             "\r\n"
             ,
-            rfc1123_date(date, now), pkgname, keep_alive(conn),
+            rfc1123_date(date, now), server_hdr, keep_alive(conn),
             llu(conn->reply_length), llu(from), llu(to),
             llu(filestat.st_size), mimetype, lastmod
         );
@@ -1918,7 +1936,7 @@ static void process_get(struct connection *conn) {
         conn->header_length = xasprintf(&(conn->header),
             "HTTP/1.1 200 OK\r\n"
             "Date: %s\r\n"
-            "Server: %s\r\n"
+            "%s" /* server */
             "Accept-Ranges: bytes\r\n"
             "%s" /* keep-alive */
             "Content-Length: %llu\r\n"
@@ -1926,7 +1944,7 @@ static void process_get(struct connection *conn) {
             "Last-Modified: %s\r\n"
             "\r\n"
             ,
-            rfc1123_date(date, now), pkgname, keep_alive(conn),
+            rfc1123_date(date, now), server_hdr, keep_alive(conn),
             llu(conn->reply_length), mimetype, lastmod
         );
         conn->http_code = 200;
@@ -2439,6 +2457,10 @@ int main(int argc, char **argv) {
      */
     sort_mime_map();
     xasprintf(&keep_alive_field, "Keep-Alive: timeout=%d\r\n", idletime);
+    if (want_server_id)
+        xasprintf(&server_hdr, "Server: %s\r\n", pkgname);
+    else
+        server_hdr = xstrdup("");
     init_sockin();
 
     /* open logfile */
@@ -2518,6 +2540,7 @@ int main(int argc, char **argv) {
             free(forward_map);
         free(keep_alive_field);
         free(wwwroot);
+        free(server_hdr);
     }
 
     /* usage stats */
index 99d7a7c..b326e9c 100755 (executable)
@@ -23,7 +23,7 @@ rm -f darkhttpd.gcda darkhttpd.log
 ./a.out >/dev/null
 
 # run tests against a basic instance (generates darkhttpd.gcda)
-./a.out $DIR --port $PORT --log darkhttpd.log &
+./a.out $DIR --port $PORT --log darkhttpd.log >/dev/null &
 PID=$!
 kill -0 $PID || exit 1
 python test.py
@@ -32,12 +32,19 @@ kill $PID
 # run forward tests
 ./a.out $DIR --port $PORT \
   --forward example.com http://www.example.com \
-  --forward secure.example.com https://www.example.com/secure &
+  --forward secure.example.com https://www.example.com/secure >/dev/null &
 PID=$!
 kill -0 $PID || exit 1
 python test_forward.py
 kill $PID
 
+# run no-server-id tests
+./a.out $DIR --port $PORT --no-server-id >/dev/null &
+PID=$!
+kill -0 $PID || exit 1
+python test_server_id.py
+kill $PID
+
 echo generating darkhttpd.c.gcov report
 gcov darkhttpd
 rm -rf $DIR
index be6e29e..9dbda91 100755 (executable)
@@ -195,6 +195,7 @@ class TestFileGet(TestHelper):
         self.assertEquals(hdrs["Accept-Ranges"], "bytes")
         self.assertEquals(hdrs["Content-Length"], str(self.datalen))
         self.assertEquals(hdrs["Content-Type"], "image/jpeg")
+        self.assertContains(hdrs["Server"], "darkhttpd/")
         self.assertEquals(body, self.data)
 
     def test_file_head(self):
diff --git a/devel/test_server_id.py b/devel/test_server_id.py
new file mode 100755 (executable)
index 0000000..f35f76b
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+import unittest
+from test import TestHelper, Conn, parse
+
+class TestForward(TestHelper):
+    def test_no_server_id(self):
+        resp = Conn().get("/", method = 'BOGUS')
+        status, hdrs, body = parse(resp)
+        self.assertContains(status, "400 Bad Request")
+        self.assertFalse(hdrs.has_key("Server"))
+        self.assertFalse("Generated by darkhttpd/" in body)
+
+if __name__ == '__main__':
+    unittest.main()
+
+# vim:set ts=4 sw=4 et: