From 81928922795ad1df74f08db9c5139bfa0acae3b8 Mon Sep 17 00:00:00 2001
From: Matei Albu For servers with more than one IP address, this attribute
specifies which address will be used for listening on the specified
- port. By default, this port will be used on all IP addresses
- associated with the server. A value of >
@@ -138,4 +194,16 @@ public abstract class AbstractAjpProtoco
return null;
}
}
+
+
+ @Override
+ public void start() throws Exception {
+ if (getSecretRequired()) {
+ String secret = getSecret();
+ if (secret == null || secret.length() == 0) {
+ throw new IllegalArgumentException(sm.getString("ajpprotocol.nosecret"));
+ }
+ }
+ super.start();
+ }
}
Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpAprProtocol.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/ajp/AjpAprProtocol.java
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpAprProtocol.java
@@ -20,6 +20,7 @@ import org.apache.coyote.AbstractProtoco
import org.apache.coyote.Processor;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AprEndpoint;
import org.apache.tomcat.util.net.AprEndpoint.Handler;
@@ -61,6 +62,7 @@ public class AjpAprProtocol extends Abst
public AjpAprProtocol() {
endpoint = new AprEndpoint();
+ endpoint.setAddress(JreCompat.getInstance().getLoopbackAddress());
cHandler = new AjpConnectionHandler(this);
((AprEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpNioProtocol.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/ajp/AjpNioProtocol.java
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpNioProtocol.java
@@ -23,6 +23,7 @@ import org.apache.coyote.AbstractProtoco
import org.apache.coyote.Processor;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.NioChannel;
import org.apache.tomcat.util.net.NioEndpoint;
@@ -56,6 +57,7 @@ public class AjpNioProtocol extends Abst
public AjpNioProtocol() {
endpoint = new NioEndpoint();
+ endpoint.setAddress(JreCompat.getInstance().getLoopbackAddress());
cHandler = new AjpConnectionHandler(this);
((NioEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpProtocol.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/ajp/AjpProtocol.java
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/AjpProtocol.java
@@ -22,6 +22,7 @@ import org.apache.coyote.AbstractProtoco
import org.apache.coyote.Processor;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.JIoEndpoint;
import org.apache.tomcat.util.net.JIoEndpoint.Handler;
@@ -57,6 +58,7 @@ public class AjpProtocol extends Abstrac
public AjpProtocol() {
endpoint = new JIoEndpoint();
+ endpoint.setAddress(JreCompat.getInstance().getLoopbackAddress());
cHandler = new AjpConnectionHandler(this);
((JIoEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
Index: apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/LocalStrings.properties
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/coyote/ajp/LocalStrings.properties
+++ apache-tomcat-8.0.53-src/java/org/apache/coyote/ajp/LocalStrings.properties
@@ -25,7 +25,6 @@ ajpprocessor.readtimeout=Timeout attempt
ajpprocessor.request.prepare=Error preparing request
ajpprocessor.request.process=Error processing request
ajpprocessor.certs.fail=Certificate conversion failed
-ajpprocessor.comet.notsupported=The Comet protocol is not supported by this connector
ajpprocessor.ssl.notsupported=The SSL protocol is not supported by this connector
ajpprocessor.httpupgrade.notsupported=HTTP upgrade is not supported by the AJP protocol
@@ -35,3 +34,4 @@ ajpmessage.invalid=Invalid message recei
ajpmessage.invalidLength=Invalid message received with length {0}
ajpMessage.invalidPos=Requested read of bytes at position [{0}] which is beyond the end of the AJP message
+ajpprotocol.nosecret=The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
Index: apache-tomcat-8.0.53-src/java/org/apache/tomcat/util/compat/JreCompat.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/tomcat/util/compat/JreCompat.java
+++ apache-tomcat-8.0.53-src/java/org/apache/tomcat/util/compat/JreCompat.java
@@ -18,8 +18,10 @@ package org.apache.tomcat.util.compat;
import java.io.File;
import java.io.IOException;
+import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
+import java.net.UnknownHostException;
import java.util.Deque;
import java.util.jar.JarFile;
@@ -69,6 +71,31 @@ public class JreCompat {
return instance;
}
+ public InetAddress getLoopbackAddress() {
+ // Javadoc for getByName() states that calling with null will return one
+ // of the loopback addresses
+ InetAddress result = null;
+ try {
+ result = InetAddress.getByName(null);
+ } catch (UnknownHostException e) {
+ // This would be unusual but ignore it in this case.
+ }
+ if (result == null) {
+ // Fallback to default IPv4 loopback address.
+ // Not perfect but good enough and if the address is not valid the
+ // bind will fail later with an appropriate error message
+ try {
+ result = InetAddress.getByName("127.0.0.1");
+ } catch (UnknownHostException e) {
+ // Unreachable.
+ // For text representations of IP addresses only the format is
+ // checked.
+ }
+ }
+
+ return result;
+ }
+
// Java 7 implementation of Java 8 methods
Index: apache-tomcat-8.0.53-src/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
+++ apache-tomcat-8.0.53-src/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
@@ -33,14 +33,26 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
public class TestAbstractAjpProcessor extends TomcatBaseTest {
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ Connector c = getTomcatInstance().getConnector();
+ c.setProperty("secretRequired", "false");
+ c.setProperty("allowedRequestAttributesPattern", "MYATTRIBUTE.*");
+ }
+
@Override
protected String getProtocol() {
/*
Index: apache-tomcat-8.0.53-src/webapps/docs/config/ajp.xml
===================================================================
--- apache-tomcat-8.0.53-src.orig/webapps/docs/config/ajp.xml
+++ apache-tomcat-8.0.53-src/webapps/docs/config/ajp.xml
@@ -310,10 +310,26 @@
127.0.0.1
- indicates that the Connector will only listen on the loopback
- interface.
The AJP protocol passes some information from the reverse proxy to the + AJP connector using request attributes. These attributes are:
+The AJP protocol supports the passing of arbitrary request attributes.
+ Requests containing arbitrary request attributes will be rejected with a
+ 403 response unless the entire attribute name matches this regular
+ expression. If not specified, the default value is null
.
Only requests from workers with this secret keyword will be accepted.
+ The default value is null
. This attrbute must be specified
+ with a non-null, non-zero length value unless
+ secretRequired is explicitly configured to be
+ false
.
If this attribute is true
, the AJP Connector will only
+ start if the secret attribute is configured with a
+ non-null, non-zero length value. The default value is true
.