This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit a41145cc0c564a7f5feff9ac4263a46ba8c0f4e7 Author: Mark Thomas <ma...@apache.org> AuthorDate: Tue Jan 21 14:24:33 2020 +0000 Rename requiredSecret to secret and add secretRequired AJP Connector will not start if secretRequired="true" and secret is set to null or zero length String. --- .../org/apache/coyote/ajp/AbstractAjpProtocol.java | 49 ++++++++++++++++++++-- java/org/apache/coyote/ajp/AjpProcessor.java | 12 +++--- java/org/apache/coyote/ajp/LocalStrings.properties | 1 + webapps/docs/config/ajp.xml | 12 +++++- 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java index 8e0593b..81da7da 100644 --- a/java/org/apache/coyote/ajp/AbstractAjpProtocol.java +++ b/java/org/apache/coyote/ajp/AbstractAjpProtocol.java @@ -143,17 +143,48 @@ public abstract class AbstractAjpProtocol<S> extends AbstractProtocol<S> { } - private String requiredSecret = null; + private String secret = null; + /** + * Set the secret that must be included with every request. + * + * @param secret The required secret + */ + public void setSecret(String secret) { + this.secret = secret; + } + protected String getSecret() { + return secret; + } /** * Set the required secret that must be included with every request. * * @param requiredSecret The required secret + * + * @deprecated Replaced by {@link #setSecret(String)}. + * Will be removed in Tomcat 11 onwards */ + @Deprecated public void setRequiredSecret(String requiredSecret) { - this.requiredSecret = requiredSecret; + setSecret(requiredSecret); } + /** + * @return The current secret + * + * @deprecated Replaced by {@link #getSecret()}. + * Will be removed in Tomcat 11 onwards + */ + @Deprecated protected String getRequiredSecret() { - return requiredSecret; + return getSecret(); + } + + + private boolean secretRequired = true; + public void setSecretRequired(boolean secretRequired) { + this.secretRequired = secretRequired; + } + public boolean getSecretRequired() { + return secretRequired; } @@ -210,4 +241,16 @@ public abstract class AbstractAjpProtocol<S> extends AbstractProtocol<S> { throw new IllegalStateException(sm.getString("ajpprotocol.noUpgradeHandler", upgradeToken.getHttpUpgradeHandler().getClass().getName())); } + + + @Override + public void init() throws Exception { + if (getSecretRequired()) { + String secret = getSecret(); + if (secret == null || secret.length() == 0) { + throw new IllegalArgumentException(sm.getString("ajpprotocol.nosecret")); + } + } + super.init(); + } } diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java index 0c593ba..128c1a0 100644 --- a/java/org/apache/coyote/ajp/AjpProcessor.java +++ b/java/org/apache/coyote/ajp/AjpProcessor.java @@ -712,8 +712,8 @@ public class AjpProcessor extends AbstractProcessor { } // Decode extra attributes - String requiredSecret = protocol.getRequiredSecret(); - boolean secret = false; + String secret = protocol.getSecret(); + boolean secretPresentInRequest = false; byte attributeCode; while ((attributeCode = requestHeaderMessage.getByte()) != Constants.SC_A_ARE_DONE) { @@ -819,9 +819,9 @@ public class AjpProcessor extends AbstractProcessor { case Constants.SC_A_SECRET: requestHeaderMessage.getBytes(tmpMB); - if (requiredSecret != null) { - secret = true; - if (!tmpMB.equals(requiredSecret)) { + if (secret != null) { + secretPresentInRequest = true; + if (!tmpMB.equals(secret)) { response.setStatus(403); setErrorState(ErrorState.CLOSE_CLEAN, null); } @@ -837,7 +837,7 @@ public class AjpProcessor extends AbstractProcessor { } // Check if secret was submitted if required - if ((requiredSecret != null) && !secret) { + if ((secret != null) && !secretPresentInRequest) { response.setStatus(403); setErrorState(ErrorState.CLOSE_CLEAN, null); } diff --git a/java/org/apache/coyote/ajp/LocalStrings.properties b/java/org/apache/coyote/ajp/LocalStrings.properties index 9b569bb..01de92a 100644 --- a/java/org/apache/coyote/ajp/LocalStrings.properties +++ b/java/org/apache/coyote/ajp/LocalStrings.properties @@ -28,5 +28,6 @@ ajpprocessor.request.prepare=Error preparing request ajpprocessor.request.process=Error processing request ajpprotocol.noSSL=SSL is not supported with AJP. The SSL host configuration for [{0}] was ignored +ajpprotocol.nosecret=The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid. ajpprotocol.noUpgrade=Upgrade is not supported with AJP. The UpgradeProtocol configuration for [{0}] was ignored ajpprotocol.noUpgradeHandler=Upgrade is not supported with AJP. The HttpUpgradeHandler [{0}] can not be processed diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml index 5535a06..3999a13 100644 --- a/webapps/docs/config/ajp.xml +++ b/webapps/docs/config/ajp.xml @@ -428,8 +428,18 @@ expected concurrent requests (synchronous and asynchronous).</p> </attribute> - <attribute name="requiredSecret" required="false"> + <attribute name="secret" required="false"> <p>Only requests from workers with this secret keyword will be accepted. + The default value is <code>null</code>. This attrbute must be specified + with a non-null, non-zero length value unless + <strong>secretRequired</strong> is explicitly configured to be + <code>false</code>.</p> + </attribute> + + <attribute name="secretRequired" required="false"> + <p>If this attribute is <code>true</code>, the AJP Connector will only + start if the <strong>secret</strong> attribute is configured with a + non-null, non-zero length value. The default value is <code>true</code>. </p> </attribute> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org