Skip to content
Permalink
Browse files

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.
  • Loading branch information
markt-asf committed Jan 21, 2020
1 parent 0d633e7 commit 40d5d93bd284033cf4a1f77f5492444f83d803e2
@@ -300,9 +300,16 @@ public void setTomcatAuthorization(boolean tomcatAuthorization) {
/**
* Required secret.
*/
@Deprecated
protected String requiredSecret = null;
protected String secret = null;
public void setSecret(String secret) {
this.secret = secret;
this.requiredSecret = secret;
}
@Deprecated
public void setRequiredSecret(String requiredSecret) {
this.requiredSecret = requiredSecret;
setSecret(requiredSecret);
}


@@ -831,7 +838,7 @@ protected void prepareRequest() {
}

// Decode extra attributes
boolean secret = false;
boolean secretPresentInRequest = false;
byte attributeCode;
while ((attributeCode = requestHeaderMessage.getByte())
!= Constants.SC_A_ARE_DONE) {
@@ -934,9 +941,9 @@ protected void prepareRequest() {

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);
}
@@ -952,7 +959,7 @@ protected void prepareRequest() {
}

// Check if secret was submitted if required
if ((requiredSecret != null) && !secret) {
if ((secret != null) && !secretPresentInRequest) {
response.setStatus(403);
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
@@ -95,13 +95,49 @@ public void setTomcatAuthorization(boolean tomcatAuthorization) {


protected 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;
this.requiredSecret = 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 getSecret();
}


private boolean secretRequired = true;
public void setSecretRequired(boolean secretRequired) {
this.secretRequired = secretRequired;
}
public boolean getSecretRequired() {
return secretRequired;
}


@@ -151,4 +187,16 @@ protected P createUpgradeProcessor(SocketWrapper<S> socket,
return null;
}
}


@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();
}
}
@@ -150,7 +150,7 @@ protected AjpAprProcessor createProcessor() {
processor.setAjpFlush(proto.getAjpFlush());
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setTomcatAuthorization(proto.getTomcatAuthorization());
processor.setRequiredSecret(proto.requiredSecret);
processor.setSecret(proto.getSecret());
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
processor.setMaxCookieCount(proto.getMaxCookieCount());
@@ -180,7 +180,7 @@ protected AjpNioProcessor createProcessor() {
processor.setAjpFlush(proto.getAjpFlush());
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setTomcatAuthorization(proto.getTomcatAuthorization());
processor.setRequiredSecret(proto.requiredSecret);
processor.setSecret(proto.getSecret());
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
processor.setMaxCookieCount(proto.getMaxCookieCount());
@@ -140,7 +140,7 @@ protected AjpProcessor createProcessor() {
processor.setAjpFlush(proto.getAjpFlush());
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setTomcatAuthorization(proto.getTomcatAuthorization());
processor.setRequiredSecret(proto.requiredSecret);
processor.setSecret(proto.getSecret());
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
processor.setClientCertProvider(proto.getClientCertProvider());
processor.setMaxCookieCount(proto.getMaxCookieCount());
@@ -37,5 +37,6 @@ ajpprocessor.ssl.notsupported=The SSL protocol is not supported by this connecto
ajpprotocol.endpoint.starterror=Error starting endpoint
ajpprotocol.failedwrite=Socket write failed
ajpprotocol.init=Initializing Coyote AJP/1.3 on [{0}]
ajpprotocol.nosecret=The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
ajpprotocol.request.register=Error registering request processor in JMX
ajpprotocol.start=Starting Coyote AJP/1.3 on [{0}]
@@ -30,14 +30,25 @@
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");
}

@Override
protected String getProtocol() {
/*
@@ -147,6 +147,14 @@
Change the default bind address for the AJP/1.3 connector to be the
loopback address. (markt)
</update>
<add>
Rename the <code>requiredSecret</code> attribute of the AJP/1.3
Connector to <code>secret</code> and add a new attribute
<code>secretRequired</code> that defaults to <code>true</code>. When
<code>secretRequired</code> is <code>true</code> the AJP/1.3 Connector
will not start unless the <code>secret</code> attribute is configured to
a non-null, non-zero length String. (markt)
</add>
</changelog>
</subsection>
<subsection name="Jasper">
@@ -431,8 +431,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>

0 comments on commit 40d5d93

Please sign in to comment.
You can’t perform that action at this time.