Commit cc6be12e authored by Guus der Kinderen's avatar Guus der Kinderen

OF-946: Use constant instead of hard-coded property name.

parent fe97ecbe
...@@ -3,6 +3,7 @@ package org.jivesoftware.openfire.net; ...@@ -3,6 +3,7 @@ package org.jivesoftware.openfire.net;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig; import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose; import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.TrustStoreConfig; import org.jivesoftware.openfire.keystore.TrustStoreConfig;
import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.util.CertificateEventListener; import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.util.CertificateManager; import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
...@@ -104,7 +105,7 @@ public class SSLConfigSocketFactory ...@@ -104,7 +105,7 @@ public class SSLConfigSocketFactory
final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE ); final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE );
final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_C2S_TRUSTSTORE ); final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_C2S_TRUSTSTORE );
final String algorithm = JiveGlobals.getProperty( "xmpp.socket.ssl.algorithm", "TLS" ); final String algorithm = JiveGlobals.getProperty( ConnectionSettings.Client.TLS_ALGORITHM, "TLS" );
final SSLContext context = SSLContext.getInstance( algorithm ); final SSLContext context = SSLContext.getInstance( algorithm );
context.init( identityStoreConfig.getKeyManagers(), trustStoreConfig.getTrustManagers(), new java.security.SecureRandom() ); context.init( identityStoreConfig.getKeyManagers(), trustStoreConfig.getTrustManagers(), new java.security.SecureRandom() );
...@@ -116,7 +117,7 @@ public class SSLConfigSocketFactory ...@@ -116,7 +117,7 @@ public class SSLConfigSocketFactory
final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE ); final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE );
final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_S2S_TRUSTSTORE ); final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) SSLConfig.getInstance().getStoreConfig( Purpose.SOCKETBASED_S2S_TRUSTSTORE );
final String algorithm = JiveGlobals.getProperty( "xmpp.socket.ssl.algorithm", "TLS" ); final String algorithm = JiveGlobals.getProperty( ConnectionSettings.Client.TLS_ALGORITHM, "TLS" );
final SSLContext context = SSLContext.getInstance( algorithm ); final SSLContext context = SSLContext.getInstance( algorithm );
context.init( identityStoreConfig.getKeyManagers(), trustStoreConfig.getTrustManagers(), new java.security.SecureRandom() ); context.init( identityStoreConfig.getKeyManagers(), trustStoreConfig.getTrustManagers(), new java.security.SecureRandom() );
......
/** /**
* $RCSfile$ * $RCSfile$
* $Revision: $ * $Revision: $
* $Date: $ * $Date: $
* *
* Copyright (C) 2005-2008 Jive Software and Artur Hefczyc. All rights reserved. * Copyright (C) 2005-2008 Jive Software and Artur Hefczyc. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jivesoftware.openfire.net; package org.jivesoftware.openfire.net;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.*; import java.security.*;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status; import javax.net.ssl.SSLEngineResult.Status;
import org.jivesoftware.openfire.Connection; import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig; import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose; import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.TrustStoreConfig; import org.jivesoftware.openfire.keystore.TrustStoreConfig;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.openfire.session.ConnectionSettings;
import org.slf4j.Logger; import org.jivesoftware.util.JiveGlobals;
import org.slf4j.LoggerFactory; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates and initializes the SSLContext instance to use to secure the plain connection. This /**
* class is also responsible for encoding and decoding the encrypted data and place it into * Creates and initializes the SSLContext instance to use to secure the plain connection. This
* the corresponding the {@link ByteBuffer}. * class is also responsible for encoding and decoding the encrypted data and place it into
* * the corresponding the {@link ByteBuffer}.
* @author Artur Hefczyc *
* @author Hao Chen * @author Artur Hefczyc
*/ * @author Hao Chen
public class TLSWrapper { */
public class TLSWrapper {
private static final Logger Log = LoggerFactory.getLogger(TLSWrapper.class);
private static final Logger Log = LoggerFactory.getLogger(TLSWrapper.class);
/*
* Enables logging of the SSLEngine operations. /*
*/ * Enables logging of the SSLEngine operations.
private boolean logging = false; */
private boolean logging = false;
private SSLEngine tlsEngine;
private SSLEngineResult tlsEngineResult; private SSLEngine tlsEngine;
private SSLEngineResult tlsEngineResult;
private int netBuffSize;
private int appBuffSize; private int netBuffSize;
private int appBuffSize;
public TLSWrapper(Connection connection, boolean clientMode, boolean needClientAuth, String remoteServer) {
public TLSWrapper(Connection connection, boolean clientMode, boolean needClientAuth, String remoteServer) {
final boolean isClientToServer = (remoteServer == null); final boolean isClientToServer = (remoteServer == null);
// Create/initialize the SSLContext with key material // Create/initialize the SSLContext with key material
try { try {
// First initialize the key and trust material. // First initialize the key and trust material.
final SSLConfig sslConfig = SSLConfig.getInstance(); final SSLConfig sslConfig = SSLConfig.getInstance();
final Purpose purpose = (isClientToServer ? Purpose.SOCKETBASED_C2S_TRUSTSTORE : Purpose.SOCKETBASED_S2S_TRUSTSTORE ); final Purpose purpose = (isClientToServer ? Purpose.SOCKETBASED_C2S_TRUSTSTORE : Purpose.SOCKETBASED_S2S_TRUSTSTORE );
final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) sslConfig.getStoreConfig( purpose ); final TrustStoreConfig trustStoreConfig = (TrustStoreConfig) sslConfig.getStoreConfig( purpose );
// TrustManager's decide whether to allow connections. // TrustManager's decide whether to allow connections.
final TrustManager[] tm; final TrustManager[] tm;
if (clientMode || needClientAuth) if (clientMode || needClientAuth)
...@@ -81,210 +82,210 @@ public class TLSWrapper { ...@@ -81,210 +82,210 @@ public class TLSWrapper {
final KeyStore ksTrust = trustStoreConfig.getStore(); final KeyStore ksTrust = trustStoreConfig.getStore();
if (isClientToServer) if (isClientToServer)
{ {
// Check if we can trust certificates presented by the client // Check if we can trust certificates presented by the client
tm = new TrustManager[]{new ClientTrustManager(ksTrust)}; tm = new TrustManager[]{new ClientTrustManager(ksTrust)};
} }
else else
{ {
// Check if we can trust certificates presented by the server // Check if we can trust certificates presented by the server
tm = new TrustManager[]{new ServerTrustManager(remoteServer, ksTrust, connection)}; tm = new TrustManager[]{new ServerTrustManager(remoteServer, ksTrust, connection)};
} }
} }
else else
{ {
tm = trustStoreConfig.getTrustManagers(); tm = trustStoreConfig.getTrustManagers();
} }
final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) sslConfig.getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE ); final IdentityStoreConfig identityStoreConfig = (IdentityStoreConfig) sslConfig.getStoreConfig( Purpose.SOCKETBASED_IDENTITYSTORE );
final String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS"); final String algorithm = JiveGlobals.getProperty( ConnectionSettings.Client.TLS_ALGORITHM, "TLS" );
final SSLContext tlsContext = SSLContext.getInstance(algorithm); final SSLContext tlsContext = SSLContext.getInstance(algorithm);
tlsContext.init( identityStoreConfig.getKeyManagers(), tm, null); tlsContext.init( identityStoreConfig.getKeyManagers(), tm, null);
/* /*
* Configure the tlsEngine to act as a server in the SSL/TLS handshake. We're a server, * Configure the tlsEngine to act as a server in the SSL/TLS handshake. We're a server,
* so no need to use host/port variant. * so no need to use host/port variant.
* *
* The first call for a server is a NEED_UNWRAP. * The first call for a server is a NEED_UNWRAP.
*/ */
tlsEngine = tlsContext.createSSLEngine(); tlsEngine = tlsContext.createSSLEngine();
tlsEngine.setUseClientMode(clientMode); tlsEngine.setUseClientMode(clientMode);
SSLSession sslSession = tlsEngine.getSession(); SSLSession sslSession = tlsEngine.getSession();
netBuffSize = sslSession.getPacketBufferSize(); netBuffSize = sslSession.getPacketBufferSize();
appBuffSize = sslSession.getApplicationBufferSize(); appBuffSize = sslSession.getApplicationBufferSize();
} }
catch ( NoSuchAlgorithmException | KeyManagementException ex ) catch ( NoSuchAlgorithmException | KeyManagementException ex )
{ {
Log.error("TLSHandler startup problem. SSLContext initialisation failed.", ex ); Log.error("TLSHandler startup problem. SSLContext initialisation failed.", ex );
} }
} }
public int getNetBuffSize() { public int getNetBuffSize() {
return netBuffSize; return netBuffSize;
} }
public int getAppBuffSize() { public int getAppBuffSize() {
return appBuffSize; return appBuffSize;
} }
/** /**
* Returns whether unwrap(ByteBuffer, ByteBuffer) will accept any more inbound data messages and * Returns whether unwrap(ByteBuffer, ByteBuffer) will accept any more inbound data messages and
* whether wrap(ByteBuffer, ByteBuffer) will produce any more outbound data messages. * whether wrap(ByteBuffer, ByteBuffer) will produce any more outbound data messages.
* *
* @return true if the TLSHandler will not consume anymore network data and will not produce any * @return true if the TLSHandler will not consume anymore network data and will not produce any
* anymore network data. * anymore network data.
*/ */
public boolean isEngineClosed() { public boolean isEngineClosed() {
return (tlsEngine.isOutboundDone() && tlsEngine.isInboundDone()); return (tlsEngine.isOutboundDone() && tlsEngine.isInboundDone());
} }
public void enableLogging(boolean logging) { public void enableLogging(boolean logging) {
this.logging = logging; this.logging = logging;
} }
/** /**
* Attempts to decode SSL/TLS network data into a subsequence of plaintext application data * Attempts to decode SSL/TLS network data into a subsequence of plaintext application data
* buffers. Depending on the state of the TLSWrapper, this method may consume network data * buffers. Depending on the state of the TLSWrapper, this method may consume network data
* without producing any application data (for example, it may consume handshake data.) * without producing any application data (for example, it may consume handshake data.)
* *
* If this TLSWrapper has not yet started its initial handshake, this method will automatically * If this TLSWrapper has not yet started its initial handshake, this method will automatically
* start the handshake. * start the handshake.
* *
* @param net a ByteBuffer containing inbound network data * @param net a ByteBuffer containing inbound network data
* @param app a ByteBuffer to hold inbound application data * @param app a ByteBuffer to hold inbound application data
* @return a ByteBuffer containing inbound application data * @return a ByteBuffer containing inbound application data
* @throws SSLException A problem was encountered while processing the data that caused the * @throws SSLException A problem was encountered while processing the data that caused the
* TLSHandler to abort. * TLSHandler to abort.
*/ */
public ByteBuffer unwrap(ByteBuffer net, ByteBuffer app) throws SSLException { public ByteBuffer unwrap(ByteBuffer net, ByteBuffer app) throws SSLException {
ByteBuffer out = app; ByteBuffer out = app;
out = resizeApplicationBuffer(out);// guarantees enough room for unwrap out = resizeApplicationBuffer(out);// guarantees enough room for unwrap
tlsEngineResult = tlsEngine.unwrap(net, out); tlsEngineResult = tlsEngine.unwrap(net, out);
log("server unwrap: ", tlsEngineResult); log("server unwrap: ", tlsEngineResult);
if (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { if (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
// If the result indicates that we have outstanding tasks to do, go // If the result indicates that we have outstanding tasks to do, go
// ahead and run them in this thread. // ahead and run them in this thread.
doTasks(); doTasks();
} }
return out; return out;
} }
/** /**
* Attempts to encode a buffer of plaintext application data into TLS network data. Depending on * Attempts to encode a buffer of plaintext application data into TLS network data. Depending on
* the state of the TLSWrapper, this method may produce network data without consuming any * the state of the TLSWrapper, this method may produce network data without consuming any
* application data (for example, it may generate handshake data). * application data (for example, it may generate handshake data).
* *
* If this TLSWrapper has not yet started its initial handshake, this method will automatically * If this TLSWrapper has not yet started its initial handshake, this method will automatically
* start the handshake. * start the handshake.
* *
* @param app a ByteBuffer containing outbound application data * @param app a ByteBuffer containing outbound application data
* @param net a ByteBuffer to hold outbound network data * @param net a ByteBuffer to hold outbound network data
* @throws SSLException A problem was encountered while processing the data that caused the * @throws SSLException A problem was encountered while processing the data that caused the
* TLSWrapper to abort. * TLSWrapper to abort.
*/ */
public void wrap(ByteBuffer app, ByteBuffer net) throws SSLException { public void wrap(ByteBuffer app, ByteBuffer net) throws SSLException {
tlsEngineResult = tlsEngine.wrap(app, net); tlsEngineResult = tlsEngine.wrap(app, net);
log("server wrap: ", tlsEngineResult); log("server wrap: ", tlsEngineResult);
if (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { if (tlsEngineResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
// If the result indicates that we have outstanding tasks to do, go // If the result indicates that we have outstanding tasks to do, go
// ahead and run them in this thread. // ahead and run them in this thread.
doTasks(); doTasks();
} }
} }
/** /**
* Signals that no more outbound application data will be sent on this TLSHandler. * Signals that no more outbound application data will be sent on this TLSHandler.
* *
* @throws SSLException * @throws SSLException
*/ */
public void close() throws SSLException { public void close() throws SSLException {
// Indicate that application is done with engine // Indicate that application is done with engine
tlsEngine.closeOutbound(); tlsEngine.closeOutbound();
} }
/** /**
* Returns the current status for this TLSHandler. * Returns the current status for this TLSHandler.
* *
* @return the current TLSStatus * @return the current TLSStatus
*/ */
public TLSStatus getStatus() { public TLSStatus getStatus() {
TLSStatus status = null; TLSStatus status = null;
if (tlsEngineResult != null && tlsEngineResult.getStatus() == Status.BUFFER_UNDERFLOW) { if (tlsEngineResult != null && tlsEngineResult.getStatus() == Status.BUFFER_UNDERFLOW) {
status = TLSStatus.UNDERFLOW; status = TLSStatus.UNDERFLOW;
} else { } else {
if (tlsEngineResult != null && tlsEngineResult.getStatus() == Status.CLOSED) { if (tlsEngineResult != null && tlsEngineResult.getStatus() == Status.CLOSED) {
status = TLSStatus.CLOSED; status = TLSStatus.CLOSED;
} else { } else {
switch (tlsEngine.getHandshakeStatus()) { switch (tlsEngine.getHandshakeStatus()) {
case NEED_WRAP: case NEED_WRAP:
status = TLSStatus.NEED_WRITE; status = TLSStatus.NEED_WRITE;
break; break;
case NEED_UNWRAP: case NEED_UNWRAP:
status = TLSStatus.NEED_READ; status = TLSStatus.NEED_READ;
break; break;
default: default:
status = TLSStatus.OK; status = TLSStatus.OK;
break; break;
} }
} }
} }
return status; return status;
} }
private ByteBuffer resizeApplicationBuffer(ByteBuffer app) { private ByteBuffer resizeApplicationBuffer(ByteBuffer app) {
// TODO Creating new buffers and copying over old one may not scale and may even be a // TODO Creating new buffers and copying over old one may not scale and may even be a
// security risk. Consider using views. Thanks to Noah for the tip. // security risk. Consider using views. Thanks to Noah for the tip.
if (app.remaining() < appBuffSize) { if (app.remaining() < appBuffSize) {
ByteBuffer bb = ByteBuffer.allocate(app.capacity() + appBuffSize); ByteBuffer bb = ByteBuffer.allocate(app.capacity() + appBuffSize);
app.flip(); app.flip();
bb.put(app); bb.put(app);
return bb; return bb;
} else { } else {
return app; return app;
} }
} }
/* /*
* Do all the outstanding handshake tasks in the current Thread. * Do all the outstanding handshake tasks in the current Thread.
*/ */
private SSLEngineResult.HandshakeStatus doTasks() { private SSLEngineResult.HandshakeStatus doTasks() {
Runnable runnable; Runnable runnable;
/* /*
* We could run this in a separate thread, but do in the current for now. * We could run this in a separate thread, but do in the current for now.
*/ */
while ((runnable = tlsEngine.getDelegatedTask()) != null) { while ((runnable = tlsEngine.getDelegatedTask()) != null) {
runnable.run(); runnable.run();
} }
return tlsEngine.getHandshakeStatus(); return tlsEngine.getHandshakeStatus();
} }
/* /*
* Logging code * Logging code
*/ */
private boolean resultOnce = true; private boolean resultOnce = true;
private void log(String str, SSLEngineResult result) { private void log(String str, SSLEngineResult result) {
if (!logging) { if (!logging) {
return; return;
} }
if (resultOnce) { if (resultOnce) {
resultOnce = false; resultOnce = false;
Log.info("The format of the SSLEngineResult is: \n" Log.info("The format of the SSLEngineResult is: \n"
+ "\t\"getStatus() / getHandshakeStatus()\" +\n" + "\t\"getStatus() / getHandshakeStatus()\" +\n"
+ "\t\"bytesConsumed() / bytesProduced()\"\n"); + "\t\"bytesConsumed() / bytesProduced()\"\n");
} }
HandshakeStatus hsStatus = result.getHandshakeStatus(); HandshakeStatus hsStatus = result.getHandshakeStatus();
Log.info(str + result.getStatus() + "/" + hsStatus + ", " + result.bytesConsumed() + "/" Log.info(str + result.getStatus() + "/" + hsStatus + ", " + result.bytesConsumed() + "/"
+ result.bytesProduced() + " bytes"); + result.bytesProduced() + " bytes");
if (hsStatus == HandshakeStatus.FINISHED) { if (hsStatus == HandshakeStatus.FINISHED) {
Log.info("\t...ready for application data"); Log.info("\t...ready for application data");
} }
} }
protected SSLEngine getTlsEngine() { protected SSLEngine getTlsEngine() {
return tlsEngine; return tlsEngine;
} }
} }
...@@ -37,8 +37,11 @@ import java.security.cert.CertificateException; ...@@ -37,8 +37,11 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Comparator; import java.util.Comparator;
import org.jivesoftware.openfire.session.ConnectionSettings;
/** /**
* SSLSocketFactory that accepts any certificate chain and also accepts expired * SSLSocketFactory that accepts any certificate chain and also accepts expired
* certificates. * certificates.
...@@ -54,7 +57,7 @@ public class SimpleSSLSocketFactory extends SSLSocketFactory implements Comparat ...@@ -54,7 +57,7 @@ public class SimpleSSLSocketFactory extends SSLSocketFactory implements Comparat
public SimpleSSLSocketFactory() { public SimpleSSLSocketFactory() {
try { try {
String algorithm = JiveGlobals.getProperty("xmpp.socket.ssl.algorithm", "TLS"); String algorithm = JiveGlobals.getProperty( ConnectionSettings.Client.TLS_ALGORITHM, "TLS" );
SSLContext sslcontent = SSLContext.getInstance(algorithm); SSLContext sslcontent = SSLContext.getInstance(algorithm);
sslcontent.init(null, // KeyManager not required sslcontent.init(null, // KeyManager not required
new TrustManager[] { new DummyTrustManager() }, new TrustManager[] { new DummyTrustManager() },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment