Skip to content

Commit

Permalink
Refactor obtaining the SSL attributes.
Browse files Browse the repository at this point in the history
Add an AprSSLSupport wrapper which allows APR to be aligned with NIO/NIO2 and then pulled up to the AbstractHttp11Processor

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1655847 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Jan 29, 2015
1 parent 27bffaa commit 4d432e7
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 181 deletions.
11 changes: 11 additions & 0 deletions java/org/apache/coyote/AbstractProcessor.java
Expand Up @@ -42,6 +42,7 @@ public abstract class AbstractProcessor<S> implements ActionHook, Processor<S> {
protected final Request request; protected final Request request;
protected final Response response; protected final Response response;
protected SocketWrapperBase<S> socketWrapper = null; protected SocketWrapperBase<S> socketWrapper = null;
private String clientCertProvider = null;


/** /**
* Error state for the request/response currently being processed. * Error state for the request/response currently being processed.
Expand Down Expand Up @@ -137,6 +138,16 @@ public Adapter getAdapter() {
} }




public String getClientCertProvider() {
return clientCertProvider;
}


public void setClientCertProvider(String s) {
this.clientCertProvider = s;
}


/** /**
* Set the socket wrapper being used. * Set the socket wrapper being used.
*/ */
Expand Down
16 changes: 16 additions & 0 deletions java/org/apache/coyote/Processor.java
Expand Up @@ -55,11 +55,27 @@ public interface Processor<S> {
*/ */
void recycle(); void recycle();


/**
* When client certificate information is presented in a form other than
* instances of {@link java.security.cert.X509Certificate} it needs to be
* converted before it can be used and this property controls which JSSE
* provider is used to perform the conversion. For example it is used with
* the AJP connectors, the HTTP APR connector and with the
* {@link org.apache.catalina.valves.SSLValve}. If not specified, the
* default provider will be used.
*
* @return The name of the JSSE provider to use for certificate
* transformation if required
*/
String getClientCertProvider();

void setSslSupport(SSLSupport sslSupport); void setSslSupport(SSLSupport sslSupport);


/** /**
* Allows retrieving additional input during the upgrade process * Allows retrieving additional input during the upgrade process
* @return leftover bytes * @return leftover bytes
*/ */
ByteBuffer getLeftoverInput(); ByteBuffer getLeftoverInput();


} }
14 changes: 1 addition & 13 deletions java/org/apache/coyote/ajp/AjpProcessor.java
Expand Up @@ -313,19 +313,6 @@ public void setRequiredSecret(String requiredSecret) {
} }




/**
* When client certificate information is presented in a form other than
* instances of {@link java.security.cert.X509Certificate} it needs to be
* converted before it can be used and this property controls which JSSE
* provider is used to perform the conversion. For example it is used with
* the AJP connectors, the HTTP APR connector and with the
* {@link org.apache.catalina.valves.SSLValve}. If not specified, the
* default provider will be used.
*/
private String clientCertProvider = null;
public String getClientCertProvider() { return clientCertProvider; }
public void setClientCertProvider(String s) { this.clientCertProvider = s; }

// --------------------------------------------------------- Public Methods // --------------------------------------------------------- Public Methods




Expand Down Expand Up @@ -415,6 +402,7 @@ public final void action(ActionCode actionCode, Object param) {
// Fill the elements. // Fill the elements.
try { try {
CertificateFactory cf; CertificateFactory cf;
String clientCertProvider = getClientCertProvider();
if (clientCertProvider == null) { if (clientCertProvider == null) {
cf = CertificateFactory.getInstance("X.509"); cf = CertificateFactory.getInstance("X.509");
} else { } else {
Expand Down
46 changes: 46 additions & 0 deletions java/org/apache/coyote/http11/AbstractHttp11Processor.java
Expand Up @@ -53,6 +53,7 @@
import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.DispatchType; import org.apache.tomcat.util.net.DispatchType;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SendfileDataBase; import org.apache.tomcat.util.net.SendfileDataBase;
import org.apache.tomcat.util.net.SocketStatus; import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapperBase; import org.apache.tomcat.util.net.SocketWrapperBase;
Expand Down Expand Up @@ -229,6 +230,12 @@ public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
protected SendfileDataBase sendfileData = null; protected SendfileDataBase sendfileData = null;




/**
* SSL information.
*/
protected SSLSupport sslSupport;


public AbstractHttp11Processor(int maxHttpHeaderSize, AbstractEndpoint<S> endpoint, public AbstractHttp11Processor(int maxHttpHeaderSize, AbstractEndpoint<S> endpoint,
int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) { int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {


Expand Down Expand Up @@ -690,6 +697,15 @@ private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
} }




/**
* Set the SSL information for this HTTP connection.
*/
@Override
public void setSslSupport(SSLSupport sslSupport) {
this.sslSupport = sslSupport;
}


/** /**
* Send an action to the connector. * Send an action to the connector.
* *
Expand Down Expand Up @@ -934,6 +950,36 @@ public final void action(ActionCode actionCode, Object param) {
} }
break; break;
} }
case REQ_SSL_ATTRIBUTE: {
try {
if (sslSupport != null) {
Object sslO = sslSupport.getCipherSuite();
if (sslO != null) {
request.setAttribute
(SSLSupport.CIPHER_SUITE_KEY, sslO);
}
sslO = sslSupport.getPeerCertificateChain(false);
if (sslO != null) {
request.setAttribute
(SSLSupport.CERTIFICATE_KEY, sslO);
}
sslO = sslSupport.getKeySize();
if (sslO != null) {
request.setAttribute
(SSLSupport.KEY_SIZE_KEY, sslO);
}
sslO = sslSupport.getSessionId();
if (sslO != null) {
request.setAttribute
(SSLSupport.SESSION_ID_KEY, sslO);
}
request.setAttribute(SSLSupport.SESSION_MGR, sslSupport);
}
} catch (Exception e) {
getLog().warn(sm.getString("http11processor.socket.ssl"), e);
}
break;
}
default: { default: {
actionInternal(actionCode, param); actionInternal(actionCode, param);
break; break;
Expand Down
73 changes: 0 additions & 73 deletions java/org/apache/coyote/http11/Http11AprProcessor.java
Expand Up @@ -55,30 +55,6 @@ public Http11AprProcessor(int maxHttpHeaderSize, AbstractEndpoint<Long> endpoint
} }




// ----------------------------------------------------- Instance Variables

/**
* When client certificate information is presented in a form other than
* instances of {@link java.security.cert.X509Certificate} it needs to be
* converted before it can be used and this property controls which JSSE
* provider is used to perform the conversion. For example it is used with
* the AJP connectors, the HTTP APR connector and with the
* {@link org.apache.catalina.valves.SSLValve}. If not specified, the
* default provider will be used.
*/
protected String clientCertProvider = null;
public String getClientCertProvider() { return clientCertProvider; }
public void setClientCertProvider(String s) { this.clientCertProvider = s; }


// --------------------------------------------------------- Public Methods

@Override
public void setSslSupport(SSLSupport sslSupport) {
// NOOP for APR
}


// ----------------------------------------------------- ActionHook Methods // ----------------------------------------------------- ActionHook Methods


/** /**
Expand All @@ -94,55 +70,6 @@ public void actionInternal(ActionCode actionCode, Object param) {
long socketRef = socketWrapper.getSocket().longValue(); long socketRef = socketWrapper.getSocket().longValue();


switch (actionCode) { switch (actionCode) {
case REQ_SSL_ATTRIBUTE: {
if (endpoint.isSSLEnabled() && (socketRef != 0)) {
try {
// Cipher suite
Object sslO = SSLSocket.getInfoS(socketRef, SSL.SSL_INFO_CIPHER);
if (sslO != null) {
request.setAttribute(SSLSupport.CIPHER_SUITE_KEY, sslO);
}
// Get client certificate and the certificate chain if present
// certLength == -1 indicates an error
int certLength = SSLSocket.getInfoI(socketRef, SSL.SSL_INFO_CLIENT_CERT_CHAIN);
byte[] clientCert = SSLSocket.getInfoB(socketRef, SSL.SSL_INFO_CLIENT_CERT);
X509Certificate[] certs = null;
if (clientCert != null && certLength > -1) {
certs = new X509Certificate[certLength + 1];
CertificateFactory cf;
if (clientCertProvider == null) {
cf = CertificateFactory.getInstance("X.509");
} else {
cf = CertificateFactory.getInstance("X.509",
clientCertProvider);
}
certs[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(clientCert));
for (int i = 0; i < certLength; i++) {
byte[] data = SSLSocket.getInfoB(socketRef, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
certs[i+1] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(data));
}
}
if (certs != null) {
request.setAttribute(SSLSupport.CERTIFICATE_KEY, certs);
}
// User key size
sslO = Integer.valueOf(SSLSocket.getInfoI(socketRef,
SSL.SSL_INFO_CIPHER_USEKEYSIZE));
request.setAttribute(SSLSupport.KEY_SIZE_KEY, sslO);

// SSL session ID
sslO = SSLSocket.getInfoS(socketRef, SSL.SSL_INFO_SESSION_ID);
if (sslO != null) {
request.setAttribute(SSLSupport.SESSION_ID_KEY, sslO);
}
//TODO provide a hook to enable the SSL session to be
// invalidated. Set AprEndpoint.SESSION_MGR req attr
} catch (Exception e) {
log.warn(sm.getString("http11processor.socket.ssl"), e);
}
}
break;
}
case REQ_SSL_CERTIFICATE: { case REQ_SSL_CERTIFICATE: {
if (endpoint.isSSLEnabled() && (socketRef != 0)) { if (endpoint.isSSLEnabled() && (socketRef != 0)) {
// Consume and buffer the request body, so that it does not // Consume and buffer the request body, so that it does not
Expand Down
12 changes: 9 additions & 3 deletions java/org/apache/coyote/http11/Http11AprProtocol.java
Expand Up @@ -28,6 +28,7 @@
import org.apache.juli.logging.LogFactory; import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.net.AprEndpoint; import org.apache.tomcat.util.net.AprEndpoint;
import org.apache.tomcat.util.net.AprEndpoint.Poller; import org.apache.tomcat.util.net.AprEndpoint.Poller;
import org.apache.tomcat.util.net.AprSSLSupport;
import org.apache.tomcat.util.net.SocketStatus; import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapperBase; import org.apache.tomcat.util.net.SocketWrapperBase;


Expand Down Expand Up @@ -264,9 +265,14 @@ public SocketState process(SocketWrapperBase<Long> socket,
} }


@Override @Override
protected void initSsl(SocketWrapperBase<Long> socket, protected void initSsl(SocketWrapperBase<Long> socket, Processor<Long> processor) {
Processor<Long> processor) { if (proto.isSSLEnabled()) {
// NOOP for APR AprSSLSupport sslSupport =
new AprSSLSupport(socket, processor.getClientCertProvider());
processor.setSslSupport(sslSupport);
} else {
processor.setSslSupport(null);
}
} }


@Override @Override
Expand Down
45 changes: 0 additions & 45 deletions java/org/apache/coyote/http11/Http11Nio2Processor.java
Expand Up @@ -45,12 +45,6 @@ protected Log getLog() {
} }




/**
* SSL information.
*/
protected SSLSupport sslSupport;


// ----------------------------------------------------------- Constructors // ----------------------------------------------------------- Constructors


public Http11Nio2Processor(int maxHttpHeaderSize, AbstractEndpoint<Nio2Channel> endpoint, public Http11Nio2Processor(int maxHttpHeaderSize, AbstractEndpoint<Nio2Channel> endpoint,
Expand All @@ -62,15 +56,6 @@ public Http11Nio2Processor(int maxHttpHeaderSize, AbstractEndpoint<Nio2Channel>


// --------------------------------------------------------- Public Methods // --------------------------------------------------------- Public Methods


/**
* Set the SSL information for this HTTP connection.
*/
@Override
public void setSslSupport(SSLSupport sslSupport) {
this.sslSupport = sslSupport;
}


@Override @Override
public SocketState asyncDispatch(SocketStatus status) { public SocketState asyncDispatch(SocketStatus status) {
SocketState state = super.asyncDispatch(status); SocketState state = super.asyncDispatch(status);
Expand All @@ -97,36 +82,6 @@ public SocketState asyncDispatch(SocketStatus status) {
public void actionInternal(ActionCode actionCode, Object param) { public void actionInternal(ActionCode actionCode, Object param) {


switch (actionCode) { switch (actionCode) {
case REQ_SSL_ATTRIBUTE: {
try {
if (sslSupport != null) {
Object sslO = sslSupport.getCipherSuite();
if (sslO != null) {
request.setAttribute
(SSLSupport.CIPHER_SUITE_KEY, sslO);
}
sslO = sslSupport.getPeerCertificateChain(false);
if (sslO != null) {
request.setAttribute
(SSLSupport.CERTIFICATE_KEY, sslO);
}
sslO = sslSupport.getKeySize();
if (sslO != null) {
request.setAttribute
(SSLSupport.KEY_SIZE_KEY, sslO);
}
sslO = sslSupport.getSessionId();
if (sslO != null) {
request.setAttribute
(SSLSupport.SESSION_ID_KEY, sslO);
}
request.setAttribute(SSLSupport.SESSION_MGR, sslSupport);
}
} catch (Exception e) {
log.warn(sm.getString("http11processor.socket.ssl"), e);
}
break;
}
case REQ_SSL_CERTIFICATE: { case REQ_SSL_CERTIFICATE: {
if (sslSupport != null && socketWrapper.getSocket() != null) { if (sslSupport != null && socketWrapper.getSocket() != null) {
/* /*
Expand Down

0 comments on commit 4d432e7

Please sign in to comment.