*/
package org.sonar.server.app;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.startup.Tomcat;
-import org.sonar.process.Props;
-
-import javax.annotation.Nullable;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import javax.annotation.Nullable;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.sonar.process.Props;
/**
* Configuration of Tomcat connectors
public static final int DISABLED_PORT = -1;
public static final String HTTP_PROTOCOL = "HTTP/1.1";
public static final String AJP_PROTOCOL = "AJP/1.3";
+ public static final int MAX_HTTP_HEADER_SIZE_BYTES = 48 * 1024;
private TomcatConnectors() {
// only static stuff
int port = props.valueAsInt("sonar.web.port", 9000);
if (port > DISABLED_PORT) {
connector = newConnector(props, HTTP_PROTOCOL, "http");
+ configureMaxHttpHeaderSize(connector);
connector.setPort(port);
}
return connector;
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
+ configureMaxHttpHeaderSize(connector);
setConnectorAttribute(connector, "keyAlias", props.value("sonar.web.https.keyAlias"));
String keyPassword = props.value("sonar.web.https.keyPass", "changeit");
setConnectorAttribute(connector, "keyPass", keyPassword);
return connector;
}
+ /**
+ * HTTP header must be at least 48kb to accommodate the authentication token used for
+ * negotiate protocol of windows authentication.
+ */
+ private static void configureMaxHttpHeaderSize(Connector connector) {
+ setConnectorAttribute(connector, "maxHttpHeaderSize", MAX_HTTP_HEADER_SIZE_BYTES);
+ }
+
private static Connector newConnector(Props props, String protocol, String scheme) {
Connector connector = new Connector(protocol);
connector.setURIEncoding("UTF-8");
package org.sonar.server.app;
import com.google.common.collect.ImmutableMap;
+import java.net.InetAddress;
+import java.util.Map;
+import java.util.Properties;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.process.Props;
-import java.net.InetAddress;
-import java.util.Map;
-import java.util.Properties;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.argThat;
TomcatConnectors.configure(tomcat, props);
verify(tomcat).setConnector(argThat(new PropertiesMatcher(
- ImmutableMap.<String, Object>of("minSpareThreads", 2, "maxThreads", 30, "acceptCount", 20)
- )));
+ ImmutableMap.<String, Object>of("minSpareThreads", 2, "maxThreads", 30, "acceptCount", 20))));
}
@Test
TomcatConnectors.configure(tomcat, props);
verify(tomcat).setConnector(argThat(new PropertiesMatcher(
- ImmutableMap.<String, Object>of("minSpareThreads", 5, "maxThreads", 50, "acceptCount", 25)
- )));
+ ImmutableMap.<String, Object>of("minSpareThreads", 5, "maxThreads", 50, "acceptCount", 25))));
}
@Test
TomcatConnectors.configure(tomcat, props);
- verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
- @Override
- public boolean matches(Object o) {
- Connector c = (Connector) o;
- return c.getScheme().equals("https") && c.getPort() == 9443
- && c.getProperty("clientAuth").equals("false");
- }
- }));
+ verifyConnectorProperty(tomcat, "https", "clientAuth", "false");
}
@Test
@Test
public void enable_client_auth() {
-
Properties p = new Properties();
-
p.setProperty("sonar.web.port", "-1");
p.setProperty("sonar.web.https.port", "9443");
p.setProperty("sonar.web.https.clientAuth", "want");
-
Props props = new Props(p);
TomcatConnectors.configure(tomcat, props);
- verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
- @Override
- public boolean matches(Object o) {
- Connector c = (Connector) o;
- return c.getScheme().equals("https") && c.getProperty("clientAuth").equals("want");
- }
- }));
+ verifyConnectorProperty(tomcat, "https", "clientAuth", "want");
}
@Test
public void require_client_auth() {
-
Properties p = new Properties();
-
p.setProperty("sonar.web.port", "-1");
p.setProperty("sonar.web.https.port", "9443");
p.setProperty("sonar.web.https.clientAuth", "true");
-
Props props = new Props(p);
TomcatConnectors.configure(tomcat, props);
- verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
+ verifyConnectorProperty(tomcat, "https", "clientAuth", "true");
+ }
+
+ @Test
+ public void test_max_http_header_size_for_http_and_https_connections() {
+ Properties properties = new Properties();
+
+ properties.setProperty("sonar.web.https.port", "9443");
+
+ Props props = new Props(properties);
+ TomcatConnectors.configure(tomcat, props);
+ verifyConnectorProperty(tomcat, "http", "maxHttpHeaderSize", TomcatConnectors.MAX_HTTP_HEADER_SIZE_BYTES);
+ verifyConnectorProperty(tomcat, "https", "maxHttpHeaderSize", TomcatConnectors.MAX_HTTP_HEADER_SIZE_BYTES);
+ }
+
+ private static void verifyConnectorProperty(Tomcat tomcat, final String connectorScheme,
+ final String property, final Object propertyValue) {
+ verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
@Override
public boolean matches(Object o) {
Connector c = (Connector) o;
- return c.getScheme().equals("https") && c.getProperty("clientAuth").equals("true");
+ return c.getScheme().equals(connectorScheme) && c.getProperty(property).equals(propertyValue);
}
}));
}