From f7036e50348484f4daf39f9e8457de602ab83939 Mon Sep 17 00:00:00 2001
From: coulbeck <coulbeck@localhost>
Date: Tue, 28 Aug 2007 15:54:13 +0000
Subject: [PATCH] Changes for replication security issues 511, 512, 608.
---
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java | 4
opends/src/messages/messages/core.properties | 7
opends/src/server/org/opends/server/replication/protocol/ProtocolSession.java | 11
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 13
opends/src/server/org/opends/server/replication/protocol/ServerStartMessage.java | 37 +
opends/src/ads/org/opends/admin/ads/ServerDescriptor.java | 3
opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java | 2
opends/tests/unit-tests-testng/resource/config-changes.ldif | 19
opends/src/server/org/opends/server/api/KeyManagerProvider.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java | 10
opends/src/server/org/opends/server/replication/server/ServerHandler.java | 41 +
opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java | 40 -
opends/src/server/org/opends/server/replication/protocol/TLSSocketSession.java | 231 ++++++++++
opends/src/server/org/opends/server/types/CryptoManager.java | 153 ++++++
opends/resource/schema/02-config.ldif | 53 ++
opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java | 43 +
opends/src/server/org/opends/server/replication/protocol/SocketSession.java | 16
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java | 19
opends/src/messages/messages/backend.properties | 73 +++
opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml | 2
opends/src/server/org/opends/server/replication/plugin/ReplicationMonitor.java | 3
opends/src/messages/messages/tools.properties | 4
opends/resource/config/config.ldif | 20
opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java | 3
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/DbHandlerTest.java | 3
opends/src/server/org/opends/server/core/DirectoryServer.java | 15
opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java | 6
opends/src/server/org/opends/server/replication/protocol/ReplServerStartMessage.java | 41 +
opends/src/server/org/opends/server/replication/server/ReplicationServer.java | 31
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 41 +
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java | 41 +
opends/src/server/org/opends/server/replication/protocol/ReplSessionSecurity.java | 283 ++++++++++++
opends/src/server/org/opends/server/config/ConfigConstants.java | 66 ++
opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java | 6
34 files changed, 1,192 insertions(+), 150 deletions(-)
diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index b536774..15de09e 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -76,6 +76,13 @@
ds-cfg-acl-handler-class: org.opends.server.authorization.dseecompat.AciHandler
ds-cfg-acl-handler-enabled: true
+dn: cn=Crypto Manager,cn=config
+objectClass: top
+objectClass: ds-cfg-crypto-manager
+cn: Crypto Manager
+ds-cfg-ssl-cert-nickname: ads-certificate
+ds-cfg-ssl-encryption: false
+
dn: cn=Account Status Notification Handlers,cn=config
objectClass: top
objectClass: ds-cfg-branch
@@ -304,6 +311,19 @@
ds-cfg-backend-writability-mode: enabled
ds-cfg-backend-base-dn: cn=config
+dn: ds-cfg-backend-id=ads-truststore,cn=Backends,cn=config
+objectClass: top
+objectClass: ds-cfg-backend
+objectClass: ds-cfg-trust-store-backend
+ds-cfg-backend-id: ads-truststore
+ds-cfg-backend-enabled: true
+ds-cfg-backend-class: org.opends.server.backends.TrustStoreBackend
+ds-cfg-backend-writability-mode: enabled
+ds-cfg-backend-base-dn: cn=trust-store
+ds-cfg-trust-store-type: JKS
+ds-cfg-trust-store-file: config/ads-truststore
+ds-cfg-trust-store-pin-file: config/ads-truststore.pin
+
dn: ds-cfg-backend-id=monitor,cn=Backends,cn=config
objectClass: top
objectClass: ds-cfg-backend
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index e0f3c89..7cd8579 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1576,6 +1576,31 @@
NAME 'ds-cfg-backend-compact-encoding'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+<<<<<<< .mine
+attributeTypes: ( ds-cfg-ssl-encryption-oid NAME 'ds-cfg-ssl-encryption'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( ds-cfg-public-key-certificate-OID
+ NAME 'ds-cfg-public-key-certificate'
+ DESC 'cryptographic public-key certificate'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.8
+ SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( ds-cfg-key-id-OID
+ NAME 'ds-cfg-key-id'
+ DESC 'cryptographic cipher-key unique identifier'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( ds-cfg-key-compromised-time-OID
+ NAME 'ds-cfg-key-compromised-time'
+ DESC 'The time a cryptographic cipher key was suspected to be compromised'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
+=======
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.476
NAME 'ds-cfg-email-address-attribute-type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
@@ -1586,6 +1611,7 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.478
NAME 'ds-cfg-message-template-file' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
X-ORIGIN 'OpenDS Directory Server' )
+>>>>>>> .r2828
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -2235,4 +2261,31 @@
ds-cfg-message-template-file ) MAY ( ds-cfg-email-address-attribute-type $
ds-cfg-recipient-address $ ds-cfg-message-subject )
X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( ds-cfg-trust-store-backend-oid
+ NAME 'ds-cfg-trust-store-backend'
+ SUP ds-cfg-backend STRUCTURAL
+ MAY ( ds-cfg-trust-store-type $ ds-cfg-trust-store-file $
+ ds-cfg-trust-store-pin $ ds-cfg-trust-store-pin-property $
+ ds-cfg-trust-store-pin-environment-variable $ ds-cfg-trust-store-pin-file )
+ X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( ds-cfg-crypto-manager-oid
+ NAME 'ds-cfg-crypto-manager'
+ SUP top
+ STRUCTURAL
+ MAY ( cn $ ds-cfg-ssl-protocol $ ds-cfg-ssl-cipher-suite $
+ ds-cfg-ssl-cert-nickname $ ds-cfg-ssl-encryption )
+ X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( ds-cfg-instance-key-OID
+ NAME 'ds-cfg-instance-key'
+ SUP top
+ STRUCTURAL
+ MUST ( ds-cfg-key-id $ ds-cfg-public-key-certificate )
+ MAY ds-cfg-key-compromised-time
+ X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( ds-cfg-self-signed-cert-request-OID
+ NAME 'ds-cfg-self-signed-cert-request'
+ SUP top
+ STRUCTURAL
+ MUST ( ds-cfg-key-id )
+ X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
index 668bb59..c481be9 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
@@ -201,7 +201,7 @@
<adm:property name="window-size" mandatory="false"
multi-valued="false">
<adm:synopsis>
- Specifies the window size that will this Domain must use when
+ Specifies the window size that this domain will use when
communicating with replication servers.
</adm:synopsis>
<adm:default-behavior>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index 04a63ba..c7fcc5e 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -81,6 +81,19 @@
</cli:relation>
</adm:profile>
</adm:relation>
+ <adm:relation name="crypto-manager">
+ <adm:one-to-one />
+ <adm:profile name="ldap">
+ <ldap:rdn-sequence>
+ cn=Crypto Manager,cn=config
+ </ldap:rdn-sequence>
+ </adm:profile>
+ <adm:profile name="cli">
+ <cli:relation>
+ <cli:default-property name="enabled" />
+ </cli:relation>
+ </adm:profile>
+ </adm:relation>
<adm:relation name="group-implementation">
<adm:one-to-many />
<adm:profile name="ldap">
diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index 8ee34d6..1e9061d 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -871,7 +871,8 @@
"schema".equalsIgnoreCase(id) ||
"config".equalsIgnoreCase(id) ||
"monitor".equalsIgnoreCase(id) ||
- "backup".equalsIgnoreCase(id);
+ "backup".equalsIgnoreCase(id) ||
+ "ads-truststore".equalsIgnoreCase(id);
}
/**
diff --git a/opends/src/messages/messages/backend.properties b/opends/src/messages/messages/backend.properties
index 1a680dd..078b3d5 100644
--- a/opends/src/messages/messages/backend.properties
+++ b/opends/src/messages/messages/backend.properties
@@ -870,3 +870,76 @@
INFO_TASK_COMPLETION_BODY_299=Task ID: %s\r\nTask State: %s\r\nScheduled \
Start Time: %s\r\nActual Start Time: %s\r\nCompletion Time: %s\r\n\r\nLog \
Messages:\r\n
+SEVERE_ERR_TRUSTSTORE_GET_ENTRY_NULL_300=Unable to retrieve an entry from the \
+ trust store backend because the requested entry was null
+SEVERE_ERR_TRUSTSTORE_INVALID_BASE_301=Requested entry %s does not exist in \
+ the trust store backend
+SEVERE_ERR_TRUSTSTORE_DN_DOES_NOT_SPECIFY_CERTIFICATE_302=Unable to process \
+ entry %s in the trust store backend because the requested DN is one level \
+ below the base DN but does not specify a certificate name
+SEVERE_ERR_TRUSTSTORE_INVALID_CERTIFICATE_303=Unable to retrieve entry %s \
+ from the trust store backend because the requested certificate is invalid: \
+ %s
+SEVERE_ERR_TRUSTSTORE_MODIFY_NOT_SUPPORTED_304=Modify operations are not \
+ supported in the trust store backend
+SEVERE_ERR_TRUSTSTORE_MODIFY_DN_NOT_SUPPORTED_305=Modify DN operations are not \
+ supported in the trust store backend
+SEVERE_ERR_TRUSTSTORE_CANNOT_DECODE_TRUSTSTORE_ROOT_DN_306=Unable to \
+ initialize the trust store backend because an error occurred while \
+ attempting to decode the base DN for the backend: %s
+SEVERE_ERR_TRUSTSTORE_IMPORT_AND_EXPORT_NOT_SUPPORTED_307=LDIF import and \
+ export operations are not supported in the trust store backend
+SEVERE_ERR_TRUSTSTORE_BACKUP_AND_RESTORE_NOT_SUPPORTED_308=Backup and \
+ restore operations are not supported in the trust store backend
+SEVERE_ERR_TRUSTSTORE_NO_SUCH_FILE_309=The trust store file %s \
+ specified in attribute ds-cfg-trust-store-file of configuration entry %s does \
+ not exist
+SEVERE_ERR_TRUSTSTORE_INVALID_TYPE_310=The trust store type %s \
+ specified in attribute ds-cfg-trust-store-type of configuration entry %s is \
+ not valid: %s
+SEVERE_ERR_TRUSTSTORE_PIN_NO_SUCH_FILE_311=File %s specified in \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s should \
+ contain the PIN needed to access the trust store, but this file \
+ does not exist
+SEVERE_ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ_312=An error occurred while \
+ trying to read the trust store PIN from file %s specified in configuration \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s: %s
+SEVERE_ERR_TRUSTSTORE_PIN_FILE_EMPTY_313=File %s specified in \
+ attribute ds-cfg-trust-store-pin-file of configuration entry %s should \
+ contain the PIN needed to access the trust store, but this file \
+ is empty
+SEVERE_ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET_314=Environment variable %s \
+ which is specified in attribute ds-cfg-trust-store-pin-environment-variable \
+ of configuration entry %s should contain the PIN needed to access the \
+ trust store, but this property is not set
+SEVERE_ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET_315=Java property %s which \
+ is specified in attribute ds-cfg-trust-store-pin-property of configuration \
+ entry %s should contain the PIN needed to access the file-based trust \
+ manager, but this property is not set
+SEVERE_ERR_TRUSTSTORE_CANNOT_DETERMINE_FILE_316=An unexpected error \
+ occurred while trying to determine the value of configuration attribute \
+ ds-cfg-trust-store-file in configuration entry %s: %s
+SEVERE_ERR_TRUSTSTORE_CANNOT_LOAD_317=An error occurred while trying \
+ to load the trust store contents from file %s: %s
+SEVERE_ERR_TRUSTSTORE_CANNOT_CREATE_FACTORY_318=An error occurred \
+ while trying to create a trust manager factory to access the contents of \
+ trust store file %s: %s
+SEVERE_ERR_TRUSTSTORE_ALIAS_IN_USE_319=The certificate entry %s already exists
+SEVERE_ERR_TRUSTSTORE_CANNOT_GENERATE_CERT_320=Error while attempting to \
+ generate a self-signed certificate %s in the trust store file %s: %s
+SEVERE_ERR_TRUSTSTORE_CANNOT_ADD_CERT_321=Error while trying to add \
+ certificate %s to the trust store file %s: %s
+SEVERE_ERR_TRUSTSTORE_DELETE_NOT_SUPPORTED_322=Delete operations are not \
+ supported in the trust store backend
+SEVERE_ERR_TRUSTSTORE_ENTRY_MISSING_CERT_ATTR_323=The entry %s could not be \
+ added because it does not contain a certificate attribute %s
+SEVERE_ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_ATTRS_324=The entry %s could \
+ not be added because it contains multiple certificate attributes %s
+SEVERE_ERR_TRUSTSTORE_ENTRY_MISSING_CERT_VALUE_325=The entry %s could not be \
+ added because it does not contain a value of certificate attribute %s
+SEVERE_ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_VALUES_326=The entry %s could \
+ not be added because it contains multiple values of certificate attribute %s
+SEVERE_ERR_TRUSTSTORE_CANNOT_WRITE_CERT_327=Error while writing certificate %s \
+ to a file: %s
+SEVERE_WARN_TRUSTSTORE_SET_PERMISSIONS_FAILED_328=Failed to set permissions \
+ on trust store file %s
diff --git a/opends/src/messages/messages/core.properties b/opends/src/messages/messages/core.properties
index 4731b81..23478ba 100644
--- a/opends/src/messages/messages/core.properties
+++ b/opends/src/messages/messages/core.properties
@@ -1645,3 +1645,10 @@
FATAL_ERR_CANNOT_SET_ENVIRONMENT_CONFIG_WHILE_RUNNING_648=The Directory \
Server is currently running. The environment configuration may not be \
altered while the server is online
+SEVERE_ERR_CRYPTOMGR_SSL_CONTEXT_CANNOT_INITIALIZE_649=An error occurred \
+ while attempting to initialize a SSL context for server to server \
+ communication: %s
+SEVERE_ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_NOT_ENABLED_650=The ADS trust \
+ store backend %s is not enabled
+SEVERE_ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS_651=The backend %s \
+ is not a trust store backend
diff --git a/opends/src/messages/messages/tools.properties b/opends/src/messages/messages/tools.properties
index 2d32c1a..fafad32 100644
--- a/opends/src/messages/messages/tools.properties
+++ b/opends/src/messages/messages/tools.properties
@@ -2295,4 +2295,6 @@
INFO_LABEL_DBTEST_INDEX_ENTRY_ID_LIST_1370=Entry ID List
INFO_LABEL_DBTEST_VLV_INDEX_LAST_SORT_KEYS_1371=Last Sort Keys
SEVERE_ERR_DBTEST_CANNOT_DECODE_SIZE_1372=An error occured while parsing the \
- min/max data size %s as a integer: %s
\ No newline at end of file
+ min/max data size %s as a integer: %s
+SEVERE_ERR_CONFIGDS_CANNOT_ENABLE_ADS_TRUST_STORE_1373=An error occurred while \
+ attempting to enable the ADS trust store: %s
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index b8475dd..048b93c 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -3577,7 +3577,7 @@
switch (type)
{
case 0:
- // Will return a figure
+ // Will return a digit
d = next % 10;
if (d < 0)
{
diff --git a/opends/src/server/org/opends/server/api/KeyManagerProvider.java b/opends/src/server/org/opends/server/api/KeyManagerProvider.java
index bb24fd3..73b8a94 100644
--- a/opends/src/server/org/opends/server/api/KeyManagerProvider.java
+++ b/opends/src/server/org/opends/server/api/KeyManagerProvider.java
@@ -99,7 +99,7 @@
* for this key manager provider, or {@code false} if not.
*/
public boolean isConfigurationAcceptable(
- KeyManagerCfg configuration,
+ T configuration,
List<Message> unacceptableReasons)
{
// This default implementation does not perform any special
diff --git a/opends/src/server/org/opends/server/config/ConfigConstants.java b/opends/src/server/org/opends/server/config/ConfigConstants.java
index b5d6200..592f63f 100644
--- a/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -2842,7 +2842,7 @@
/**
- * The DN of the entry that be the base of the configuration information for
+ * The DN of the entry that is the base of the configuration information for
* the Directory Server trust manager providers.
*/
public static final String DN_TRUSTMANAGER_PROVIDER_CONFIG_BASE =
@@ -2851,6 +2851,70 @@
/**
+ * The ADS trust store backend id.
+ */
+ public static final String ID_ADS_TRUST_STORE_BACKEND = "ads-truststore";
+
+
+
+ /**
+ * The DN of the trust store backend configuration entry.
+ */
+ public static final String DN_TRUST_STORE_BACKEND =
+ ATTR_BACKEND_ID + "=" + ID_ADS_TRUST_STORE_BACKEND +
+ "," + DN_BACKEND_BASE;
+
+
+
+ /**
+ * Alias of the local instance certificate in the ADS keystore.
+ */
+ public static final String ADS_CERTIFICATE_ALIAS = "ads-certificate";
+
+
+
+ /**
+ * The DN of the entry that will serve as the base for local ADS trust store
+ * information.
+ */
+ public static final String DN_TRUST_STORE_ROOT = "cn=ads-truststore";
+
+
+
+ /**
+ * The name of the attribute that holds a server certificate alias.
+ */
+ public static final String ATTR_CERT_ALIAS = NAME_PREFIX_CFG + "key-id";
+
+
+
+ /**
+ * The name of the objectclass that will be used for a server
+ * certificate entry.
+ */
+ public static final String OC_INSTANCE_KEY =
+ NAME_PREFIX_CFG + "instance-key";
+
+
+
+ /**
+ * The name of the objectclass that will be used for a self-signed
+ * certificate request.
+ */
+ public static final String OC_SELF_SIGNED_CERT_REQUEST =
+ NAME_PREFIX_CFG + "self-signed-cert-request";
+
+
+
+ /**
+ * The name of the attribute that is used to specify a server
+ * instance key.
+ */
+ public static final String ATTR_ADS_CERTIFICATE =
+ NAME_PREFIX_CFG + "public-key-certificate";
+
+
+ /**
* The DN of the entry that will serve as the base for all Directory Server
* loggers.
*/
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index f844056..fd0c3fe 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -30,15 +30,7 @@
import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.server.ServerManagementContext;
-import org.opends.server.admin.std.server.AlertHandlerCfg;
-import org.opends.server.admin.std.server.AttributeSyntaxCfg;
-import org.opends.server.admin.std.server.ConnectionHandlerCfg;
-import org.opends.server.admin.std.server.DirectoryStringAttributeSyntaxCfg;
-import org.opends.server.admin.std.server.MonitorProviderCfg;
-import org.opends.server.admin.std.server.PasswordValidatorCfg;
-import org.opends.server.admin.std.server.RootCfg;
-import org.opends.server.admin.std.server.RootDSEBackendCfg;
-import org.opends.server.admin.std.server.SynchronizationProviderCfg;
+import org.opends.server.admin.std.server.*;
import org.opends.server.api.AccountStatusNotificationHandler;
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.AlertHandler;
@@ -2189,7 +2181,10 @@
public void initializeCryptoManager()
throws ConfigException, InitializationException
{
- cryptoManager = new CryptoManager();
+ RootCfg root =
+ ServerManagementContext.getInstance().getRootConfiguration();
+ CryptoManagerCfg cryptoManagerCfg = root.getCryptoManager();
+ cryptoManager = new CryptoManager(cryptoManagerCfg);
}
diff --git a/opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java b/opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java
index 32ba882..94901e4 100644
--- a/opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java
+++ b/opends/src/server/org/opends/server/extensions/FileBasedKeyManagerProvider.java
@@ -43,7 +43,6 @@
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.FileBasedKeyManagerCfg;
-import org.opends.server.admin.std.server.KeyManagerCfg;
import org.opends.server.api.KeyManagerProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
@@ -315,11 +314,10 @@
* {@inheritDoc}
*/
@Override()
- public boolean isConfigurationAcceptable(KeyManagerCfg configuration,
+ public boolean isConfigurationAcceptable(FileBasedKeyManagerCfg configuration,
List<Message> unacceptableReasons)
{
- FileBasedKeyManagerCfg config = (FileBasedKeyManagerCfg) configuration;
- return isConfigurationChangeAcceptable(config, unacceptableReasons);
+ return isConfigurationChangeAcceptable(configuration, unacceptableReasons);
}
diff --git a/opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java b/opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java
index 1278a42..34e69b7 100644
--- a/opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java
+++ b/opends/src/server/org/opends/server/extensions/PKCS11KeyManagerProvider.java
@@ -40,7 +40,6 @@
import javax.net.ssl.KeyManagerFactory;
import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.admin.std.server.KeyManagerCfg;
import org.opends.server.admin.std.server.PKCS11KeyManagerCfg;
import org.opends.server.api.KeyManagerProvider;
import org.opends.server.config.ConfigException;
@@ -273,11 +272,10 @@
* {@inheritDoc}
*/
@Override()
- public boolean isConfigurationAcceptable(KeyManagerCfg configuration,
+ public boolean isConfigurationAcceptable(PKCS11KeyManagerCfg configuration,
List<Message> unacceptableReasons)
{
- PKCS11KeyManagerCfg config = (PKCS11KeyManagerCfg) configuration;
- return isConfigurationChangeAcceptable(config, unacceptableReasons);
+ return isConfigurationChangeAcceptable(configuration, unacceptableReasons);
}
diff --git a/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java b/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
index ab3ae34..2869023 100644
--- a/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
+++ b/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
@@ -54,15 +54,7 @@
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.protocol.ProtocolSession;
-import org.opends.server.replication.protocol.ProtocolVersion;
-import org.opends.server.replication.protocol.ReplServerStartMessage;
-import org.opends.server.replication.protocol.ReplicationMessage;
-import org.opends.server.replication.protocol.ServerStartMessage;
-import org.opends.server.replication.protocol.SocketSession;
-import org.opends.server.replication.protocol.UpdateMessage;
-import org.opends.server.replication.protocol.WindowMessage;
-import org.opends.server.replication.protocol.WindowProbe;
+import org.opends.server.replication.protocol.*;
import org.opends.server.types.DN;
import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.ResultCode;
@@ -101,6 +93,7 @@
private int maxRcvWindow;
private int timeout = 0;
private short protocolVersion;
+ private ReplSessionSecurity replSessionSecurity;
/**
* The time in milliseconds between heartbeats from the replication
@@ -150,10 +143,12 @@
* @param window The size of the send and receive window to use.
* @param heartbeatInterval The interval between heartbeats requested of the
* replicationServer, or zero if no heartbeats are requested.
+ * @param replSessionSecurity The session security configuration.
*/
public ReplicationBroker(ServerState state, DN baseDn, short serverID,
int maxReceiveQueue, int maxReceiveDelay, int maxSendQueue,
- int maxSendDelay, int window, long heartbeatInterval)
+ int maxSendDelay, int window, long heartbeatInterval,
+ ReplSessionSecurity replSessionSecurity)
{
this.baseDn = baseDn;
this.serverID = serverID;
@@ -169,6 +164,7 @@
this.halfRcvWindow = window/2;
this.heartbeatInterval = heartbeatInterval;
this.protocolVersion = ProtocolVersion.currentVersion();
+ this.replSessionSecurity = replSessionSecurity;
}
/**
@@ -199,7 +195,6 @@
* Connect to a ReplicationServer.
*
* @throws NumberFormatException address was invalid
- * @throws IOException error during connection phase
*/
private void connect()
{
@@ -236,15 +231,16 @@
socket.setReceiveBufferSize(1000000);
socket.setTcpNoDelay(true);
socket.connect(ServerAddr, 500);
- session = new SocketSession(socket);
-
+ session = replSessionSecurity.createClientSession(server, socket);
+ boolean isSslEncryption =
+ replSessionSecurity.isSslEncryption(server);
/*
* Send our ServerStartMessage.
*/
ServerStartMessage msg = new ServerStartMessage(serverID, baseDn,
maxReceiveDelay, maxReceiveQueue, maxSendDelay, maxSendQueue,
halfRcvWindow*2, heartbeatInterval, state,
- protocolVersion);
+ protocolVersion, isSslEncryption);
session.publish(msg);
@@ -264,6 +260,11 @@
startMsg.getVersion());
session.setSoTimeout(timeout);
+ if (!isSslEncryption)
+ {
+ session.stopEncryption();
+ }
+
/*
* We must not publish changes to a replicationServer that has not
* seen all our previous changes because this could cause some
@@ -854,4 +855,18 @@
{
return !connectionError;
}
+
+ /**
+ * Determine whether the connection to the replication server is encrypted.
+ * @return true if the connection is encrypted, false otherwise.
+ */
+ public boolean isSessionEncrypted()
+ {
+ boolean isEncrypted = false;
+ if (session != null)
+ {
+ return session.isEncrypted();
+ }
+ return isEncrypted;
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java b/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
index 05233d3..cfe18ab 100644
--- a/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
+++ b/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -80,22 +80,7 @@
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.protocol.AckMessage;
-import org.opends.server.replication.protocol.AddContext;
-import org.opends.server.replication.protocol.AddMsg;
-import org.opends.server.replication.protocol.DeleteContext;
-import org.opends.server.replication.protocol.DoneMessage;
-import org.opends.server.replication.protocol.EntryMessage;
-import org.opends.server.replication.protocol.ErrorMessage;
-import org.opends.server.replication.protocol.InitializeRequestMessage;
-import org.opends.server.replication.protocol.InitializeTargetMessage;
-import org.opends.server.replication.protocol.ModifyContext;
-import org.opends.server.replication.protocol.ModifyDNMsg;
-import org.opends.server.replication.protocol.ModifyDnContext;
-import org.opends.server.replication.protocol.OperationContext;
-import org.opends.server.replication.protocol.RoutableMessage;
-import org.opends.server.replication.protocol.ReplicationMessage;
-import org.opends.server.replication.protocol.UpdateMessage;
+import org.opends.server.replication.protocol.*;
import org.opends.server.tasks.InitializeTargetTask;
import org.opends.server.tasks.InitializeTask;
import org.opends.server.tasks.TaskUtils;
@@ -357,12 +342,12 @@
configDn = configuration.dn();
/*
- * Modify conflicts are solved for all suffixes but the schema suffix
- * because we don't want to store extra information in the schema
- * ldif files.
- * This has no negative impact because the changes on schema should
- * not produce conflicts.
- */
+ * Modify conflicts are solved for all suffixes but the schema suffix
+ * because we don't want to store extra information in the schema
+ * ldif files.
+ * This has no negative impact because the changes on schema should
+ * not produce conflicts.
+ */
if (baseDN.compareTo(DirectoryServer.getSchemaDN()) == 0)
{
solveConflictFlag = false;
@@ -390,7 +375,7 @@
*/
broker = new ReplicationBroker(state, baseDN, serverId, maxReceiveQueue,
maxReceiveDelay, maxSendQueue, maxSendDelay, window,
- heartbeatInterval);
+ heartbeatInterval, new ReplSessionSecurity(configuration));
broker.start(replicationServers);
@@ -2997,4 +2982,13 @@
{
return configDn;
}
+
+ /**
+ * Determine whether the connection to the replication server is encrypted.
+ * @return true if the connection is encrypted, false otherwise.
+ */
+ public boolean isSessionEncrypted()
+ {
+ return broker.isSessionEncrypted();
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/plugin/ReplicationMonitor.java b/opends/src/server/org/opends/server/replication/plugin/ReplicationMonitor.java
index 3dffce0..f9e1fa1 100644
--- a/opends/src/server/org/opends/server/replication/plugin/ReplicationMonitor.java
+++ b/opends/src/server/org/opends/server/replication/plugin/ReplicationMonitor.java
@@ -150,6 +150,9 @@
attr = new Attribute(type, ATTR_SERVER_STATE, values);
attributes.add(attr);
+ attributes.add(new Attribute("ssl-encryption",
+ String.valueOf(domain.isSessionEncrypted())));
+
return attributes;
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ProtocolSession.java b/opends/src/server/org/opends/server/replication/protocol/ProtocolSession.java
index 36fa680..e56b69c 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ProtocolSession.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ProtocolSession.java
@@ -83,6 +83,17 @@
DataFormatException;
/**
+ * Stop using the security layer, if there is any.
+ */
+ public abstract void stopEncryption();
+
+ /**
+ * Determine whether the session is using a security layer.
+ * @return true if the connection is encrypted, false otherwise.
+ */
+ public abstract boolean isEncrypted();
+
+ /**
* Retrieve the IP address of the remote server.
*
* @return The IP address of the remote server.
diff --git a/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMessage.java b/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMessage.java
index 013d4cd..96140c3 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMessage.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMessage.java
@@ -43,12 +43,18 @@
{
private static final long serialVersionUID = -5871385537169856856L;
- private String baseDn = null;
private short serverId;
private String serverURL;
+ private String baseDn = null;
+ private int windowSize;
private ServerState serverState;
- private int windowSize;
+ /**
+ * Whether to continue using SSL to encrypt messages after the start
+ * messages have been exchanged.
+ */
+ private boolean sslEncryption;
+
/**
* Create a ReplServerStartMessage.
@@ -59,11 +65,14 @@
* @param windowSize The window size.
* @param serverState our ServerState for this baseDn.
* @param protocolVersion The replication protocol version of the creator.
+ * @param sslEncryption Whether to continue using SSL to encrypt messages
+ * after the start messages have been exchanged.
*/
public ReplServerStartMessage(short serverId, String serverURL, DN baseDn,
int windowSize,
ServerState serverState,
- short protocolVersion)
+ short protocolVersion,
+ boolean sslEncryption)
{
super(protocolVersion);
this.serverId = serverId;
@@ -74,6 +83,7 @@
this.baseDn = null;
this.windowSize = windowSize;
this.serverState = serverState;
+ this.sslEncryption = sslEncryption;
}
/**
@@ -125,6 +135,13 @@
pos += length +1;
/*
+ * read the sslEncryption setting
+ */
+ length = getNextLength(in, pos);
+ sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
+ pos += length +1;
+
+ /*
* read the ServerState
*/
serverState = new ServerState(in, pos, in.length-1);
@@ -194,9 +211,12 @@
byte[] byteServerUrl = serverURL.getBytes("UTF-8");
byte[] byteServerState = serverState.getBytes();
byte[] byteWindowSize = String.valueOf(windowSize).getBytes("UTF-8");
+ byte[] byteSSLEncryption =
+ String.valueOf(sslEncryption).getBytes("UTF-8");
int length = byteDn.length + 1 + byteServerId.length + 1 +
byteServerUrl.length + 1 + byteWindowSize.length + 1 +
+ byteSSLEncryption.length + 1 +
byteServerState.length + 1;
/* encode the header in a byte[] large enough to also contain the mods */
@@ -215,6 +235,9 @@
/* put the window size */
pos = addByteArray(byteWindowSize, resultByteArray, pos);
+ /* put the SSL Encryption setting */
+ pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
+
/* put the ServerState */
pos = addByteArray(byteServerState, resultByteArray, pos);
@@ -235,4 +258,16 @@
{
return windowSize;
}
+
+ /**
+ * Get the SSL encryption value for the server that created the
+ * message.
+ *
+ * @return The SSL encryption value for the server that created the
+ * message.
+ */
+ public boolean getSSLEncryption()
+ {
+ return sslEncryption;
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ReplSessionSecurity.java b/opends/src/server/org/opends/server/replication/protocol/ReplSessionSecurity.java
new file mode 100644
index 0000000..f77f3a7
--- /dev/null
+++ b/opends/src/server/org/opends/server/replication/protocol/ReplSessionSecurity.java
@@ -0,0 +1,283 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.replication.protocol;
+
+import org.opends.server.admin.std.server.ReplicationServerCfg;
+import org.opends.server.admin.std.server.MultimasterDomainCfg;
+import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.CryptoManager;
+import org.opends.server.config.ConfigException;
+
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import java.util.SortedSet;
+import java.net.Socket;
+import java.io.IOException;
+
+/**
+ * This class represents the security configuration for replication protocol
+ * sessions. It contains all the configuration required to use SSL, and it
+ * determines whether encryption should be enabled for a session to a given
+ * replication server.
+ *
+ */
+public class ReplSessionSecurity
+{
+ /**
+ * Whether the replication server should listen on a secure port.
+ * Set false for test purposes only.
+ */
+ private static boolean useSSL = true;
+
+ /**
+ * Whether replication sessions use SSL encryption.
+ */
+ private boolean sslEncryption;
+
+ /**
+ * The name of the local certificate to use, or null if none is specified.
+ */
+ private String sslCertNickname;
+
+ /**
+ * The set of enabled SSL protocols, or null for the default set.
+ */
+ private String sslProtocols[];
+
+ /**
+ * The set of enabled SSL cipher suites, or null for the default set.
+ */
+ private String sslCipherSuites[];
+
+
+ /**
+ * Create a ReplSessionSecurity instance from the supplied configuration
+ * values.
+ *
+ * @param sslCertNickname The name of the local certificate to use, or null
+ * if none is specified.
+ * @param sslProtocols The protocols that should be enabled, or null if
+ * the default protocols should be used.
+ * @param sslCipherSuites The cipher suites that should be enabled, or null
+ * if the default cipher suites should be used.
+ * @param sslEncryption Whether replication sessions use SSL encryption.
+ *
+ * @throws ConfigException If the supplied configuration was not valid.
+ */
+ public ReplSessionSecurity(String sslCertNickname,
+ SortedSet<String> sslProtocols,
+ SortedSet<String> sslCipherSuites,
+ boolean sslEncryption)
+ throws ConfigException
+ {
+ if (sslProtocols == null || sslProtocols.size() == 0)
+ {
+ this.sslProtocols = null;
+ }
+ else
+ {
+ this.sslProtocols = new String[sslProtocols.size()];
+ sslProtocols.toArray(this.sslProtocols);
+ }
+
+ if (sslCipherSuites == null || sslCipherSuites.size() == 0)
+ {
+ this.sslCipherSuites = null;
+ }
+ else
+ {
+ this.sslCipherSuites = new String[sslProtocols.size()];
+ sslProtocols.toArray(this.sslCipherSuites);
+ }
+
+ this.sslEncryption = sslEncryption;
+ this.sslCertNickname = sslCertNickname;
+ }
+
+ /**
+ * Create a ReplSessionSecurity instance from a provided replication server
+ * configuration.
+ *
+ * @param replServerCfg The replication server configuration.
+ *
+ * @throws ConfigException If the supplied configuration was not valid.
+ */
+ public ReplSessionSecurity(ReplicationServerCfg replServerCfg)
+ throws ConfigException
+ {
+ // Currently use global settings from the crypto manager.
+ this(DirectoryConfig.getCryptoManager().getSslCertNickname(),
+ DirectoryConfig.getCryptoManager().getSslProtocols(),
+ DirectoryConfig.getCryptoManager().getSslCipherSuites(),
+ DirectoryConfig.getCryptoManager().isSslEncryption());
+ }
+
+ /**
+ * Create a ReplSessionSecurity instance from a provided multimaster domain
+ * configuration.
+ *
+ * @param multimasterDomainCfg The multimaster domain configuration.
+ *
+ * @throws ConfigException If the supplied configuration was not valid.
+ */
+ public ReplSessionSecurity(MultimasterDomainCfg multimasterDomainCfg)
+ throws ConfigException
+ {
+ // Currently use global settings from the crypto manager.
+ this(DirectoryConfig.getCryptoManager().getSslCertNickname(),
+ DirectoryConfig.getCryptoManager().getSslProtocols(),
+ DirectoryConfig.getCryptoManager().getSslCipherSuites(),
+ DirectoryConfig.getCryptoManager().isSslEncryption());
+ }
+
+ /**
+ * Determine whether a given replication server is listening on a secure
+ * port.
+ * @param serverURL The replication server URL.
+ * @return true if the given replication server is listening on a secure
+ * port, or false if it is listening on a non-secure port.
+ */
+ private boolean isSecurePort(String serverURL)
+ {
+ // Always true unless changed for test purposes.
+ return useSSL;
+ }
+
+ /**
+ * Determine whether sessions to a given replication server should be
+ * encrypted.
+ * @param serverURL The replication server URL.
+ * @return true if sessions to the given replication server should be
+ * encrypted, or false if they should not be encrypted.
+ */
+ public boolean isSslEncryption(String serverURL)
+ {
+ // Currently use global settings from the crypto manager.
+ return sslEncryption;
+ }
+
+ /**
+ * Create a new protocol session in the client role on the provided socket.
+ * @param serverURL The remote replication server to which the socket is
+ * connected.
+ * @param socket The connected socket.
+ * @return The new protocol session.
+ * @throws ConfigException If the protocol session could not be established
+ * due to a configuration problem.
+ * @throws IOException If the protocol session could not be established
+ * for some other reason.
+ */
+ public ProtocolSession createClientSession(String serverURL, Socket socket)
+ throws ConfigException, IOException
+ {
+ boolean useSSL = isSecurePort(serverURL);
+ if (useSSL)
+ {
+ // Create a new SSL context every time to make sure we pick up the
+ // latest contents of the trust store.
+ CryptoManager cryptoManager = DirectoryConfig.getCryptoManager();
+ SSLContext sslContext = cryptoManager.getSslContext(sslCertNickname);
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+ SSLSocket secureSocket = (SSLSocket)
+ sslSocketFactory.createSocket(socket,
+ socket.getInetAddress().getHostName(),
+ socket.getPort(), false);
+ secureSocket.setUseClientMode(true);
+
+ if (sslProtocols != null)
+ {
+ secureSocket.setEnabledProtocols(sslProtocols);
+ }
+
+ if (sslCipherSuites != null)
+ {
+ secureSocket.setEnabledCipherSuites(sslCipherSuites);
+ }
+
+ // Force TLS negotiation now.
+ secureSocket.startHandshake();
+
+ return new TLSSocketSession(socket, secureSocket);
+ }
+ else
+ {
+ return new SocketSession(socket);
+ }
+ }
+
+ /**
+ * Create a new protocol session in the server role on the provided socket.
+ * @param socket The connected socket.
+ * @return The new protocol session.
+ * @throws ConfigException If the protocol session could not be established
+ * due to a configuration problem.
+ * @throws IOException If the protocol session could not be established
+ * for some other reason.
+ */
+ public ProtocolSession createServerSession(Socket socket)
+ throws ConfigException, IOException
+ {
+ if (useSSL)
+ {
+ // Create a new SSL context every time to make sure we pick up the
+ // latest contents of the trust store.
+ CryptoManager cryptoManager = DirectoryConfig.getCryptoManager();
+ SSLContext sslContext = cryptoManager.getSslContext(sslCertNickname);
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+ SSLSocket secureSocket = (SSLSocket)
+ sslSocketFactory.createSocket(socket,
+ socket.getInetAddress().getHostName(),
+ socket.getPort(), false);
+ secureSocket.setUseClientMode(false);
+ secureSocket.setNeedClientAuth(true);
+
+ if (sslProtocols != null)
+ {
+ secureSocket.setEnabledProtocols(sslProtocols);
+ }
+
+ if (sslCipherSuites != null)
+ {
+ secureSocket.setEnabledCipherSuites(sslCipherSuites);
+ }
+
+ // Force TLS negotiation now.
+ secureSocket.startHandshake();
+
+ return new TLSSocketSession(socket, secureSocket);
+ }
+ else
+ {
+ return new SocketSession(socket);
+ }
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/replication/protocol/ServerStartMessage.java b/opends/src/server/org/opends/server/replication/protocol/ServerStartMessage.java
index a046356..693223f 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ServerStartMessage.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ServerStartMessage.java
@@ -63,6 +63,12 @@
private long heartbeatInterval = 0;
/**
+ * Whether to continue using SSL to encrypt messages after the start
+ * messages have been exchanged.
+ */
+ private boolean sslEncryption;
+
+ /**
* Create a new ServerStartMessage.
*
* @param serverId The serverId of the server for which the ServerStartMessage
@@ -76,13 +82,16 @@
* @param heartbeatInterval The requested heartbeat interval.
* @param serverState The state of this server.
* @param protocolVersion The replication protocol version of the creator.
+ * @param sslEncryption Whether to continue using SSL to encrypt messages
+ * after the start messages have been exchanged.
*/
public ServerStartMessage(short serverId, DN baseDn, int maxReceiveDelay,
int maxReceiveQueue, int maxSendDelay,
int maxSendQueue, int windowSize,
long heartbeatInterval,
ServerState serverState,
- short protocolVersion)
+ short protocolVersion,
+ boolean sslEncryption)
{
super(protocolVersion);
@@ -94,7 +103,7 @@
this.maxSendQueue = maxSendQueue;
this.windowSize = windowSize;
this.heartbeatInterval = heartbeatInterval;
-
+ this.sslEncryption = sslEncryption;
this.serverState = serverState;
try
@@ -194,6 +203,13 @@
pos += length +1;
/*
+ * read the sslEncryption setting
+ */
+ length = getNextLength(in, pos);
+ sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
+ pos += length +1;
+
+ /*
* read the ServerState
*/
serverState = new ServerState(in, pos, in.length-1);
@@ -308,6 +324,8 @@
String.valueOf(windowSize).getBytes("UTF-8");
byte[] byteHeartbeatInterval =
String.valueOf(heartbeatInterval).getBytes("UTF-8");
+ byte[] byteSSLEncryption =
+ String.valueOf(sslEncryption).getBytes("UTF-8");
byte[] byteServerState = serverState.getBytes();
int length = byteDn.length + 1 + byteServerId.length + 1 +
@@ -318,6 +336,7 @@
byteMaxSendQueue.length + 1 +
byteWindowSize.length + 1 +
byteHeartbeatInterval.length + 1 +
+ byteSSLEncryption.length + 1 +
byteServerState.length + 1;
/* encode the header in a byte[] large enough to also contain the mods */
@@ -342,6 +361,8 @@
pos = addByteArray(byteHeartbeatInterval, resultByteArray, pos);
+ pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
+
pos = addByteArray(byteServerState, resultByteArray, pos);
return resultByteArray;
@@ -373,4 +394,16 @@
{
return heartbeatInterval;
}
+
+ /**
+ * Get the SSL encryption value for the ldap server that created the
+ * message.
+ *
+ * @return The SSL encryption value for the ldap server that created the
+ * message.
+ */
+ public boolean getSSLEncryption()
+ {
+ return sslEncryption;
+ }
}
diff --git a/opends/src/server/org/opends/server/replication/protocol/SocketSession.java b/opends/src/server/org/opends/server/replication/protocol/SocketSession.java
index d71a0d2..91b8130 100644
--- a/opends/src/server/org/opends/server/replication/protocol/SocketSession.java
+++ b/opends/src/server/org/opends/server/replication/protocol/SocketSession.java
@@ -165,6 +165,22 @@
/**
* {@inheritDoc}
*/
+ public void stopEncryption()
+ {
+ // There is no security layer.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEncrypted()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public long getLastPublishTime()
{
return lastPublishTime;
diff --git a/opends/src/server/org/opends/server/replication/protocol/TLSSocketSession.java b/opends/src/server/org/opends/server/replication/protocol/TLSSocketSession.java
new file mode 100644
index 0000000..d3f544d
--- /dev/null
+++ b/opends/src/server/org/opends/server/replication/protocol/TLSSocketSession.java
@@ -0,0 +1,231 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.replication.protocol;
+
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.zip.DataFormatException;
+
+import org.opends.server.loggers.debug.DebugTracer;
+
+import javax.net.ssl.SSLSocket;
+
+/**
+ * This class implements a protocol session using TLS.
+ */
+public class TLSSocketSession implements ProtocolSession
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+ private Socket plainSocket;
+ private SSLSocket secureSocket;
+ private InputStream input;
+ private OutputStream output;
+ private InputStream plainInput;
+ private OutputStream plainOutput;
+ byte[] rcvLengthBuf = new byte[8];
+
+ /**
+ * The time the last message published to this session.
+ */
+ private long lastPublishTime = 0;
+
+
+ /**
+ * The time the last message was received on this session.
+ */
+ private long lastReceiveTime = 0;
+
+
+ /**
+ * Creates a new TLSSocketSession.
+ *
+ * @param socket The regular Socket on which the SocketSession will be
+ * based.
+ * @param secureSocket The secure Socket on which the SocketSession will be
+ * based.
+ * @throws IOException When an IException happens on the socket.
+ */
+ public TLSSocketSession(Socket socket, SSLSocket secureSocket)
+ throws IOException
+ {
+ plainSocket = socket;
+ this.secureSocket = secureSocket;
+ plainInput = plainSocket.getInputStream();
+ plainOutput = plainSocket.getOutputStream();
+ input = secureSocket.getInputStream();
+ output = secureSocket.getOutputStream();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws IOException
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugVerbose("Closing SocketSession.");
+ }
+ if (plainSocket != null && !plainSocket.isClosed())
+ {
+ plainSocket.close();
+ }
+ if (secureSocket != null && !secureSocket.isClosed())
+ {
+ secureSocket.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized void publish(ReplicationMessage msg)
+ throws IOException
+ {
+ byte[] buffer = msg.getBytes();
+ String str = String.format("%08x", buffer.length);
+ byte[] sendLengthBuf = str.getBytes();
+
+ output.write(sendLengthBuf);
+ output.write(buffer);
+ output.flush();
+
+ lastPublishTime = System.currentTimeMillis();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ReplicationMessage receive() throws IOException,
+ ClassNotFoundException, DataFormatException
+ {
+ /* Read the first 8 bytes containing the packet length */
+ int length = 0;
+
+ /* Let's start the stop-watch before waiting on read */
+ /* for the heartbeat check to be operationnal */
+ lastReceiveTime = System.currentTimeMillis();
+
+ while (length<8)
+ {
+ int read = input.read(rcvLengthBuf, length, 8-length);
+ if (read == -1)
+ {
+ lastReceiveTime=0;
+ throw new IOException("no more data");
+ }
+ else
+ {
+ length += read;
+ }
+ }
+
+ int totalLength = Integer.parseInt(new String(rcvLengthBuf), 16);
+
+ try
+ {
+ length = 0;
+ byte[] buffer = new byte[totalLength];
+ while (length < totalLength)
+ {
+ length += input.read(buffer, length, totalLength - length);
+ }
+ /* We do not want the heartbeat to close the session when */
+ /* we are processing a message even a time consuming one. */
+ lastReceiveTime=0;
+ return ReplicationMessage.generateMsg(buffer);
+ }
+ catch (OutOfMemoryError e)
+ {
+ throw new IOException("Packet too large, can't allocate "
+ + totalLength + " bytes.");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stopEncryption()
+ {
+ input = plainInput;
+ output = plainOutput;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEncrypted()
+ {
+ return !(input == plainInput);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastPublishTime()
+ {
+ return lastPublishTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastReceiveTime()
+ {
+ if (lastReceiveTime==0)
+ {
+ return System.currentTimeMillis();
+ }
+ return lastReceiveTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getRemoteAddress()
+ {
+ return plainSocket.getInetAddress().getHostAddress();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ plainSocket.setSoTimeout(timeout);
+ }
+}
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
index 48b6f69..2ae06c4 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -53,7 +53,8 @@
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.replication.protocol.SocketSession;
+import org.opends.server.replication.protocol.ReplSessionSecurity;
+import org.opends.server.replication.protocol.ProtocolSession;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -103,6 +104,7 @@
private int replicationPort;
// de deleted from the persistent storage.
private boolean stopListen = false;
+ private ReplSessionSecurity replSessionSecurity;
/**
* Creates a new Replication server using the provided configuration entry.
@@ -129,7 +131,7 @@
{
dbDirname = "changelogDb";
}
- // Chech that this path exists or create it.
+ // Check that this path exists or create it.
File f = getFileForPath(dbDirname);
try
{
@@ -149,6 +151,7 @@
throw new ConfigException(msg, e);
}
+ replSessionSecurity = new ReplSessionSecurity(configuration);
initialize(replicationServerId, replicationPort);
configuration.addChangeListener(this);
DirectoryServer.registerMonitorProvider(this);
@@ -164,7 +167,7 @@
void runListen()
{
- Socket newSocket = null;
+ Socket newSocket;
while ((shutdown == false) && (stopListen == false))
{
// Wait on the replicationServer port.
@@ -177,10 +180,13 @@
newSocket.setReceiveBufferSize(1000000);
newSocket.setTcpNoDelay(true);
newSocket.setKeepAlive(true);
- ServerHandler handler = new ServerHandler(
- new SocketSession(newSocket), queueSize);
- handler.start(null, serverId, serverURL, rcvWindow, this);
- } catch (IOException e)
+ ProtocolSession session =
+ replSessionSecurity.createServerSession(newSocket);
+ ServerHandler handler = new ServerHandler(session, queueSize);
+ handler.start(null, serverId, serverURL, rcvWindow,
+ false, this);
+ }
+ catch (Exception e)
{
// The socket has probably been closed as part of the
// shutdown or changing the port number process.
@@ -264,6 +270,7 @@
int separator = serverURL.lastIndexOf(':');
String port = serverURL.substring(separator + 1);
String hostname = serverURL.substring(0, separator);
+ boolean sslEncryption = replSessionSecurity.isSslEncryption(serverURL);
try
{
@@ -275,10 +282,12 @@
socket.connect(ServerAddr, 500);
ServerHandler handler = new ServerHandler(
- new SocketSession(socket), queueSize);
- handler.start(baseDn, serverId, this.serverURL, rcvWindow, this);
+ replSessionSecurity.createClientSession(serverURL, socket),
+ queueSize);
+ handler.start(baseDn, serverId, this.serverURL, rcvWindow,
+ sslEncryption, this);
}
- catch (IOException e)
+ catch (Exception e)
{
// ignore
}
@@ -523,7 +532,7 @@
}
if ((configuration.getReplicationDbDirectory() != null) &&
- (dbDirname != configuration.getReplicationDbDirectory()))
+ (!dbDirname.equals(configuration.getReplicationDbDirectory())))
{
return new ConfigChangeResult(ResultCode.SUCCESS, true);
}
diff --git a/opends/src/server/org/opends/server/replication/server/ServerHandler.java b/opends/src/server/org/opends/server/replication/server/ServerHandler.java
index 1a888a9..b67cade 100644
--- a/opends/src/server/org/opends/server/replication/server/ServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/ServerHandler.java
@@ -51,18 +51,7 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.protocol.ProtocolVersion;
-import org.opends.server.replication.protocol.AckMessage;
-import org.opends.server.replication.protocol.ReplServerStartMessage;
-import org.opends.server.replication.protocol.HeartbeatThread;
-import org.opends.server.replication.protocol.ProtocolSession;
-import org.opends.server.replication.protocol.RoutableMessage;
-import org.opends.server.replication.protocol.ServerStartMessage;
-import org.opends.server.replication.protocol.ReplicationMessage;
-import org.opends.server.replication.protocol.UpdateMessage;
-import org.opends.server.replication.protocol.WindowMessage;
-import org.opends.server.replication.protocol.WindowProbe;
-import org.opends.server.replication.protocol.ReplServerInfoMessage;
+import org.opends.server.replication.protocol.*;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -180,12 +169,16 @@
* @param replicationServerURL The URL of the replicationServer that creates
* this server handler.
* @param windowSize the window size that this server handler must use.
+ * @param sslEncryption For outgoing connections indicates whether encryption
+ * should be used after the exchange of start messages.
+ * Ignored for incoming connections.
* @param replicationServer the ReplicationServer that created this server
* handler.
*/
public void start(DN baseDn, short replicationServerId,
String replicationServerURL,
- int windowSize, ReplicationServer replicationServer)
+ int windowSize, boolean sslEncryption,
+ ReplicationServer replicationServer)
{
this.replicationServerId = replicationServerId;
rcvWindowSizeHalf = windowSize/2;
@@ -202,8 +195,7 @@
ReplServerStartMessage msg =
new ReplServerStartMessage(replicationServerId, replicationServerURL,
baseDn, windowSize, localServerState,
- protocolVersion);
-
+ protocolVersion, sslEncryption);
session.publish(msg);
}
@@ -227,6 +219,9 @@
maxSendQueue = receivedMsg.getMaxSendQueue();
heartbeatInterval = receivedMsg.getHeartbeatInterval();
+ // The session initiator decides whether to use SSL.
+ sslEncryption = receivedMsg.getSSLEncryption();
+
if (maxReceiveQueue > 0)
restartReceiveQueue = (maxReceiveQueue > 1000 ?
maxReceiveQueue - 200 :
@@ -266,7 +261,7 @@
ReplServerStartMessage myStartMsg =
new ReplServerStartMessage(replicationServerId, replicationServerURL,
this.baseDn, windowSize, localServerState,
- protocolVersion);
+ protocolVersion, sslEncryption);
session.publish(myStartMsg);
sendWindowSize = receivedMsg.getWindowSize();
}
@@ -288,12 +283,15 @@
replicationCache = replicationServer.getReplicationCache(this.baseDn);
ServerState serverState = replicationCache.getDbServerState();
+ // The session initiator decides whether to use SSL.
+ sslEncryption = receivedMsg.getSSLEncryption();
+
// Publish our start message
ReplServerStartMessage outMsg =
new ReplServerStartMessage(replicationServerId,
replicationServerURL,
this.baseDn, windowSize, serverState,
- protocolVersion);
+ protocolVersion, sslEncryption);
session.publish(outMsg);
}
else
@@ -309,6 +307,11 @@
return; // we did not recognize the message, ignore it
}
+ if (!sslEncryption)
+ {
+ session.stopEncryption();
+ }
+
replicationCache = replicationServer.getReplicationCache(this.baseDn);
boolean started;
@@ -1230,6 +1233,10 @@
}
Attribute attr = new Attribute(type, ATTR_SERVER_STATE, values);
attributes.add(attr);
+
+ attributes.add(new Attribute("ssl-encryption",
+ String.valueOf(session.isEncrypted())));
+
return attributes;
}
diff --git a/opends/src/server/org/opends/server/types/CryptoManager.java b/opends/src/server/org/opends/server/types/CryptoManager.java
index 5713fe9..f29db43 100644
--- a/opends/src/server/org/opends/server/types/CryptoManager.java
+++ b/opends/src/server/org/opends/server/types/CryptoManager.java
@@ -26,7 +26,7 @@
*/
package org.opends.server.types;
import org.opends.messages.Message;
-
+import static org.opends.messages.CoreMessages.*;
import java.io.InputStream;
@@ -40,19 +40,29 @@
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
+import java.util.SortedSet;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.X509ExtendedKeyManager;
import org.opends.server.config.ConfigException;
+import org.opends.server.config.ConfigConstants;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.util.StaticUtils.*;
-
+import org.opends.server.util.SelectableCertificateKeyManager;
+import org.opends.server.api.Backend;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.backends.TrustStoreBackend;
+import org.opends.server.admin.std.server.CryptoManagerCfg;
/**
* This class provides the interface to the Directory Server
@@ -92,10 +102,23 @@
// The preferred MAC algorithm for the Directory Server.
private String preferredMACAlgorithm;
+ // The name of the local certificate to use for SSL.
+ private String sslCertNickname;
+ // Whether replication sessions use SSL encryption.
+ private boolean sslEncryption;
+
+ // The set of SSL protocols enabled or null for the default set.
+ private SortedSet<String> sslProtocols;
+
+ // The set of SSL cipher suites enabled or null for the default set.
+ private SortedSet<String> sslCipherSuites;
/**
- * Creates a new instance of this crypto manager object.
+ * Creates a new instance of this crypto manager object from a given
+ * configuration.
+ *
+ * @param cfg The configuration of this crypto manager.
*
* @throws ConfigException If a problem occurs while creating this
* crypto manager that is a result of a
@@ -106,7 +129,7 @@
* that is not the result of a
* problem in the configuration.
*/
- public CryptoManager()
+ public CryptoManager(CryptoManagerCfg cfg)
throws ConfigException, InitializationException
{
// FIXME -- Get the defaults from the configuration rather than
@@ -175,6 +198,11 @@
Message.raw("Can't get preferred cipher: " +
getExceptionMessage(e).toString()), e);
}
+
+ sslCertNickname = cfg.getSSLCertNickname();
+ sslEncryption = cfg.isSSLEncryption();
+ sslProtocols = cfg.getSSLProtocols();
+ sslCipherSuites = cfg.getSSLCipherSuites();
}
@@ -865,5 +893,122 @@
inflater.end();
}
}
+
+
+ /**
+ * Retrieve the ADS trust store backend.
+ * @return The ADS trust store backend.
+ * @throws ConfigException If the ADS trust store backend is
+ * not configured.
+ */
+ private TrustStoreBackend getTrustStoreBackend()
+ throws ConfigException
+ {
+ Backend b = DirectoryServer.getBackend(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ if (b == null)
+ {
+ Message msg =
+ ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_NOT_ENABLED.get(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ throw new ConfigException(msg);
+ }
+ if (!(b instanceof TrustStoreBackend))
+ {
+ Message msg =
+ ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS.get(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ throw new ConfigException(msg);
+ }
+ return (TrustStoreBackend)b;
+ }
+
+ /**
+ * Create an SSL context that may be used for communication to
+ * another ADS component.
+ *
+ * @param sslCertNickname The name of the local certificate to use,
+ * or null if none is specified.
+ * @return A new SSL Context.
+ * @throws ConfigException If the context could not be created.
+ */
+ public SSLContext getSslContext(String sslCertNickname)
+ throws ConfigException
+ {
+ SSLContext sslContext;
+ try
+ {
+ TrustStoreBackend trustStoreBackend = getTrustStoreBackend();
+ KeyManager[] keyManagers = trustStoreBackend.getKeyManagers();
+ TrustManager[] trustManagers =
+ trustStoreBackend.getTrustManagers();
+
+ sslContext = SSLContext.getInstance("TLS");
+
+ if (sslCertNickname == null)
+ {
+ sslContext.init(keyManagers, trustManagers, null);
+ }
+ else
+ {
+ X509ExtendedKeyManager[] extendedKeyManagers =
+ SelectableCertificateKeyManager.wrap(
+ keyManagers,
+ sslCertNickname);
+ sslContext.init(extendedKeyManagers, trustManagers, null);
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message =
+ ERR_CRYPTOMGR_SSL_CONTEXT_CANNOT_INITIALIZE.get(
+ getExceptionMessage(e));
+ throw new ConfigException(message, e);
+ }
+
+ return sslContext;
+ }
+
+
+ /**
+ * Get the name of the local certificate to use for SSL.
+ * @return The name of the local certificate to use for SSL.
+ */
+ public String getSslCertNickname()
+ {
+ return sslCertNickname;
+ }
+
+ /**
+ * Determine whether SSL encryption is enabled.
+ * @return true if SSL encryption is enabled.
+ */
+ public boolean isSslEncryption()
+ {
+ return sslEncryption;
+ }
+
+ /**
+ * Get the set of enabled SSL protocols.
+ * @return The set of enabled SSL protocols.
+ */
+ public SortedSet<String> getSslProtocols()
+ {
+ return sslProtocols;
+ }
+
+ /**
+ * Get the set of enabled SSL cipher suites.
+ * @return The set of enabled SSL cipher suites.
+ */
+ public SortedSet<String> getSslCipherSuites()
+ {
+ return sslCipherSuites;
+ }
}
diff --git a/opends/tests/unit-tests-testng/resource/config-changes.ldif b/opends/tests/unit-tests-testng/resource/config-changes.ldif
index c751436..b546bb7 100644
--- a/opends/tests/unit-tests-testng/resource/config-changes.ldif
+++ b/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -335,6 +335,25 @@
-
replace: ds-cfg-key-store-pin-file
+dn: cn=Crypto Manager,cn=config
+changetype: modify
+replace: ds-cfg-ssl-cert-nickname
+ds-cfg-ssl-cert-nickname: server-cert
+-
+
+dn: ds-cfg-backend-id=ads-truststore,cn=Backends,cn=config
+changetype: modify
+replace: ds-cfg-backend-enabled
+ds-cfg-backend-enabled: true
+-
+replace: ds-cfg-trust-store-file
+ds-cfg-trust-store-file: config/server.keystore
+-
+replace: ds-cfg-trust-store-pin
+ds-cfg-trust-store-pin: password
+-
+replace: ds-cfg-trust-store-pin-file
+
dn: cn=PKCS12,cn=Key Manager Providers,cn=config
changetype: modify
replace: ds-cfg-key-manager-provider-enabled
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
index e61f1d0..2e48a53 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -53,12 +53,9 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.LockFileManager;
import org.opends.server.extensions.ConfigFileHandler;
-import org.opends.server.loggers.AccessLogger;
import org.opends.server.loggers.TextErrorLogPublisher;
-import org.opends.server.loggers.ErrorLogger;
import org.opends.server.loggers.TextAccessLogPublisher;
import org.opends.server.loggers.debug.TextDebugLogPublisher;
-import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.plugins.InvocationCounterPlugin;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.asn1.ASN1Reader;
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
index ab60995..6557146 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
@@ -275,7 +275,7 @@
ServerSocket socket = TestCaseUtils.bindFreePort();
replServerPort = socket.getLocalPort();
socket.close();
-
+
// Change log
String replServerLdif =
"dn: " + "cn=Replication Server, " + synchroPluginStringDN + "\n"
@@ -334,7 +334,7 @@
assertEquals(modOp.getResultCode(), ResultCode.SUCCESS);
}
}
-
+
@Test(enabled=true)
public void protocolVersion() throws Exception
{
@@ -349,24 +349,25 @@
ProtocolVersion.setCurrentVersion((short)2);
ReplicationBroker broker = new ReplicationBroker(
- new ServerState(),
- baseDn,
- (short) 13, 0, 0, 0, 0, 1000, 0);
-
+ new ServerState(),
+ baseDn,
+ (short) 13, 0, 0, 0, 0, 1000, 0,
+ getReplSessionSecurity());
+
// Check broker hard-coded version
short pversion = broker.getProtocolVersion();
assertEquals(pversion, 2);
-
+
// Connect the broker to the replication server
ProtocolVersion.setCurrentVersion((short)0);
ArrayList<String> servers = new ArrayList<String>(1);
servers.add("localhost:" + replServerPort);
broker.start(servers);
TestCaseUtils.sleep(100); // wait for connection established
-
+
// Check broker negociated version
pversion = broker.getProtocolVersion();
assertEquals(pversion, 0);
- }
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
index 016d567..35ba5fd 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -28,13 +28,13 @@
import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
+import org.opends.server.config.ConfigException;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import java.net.SocketException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@@ -58,6 +58,7 @@
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.plugin.PersistentServerState;
import org.opends.server.replication.plugin.ReplicationBroker;
+import org.opends.server.replication.protocol.ReplSessionSecurity;
import org.opends.server.schema.DirectoryStringSyntax;
import org.opends.server.schema.IntegerSyntax;
import org.opends.server.types.Attribute;
@@ -106,7 +107,7 @@
private DN monitorDn;
private String monitorAttr;
private long lastCount;
-
+
/**
* schema check flag
*/
@@ -141,7 +142,7 @@
protected ReplicationBroker openReplicationSession(
final DN baseDn, short serverId, int window_size,
int port, int timeout, boolean emptyOldChanges)
- throws Exception, SocketException
+ throws Exception
{
ServerState state;
if (emptyOldChanges)
@@ -150,7 +151,8 @@
state = new ServerState();
ReplicationBroker broker = new ReplicationBroker(
- state, baseDn, serverId, 0, 0, 0, 0, window_size, 0);
+ state, baseDn, serverId, 0, 0, 0, 0, window_size, 0,
+ getReplSessionSecurity());
ArrayList<String> servers = new ArrayList<String>(1);
servers.add("localhost:" + port);
broker.start(servers);
@@ -188,10 +190,11 @@
protected ReplicationBroker openReplicationSession(
final DN baseDn, short serverId, int window_size,
int port, int timeout, ServerState state)
- throws Exception, SocketException
+ throws Exception
{
ReplicationBroker broker = new ReplicationBroker(
- state, baseDn, serverId, 0, 0, 0, 0, window_size, 0);
+ state, baseDn, serverId, 0, 0, 0, 0, window_size, 0,
+ getReplSessionSecurity());
ArrayList<String> servers = new ArrayList<String>(1);
servers.add("localhost:" + port);
broker.start(servers);
@@ -210,7 +213,7 @@
final DN baseDn, short serverId, int window_size,
int port, int timeout, int maxSendQueue, int maxRcvQueue,
boolean emptyOldChanges)
- throws Exception, SocketException
+ throws Exception
{
ServerState state;
if (emptyOldChanges)
@@ -220,7 +223,8 @@
ReplicationBroker broker = new ReplicationBroker(
state, baseDn, serverId, maxRcvQueue, 0,
- maxSendQueue, 0, window_size, 0);
+ maxSendQueue, 0, window_size, 0,
+ getReplSessionSecurity());
ArrayList<String> servers = new ArrayList<String>(1);
servers.add("localhost:" + port);
broker.start(servers);
@@ -367,7 +371,7 @@
while (op.getSearchEntries().isEmpty() && (count<100));
if (op.getSearchEntries().isEmpty())
throw new Exception("Could not read monitoring information");
-
+
SearchResultEntry entry = op.getSearchEntries().getFirst();
AttributeType attrType =
DirectoryServer.getDefaultAttributeType(attr);
@@ -481,7 +485,7 @@
LockManager.unlock(dn, lock);
}
}
-
+
/**
* Update the monitor count for the specified monitor attribute.
*/
@@ -498,7 +502,7 @@
assertTrue(false);
}
}
-
+
/**
* Get the delta between the current / last monitor counts.
* @return The delta between the current and last monitor count.
@@ -535,7 +539,7 @@
mods.add(mod);
return mods;
}
-
+
/**
* Utility method to create, run a task and check its result.
*/
@@ -606,4 +610,17 @@
"The task completed in an unexpected state");
}
+ /**
+ * Create a new replication session security object that can be used in
+ * unit tests.
+ *
+ * @return A new replication session security object.
+ * @throws ConfigException If an error occurs.
+ */
+ protected static ReplSessionSecurity getReplSessionSecurity()
+ throws ConfigException
+ {
+ return new ReplSessionSecurity(null, null, null, true);
+ }
+
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java
index be4b289..e07fa06 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java
@@ -29,8 +29,6 @@
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.ChangeNumber;
-import org.opends.server.replication.plugin.ReplicationBroker;
-import org.opends.server.replication.plugin.Historical;
import org.opends.server.replication.protocol.ModifyMsg;
import org.opends.server.TestCaseUtils;
import org.opends.server.protocols.internal.InternalClientConnection;
@@ -71,7 +69,7 @@
// Create an internal connection.
connection = InternalClientConnection.getRootConnection();
-
+
// find a free port for the replicationServer
ServerSocket socket = TestCaseUtils.bindFreePort();
replServerPort = socket.getLocalPort();
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
index 06bba70..1866047 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -493,7 +493,7 @@
{
state.update(new ChangeNumber((long)1, 1,(short)1));
ServerStartMessage msg = new ServerStartMessage(serverId, baseDN,
- window, window, window, window, window, window, state, (short)1);
+ window, window, window, window, window, window, state, (short)1, true);
ServerStartMessage newMsg = new ServerStartMessage(msg.getBytes());
assertEquals(msg.getServerId(), newMsg.getServerId());
assertEquals(msg.getBaseDn(), newMsg.getBaseDn());
@@ -503,6 +503,7 @@
assertEquals(msg.getMaxSendQueue(), newMsg.getMaxSendQueue());
assertEquals(msg.getWindowSize(), newMsg.getWindowSize());
assertEquals(msg.getHeartbeatInterval(), newMsg.getHeartbeatInterval());
+ assertEquals(msg.getSSLEncryption(), newMsg.getSSLEncryption());
assertEquals(msg.getServerState().getMaxChangeNumber((short)1),
newMsg.getServerState().getMaxChangeNumber((short)1));
assertEquals(msg.getVersion(), newMsg.getVersion());
@@ -526,15 +527,16 @@
{
state.update(new ChangeNumber((long)1, 1,(short)1));
ReplServerStartMessage msg = new ReplServerStartMessage(serverId,
- url, baseDN, window, state, (short)1);
+ url, baseDN, window, state, (short)1, true);
ReplServerStartMessage newMsg = new ReplServerStartMessage(msg.getBytes());
assertEquals(msg.getServerId(), newMsg.getServerId());
+ assertEquals(msg.getServerURL(), newMsg.getServerURL());
assertEquals(msg.getBaseDn(), newMsg.getBaseDn());
assertEquals(msg.getWindowSize(), newMsg.getWindowSize());
- assertEquals(msg.getWindowSize(), newMsg.getWindowSize());
assertEquals(msg.getServerState().getMaxChangeNumber((short)1),
newMsg.getServerState().getMaxChangeNumber((short)1));
assertEquals(msg.getVersion(), newMsg.getVersion());
+ assertEquals(msg.getSSLEncryption(), newMsg.getSSLEncryption());
}
/**
@@ -548,7 +550,7 @@
WindowMessage newMsg = new WindowMessage(msg.getBytes());
assertEquals(msg.getNumAck(), newMsg.getNumAck());
}
-
+
/**
* Test that WindowProbe encoding and decoding works
* by checking that : new WindowProbe(msg.getBytes()) does not throws
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/DbHandlerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/DbHandlerTest.java
index bd0bf55..3488877 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/DbHandlerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/DbHandlerTest.java
@@ -34,9 +34,6 @@
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.protocol.DeleteMsg;
-import org.opends.server.replication.server.ReplicationServer;
-import org.opends.server.replication.server.ReplicationDbEnv;
-import org.opends.server.replication.server.DbHandler;
import org.opends.server.types.DN;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
index e3eed8c..0e1509f 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplicationServerTest.java
@@ -48,25 +48,14 @@
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.plugin.ReplicationBroker;
-import org.opends.server.replication.protocol.AddMsg;
-import org.opends.server.replication.protocol.DeleteMsg;
-import org.opends.server.replication.protocol.ModifyDNMsg;
-import org.opends.server.replication.protocol.ModifyDnContext;
-import org.opends.server.replication.protocol.ModifyMsg;
-import org.opends.server.replication.protocol.ProtocolVersion;
-import org.opends.server.replication.protocol.ReplServerStartMessage;
-import org.opends.server.replication.protocol.ReplicationMessage;
-import org.opends.server.replication.protocol.ServerStartMessage;
-import org.opends.server.replication.protocol.SocketSession;
-import org.opends.server.replication.protocol.WindowMessage;
-import org.opends.server.replication.protocol.WindowProbe;
-import org.opends.server.replication.server.ReplicationServer;
+import org.opends.server.replication.protocol.*;
import org.opends.server.types.Attribute;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.RDN;
+import org.opends.server.types.DirectoryConfig;
import org.opends.server.util.TimeThread;
import org.opends.server.workflowelement.localbackend.LocalBackendModifyDNOperation;
import org.testng.annotations.AfterClass;
@@ -782,14 +771,20 @@
* This should guarantee that old changes are not perturbing this test.
*/
- // open the first session to the
+ // open the first session to the replication server
+ String serverURL = "localhost:" + replicationServerPort;
InetSocketAddress ServerAddr = new InetSocketAddress(
InetAddress.getByName("localhost"), replicationServerPort);
Socket socket = new Socket();
socket.setReceiveBufferSize(1000000);
socket.setTcpNoDelay(true);
socket.connect(ServerAddr, 500);
- SocketSession session = new SocketSession(socket);
+ ReplSessionSecurity replSessionSecurity = getReplSessionSecurity();
+ ProtocolSession session =
+ replSessionSecurity.createClientSession(serverURL, socket);
+
+ boolean sslEncryption =
+ DirectoryConfig.getCryptoManager().isSslEncryption();
try
{
@@ -797,7 +792,7 @@
ServerStartMessage msg =
new ServerStartMessage((short) 1723, DN.decode("dc=example,dc=com"),
0, 0, 0, 0, WINDOW, (long) 5000, new ServerState(),
- ProtocolVersion.currentVersion());
+ ProtocolVersion.currentVersion(), sslEncryption);
session.publish(msg);
// Read the Replication Server state from the ReplServerStartMessage that
@@ -807,6 +802,11 @@
int serverwindow = replStartMsg.getWindowSize();
ServerState replServerState = replStartMsg.getServerState();
+ if (!sslEncryption)
+ {
+ session.stopEncryption();
+ }
+
// close the session
session.close();
@@ -815,19 +815,24 @@
socket.setReceiveBufferSize(1000000);
socket.setTcpNoDelay(true);
socket.connect(ServerAddr, 500);
- session = new SocketSession(socket);
+ session = replSessionSecurity.createClientSession(serverURL, socket);
// send a ServerStartMessage containing the ServerState that was just
// received.
msg = new ServerStartMessage(
(short) 1724, DN.decode("dc=example,dc=com"),
0, 0, 0, 0, WINDOW, (long) 5000, replServerState,
- ProtocolVersion.currentVersion());
+ ProtocolVersion.currentVersion(), sslEncryption);
session.publish(msg);
// Read the ReplServerStartMessage that come back.
session.receive();
+ if (!sslEncryption)
+ {
+ session.stopEncryption();
+ }
+
// Now comes the real test : check that the Replication Server
// answers correctly to a WindowProbe Message.
session.publish(new WindowProbe());
--
Gitblit v1.10.0