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

OF-946: Centralize connection configuration.

This commit (which is compilable, but breaks some important
functionality - work in progess) aims to centralize the configuration
for connections. "Connections" are used in a broad sense here, and
includes socket-based (TLS and legacy-mode SSL) client connections,
BOSH-based client connections, component connections, connectionmanager
(multiplexer) connections, but also connections to the admin panel.
parent 123c96e5
......@@ -56,6 +56,15 @@
</filter>
</appender>
<appender name="all-out" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${openfireHome}/logs/all.log" />
<param name="MaxFileSize" value="1024KB"/>
<param name="MaxBackupIndex" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy.MM.dd HH:mm:ss} %-5p [%t]: %c - %m%n" />
</layout>
</appender>
<!-- OF-506: Jetty INFO messages are generally not useful. Ignore them by default. -->
<logger name="org.eclipse.jetty">
<level value="warn" />
......@@ -63,6 +72,7 @@
<root>
<level value="info" />
<appender-ref ref="all-out" />
<appender-ref ref="debug-out" />
<appender-ref ref="info-out" />
<appender-ref ref="warn-out" />
......
......@@ -114,6 +114,19 @@ if [ ! -x "$JAVACMD" ] ; then
exit 1
fi
for arguments in "$@"
do
case $arguments in
-debug)
JAVACMD="$JAVACMD -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
;;
*)
# unknown option
;;
esac
done
if [ -z "$LOCALCLASSPATH" ] ; then
LOCALCLASSPATH=$OPENFIRE_LIB/startup.jar
else
......
This diff is collapsed.
......@@ -26,6 +26,7 @@ import java.security.cert.Certificate;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.xmpp.packet.Packet;
/**
......@@ -354,7 +355,7 @@ public interface Connection extends Closeable {
* otherwise a {@link org.jivesoftware.openfire.net.ServerTrustManager} will be used.
* @param authentication policy to use for authenticating the remote peer.
* @throws Exception if an error occured while securing the connection.
* @deprecated Use {@link #startTLS(boolean, boolean, ClientAuth)} instead, with isPeerClient = (remoteServer == null)
* @deprecated Use {@link #startTLS(boolean)} instead.
*/
@Deprecated
void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception;
......@@ -364,22 +365,15 @@ public interface Connection extends Closeable {
* connection the server requesting the TLS negotiation will be the client and the other server
* will be the server during the TLS negotiation. Therefore, the server requesting the TLS
* negotiation must pass <code>true</code> in the <tt>clientMode</tt> parameter and the server
* receiving the TLS request must pass <code>false</code> in the <tt>clientMode</tt> parameter.
* Both servers should specify the xmpp domain of the other server in the <tt>remoteServer</tt>
* parameter.<p>
* receiving the TLS request must pass <code>false</code> in the <tt>clientMode</tt> parameter.<p>
*
* In the case of client-2-server the XMPP server must pass <code>false</code> in the
* <tt>clientMode</tt> parameter since it will behave as the server in the TLS negotiation. The
* <tt>remoteServer</tt> parameter will always be <tt>null</tt>.
* <tt>clientMode</tt> parameter since it will behave as the server in the TLS negotiation.
*
* @param clientMode boolean indicating if this entity is a client or a server in the TLS negotiation.
* @param isPeerClient indicates if the remote party is a client. When true a
* {@link org.jivesoftware.openfire.net.ClientTrustManager} will be used for verifying certificates
* otherwise a {@link org.jivesoftware.openfire.net.ServerTrustManager} will be used.
* @param authentication policy to use for authenticating the remote peer.
* @throws Exception if an error occured while securing the connection.
*/
void startTLS(boolean clientMode, boolean isPeerClient, ClientAuth authentication) throws Exception;
void startTLS(boolean clientMode) throws Exception;
/**
* Adds the compression filter to the connection but only filter incoming traffic. Do not filter
......@@ -396,6 +390,15 @@ public interface Connection extends Closeable {
*/
void startCompression();
/**
* Returns a representation of the desired state for this connection. Note that this is different from the current
* state of the connection. For example, TLS can be required by configuration, but while the connection has yet to
* be fully initialized, the current state might not be TLS-encrypted.
*
* @return The desired configuration for the connection (never null).
*/
ConnectionConfiguration getConfiguration();
/**
* Enumeration of possible compression policies required to interact with the server.
*/
......@@ -434,7 +437,14 @@ public interface Connection extends Closeable {
* TLS is not available. Entities that request a TLS negotiation will get a stream
* error and their connections will be closed.
*/
disabled
disabled,
/**
* A policy that requires connections to be encrypted immediately (as opposed to the
* 'required' policy, that allows for an initially unencrypted connection to become
* encrypted through StartTLS.
*/
legacyMode
}
/**
......
......@@ -48,15 +48,27 @@ public interface ConnectionManager {
* The default XMPP port for external components.
*/
final int DEFAULT_COMPONENT_PORT = 5275;
/**
* The XMPP port for external components using SSL traffic.
*/
final int DEFAULT_COMPONENT_SSL_PORT = 5276;
/**
* The default XMPP port for server2server communication.
*/
final int DEFAULT_SERVER_PORT = 5269;
/**
* The default XMPP port for connection multiplex.
*/
final int DEFAULT_MULTIPLEX_PORT = 5262;
/**
* The default XMPP port for connection multiplex.
*/
final int DEFAULT_MULTIPLEX_SSL_PORT = 5263;
/**
* Returns an array of the ports managed by this connection manager.
*
......@@ -76,7 +88,9 @@ public interface ConnectionManager {
* @param useBlockingMode true means that the server will use a thread per connection.
* @return the created socket reader.
* @throws java.io.IOException when there is an error creating the socket reader.
* @deprecated This is part of the legacy blocking IO implementation. It should no longer be used in favor of NIO.
*/
@Deprecated
public SocketReader createSocketReader(Socket socket, boolean isSecure, ServerPort serverPort,
boolean useBlockingMode) throws IOException;
......
......@@ -30,7 +30,9 @@ import java.util.List;
* regarding the port while hiding implementation details.
*
* @author Iain Shigeoka
* @Deprecated
*/
@Deprecated
public class ServerPort {
private int port;
......
......@@ -38,17 +38,17 @@ import org.jivesoftware.openfire.filetransfer.DefaultFileTransferManager;
import org.jivesoftware.openfire.filetransfer.FileTransferManager;
import org.jivesoftware.openfire.filetransfer.proxy.FileTransferProxy;
import org.jivesoftware.openfire.handler.*;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.keystore.IdentityStore;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.mediaproxy.MediaProxyService;
import org.jivesoftware.openfire.muc.MultiUserChatManager;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.net.ServerTrafficCounter;
import org.jivesoftware.openfire.pep.IQPEPHandler;
import org.jivesoftware.openfire.pubsub.PubSubModule;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.session.RemoteSessionLocator;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.openfire.spi.XMPPServerInfoImpl;
import org.jivesoftware.openfire.transport.TransportHandler;
import org.jivesoftware.openfire.update.UpdateManager;
......@@ -375,8 +375,8 @@ public class XMPPServer {
// Update certificates (if required)
try {
// Check if keystore already has certificates for current domain
final IdentityStoreConfig storeConfig = SSLConfig.getInstance().getIdentityStoreConfig( Purpose.SOCKET_C2S );
// Check if keystore (that out-of-the-box is a fallback for all keystores) already has certificates for current domain.
final IdentityStore storeConfig = CertificateStoreManager.getIdentityStore( ConnectionType.SOCKET_C2S );
storeConfig.ensureDomainCertificates( "DSA", "RSA" );
} catch (Exception e) {
logger.error("Error generating self-signed certificates", e);
......@@ -474,11 +474,10 @@ public class XMPPServer {
@SuppressWarnings("unchecked")
private void loadModules() {
File modulesXml = new File(JiveGlobals.getHomeDirectory(), "conf/modules.xml");
logger.info("Loading modules from " + modulesXml.getAbsolutePath());
SAXReader xmlReader = new SAXReader();
xmlReader.setEncoding("UTF-8");
File modulesXml = new File(JiveGlobals.getHomeDirectory(), "conf/modules.xml");
logger.info("Loading modules from " + modulesXml.getAbsolutePath());
SAXReader xmlReader = new SAXReader();
xmlReader.setEncoding("UTF-8");
try (FileReader in = new FileReader(modulesXml)) {
Document document = xmlReader.read(in);
Element root = document.getRootElement();
......
......@@ -69,6 +69,7 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.ConnectionManager;
import org.jivesoftware.openfire.IQRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.XMPPServerInfo;
......@@ -86,6 +87,8 @@ import org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.session.ComponentSession;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.AlreadyExistsException;
import org.jivesoftware.util.CertificateEventListener;
......@@ -778,12 +781,13 @@ public class ClearspaceManager extends BasicModule implements ExternalComponentM
private void updateClearspaceClientSettings() {
String xmppBoshSslPort = "0";
String xmppBoshPort = "0";
String xmppPort = String.valueOf(XMPPServer.getInstance().getConnectionManager().getClientListenerPort());
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
String xmppPort = String.valueOf( connectionManager.getConfiguration( ConnectionType.SOCKET_C2S, false ).getPort() );
if (JiveGlobals.getBooleanProperty(HttpBindManager.HTTP_BIND_ENABLED, HttpBindManager.HTTP_BIND_ENABLED_DEFAULT)) {
int boshSslPort = HttpBindManager.getInstance().getHttpBindSecurePort();
int boshPort = HttpBindManager.getInstance().getHttpBindUnsecurePort();
try {
if (HttpBindManager.getInstance().isHttpsBindActive() && LocalClientSession.getTLSPolicy() != org.jivesoftware.openfire.Connection.TLSPolicy.disabled) {
if (HttpBindManager.getInstance().isHttpsBindActive() && connectionManager.getConfiguration( ConnectionType.SOCKET_C2S, false ).getTlsPolicy() != org.jivesoftware.openfire.Connection.TLSPolicy.disabled) {
xmppBoshSslPort = String.valueOf(boshSslPort);
}
}
......
......@@ -35,8 +35,8 @@ import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -63,19 +63,19 @@ public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory {
private SSLContext createSSLContext(String host) {
try {
final SSLContext context = SSLConfig.getSSLContext( Purpose.ADMIN );
final SSLContext context = SSLContext.getInstance( "TLSv1" );
context.init(
null,
new TrustManager[] {
new ClearspaceX509TrustManager(
host,
manager.getProperties(),
SSLConfig.getTrustStore( Purpose.ADMIN ) )
CertificateStoreManager.getTrustStore( ConnectionType.ADMIN ).getStore() )
},
null);
return context;
} catch (Exception e) {
Log.error(e.getMessage(), e);
Log.error("An exception occurred while trying to create an SSL Context for host: '"+host+"'", e);
throw new HttpClientError(e.toString());
}
}
......
......@@ -47,11 +47,11 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreConfig;
import org.jivesoftware.openfire.keystore.TrustStoreConfig;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.keystore.IdentityStore;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
......@@ -141,19 +141,20 @@ public class AdminConsolePlugin implements Plugin {
// Create a connector for https traffic if it's enabled.
sslEnabled = false;
try {
final IdentityStoreConfig identityStoreConfig = SSLConfig.getInstance().getIdentityStoreConfig( Purpose.WEBADMIN );
if (adminSecurePort > 0 && identityStoreConfig.getStore().aliases().hasMoreElements() )
final IdentityStore identityStore = CertificateStoreManager.getIdentityStore( ConnectionType.WEBADMIN );
if (adminSecurePort > 0 && !identityStore.getAllCertificates().isEmpty() )
{
if ( !identityStoreConfig.containsDomainCertificate( "RSA" )) {
if ( !identityStore.containsDomainCertificate( "RSA" )) {
Log.warn("Admin console: Using RSA certificates but they are not valid for the hosted domain");
}
final SslContextFactory sslContextFactory = SSLConfig.getSslContextFactory( Purpose.WEBADMIN );
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
final ConnectionConfiguration configuration = connectionManager.getConfiguration( ConnectionType.WEBADMIN, true );
final SslContextFactory sslContextFactory = configuration.getSslContextFactory();
final ServerConnector httpsConnector;
if ("npn".equals(JiveGlobals.getXMLProperty("spdy.protocol", ""))) {
httpsConnector = new HTTPSPDYServerConnector(adminServer, sslContextFactory);
} else {
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSendServerVersion( false );
......
......@@ -61,12 +61,12 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.JMXManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreConfig;
import org.jivesoftware.openfire.keystore.TrustStoreConfig;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.keystore.IdentityStore;
import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
......@@ -251,16 +251,17 @@ public final class HttpBindManager {
private void createSSLConnector(int securePort, int bindThreads) {
httpsConnector = null;
try {
final IdentityStoreConfig identityStoreConfig = SSLConfig.getInstance().getIdentityStoreConfig( Purpose.BOSH_C2S );
final KeyStore keyStore = identityStoreConfig.getStore();
final IdentityStore identityStore = CertificateStoreManager.getIdentityStore( ConnectionType.BOSH_C2S );
if (securePort > 0 && identityStoreConfig.getStore().aliases().hasMoreElements() ) {
if ( !identityStoreConfig.containsDomainCertificate( "RSA" ) ) {
if (securePort > 0 && identityStore.getStore().aliases().hasMoreElements() ) {
if ( !identityStore.containsDomainCertificate( "RSA" ) ) {
Log.warn("HTTP binding: Using RSA certificates but they are not valid for " +
"the hosted domain");
}
final SslContextFactory sslContextFactory = SSLConfig.getSslContextFactory( Purpose.BOSH_C2S );
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
final ConnectionConfiguration configuration = connectionManager.getConfiguration( ConnectionType.BOSH_C2S, true );
final SslContextFactory sslContextFactory = configuration.getSslContextFactory();
final HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
......
......@@ -45,6 +45,7 @@ import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.VirtualConnection;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.TaskEngine;
......@@ -1118,6 +1119,7 @@ public class HttpSession extends LocalClientSession {
public static class HttpVirtualConnection extends VirtualConnection {
private InetAddress address;
private ConnectionConfiguration configuration;
public HttpVirtualConnection(InetAddress address) {
this.address = address;
......@@ -1158,6 +1160,11 @@ public class HttpSession extends LocalClientSession {
((HttpSession) session).deliver(text);
}
@Override
public ConnectionConfiguration getConfiguration() {
return session.getConnection().getConfiguration();
}
@Override
public Certificate[] getPeerCertificates() {
return ((HttpSession) session).getPeerCertificates();
......
package org.jivesoftware.openfire.keystore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.util.CertificateEventListener;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -24,8 +23,8 @@ import java.util.*;
*
* A subclass of this class exists for each of the two distinct types of key store.
* <ul>
* <li>one that is used to provide credentials, an <em>identity store</em>, in {@link IdentityStoreConfig}</li>
* <li>one that is used to verify credentials, a <em>trust store</em>, in {@link TrustStoreConfig}</li>
* <li>one that is used to provide credentials, an <em>identity store</em>, in {@link IdentityStore}</li>
* <li>one that is used to verify credentials, a <em>trust store</em>, in {@link TrustStore}</li>
* </ul>
*
* Note that in Java terminology, an identity store is commonly referred to as a 'key store', while the same name is
......@@ -34,9 +33,9 @@ import java.util.*;
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public abstract class CertificateStoreConfig
public abstract class CertificateStore
{
private static final Logger Log = LoggerFactory.getLogger( CertificateStoreConfig.class );
private static final Logger Log = LoggerFactory.getLogger( CertificateStore.class );
protected static final Provider PROVIDER = new BouncyCastleProvider();
......@@ -47,39 +46,41 @@ public abstract class CertificateStoreConfig
}
protected final KeyStore store;
protected final char[] password;
protected final String canonicalPath;
protected final CertificateStoreConfiguration configuration;
public CertificateStoreConfig( String path, String password, String type, boolean createIfAbsent ) throws CertificateStoreConfigException
public CertificateStore( CertificateStoreConfiguration configuration, boolean createIfAbsent ) throws CertificateStoreConfigException
{
if (configuration == null)
{
throw new IllegalArgumentException( "Argument 'configuration' cannot be null." );
}
this.configuration = configuration;
try
{
this.canonicalPath = Purpose.canonicalize( path );
final File file = new File( canonicalPath );
final File file = configuration.getFile();
if ( createIfAbsent && !file.exists() )
{
try ( final FileOutputStream os = new FileOutputStream( canonicalPath ) )
try ( final FileOutputStream os = new FileOutputStream( file.getPath() ) )
{
store = KeyStore.getInstance( type );
store.load( null, password.toCharArray() );
store.store( os, password.toCharArray() );
this.password = password.toCharArray();
store = KeyStore.getInstance( configuration.getType() );
store.load( null, configuration.getPassword() );
store.store( os, configuration.getPassword() );
}
}
else
{
try ( final FileInputStream is = new FileInputStream( canonicalPath ) )
try ( final FileInputStream is = new FileInputStream( file ) )
{
store = KeyStore.getInstance( type );
store.load( is, password.toCharArray() );
this.password = password.toCharArray();
store = KeyStore.getInstance( configuration.getType() );
store.load( is, configuration.getPassword() );
}
}
}
catch ( IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException ex )
{
throw new CertificateStoreConfigException( "Unable to load store of type '" + type + "' from location '" + path + "'", ex );
throw new CertificateStoreConfigException( "Unable to load store of type '" + configuration.getType() + "' from file '" + configuration.getFile() + "'", ex );
}
}
......@@ -89,13 +90,13 @@ public abstract class CertificateStoreConfig
*/
public void reload() throws CertificateStoreConfigException
{
try ( final FileInputStream is = new FileInputStream( canonicalPath ) )
try ( final FileInputStream is = new FileInputStream( configuration.getFile() ) )
{
store.load( is, password );
store.load( is, configuration.getPassword() );
}
catch ( IOException | NoSuchAlgorithmException | CertificateException ex )
{
throw new CertificateStoreConfigException( "Unable to reload store in location '" + canonicalPath + "'", ex );
throw new CertificateStoreConfigException( "Unable to reload store in '" + configuration.getFile() + "'", ex );
}
}
......@@ -105,13 +106,13 @@ public abstract class CertificateStoreConfig
*/
public void persist() throws CertificateStoreConfigException
{
try ( final FileOutputStream os = new FileOutputStream( canonicalPath ) )
try ( final FileOutputStream os = new FileOutputStream( configuration.getFile() ) )
{
store.store( os, password );
store.store( os, configuration.getPassword() );
}
catch ( NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException ex )
{
throw new CertificateStoreConfigException( "Unable to save changes to store in location '" + canonicalPath + "'", ex );
throw new CertificateStoreConfigException( "Unable to save changes to store in '" + configuration.getFile() + "'", ex );
}
}
......@@ -177,31 +178,13 @@ public abstract class CertificateStoreConfig
// TODO: Notify listeners that a new certificate has been removed.
}
public String getType()
{
return store.getType();
}
public KeyStore getStore()
{
return store;
}
public String getPassword()
{
return String.valueOf( password );
}
public String getCanonicalPath()
{
return canonicalPath;
}
public String getPath()
public CertificateStoreConfiguration getConfiguration()
{
final Path path = Paths.get( canonicalPath );
final Path home = Paths.get( JiveGlobals.getHomeDirectory() );
final Path corrected = path.startsWith( home ) ? home.relativize( path ) : path;
return corrected.toString();
return configuration;
}
}
package org.jivesoftware.openfire.keystore;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
/**
* Certificate stores are configured using a defined set of properties. This is a wrapper class for all of them.
*
* Instances of this class are immutable and safe for use by multiple concurrent threads.
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class CertificateStoreConfiguration
{
protected final String type;
protected final File file;
protected final char[] password;
/**
* Creates a new instance.
*
* @param type The store type (jks, jceks, pkcs12, etc). Cannot be null or an empty string.
* @param file The file-system based representation of the store (cannot be null).
* @param password the password used to check the integrity of the store, the password used to unlock the store, or null.
*/
public CertificateStoreConfiguration( String type, File file, char[] password )
{
if ( type == null || type.isEmpty() )
{
throw new IllegalArgumentException( "Argument 'type' cannot be null or an empty string." );
}
if ( file == null )
{
throw new IllegalArgumentException( "Argument 'file' cannot be null." );
}
this.type = type;
this.file = file;
this.password = password;
}
public String getType()
{
return type;
}
public File getFile()
{
return file;
}
public char[] getPassword()
{
return password;
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( !( o instanceof CertificateStoreConfiguration ) )
{
return false;
}
CertificateStoreConfiguration that = (CertificateStoreConfiguration) o;
if ( !type.equals( that.type ) )
{
return false;
}
if ( !file.equals( that.file ) )
{
return false;
}
return Arrays.equals( password, that.password );
}
@Override
public int hashCode()
{
int result = type.hashCode();
result = 31 * result + file.hashCode();
result = 31 * result + ( password != null ? Arrays.hashCode( password ) : 0 );
return result;
}
@Override
public String toString()
{
return "CertificateStoreConfiguration{" +
"type='" + type + '\'' +
", file=" + file +
", password hashcode=" + password.hashCode() + // java.lang.Array.hashCode inherits from Object. As it is a reference, it should be safe to log and useful enough to compare against other passwords.
'}';
}
}
......@@ -155,10 +155,10 @@ public class CertificateUtils
final Principal subject = certificate.getSubjectDN();
if ( byIssuer.put( issuer, certificate ) != null ) {
throw new CertificateException( "The provided input should not contain multiple certificates with identical issuerDN values." );
throw new CertificateException( "The provided input should not contain multiple certificates with identical issuerDN values. Offending value: " + issuer );
}
if ( bySubject.put( subject, certificate ) != null ) {
throw new CertificateException( "The provided input should not contain multiple certificates with identical subjectDN values." );
throw new CertificateException( "The provided input should not contain multiple certificates with identical subjectDN values. Offending value: " + subject );
}
}
......
package org.jivesoftware.openfire.keystore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.DNSUtil;
import org.jivesoftware.util.CertificateManager;
......@@ -37,31 +36,30 @@ import java.util.List;
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class IdentityStoreConfig extends CertificateStoreConfig
public class IdentityStore extends CertificateStore
{
private static final Logger Log = LoggerFactory.getLogger( IdentityStoreConfig.class );
private static final Logger Log = LoggerFactory.getLogger( IdentityStore.class );
protected final KeyManagerFactory keyFactory;
// protected final KeyManagerFactory keyFactory;
public IdentityStoreConfig( String path, String password, String type, boolean createIfAbsent ) throws CertificateStoreConfigException
public IdentityStore( CertificateStoreConfiguration configuration, boolean createIfAbsent ) throws CertificateStoreConfigException
{
super( path, password, type, createIfAbsent );
try
{
keyFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() );
keyFactory.init( store, password.toCharArray() );
}
catch ( UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException ex )
{
throw new CertificateStoreConfigException( "Unable to load store of type '" + type + "' from location '" + path + "'", ex );
}
super( configuration, createIfAbsent );
// try
// {
// keyFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() );
// keyFactory.init( store, configuration.getPassword() );
// }
// catch ( UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException ex )
// {
// throw new CertificateStoreConfigException( "Unable to load store of type '" + configuration.getType() + "' from location '" + configuration.getFile() + "'", ex );
// }
}
public KeyManager[] getKeyManagers()
{
return keyFactory.getKeyManagers();
}
// public KeyManager[] getKeyManagers()
// {
// return keyFactory.getKeyManagers();
// }
/**
* Creates a Certificate Signing Request based on the private key and certificate identified by the provided alias.
......@@ -97,7 +95,7 @@ public class IdentityStoreConfig extends CertificateStoreConfig
throw new CertificateStoreConfigException( "Cannot generate CSR for alias '"+ alias +"': there is no corresponding certificate in the store, or it is not an X509 certificate." );
}
final Key key = store.getKey( alias, password );
final Key key = store.getKey( alias, configuration.getPassword() );
if ( key == null || (!(key instanceof PrivateKey) ) )
{
throw new CertificateStoreConfigException( "Cannot generate CSR for alias '"+ alias +"': there is no corresponding key in the store, or it is not a private key." );
......@@ -165,14 +163,14 @@ public class IdentityStoreConfig extends CertificateStoreConfig
}
// All appears to be in order. Update the existing entry in the store.
store.setKeyEntry( alias, store.getKey( alias, password ), password, ordered.toArray( new X509Certificate[ ordered.size() ] ) );
store.setKeyEntry( alias, store.getKey( alias, configuration.getPassword() ), configuration.getPassword(), ordered.toArray( new X509Certificate[ ordered.size() ] ) );
}
catch ( RuntimeException | IOException | CertificateException | UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException e )
{
reload(); // reset state of the store.
throw new CertificateStoreConfigException( "Unable to install a singing reply into an identity store.", e );
}
// TODO notifiy listneers.
// TODO notifiy listeners.
}
protected boolean corresponds( String alias, List<X509Certificate> certificates ) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException
......@@ -181,7 +179,7 @@ public class IdentityStoreConfig extends CertificateStoreConfig
return false;
}
final Key key = store.getKey( alias, password );
final Key key = store.getKey( alias, configuration.getPassword() );
if ( key == null ) {
return false;
}
......@@ -266,7 +264,7 @@ public class IdentityStoreConfig extends CertificateStoreConfig
final PrivateKey privateKey = CertificateManager.parsePrivateKey( pemPrivateKey, passPhrase );
// All appears to be in order. Install in the store.
store.setKeyEntry( alias, privateKey, password, ordered.toArray( new X509Certificate[ ordered.size() ] ) );
store.setKeyEntry( alias, privateKey, configuration.getPassword(), ordered.toArray( new X509Certificate[ ordered.size() ] ) );
persist();
}
......@@ -298,8 +296,10 @@ public class IdentityStoreConfig extends CertificateStoreConfig
{
for ( String algorithm : algorithms )
{
Log.debug( "Verifying that a domain certificate ({} algorithm) is available in this store.", algorithm);
if ( !containsDomainCertificate( algorithm ) )
{
Log.debug( "Store does not contain a domain certificate ({} algorithm). A self-signed certificate will be generated.", algorithm);
addSelfSignedDomainCertificate( algorithm );
}
}
......@@ -371,19 +371,19 @@ public class IdentityStoreConfig extends CertificateStoreConfig
final String name = JiveGlobals.getProperty( "xmpp.domain" ).toLowerCase();
final String alias = name + "_" + algorithm.toLowerCase();
final String distinctName = "cn=" + name;
final String domain = "*." + name;
final int validityInDays = 60;
Log.info( "Generating a new private key and corresponding self-signed certificate for domain name '{}', using the {} algorithm (sign-algorithm: {} with a key size of {} bits). Certificate will be valid for {} days.", name, algorithm, signAlgorithm, keySize, validityInDays );
// Generate public and private keys
try
{
final KeyPair keyPair = generateKeyPair( algorithm.toUpperCase(), keySize );
// Create X509 certificate with keys and specified domain
final X509Certificate cert = CertificateManager.createX509V3Certificate( keyPair, validityInDays, distinctName, distinctName, domain, signAlgorithm );
final X509Certificate cert = CertificateManager.createX509V3Certificate( keyPair, validityInDays, distinctName, distinctName, name, signAlgorithm );
// Store new certificate and private key in the key store
store.setKeyEntry( alias, keyPair.getPrivate(), password, new X509Certificate[]{cert} );
store.setKeyEntry( alias, keyPair.getPrivate(), configuration.getPassword(), new X509Certificate[]{cert} );
// Persist the changes in the store to disk.
persist();
......
......@@ -16,7 +16,7 @@ import java.util.*;
*/
// TODO re-enable optional OCSP checking.
// TODO re-enable CRL checking.
public class OpenfireX509ExtendedTrustManager implements X509TrustManager
public class OpenfireX509TrustManager implements X509TrustManager
{
private static final Provider PROVIDER = new BouncyCastleProvider();
......@@ -43,7 +43,7 @@ public class OpenfireX509ExtendedTrustManager implements X509TrustManager
*/
protected final Set<X509Certificate> trustedIssuers;
public OpenfireX509ExtendedTrustManager( KeyStore trustStore, boolean acceptSelfSigned, boolean checkValidity ) throws NoSuchAlgorithmException, KeyStoreException
public OpenfireX509TrustManager( KeyStore trustStore, boolean acceptSelfSigned, boolean checkValidity ) throws NoSuchAlgorithmException, KeyStoreException
{
this.acceptSelfSigned = acceptSelfSigned;
this.checkValidity = checkValidity;
......
package org.jivesoftware.openfire.keystore;
import org.jivesoftware.util.JiveGlobals;
import java.io.File;
import java.io.IOException;
import java.util.Set;
/**
* Potential intended usages (for TLS connectivity).
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public enum Purpose
{
/**
* Socket-based server-to-server (XMPP federation) connectivity.
*/
SOCKET_S2S( "xmpp.socket.ssl.", null ),
/**
* Socket-based client connectivity.
*/
SOCKET_C2S( "xmpp.socket.ssl.client.", null ),
/**
* BOSH (HTTP-bind) based client connectivity.
*/
BOSH_C2S( "xmpp.bosh.ssl.client.", SOCKET_C2S),
/**
* Generic administrative services (eg: user providers).
*/
ADMIN( "admin.ssl.", SOCKET_S2S),
/**
* Openfire web-admin console.
*/
WEBADMIN( "admin.web.ssl.", ADMIN);
String prefix;
Purpose fallback;
Purpose( String prefix, Purpose fallback) {
this.prefix = prefix;
this.fallback = fallback;
}
public String getPrefix()
{
return prefix;
}
public Purpose getFallback()
{
return fallback;
}
public String getIdentityStoreType()
{
final String propertyName = prefix + "storeType";
final String defaultValue = "jks";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getIdentityStoreType() ).trim();
}
}
public String getTrustStoreType()
{
return getIdentityStoreType();
}
public String getIdentityStorePassword()
{
final String propertyName = prefix + "keypass";
final String defaultValue = "changeit";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getIdentityStorePassword() ).trim();
}
}
public String getTrustStorePassword()
{
final String propertyName = prefix + "trustpass";
final String defaultValue = "changeit";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getTrustStorePassword() ).trim();
}
}
public boolean acceptSelfSigned()
{
// TODO these are new properties! Deprecate (migrate?) all existing 'accept-selfsigned properties' (Eg: org.jivesoftware.openfire.session.ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS )
final String propertyName = prefix + "certificate.accept-selfsigned";
final boolean defaultValue = false;
if ( fallback == null )
{
return JiveGlobals.getBooleanProperty( propertyName, defaultValue );
}
else
{
return JiveGlobals.getBooleanProperty( propertyName, fallback.acceptSelfSigned() );
}
}
public boolean verifyValidity()
{
// TODO these are new properties! Deprecate (migrate?) all existing 'verify / verify-validity properties' (Eg: org.jivesoftware.openfire.session.ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY_VALIDITY )
final String propertyName = prefix + "certificate.verify.validity";
final boolean defaultValue = true;
if ( fallback == null )
{
return JiveGlobals.getBooleanProperty( propertyName, defaultValue );
}
else
{
return JiveGlobals.getBooleanProperty( propertyName, fallback.acceptSelfSigned() );
}
}
public String getIdentityStoreLocation() throws IOException
{
return canonicalize( getIdentityStoreLocationNonCanonicalized() );
}
public String getIdentityStoreLocationNonCanonicalized()
{
final String propertyName = prefix + "keystore";
final String defaultValue = "resources" + File.separator + "security" + File.separator + "keystore";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getIdentityStoreLocationNonCanonicalized() ).trim();
}
}
public String getTrustStoreLocation() throws IOException
{
return canonicalize( getTrustStoreLocationNonCanonicalized() );
}
public String getTrustStoreLocationNonCanonicalized()
{
final String propertyName = prefix + "truststore";
final String defaultValue = "resources" + File.separator + "security" + File.separator + "truststore";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getTrustStoreLocationNonCanonicalized() ).trim();
}
}
public String getProtocolsEnabled()
{
final String propertyName = prefix + "protocols.enabled";
final String defaultValue = "TLSv1,TLSv1.1,TLSv1.2";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getProtocolsEnabled() ).trim();
}
}
public String getProtocolsDisabled()
{
final String propertyName = prefix + "protocols.disabled";
final String defaultValue = "SSLv1,SSLv2,SSLv2Hello,SSLv3";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getProtocolsDisabled() ).trim();
}
}
public String getCipherSuitesEnabled()
{
final String propertyName = prefix + "ciphersuites.enabled";
final String defaultValue = "";
final String result;
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue );
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getCipherSuitesEnabled() );
}
}
public String getCipherSuitesDisabled()
{
final String propertyName = prefix + "ciphersuites.disabled";
final String defaultValue = "";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getCipherSuitesDisabled() ).trim();
}
}
public static String canonicalize( String path ) throws IOException
{
File file = new File( path );
if (!file.isAbsolute()) {
file = new File( JiveGlobals.getHomeDirectory() + File.separator + path );
}
return file.getCanonicalPath();
}
}
package org.jivesoftware.openfire.keystore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jivesoftware.openfire.net.ClientTrustManager;
import org.jivesoftware.openfire.net.ServerTrustManager;
import org.jivesoftware.util.CertificateManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.cert.*;
import java.util.*;
......@@ -26,65 +20,13 @@ import java.util.*;
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class TrustStoreConfig extends CertificateStoreConfig
public class TrustStore extends CertificateStore
{
private static final Logger Log = LoggerFactory.getLogger( TrustStoreConfig.class );
private static final Logger Log = LoggerFactory.getLogger( TrustStore.class );
private transient TrustManager[] trustManagers;
private boolean acceptSelfSigned;
private boolean checkValidity;
public TrustStoreConfig( String path, String password, String type, boolean createIfAbsent, boolean acceptSelfSigned, boolean checkValidity ) throws CertificateStoreConfigException
{
super( path, password, type, createIfAbsent );
this.acceptSelfSigned = acceptSelfSigned;
this.checkValidity = checkValidity;
}
public synchronized TrustManager[] getTrustManagers() throws KeyStoreException, NoSuchAlgorithmException
{
if ( trustManagers == null ) {
trustManagers = new TrustManager[] { new OpenfireX509ExtendedTrustManager( this.getStore(), acceptSelfSigned, checkValidity ) };
}
return trustManagers;
}
public synchronized void reconfigure( boolean acceptSelfSigned, boolean checkValidity ) throws CertificateStoreConfigException
{
boolean needsReload = false;
if ( this.acceptSelfSigned != acceptSelfSigned )
{
this.acceptSelfSigned = acceptSelfSigned;
needsReload = true;
}
if ( this.checkValidity != checkValidity )
{
this.checkValidity = checkValidity;
needsReload = true;
}
if ( needsReload ) {
reload();
}
}
public boolean isAcceptSelfSigned()
{
return acceptSelfSigned;
}
public boolean isCheckValidity()
{
return checkValidity;
}
@Override
public synchronized void reload() throws CertificateStoreConfigException
public TrustStore( CertificateStoreConfiguration configuration, boolean createIfAbsent ) throws CertificateStoreConfigException
{
super.reload();
trustManagers = null;
super( configuration, createIfAbsent );
}
/**
......
......@@ -24,6 +24,9 @@ import org.dom4j.Element;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.VirtualConnection;
import org.jivesoftware.openfire.session.ConnectionMultiplexerSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
......@@ -114,6 +117,14 @@ public class ClientSessionConnection extends VirtualConnection {
}
@Override
public ConnectionConfiguration getConfiguration()
{
// Here, a client-to-server configuration is mocked. It is likely not used, as actual connection handling takes
// place at the connection manager.
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
return connectionManager.getConfiguration( ConnectionType.SOCKET_C2S, false );
}
public byte[] getAddress() throws UnknownHostException {
if (hostAddress != null) {
return InetAddress.getByName(hostAddress).getAddress();
......
......@@ -35,7 +35,9 @@ import org.slf4j.LoggerFactory;
* Accepts new socket connections and uses a thread for each new connection.
*
* @author Gaston Dombiak
* @deprecated Old, pre NIO / MINA code. Should not be used as NIO offers better performance
*/
@Deprecated
class BlockingAcceptingMode extends SocketAcceptingMode {
private static final Logger Log = LoggerFactory.getLogger(BlockingAcceptingMode.class);
......
......@@ -45,8 +45,13 @@ import org.xmpp.packet.Presence;
*/
public class ClientStanzaHandler extends StanzaHandler {
public ClientStanzaHandler(PacketRouter router, Connection connection) {
super(router, connection);
}
@Deprecated
public ClientStanzaHandler(PacketRouter router, String serverName, Connection connection) {
super(router, serverName, connection);
super(router, connection);
}
/**
......@@ -110,12 +115,6 @@ public class ClientStanzaHandler extends StanzaHandler {
@Override
void startTLS() throws Exception {
Connection.ClientAuth policy;
try {
policy = Connection.ClientAuth.valueOf(JiveGlobals.getProperty(ConnectionSettings.Client.AUTH_PER_CLIENTCERT_POLICY, "disabled"));
} catch (IllegalArgumentException e) {
policy = Connection.ClientAuth.disabled;
}
connection.startTLS(false, true, policy);
connection.startTLS(false);
}
}
......@@ -22,6 +22,7 @@ package org.jivesoftware.openfire.net;
import org.dom4j.Element;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.component.InternalComponentManager;
import org.jivesoftware.openfire.session.ComponentSession;
......@@ -51,8 +52,13 @@ public class ComponentStanzaHandler extends StanzaHandler {
private static final Logger Log = LoggerFactory.getLogger(ComponentStanzaHandler.class);
public ComponentStanzaHandler(PacketRouter router, Connection connection) {
super(router, connection);
}
@Deprecated
public ComponentStanzaHandler(PacketRouter router, String serverName, Connection connection) {
super(router, serverName, connection);
super(router, connection);
}
@Override
......@@ -98,7 +104,7 @@ public class ComponentStanzaHandler extends StanzaHandler {
try {
// Get the requested subdomain
String subdomain = extraDomain;
int index = extraDomain.indexOf(serverName);
int index = extraDomain.indexOf( XMPPServer.getInstance().getServerInfo().getXMPPDomain() );
if (index > -1) {
subdomain = extraDomain.substring(0, index -1);
}
......@@ -186,7 +192,7 @@ public class ComponentStanzaHandler extends StanzaHandler {
@Override
void startTLS() throws Exception {
connection.startTLS(false, false, Connection.ClientAuth.disabled);
connection.startTLS(false);
}
@Override
......
......@@ -46,6 +46,11 @@ public class MultiplexerStanzaHandler extends StanzaHandler {
*/
private MultiplexerPacketHandler packetHandler;
public MultiplexerStanzaHandler(PacketRouter router, Connection connection) {
super(router, connection);
}
@Deprecated
public MultiplexerStanzaHandler(PacketRouter router, String serverName, Connection connection) {
super(router, serverName, connection);
}
......@@ -151,6 +156,6 @@ public class MultiplexerStanzaHandler extends StanzaHandler {
@Override
void startTLS() throws Exception {
connection.startTLS(false, false, Connection.ClientAuth.disabled);
connection.startTLS(false);
}
}
......@@ -49,7 +49,7 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.AuthorizationManager;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.ConnectionSettings;
......@@ -58,6 +58,7 @@ import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.session.LocalIncomingServerSession;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.StringUtils;
......@@ -88,7 +89,6 @@ public class SASLAuthentication {
// plus an extra regex alternative to catch a single equals sign ('=', see RFC 6120 6.4.2)
private static final Pattern BASE64_ENCODED = Pattern.compile("^(=|([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==))$");
private static final String SASL_NAMESPACE = "xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"";
private static Map<String, ElementType> typeMap = new TreeMap<>();
......@@ -195,8 +195,8 @@ public class SASLAuthentication {
// Server connections don't follow the same rules as clients
if (session.isSecure()) {
LocalIncomingServerSession svr = (LocalIncomingServerSession)session;
final KeyStore keyStore = SSLConfig.getIdentityStore( Purpose.SOCKET_S2S );
final KeyStore trustStore = SSLConfig.getTrustStore( Purpose.SOCKET_S2S );
final KeyStore keyStore = svr.getConnection().getConfiguration().getIdentityStore().getStore();
final KeyStore trustStore = svr.getConnection().getConfiguration().getTrustStore().getStore();
final X509Certificate trusted = CertificateManager.getEndEntityCertificate( svr.getConnection().getPeerCertificates(), keyStore, trustStore );
boolean haveTrustedCertificate = trusted != null;
......@@ -574,8 +574,9 @@ public class SASLAuthentication {
return Status.failed;
}
final KeyStore keyStore = SSLConfig.getIdentityStore( Purpose.SOCKET_C2S );
final KeyStore trustStore = SSLConfig.getTrustStore( Purpose.SOCKET_C2S );
final KeyStore keyStore = connection.getConfiguration().getIdentityStore().getStore();
final KeyStore trustStore = connection.getConfiguration().getTrustStore().getStore();
final X509Certificate trusted = CertificateManager.getEndEntityCertificate( connection.getPeerCertificates(), keyStore, trustStore );
if (trusted == null) {
......@@ -655,9 +656,9 @@ public class SASLAuthentication {
}
public static boolean verifyCertificates(Certificate[] chain, String hostname, boolean isS2S) {
final Purpose purpose = isS2S ? Purpose.SOCKET_S2S : Purpose.SOCKET_C2S;
final KeyStore keyStore = SSLConfig.getIdentityStore( purpose );
final KeyStore trustStore = SSLConfig.getTrustStore( purpose );
final ConnectionType connectionType = isS2S ? ConnectionType.SOCKET_S2S : ConnectionType.SOCKET_C2S;
final KeyStore keyStore = CertificateStoreManager.getIdentityStore( connectionType ).getStore();
final KeyStore trustStore = CertificateStoreManager.getTrustStore( connectionType ).getStore();
final X509Certificate trusted = CertificateManager.getEndEntityCertificate( chain, keyStore, trustStore );
if (trusted != null) {
return verifyCertificate(trusted, hostname);
......
This diff is collapsed.
......@@ -55,8 +55,13 @@ public class ServerStanzaHandler extends StanzaHandler {
private static final Logger Log = LoggerFactory.getLogger(ServerStanzaHandler.class);
public ServerStanzaHandler(PacketRouter router, Connection connection) {
super(router, connection);
}
@Deprecated
public ServerStanzaHandler(PacketRouter router, String serverName, Connection connection) {
super(router, serverName, connection);
super(router, connection);
}
@Override
......@@ -110,7 +115,8 @@ public class ServerStanzaHandler extends StanzaHandler {
boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
!JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false);
connection.startTLS(false, false, needed ? Connection.ClientAuth.needed : Connection.ClientAuth.wanted);
//needed ? Connection.ClientAuth.needed : Connection.ClientAuth.wanted
connection.startTLS(false);
}
@Override
protected void processIQ(IQ packet) throws UnauthorizedException {
......
......@@ -35,7 +35,9 @@ import java.net.InetAddress;
* changes to the system property.
*
* @author Gaston Dombiak
* @deprecated Old, pre NIO / MINA code. Should not be used as NIO offers better performance
*/
@Deprecated
public class SocketAcceptThread extends Thread {
/**
......
......@@ -30,7 +30,9 @@ import java.net.ServerSocket;
* Abstract class for {@link BlockingAcceptingMode}.
*
* @author Gaston Dombiak
* @deprecated Old, pre NIO / MINA code. Should not be used as NIO offers better performance
*/
@Deprecated
abstract class SocketAcceptingMode {
/**
......
......@@ -39,14 +39,14 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLPeerUnverifiedException;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.ConnectionCloseListener;
import org.jivesoftware.openfire.PacketDeliverer;
import org.jivesoftware.openfire.PacketException;
import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.session.IncomingServerSession;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.slf4j.Logger;
......@@ -62,6 +62,7 @@ import com.jcraft.jzlib.ZOutputStream;
* client and server.
*
* @author Iain Shigeoka
* @deprecated Old, pre NIO / MINA code. Should not be used as NIO offers better performance. Currently only in use for s2s.
*/
public class SocketConnection implements Connection {
......@@ -168,13 +169,13 @@ public class SocketConnection implements Connection {
@Deprecated
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
final boolean isPeerClient = ( remoteServer == null );
startTLS( clientMode, isPeerClient, authentication );
startTLS( clientMode );
}
public void startTLS(boolean clientMode, boolean isPeerClient, ClientAuth authentication) throws IOException {
public void startTLS(boolean clientMode) throws IOException {
if (!secure) {
secure = true;
// Prepare for TLS
final ClientAuth clientAuth;
if (session instanceof IncomingServerSession)
......@@ -185,7 +186,7 @@ public class SocketConnection implements Connection {
{
clientAuth = ClientAuth.wanted;
}
tlsStreamHandler = new TLSStreamHandler(socket, clientMode, isPeerClient, clientAuth);
tlsStreamHandler = new TLSStreamHandler(socket, getConfiguration(), clientMode);
if (!clientMode) {
// Indicate the client that the server is ready to negotiate TLS
deliverRawText("<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
......@@ -193,7 +194,7 @@ public class SocketConnection implements Connection {
// Start handshake
tlsStreamHandler.start();
// Use new wrapped writers
writer = new BufferedWriter(new OutputStreamWriter(tlsStreamHandler.getOutputStream(), StandardCharsets.UTF_8));
writer = new BufferedWriter(new OutputStreamWriter(tlsStreamHandler.getOutputStream(), CHARSET));
xmlSerializer = new XMLSocketWriter(writer, this);
}
}
......@@ -230,6 +231,15 @@ public class SocketConnection implements Connection {
}
@Override
public ConnectionConfiguration getConfiguration()
{
// This is an ugly hack to get backwards compatibility with the pre-MINA era. As this implementation is being
// removed (it is marked as deprecated - at the time of writing, it is only used for S2S). The ugly hack: assume
// S2S:
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
return connectionManager.getConfiguration( ConnectionType.SOCKET_S2S, false );
}
public boolean validate() {
if (isClosed()) {
return false;
......@@ -582,7 +592,7 @@ public class SocketConnection implements Connection {
private void release() {
writeStarted = -1;
instances.remove(this);
}
}
private void closeConnection() {
release();
......
......@@ -82,7 +82,7 @@ abstract class SocketReadingMode {
// Client requested to secure the connection using TLS. Negotiate TLS.
try {
// This code is only used for s2s
socketReader.connection.startTLS(false, false, Connection.ClientAuth.disabled);
socketReader.connection.startTLS(false);
}
catch (IOException e) {
Log.error("Error while negotiating TLS: " + socketReader.connection, e);
......
......@@ -78,10 +78,6 @@ public abstract class StanzaHandler {
* Session associated with the socket reader.
*/
protected LocalSession session;
/**
* Server name for which we are attending clients.
*/
protected String serverName;
/**
* Router used to route incoming packets to the correct channels.
......@@ -92,11 +88,15 @@ public abstract class StanzaHandler {
* Creates a dedicated reader for a socket.
*
* @param router the router for sending packets that were read.
* @param serverName the name of the server this socket is working for.
* @param connection the connection being read.
*/
public StanzaHandler(PacketRouter router, Connection connection) {
this.router = router;
this.connection = connection;
}
@Deprecated
public StanzaHandler(PacketRouter router, String serverName, Connection connection) {
this.serverName = serverName;
this.router = router;
this.connection = connection;
}
......@@ -576,7 +576,7 @@ public abstract class StanzaHandler {
sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"");
sb.append(getNamespace());
sb.append("\" from=\"");
sb.append(serverName);
sb.append(XMPPServer.getInstance().getServerInfo().getXMPPDomain());
sb.append("\" id=\"");
sb.append(session.getStreamID());
sb.append("\" xml:lang=\"");
......@@ -617,6 +617,8 @@ public abstract class StanzaHandler {
eventType = xpp.next();
}
final String serverName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
// Check that the TO attribute of the stream header matches the server name or a valid
// subdomain. If the value of the 'to' attribute is not valid then return a host-unknown
// error and close the underlying connection.
......@@ -676,7 +678,7 @@ public abstract class StanzaHandler {
// have a TO attribute
return false;
}
if (serverName.equals(host)) {
if (XMPPServer.getInstance().getServerInfo().getXMPPDomain().equals( host )) {
// requested host matched the server name
return false;
}
......
......@@ -22,6 +22,7 @@ package org.jivesoftware.openfire.net;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveGlobals;
import javax.net.ssl.SSLEngine;
......@@ -88,7 +89,7 @@ public class TLSStreamHandler {
private static ByteBuffer hsBB = ByteBuffer.allocate(0);
/**
* @deprecated Use the other constructor. There's no functional change.
* @deprecated Use the other constructor.
*/
@Deprecated
public TLSStreamHandler(Connection connection, Socket socket, boolean clientMode, String remoteServer,
......@@ -96,9 +97,8 @@ public class TLSStreamHandler {
{
this(
socket,
clientMode,
remoteServer==null,
needClientAuth?Connection.ClientAuth.needed: Connection.ClientAuth.wanted
connection.getConfiguration(),
clientMode
);
}
......@@ -110,12 +110,10 @@ public class TLSStreamHandler {
*
* @param socket the plain socket connection to secure
* @param clientMode boolean indicating if this entity is a client or a server.
* @param isPeerClient indicates if the remote party is a client (or server).
* @param clientAuth indicates if client should authenticate during the TLS negotiation.
* @throws java.io.IOException
*/
public TLSStreamHandler(Socket socket, boolean clientMode, boolean isPeerClient, Connection.ClientAuth clientAuth) throws IOException {
wrapper = new TLSWrapper(clientMode, clientAuth, isPeerClient);
public TLSStreamHandler(Socket socket, ConnectionConfiguration configuration, boolean clientMode) throws IOException {
wrapper = new TLSWrapper(configuration, clientMode);
tlsEngine = wrapper.getTlsEngine();
reader = new TLSStreamReader(wrapper, socket);
writer = new TLSStreamWriter(wrapper, socket);
......@@ -148,7 +146,7 @@ public class TLSStreamHandler {
initialHSStatus = HandshakeStatus.NEED_WRAP;
tlsEngine.beginHandshake();
}
else if (clientAuth == Connection.ClientAuth.needed) {
else if (configuration.getClientAuth() == Connection.ClientAuth.needed) {
// Only REQUIRE client authentication if we are fully verifying certificates
if (JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
......
......@@ -31,7 +31,8 @@ import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -59,31 +60,29 @@ public class TLSWrapper {
private int appBuffSize;
/**
* @deprecated Use the other constructor. There's no functional change.
* @deprecated Use the other constructor.
*/
@Deprecated
public TLSWrapper(Connection connection, boolean clientMode, boolean needClientAuth, String remoteServer)
{
this(
clientMode,
needClientAuth?Connection.ClientAuth.needed:Connection.ClientAuth.wanted,
remoteServer == null
connection.getConfiguration(),
clientMode
);
}
public TLSWrapper(boolean clientMode, Connection.ClientAuth clientAuth, boolean isPeerClient) {
public TLSWrapper(ConnectionConfiguration configuration, boolean clientMode ) {
try
{
final SSLEngine sslEngine;
if ( clientMode )
{
sslEngine = SSLConfig.getClientModeSSLEngine( Purpose.SOCKET_S2S );
sslEngine = configuration.createClientModeSSLEngine();
}
else
{
final Purpose purpose = isPeerClient ? Purpose.SOCKET_C2S : Purpose.SOCKET_S2S;
sslEngine = SSLConfig.getServerModeSSLEngine( purpose, clientAuth );
sslEngine = configuration.createServerModeSSLEngine();
}
final SSLSession sslSession = sslEngine.getSession();
......@@ -91,7 +90,7 @@ public class TLSWrapper {
netBuffSize = sslSession.getPacketBufferSize();
appBuffSize = sslSession.getApplicationBufferSize();
}
catch ( NoSuchAlgorithmException | KeyManagementException | KeyStoreException ex )
catch ( NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException ex )
{
Log.error("TLSHandler startup problem. SSLContext initialisation failed.", ex );
}
......
......@@ -30,6 +30,7 @@ import org.jivesoftware.openfire.ConnectionCloseListener;
import org.jivesoftware.openfire.PacketDeliverer;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.LocaleUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -154,12 +155,15 @@ public abstract class VirtualConnection implements Connection {
return null;
}
@Deprecated
@Override
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
//Ignore
}
@Override
public void startTLS(boolean clientMode) throws Exception {
//Ignore
}
public void addCompression() {
//Ignore
......
......@@ -27,6 +27,7 @@ import org.jivesoftware.openfire.handler.IQPingHandler;
import org.jivesoftware.openfire.net.ClientStanzaHandler;
import org.jivesoftware.openfire.net.StanzaHandler;
import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -44,18 +45,18 @@ public class ClientConnectionHandler extends ConnectionHandler {
private static final Logger Log = LoggerFactory.getLogger(ClientConnectionHandler.class);
public ClientConnectionHandler(String serverName) {
super(serverName);
public ClientConnectionHandler(ConnectionConfiguration configuration) {
super(configuration);
}
@Override
NIOConnection createNIOConnection(IoSession session) {
return new NIOConnection(session, new OfflinePacketDeliverer());
return new NIOConnection(session, new OfflinePacketDeliverer(), configuration );
}
@Override
StanzaHandler createStanzaHandler(NIOConnection connection) {
return new ClientStanzaHandler(XMPPServer.getInstance().getPacketRouter(), serverName, connection);
return new ClientStanzaHandler(XMPPServer.getInstance().getPacketRouter(), connection);
}
@Override
......@@ -97,7 +98,7 @@ public class ClientConnectionHandler extends ConnectionHandler {
final IQ pingRequest = new IQ(Type.get);
pingRequest.setChildElement("ping",
IQPingHandler.NAMESPACE);
pingRequest.setFrom(serverName);
pingRequest.setFrom( XMPPServer.getInstance().getServerInfo().getXMPPDomain() );
pingRequest.setTo(entity);
// Get the connection for this session
......
......@@ -23,6 +23,7 @@ import org.apache.mina.core.session.IoSession;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.ComponentStanzaHandler;
import org.jivesoftware.openfire.net.StanzaHandler;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveGlobals;
/**
......@@ -32,18 +33,19 @@ import org.jivesoftware.util.JiveGlobals;
* @author Gaston Dombiak
*/
public class ComponentConnectionHandler extends ConnectionHandler {
public ComponentConnectionHandler(String serverName) {
super(serverName);
public ComponentConnectionHandler(ConnectionConfiguration configuration) {
super(configuration);
}
@Override
NIOConnection createNIOConnection(IoSession session) {
return new NIOConnection(session, XMPPServer.getInstance().getPacketDeliverer());
return new NIOConnection(session, XMPPServer.getInstance().getPacketDeliverer(), configuration );
}
@Override
StanzaHandler createStanzaHandler(NIOConnection connection) {
return new ComponentStanzaHandler(XMPPServer.getInstance().getPacketRouter(), serverName, connection);
return new ComponentStanzaHandler(XMPPServer.getInstance().getPacketRouter(), connection);
}
@Override
......
......@@ -24,9 +24,11 @@ import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.ServerTrafficCounter;
import org.jivesoftware.openfire.net.StanzaHandler;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParserException;
......@@ -49,7 +51,6 @@ public abstract class ConnectionHandler extends IoHandlerAdapter {
protected static final String HANDLER = "HANDLER";
protected static final String CONNECTION = "CONNECTION";
protected String serverName;
private static final ThreadLocal<XMPPPacketReader> PARSER_CACHE = new ThreadLocal<XMPPPacketReader>()
{
@Override
......@@ -75,8 +76,13 @@ public abstract class ConnectionHandler extends IoHandlerAdapter {
}
}
protected ConnectionHandler(String serverName) {
this.serverName = serverName;
/**
* The configuration for new connections.
*/
protected final ConnectionConfiguration configuration;
protected ConnectionHandler( ConnectionConfiguration configuration ) {
this.configuration = configuration;
}
@Override
......
......@@ -20,6 +20,7 @@
package org.jivesoftware.openfire.nio;
import org.apache.mina.core.session.IoSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.multiplex.MultiplexerPacketDeliverer;
......@@ -34,18 +35,18 @@ import org.jivesoftware.openfire.net.StanzaHandler;
*/
public class MultiplexerConnectionHandler extends ConnectionHandler {
public MultiplexerConnectionHandler(String serverName) {
super(serverName);
public MultiplexerConnectionHandler(ConnectionConfiguration configuration) {
super(configuration);
}
@Override
NIOConnection createNIOConnection(IoSession session) {
return new NIOConnection(session, new MultiplexerPacketDeliverer());
return new NIOConnection(session, new MultiplexerPacketDeliverer(), configuration );
}
@Override
StanzaHandler createStanzaHandler(NIOConnection connection) {
return new MultiplexerStanzaHandler(XMPPServer.getInstance().getPacketRouter(), serverName, connection);
return new MultiplexerStanzaHandler(XMPPServer.getInstance().getPacketRouter(), connection);
}
@Override
......
......@@ -50,6 +50,8 @@ import org.jivesoftware.openfire.keystore.*;
import org.jivesoftware.openfire.net.*;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -64,6 +66,7 @@ import org.xmpp.packet.Packet;
public class NIOConnection implements Connection {
private static final Logger Log = LoggerFactory.getLogger(NIOConnection.class);
private ConnectionConfiguration configuration;
public enum State { RUNNING, CLOSING, CLOSED }
......@@ -87,7 +90,6 @@ public class NIOConnection implements Connection {
private int minorVersion = 0;
private String language = null;
// TODO Uso el #checkHealth????
/**
* TLS policy currently in use for this connection.
*/
......@@ -119,9 +121,10 @@ public class NIOConnection implements Connection {
*/
private final ReentrantLock ioSessionLock = new ReentrantLock(true);
public NIOConnection(IoSession session, PacketDeliverer packetDeliverer) {
public NIOConnection( IoSession session, PacketDeliverer packetDeliverer, ConnectionConfiguration configuration ) {
this.ioSession = session;
this.backupDeliverer = packetDeliverer;
this.configuration = configuration;
state = State.RUNNING;
}
......@@ -366,20 +369,19 @@ public class NIOConnection implements Connection {
@Deprecated
@Override
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
final boolean isPeerClient = ( remoteServer == null );
startTLS( clientMode, isPeerClient, authentication );
startTLS( clientMode );
}
public void startTLS(boolean clientMode, boolean isPeerClient, ClientAuth authentication) throws Exception {
public void startTLS(boolean clientMode) throws Exception {
final SslFilter filter;
if ( clientMode ) {
filter = SSLConfig.getClientModeSslFilter( Purpose.SOCKET_S2S );
if ( clientMode )
{
filter = configuration.createClientModeSslFilter();
}
else
{
final Purpose purpose = isPeerClient ? Purpose.SOCKET_C2S : Purpose.SOCKET_S2S;
filter = SSLConfig.getServerModeSslFilter( purpose, authentication );
filter = configuration.createServerModeSslFilter();
}
ioSession.getFilterChain().addBefore(EXECUTOR_FILTER_NAME, TLS_FILTER_NAME, filter);
......@@ -408,6 +410,11 @@ public class NIOConnection implements Connection {
}
@Override
public ConnectionConfiguration getConfiguration()
{
return configuration;
}
public boolean isFlashClient() {
return flashClient;
}
......
package org.jivesoftware.openfire.nio;
import org.apache.mina.core.session.IoSession;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.net.ServerStanzaHandler;
import org.jivesoftware.openfire.net.StanzaHandler;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.util.JiveGlobals;
/**
* ConnectionHandler that knows which subclass of {@link StanzaHandler} should be created and how to build and configure
* a {@link NIOConnection}.
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
public class ServerConnectionHandler extends ConnectionHandler
{
public ServerConnectionHandler( ConnectionConfiguration configuration )
{
super( configuration );
}
@Override
NIOConnection createNIOConnection( IoSession session )
{
return new NIOConnection( session, XMPPServer.getInstance().getPacketDeliverer(), configuration );
}
@Override
StanzaHandler createStanzaHandler( NIOConnection connection )
{
return new ServerStanzaHandler( XMPPServer.getInstance().getPacketRouter(), connection );
}
@Override
int getMaxIdleTime()
{
return JiveGlobals.getIntProperty( "xmpp.server.idle", 6 * 60 * 1000 ) / 1000;
}
}
......@@ -27,9 +27,6 @@ public final class ConnectionSettings {
public static final String MAX_THREADS_SSL = "xmpp.client_ssl.processing.threads";
public static final String MAX_READ_BUFFER_SSL = "xmpp.client_ssl.maxReadBufferSize";
public static final String TLS_ALGORITHM = "xmpp.socket.ssl.algorithm";
private Client() {
}
}
public static final class Server {
......@@ -43,7 +40,14 @@ public final class ConnectionSettings {
public static final String QUEUE_SIZE = "xmpp.server.outgoing.queue";
public static final String DIALBACK_ENABLED = "xmpp.server.dialback.enabled";
public static final String TLS_POLICY = "xmpp.server.tls.policy";
/**
* @deprecated Replaced by #TLS_POLICY
*/
@Deprecated
public static final String TLS_ENABLED = "xmpp.server.tls.enabled";
public static final String TLS_ACCEPT_SELFSIGNED_CERTS = "xmpp.server.certificate.accept-selfsigned";
public static final String TLS_CERTIFICATE_VERIFY = "xmpp.server.certificate.verify";
public static final String TLS_CERTIFICATE_VERIFY_VALIDITY = "xmpp.server.certificate.verify.validity";
......@@ -53,9 +57,7 @@ public final class ConnectionSettings {
public static final String COMPRESSION_SETTINGS = "xmpp.server.compression.policy";
public static final String PERMISSION_SETTINGS = "xmpp.server.permission";
private Server() {
}
public static final String AUTH_PER_CLIENTCERT_POLICY = "xmpp.server.cert.policy";
}
public static final class Multiplex {
......@@ -65,13 +67,21 @@ public final class ConnectionSettings {
public static final String TLS_POLICY = "xmpp.multiplex.tls.policy";
public static final String COMPRESSION_SETTINGS = "xmpp.multiplex.compression.policy";
private Multiplex() {
}
public static final String OLD_SSLPORT = "xmpp.multiplex.ssl.port";
public static final String ENABLE_OLD_SSLPORT = "xmpp.multiplex.ssl.active";
public static final String MAX_THREADS ="xmpp.multiplex.processing.threads";
public static final String MAX_THREADS_SSL = "xmpp.multiplex.ssl.processing.threads";
public static final String AUTH_PER_CLIENTCERT_POLICY = "xmpp.multiplex.cert.policy" ;
}
public static final class Component {
public static final String SOCKET_ACTIVE = "xmpp.component.socket.active";
public static final String PORT = "xmpp.component.socket.port";
public static final String OLD_SSLPORT = "xmpp.component.ssl.port";
public static final String ENABLE_OLD_SSLPORT = "xmpp.component.ssl.active";
public static final String MAX_THREADS = "xmpp.component.processing.threads";
public static final String MAX_THREADS_SSL = "xmpp.component.ssl.processing.threads";
public static final String AUTH_PER_CLIENTCERT_POLICY = "xmpp.component.cert.policy";
public static final String TLS_POLICY = "xmpp.component.tls.policy";
}
}
......@@ -34,9 +34,7 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.cluster.ClusterManager;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.privacy.PrivacyList;
import org.jivesoftware.openfire.privacy.PrivacyListManager;
......@@ -256,12 +254,12 @@ public class LocalClientSession extends LocalSession implements ClientSession {
if (!connection.isSecure()) {
boolean hasCertificates = false;
try {
hasCertificates = SSLConfig.getIdentityStore( Purpose.SOCKET_C2S ).size() > 0;
hasCertificates = connection.getConfiguration().getIdentityStore().getAllCertificates().size() > 0;
}
catch (Exception e) {
Log.error(e.getMessage(), e);
}
Connection.TLSPolicy tlsPolicy = getTLSPolicy();
Connection.TLSPolicy tlsPolicy = connection.getConfiguration().getTlsPolicy();
if (Connection.TLSPolicy.required == tlsPolicy && !hasCertificates) {
Log.error("Client session rejected. TLS is required but no certificates " +
"were created.");
......@@ -412,46 +410,13 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
}
/**
* Returns whether TLS is mandatory, optional or is disabled for clients. When TLS is
* mandatory clients are required to secure their connections or otherwise their connections
* will be closed. On the other hand, when TLS is disabled clients are not allowed to secure
* their connections using TLS. Their connections will be closed if they try to secure the
* connection. in this last case.
*
* @return whether TLS is mandatory, optional or is disabled.
*/
public static SocketConnection.TLSPolicy getTLSPolicy() {
// Set the TLS policy stored as a system property
String policyName = JiveGlobals.getProperty(ConnectionSettings.Client.TLS_POLICY, Connection.TLSPolicy.optional.toString());
SocketConnection.TLSPolicy tlsPolicy;
try {
tlsPolicy = Connection.TLSPolicy.valueOf(policyName);
} catch (IllegalArgumentException e) {
Log.error("Error parsing xmpp.client.tls.policy: " + policyName, e);
tlsPolicy = Connection.TLSPolicy.optional;
}
return tlsPolicy;
}
/**
* Sets whether TLS is mandatory, optional or is disabled for clients. When TLS is
* mandatory clients are required to secure their connections or otherwise their connections
* will be closed. On the other hand, when TLS is disabled clients are not allowed to secure
* their connections using TLS. Their connections will be closed if they try to secure the
* connection. in this last case.
*
* @param policy whether TLS is mandatory, optional or is disabled.
*/
public static void setTLSPolicy(SocketConnection.TLSPolicy policy) {
JiveGlobals.setProperty(ConnectionSettings.Client.TLS_POLICY, policy.toString());
}
/**
* Returns whether compression is optional or is disabled for clients.
*
* @return whether compression is optional or is disabled.
*/
// TODO Move this to ConnectionConfiguration.
public static SocketConnection.CompressionPolicy getCompressionPolicy() {
// Set the Compression policy stored as a system property
String policyName = JiveGlobals
......@@ -471,6 +436,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
*
* @param policy whether compression is optional or is disabled.
*/
// TODO Move this to ConnectionConfiguration.
public static void setCompressionPolicy(SocketConnection.CompressionPolicy policy) {
JiveGlobals.setProperty(ConnectionSettings.Client.COMPRESSION_SETTINGS, policy.toString());
}
......
......@@ -49,6 +49,7 @@ import org.xmpp.packet.StreamError;
*
* @author Gaston Dombiak
*/
// TODO implement TLS and observe org.jivesoftware.openfire.session.ConnectionSettings.Component.TLS_POLICY
public class LocalComponentSession extends LocalSession implements ComponentSession {
private static final Logger Log = LoggerFactory.getLogger(LocalComponentSession.class);
......
......@@ -29,6 +29,9 @@ import org.jivesoftware.openfire.multiplex.ConnectionMultiplexerManager;
import org.jivesoftware.openfire.multiplex.MultiplexerPacketDeliverer;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -261,13 +264,17 @@ public class LocalConnectionMultiplexerSession extends LocalSession implements C
* </ul
*/
private void sendClientOptions() {
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
final ConnectionConfiguration configuration = connectionManager.getConfiguration( ConnectionType.SOCKET_C2S, false );
IQ options = new IQ(IQ.Type.set);
Element child = options.setChildElement("configuration",
"http://jabber.org/protocol/connectionmanager");
// Add info about TLS
if (LocalClientSession.getTLSPolicy() != Connection.TLSPolicy.disabled) {
if (configuration.getTlsPolicy() != Connection.TLSPolicy.disabled) {
Element tls = child.addElement("starttls", "urn:ietf:params:xml:ns:xmpp-tls");
if (LocalClientSession.getTLSPolicy() == Connection.TLSPolicy.required) {
if (configuration.getTlsPolicy() == Connection.TLSPolicy.required) {
tls.addElement("required");
}
......
......@@ -35,11 +35,11 @@ import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreManager;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.server.ServerDialback;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.CertificateManager;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
......@@ -153,7 +153,7 @@ public class LocalIncomingServerSession extends LocalServerSession implements In
Connection.TLSPolicy.required;
boolean hasCertificates = false;
try {
hasCertificates = SSLConfig.getIdentityStore( Purpose.SOCKET_S2S ).size() > 0;
hasCertificates = CertificateStoreManager.getIdentityStore( ConnectionType.SOCKET_S2S ).getStore().size() > 0;
}
catch (Exception e) {
Log.error(e.getMessage(), e);
......@@ -374,7 +374,7 @@ public class LocalIncomingServerSession extends LocalServerSession implements In
usingSelfSigned = true;
} else {
try {
final KeyStore keyStore = SSLConfig.getIdentityStore( Purpose.SOCKET_S2S );
final KeyStore keyStore = CertificateStoreManager.getIdentityStore( ConnectionType.SOCKET_S2S ).getStore();
usingSelfSigned = CertificateManager.isSelfSignedCertificate(keyStore, (X509Certificate) chain[0]);
} catch (KeyStoreException ex) {
Log.warn("Exception occurred while trying to determine whether local certificate is self-signed. Proceeding as if it is.", ex);
......
......@@ -379,10 +379,10 @@ public class LocalOutgoingServerSession extends LocalServerSession implements Ou
if (proceed != null && proceed.getName().equals("proceed")) {
log.debug("Negotiating TLS...");
try {
boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
!JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false);
connection.startTLS(true, false, needed ? Connection.ClientAuth.needed : Connection.ClientAuth.wanted);
// boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
// JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
// !JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false);
connection.startTLS(true);
} catch(Exception e) {
log.debug("Got an exception whilst negotiating TLS: " + e.getMessage());
throw e;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -40,8 +40,6 @@ import java.security.cert.X509Certificate;
import java.util.Comparator;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.session.ConnectionSettings;
/**
* SSLSocketFactory that accepts any certificate chain and also accepts expired
......
......@@ -6,7 +6,7 @@ Fonthead Design End User License Agreement
By downloading and/or installing Fonthead Design fonts (&quot;software&quot;) you agree to the following user license terms:
1) Grant of License: The purchase of this software grants to you (&quot;user&quot;) as licensee, the non-exclusive right to use and display the software at a single home or business location on a maximum of 5 CPUs. You also may give a copy of this software to any service bureau which you hire to output your film, paper or color proofs, provided that they do not use the font software for any purpose other than outputing your work. They may keep the font software on file for use with future jobs on your behalf.
1) Grant of License: The purchase of this software grants to you (&quot;user&quot;) as licensee, the non-exclusive right to use and display the software at a single home or business location on a maximum of 5 CPUs. You also may give a copy of this software to any service bureau which you hire to output your film, paper or color proofs, provided that they do not use the font software for any connectionType other than outputing your work. They may keep the font software on file for use with future jobs on your behalf.
2) Backup: One copy of the software may be made for backup.
......
......@@ -109,7 +109,7 @@ class RegisterProcessing {
// }
/*
* else{ SipURI uri = (SipURI) address.getURI();
* scheduleReRegistration(uri.getHost(), uri.getPort(),
* scheduleReRegistration(uri.getHost(), uri.getServerPort(),
* uri.getTransportParam(), expires); }
*/
sipManCallback.fireRegistered(address.toString());
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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