Bug 48004 - setHeader() does not replace the previous value for a "Server"
Summary: setHeader() does not replace the previous value for a "Server"
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 5
Classification: Unclassified
Component: Unknown (show other bugs)
Version: 5.5.28
Hardware: All All
: P2 normal with 1 vote (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
: 48005 (view as bug list)
Depends on:
Blocks:
 
Reported: 2009-10-15 11:16 UTC by olivier dupuy
Modified: 2010-03-03 23:31 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description olivier dupuy 2009-10-15 11:16:16 UTC
Hello,
In a servlet or in a filter (before passing the control to doFilter() or after) try the following
HttpServletResponse myResponse = ...
myResponse.setHeader("Server","My own server name because I do not want to expose the real server name to the public for security reasons");
...

In the headers of the response you will get
Server	Apache-Coyote/1.1, My own server name...

According to the J2EE API for HttpServletResponse.html.setHeader()
http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpServletResponse.html#setHeader(java.lang.String,%20java.lang.String)
...
Sets a response header with the given name and value. If the header had already been set, the new value overwrites the previous one. The containsHeader method can be used to test for the presence of a header before setting its value.
...
In fact if I call myResponse.containsHeader("Server") I even get a false!!!

If you look in the IDE at the response object and dig in the responses and wrappers, you will find at the end a buffer with some data already set by Tomcat with this value and other things
.
As I understand it Tomcat (or Coyote) does not let this header to be changed while nothing in the specification says that it is special.
I did not find either a parameter in server.xml or other where the server name is specified to be overiden.

So the spec is not implemented properly for this specific header.
Some other values are in this buffer, my goal was not to change them but other headers or values could have the same issue.

This issue is the same in Tomcat 5.5.28 and Tomcat 6.0.20. Not tested on 7.x.

Thanks 
Olivier
Comment 1 Mark Thomas 2009-10-15 11:31:43 UTC
*** Bug 48005 has been marked as a duplicate of this bug. ***
Comment 2 Mark Thomas 2010-01-12 13:39:06 UTC
This has been fixed in trunk and proposed for 6.0.x and 5.5.x.

Note that you can set the server attribute on the connector to override the default server name. I updated the HTTP connector docs to clarify how this works.
Comment 3 Mark Thomas 2010-01-13 02:42:12 UTC
The patch has been applied to 6.0.x and will be included in 6.0.23 onwards.
Comment 4 quartz 2010-02-08 14:51:27 UTC
This fix is imcomplete.

There should be a distinction between setting a header to an empty string "" and setting it to null (which should clear the header entirely since there is no .removeHeader() on http response).

Nevertheless, there is no way to completely avoid sending the "Server" header.
Security audits fail just because of the header presence, under the assupmtion that the specific header, even if blank, is still revealing something about the server.

The solution I have is this (Http11Processor for now):

1-add a field
"protected boolean addServerHeader = true;"


2-Implement the setServer() this way, to distinguish the desire to avoid the header completely. If the server.xml doesn't have a server property, the setServer() shouldn't be called and the default is to add server header.

    public void setServer( String server ) {
        if (server==null) {
            this.server = null;
            this.addServerHeader = true;
        } else if (server.equals("")) {
            this.server = null;
            this.addServerHeader = false;
        } else {
            this.server = server;
            this.addServerHeader = true;
        }
    }


3-At the end of prepareResponse(), conditionally add the server header:

        if(addServerHeader) {
        	if (server != null) {
            	// Always overrides anything the app might set
	            headers.setValue("Server").setString(server);
        	} else if (headers.getValue("Server") == null) {
            	// If app didn't set the header, use the default
	            outputBuffer.write(Constants.SERVER_BYTES);
        	}
        }


This is the proper fix which at least is tomcat specific and doesn't break the servlet spec. I won't argue about the httpresponse.setHeader("Server", null) since it is not specified in the servelt spec (which means it should be legal to remove the header!).
Comment 5 Mark Thomas 2010-03-03 23:31:49 UTC
This has been fixed in 5..5.x and will be included in 5.5.29 onwards.