diff --git a/darkhttpd.c b/darkhttpd.c index 4648938..893782e 100644 --- a/darkhttpd.c +++ b/darkhttpd.c @@ -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, "

%s

\n" /* errname */ "%s\n" /* reason */ "
\n" - "Generated by %s on %s\n" + "%s" /* generated on */ "\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, ...) { "

Moved Permanently

\n" "Moved to: %s\n" /* where x 2 */ "
\n" - "Generated by %s on %s\n" + "%s" /* generated on */ "\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, "\n" - "
\n" - "Generated by "); - append(listing, pkgname); - append(listing, " on "); - append(listing, date); - append(listing, "\n\n\n"); + "
\n"); + + rfc1123_date(date, now); + append(listing, generated_on(date)); + append(listing, "\n\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 */ diff --git a/devel/cover b/devel/cover index 99d7a7c..b326e9c 100755 --- a/devel/cover +++ b/devel/cover @@ -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 diff --git a/devel/test.py b/devel/test.py index be6e29e..9dbda91 100755 --- a/devel/test.py +++ b/devel/test.py @@ -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 index 0000000..f35f76b --- /dev/null +++ b/devel/test_server_id.py @@ -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: