Add new AJP attribute allowedArbitraryRequestAttributes · apache/tomcat@64fa5b9 · GitHub
Skip to content

Commit

Permalink
Add new AJP attribute allowedArbitraryRequestAttributes
Browse files Browse the repository at this point in the history
Requests with unrecognised attributes will be blocked with a 403
  • Loading branch information
markt-asf committed Feb 4, 2020
1 parent 9ac9053 commit 64fa5b9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
13 changes: 13 additions & 0 deletions java/org/apache/coyote/ajp/AbstractAjpProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.coyote.ajp;

import java.net.InetAddress;
import java.util.regex.Pattern;

import org.apache.coyote.AbstractProtocol;
import org.apache.coyote.Processor;
Expand Down Expand Up @@ -188,6 +189,18 @@ public boolean getSecretRequired() {
}


private Pattern allowedArbitraryRequestAttributesPattern;
public void setAllowedArbitraryRequestAttributes(String allowedArbitraryRequestAttributes) {
this.allowedArbitraryRequestAttributesPattern = Pattern.compile(allowedArbitraryRequestAttributes);
}
public String getAllowedArbitraryRequestAttributes() {
return allowedArbitraryRequestAttributesPattern.pattern();
}
protected Pattern getAllowedArbitraryRequestAttributesPattern() {
return allowedArbitraryRequestAttributesPattern;
}


/**
* AJP packet size.
*/
Expand Down
36 changes: 35 additions & 1 deletion java/org/apache/coyote/ajp/AjpProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
import java.security.NoSuchProviderException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

Expand Down Expand Up @@ -78,6 +83,9 @@ public class AjpProcessor extends AbstractProcessor {
private static final byte[] pongMessageArray;


private static final Set<String> javaxAttributes;


static {
// Allocate the end message array
AjpMessage endMessage = new AjpMessage(16);
Expand Down Expand Up @@ -118,6 +126,14 @@ public class AjpProcessor extends AbstractProcessor {
pongMessageArray = new byte[pongMessage.getLen()];
System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray,
0, pongMessage.getLen());

// Build the Set of javax attributes
Set<String> s = new HashSet<>();
s.add("javax.servlet.request.cipher_suite");
s.add("javax.servlet.request.key_size");
s.add("javax.servlet.request.ssl_session");
s.add("javax.servlet.request.X509Certificate");
javaxAttributes= Collections.unmodifiableSet(s);
}


Expand Down Expand Up @@ -728,8 +744,26 @@ private void prepareRequest() {
}
} else if(n.equals(Constants.SC_A_SSL_PROTOCOL)) {
request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, v);
} else if (n.equals("JK_LB_ACTIVATION")) {
request.setAttribute(n, v);
} else if (javaxAttributes.contains(n)) {
request.setAttribute(n, v);
} else {
request.setAttribute(n, v );
// All 'known' attributes will be processed by the previous
// blocks. Any remaining attribute is an 'arbitrary' one.
Pattern pattern = protocol.getAllowedArbitraryRequestAttributesPattern();
if (pattern == null) {
response.setStatus(403);
setErrorState(ErrorState.CLOSE_CLEAN, null);
} else {
Matcher m = pattern.matcher(n);
if (m.matches()) {
request.setAttribute(n, v);
} else {
response.setStatus(403);
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
}
}
break;

Expand Down
5 changes: 5 additions & 0 deletions webapps/docs/changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@
will not start unless the <code>secret</code> attribute is configured to
a non-null, non-zero length String. (markt)
</add>
<add>
Add a new attribute, <code>allowedArbitraryRequestAttributes</code> to
the AJP/1.3 Connector. Requests with unreconised attributes will be
blocked with a 403. (markt)
</add>
</changelog>
</subsection>
<subsection name="Jasper">
Expand Down
19 changes: 19 additions & 0 deletions webapps/docs/config/ajp.xml
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,25 @@
port. By default, the loopback address will be used.</p>
</attribute>

<attribute name="allowedArbitraryRequestAttributes" required="false">
<p>The AJP protocol passes some information from the reverse proxy to the
AJP connector using request attributes. These attributes are:</p>
<ul>
<li>javax.servlet.request.cipher_suite</li>
<li>javax.servlet.request.key_size</li>
<li>javax.servlet.request.ssl_session</li>
<li>javax.servlet.request.X509Certificate</li>
<li>AJP_LOCAL_ADDR</li>
<li>AJP_REMOTE_PORT</li>
<li>AJP_SSL_PROTOCOL</li>
<li>JK_LB_ACTIVATION</li>
</ul>
<p>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 <code>null</code>.</p>
</attribute>

<attribute name="bindOnInit" required="false">
<p>Controls when the socket used by the connector is bound. By default it
is bound when the connector is initiated and unbound when the connector is
Expand Down

0 comments on commit 64fa5b9

Please sign in to comment.