From 410c65c22c94384d9afd0741b618c96a97b81ed6 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Tue, 26 Jun 2007 18:57:13 +0000
Subject: [PATCH] Update the way that the password policy import plugin encodes passwords during an LDIF import. The basic practice is as follows:
---
opends/resource/schema/02-config.ldif | 11
opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java | 635 +++++++++++++++++++++++++++++++++------
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml | 119 +++++++
opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/PasswordPolicyImportPluginTestCase.java | 64 +++
opends/resource/config/config.ldif | 3
opends/src/server/org/opends/server/messages/PluginMessages.java | 91 +++++
6 files changed, 818 insertions(+), 105 deletions(-)
diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index d1dad8b..59a1c70 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -1068,7 +1068,7 @@
objectClass: ds-cfg-password-policy
cn: Root Password Policy
ds-cfg-password-attribute: userPassword
-ds-cfg-default-password-storage-scheme: SSHA
+ds-cfg-default-password-storage-scheme: SSHA512
ds-cfg-allow-expired-password-changes: false
ds-cfg-allow-multiple-password-values: false
ds-cfg-allow-pre-encoded-passwords: false
@@ -1278,6 +1278,7 @@
dn: cn=Password Policy Import,cn=Plugins,cn=config
objectClass: top
objectClass: ds-cfg-plugin
+objectClass: ds-cfg-password-policy-import-plugin
cn: Password Policy Import
ds-cfg-plugin-class: org.opends.server.plugins.PasswordPolicyImportPlugin
ds-cfg-plugin-enabled: true
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index ac833f7..4c40418 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1457,6 +1457,12 @@
NAME 'ds-cfg-plugin-order-intermediate-response'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.429
+ NAME 'ds-cfg-default-user-password-storage-scheme'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.430
+ NAME 'ds-cfg-default-auth-password-storage-scheme'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
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 )
@@ -2048,4 +2054,9 @@
ds-cfg-plugin-order-search-result-reference $
ds-cfg-plugin-order-intermediate-response )
X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.115
+ NAME 'ds-cfg-password-policy-import-plugin' SUP ds-cfg-plugin STRUCTURAL
+ MAY ( ds-cfg-default-user-password-storage-scheme $
+ ds-cfg-default-auth-password-storage-scheme )
+ X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml
new file mode 100644
index 0000000..32f2eb4
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+! 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.
+! -->
+
+<adm:managed-object name="password-policy-import-plugin"
+plural-name="password-policy-import-plugins"
+package="org.opends.server.admin.std" extends="plugin"
+xmlns:adm="http://www.opends.org/admin"
+xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ is used to ensure that clear-text passwords contained in LDIF entries are
+ properly encoded before they are stored in the appropriate Directory Server
+ backend.
+ </adm:synopsis>
+
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.115</ldap:oid>
+ <ldap:name>ds-cfg-password-policy-import-plugin</ldap:name>
+ <ldap:superior>ds-cfg-plugin</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+
+ <adm:property-override name="plugin-class">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>
+ org.opends.server.plugins.PasswordPolicyImportPlugin
+ </adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+
+ <adm:property name="default-user-password-storage-scheme" mandatory="false"
+ multi-valued="true">
+ <adm:synopsis>
+ Specifies the name(s) of the storage scheme(s) that will be used for
+ encoding passwords contained in attributes with the user password syntax
+ for entries that do not include the ds-pwp-password-policy-dn attribute to
+ specify which password policy should be used to govern them.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:alias>
+ <adm:synopsis>
+ If the default password policy uses the attribute with the user
+ password syntax, then the server will use the default password storage
+ schemes for that password policy. Otherwise, it will encode user
+ password values using the "SSHA" scheme.
+ </adm:synopsis>
+ </adm:alias>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.429</ldap:oid>
+ <ldap:name>ds-cfg-default-user-password-storage-scheme</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
+ <adm:property name="default-auth-password-storage-scheme" mandatory="false"
+ multi-valued="true">
+ <adm:synopsis>
+ Specifies the name(s) of the storage scheme(s) that will be used for
+ encoding passwords contained in attributes with the auth password syntax
+ for entries that do not include the ds-pwp-password-policy-dn attribute to
+ specify which password policy should be used to govern them.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:alias>
+ <adm:synopsis>
+ If the default password policy uses an attribute with the auth
+ password syntax, then the server will use the default password storage
+ schemes for that password policy. Otherwise, it will encode auth
+ password values using the "SHA1" scheme.
+ </adm:synopsis>
+ </adm:alias>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.430</ldap:oid>
+ <ldap:name>ds-cfg-default-auth-password-storage-scheme</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
+</adm:managed-object>
+
diff --git a/opends/src/server/org/opends/server/messages/PluginMessages.java b/opends/src/server/org/opends/server/messages/PluginMessages.java
index 450051b..ce1b4b0 100644
--- a/opends/src/server/org/opends/server/messages/PluginMessages.java
+++ b/opends/src/server/org/opends/server/messages/PluginMessages.java
@@ -789,6 +789,69 @@
/**
+ * The message ID for the message that will be used if the password policy
+ * import plugin is not configured with any default auth password schemes and
+ * the SHA1 scheme is not available. This takes a single argument, which is
+ * the name of the SHA1 scheme.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_AUTH_SCHEMES =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_ERROR | 69;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user specifies a
+ * default auth password storage scheme that is unknown to the server. This
+ * takes a single argument, which is the specified scheme name.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_AUTH_SCHEME =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_ERROR | 70;
+
+
+
+ /**
+ * The message ID for the message that will be used if the password policy
+ * import plugin is not configured with any default user password schemes and
+ * the SSHA scheme is not available. This takes a single argument, which is
+ * the name of the SSHA scheme.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_USER_SCHEMES =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_ERROR | 71;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user specifies a
+ * default user password storage scheme that is unknown to the server. This
+ * takes a single argument, which is the specified scheme name.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_USER_SCHEME =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_ERROR | 72;
+
+
+
+ /**
+ * The message ID for the message that will be used if an entry references a
+ * custom password policy that does not exist. This takes two arguments,
+ * which are the DN of the target entry and the DN of the password policy.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_NO_SUCH_POLICY =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_WARNING | 73;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to decode the custom passwod policy DN. This takes two arguments,
+ * which are the DN of the target entry and a message explaining the problem
+ * that occured.
+ */
+ public static final int MSGID_PLUGIN_PWIMPORT_CANNOT_DECODE_POLICY_DN =
+ CATEGORY_MASK_PLUGIN | SEVERITY_MASK_SEVERE_WARNING | 74;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -1143,6 +1206,34 @@
"An error occurred while attempting to encode a password " +
"value stored in attribute %s of user entry %s: %s. " +
"Password values for this user will not be encoded");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_AUTH_SCHEMES,
+ "The password policy import plugin is not configured " +
+ "any default auth password schemes, and the server does " +
+ "not support the %s auth password scheme");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_AUTH_SCHEME,
+ "Auth password storage scheme %s referenced by the " +
+ "password policy import plugin is not configured for use " +
+ "in the server");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_USER_SCHEMES,
+ "The password policy import plugin is not configured " +
+ "any default user password schemes, and the server does " +
+ "not support the %s auth password scheme");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_USER_SCHEME,
+ "User password storage scheme %s referenced by the " +
+ "password policy import plugin is not configured for use " +
+ "in the server");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_NO_SUCH_POLICY,
+ "Entry '%s' indicates that it uses custom password " +
+ "policy '%s', but no such policy is defined in the " +
+ "server. Any passwords contained in the entry will be " +
+ "encoded using the default storage schemes, but " +
+ "authentication as this user may not be possible");
+ registerMessage(MSGID_PLUGIN_PWIMPORT_CANNOT_DECODE_POLICY_DN,
+ "An error occurred while attempting to decode the " +
+ "value of the custom password policy attribute in " +
+ "entry '%s': %s. Any passwords contained in the entry " +
+ "will be encoded using the default storage schemes, but " +
+ "authentication as this user may not be possible");
registerMessage(MSGID_PLUGIN_TYPE_NOT_SUPPORTED,
diff --git a/opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java b/opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java
index e35cd8b..38a47cb 100644
--- a/opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java
+++ b/opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java
@@ -30,6 +30,7 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
@@ -38,7 +39,9 @@
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.meta.PluginCfgDefn;
-import org.opends.server.admin.std.server.PluginCfg;
+import org.opends.server.admin.std.server.PasswordPolicyImportPluginCfg;
+import org.opends.server.api.Backend;
+import org.opends.server.api.ImportTaskListener;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.api.plugin.DirectoryServerPlugin;
import org.opends.server.api.plugin.LDIFPluginResult;
@@ -46,6 +49,7 @@
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PasswordPolicy;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.schema.AuthPasswordSyntax;
import org.opends.server.schema.UserPasswordSyntax;
import org.opends.server.types.Attribute;
@@ -53,18 +57,22 @@
import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.ResultCode;
-import org.opends.server.types.DebugLogLevel;
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.extensions.ExtensionsConstants.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.PluginMessages.*;
+import static org.opends.server.schema.SchemaConstants.*;
import static org.opends.server.util.StaticUtils.*;
@@ -75,21 +83,37 @@
* that all of the password values are properly encoded before they are stored.
*/
public final class PasswordPolicyImportPlugin
- extends DirectoryServerPlugin<PluginCfg>
- implements ConfigurationChangeListener<PluginCfg>
+ extends DirectoryServerPlugin<PasswordPolicyImportPluginCfg>
+ implements ConfigurationChangeListener<PasswordPolicyImportPluginCfg>,
+ ImportTaskListener
{
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
- // The sets of password storage schemes for the auth password attributes.
- private final HashMap<AttributeType,PasswordStorageScheme[]>
- authPasswordSchemes;
- // The sets of password storage schemes for the user password attributes.
- private final HashMap<AttributeType,PasswordStorageScheme[]>
- userPasswordSchemes;
+
+ // The attribute type used to specify the password policy for an entry.
+ private AttributeType customPolicyAttribute;
+
+ // The set of attribute types defined in the schema with the auth password
+ // syntax.
+ private AttributeType[] authPasswordTypes;
+
+ // The set of attribute types defined in the schema with the user password
+ // syntax.
+ private AttributeType[] userPasswordTypes;
+
+ // The set of password storage schemes to use for the various password
+ // policies defined in the server.
+ private HashMap<DN,PasswordStorageScheme[]> schemesByPolicy;
+
+ // The default password storage schemes for auth password attributes.
+ private PasswordStorageScheme[] defaultAuthPasswordSchemes;
+
+ // The default password storage schemes for user password attributes.
+ private PasswordStorageScheme[] defaultUserPasswordSchemes;
@@ -97,82 +121,11 @@
* Creates a new instance of this Directory Server plugin. Every plugin must
* implement a default constructor (it is the only one that will be used to
* create plugins defined in the configuration), and every plugin constructor
- * must call <CODE>super()</CODE> as its first element.
+ * must call {@code super()} as its first element.
*/
public PasswordPolicyImportPlugin()
{
super();
-
-
- // Get the password policies from the Directory Server configuration. This
- // is done in the constructor to allow the instance variables to be declared
- // "final".
- authPasswordSchemes = new HashMap<AttributeType,PasswordStorageScheme[]>();
- userPasswordSchemes = new HashMap<AttributeType,PasswordStorageScheme[]>();
- for (PasswordPolicy p : DirectoryServer.getPasswordPolicies())
- {
- AttributeType t = p.getPasswordAttribute();
- if (p.usesAuthPasswordSyntax())
- {
- PasswordStorageScheme[] schemes = authPasswordSchemes.get(t);
- if (schemes == null)
- {
- CopyOnWriteArrayList<PasswordStorageScheme> defaultSchemes =
- p.getDefaultStorageSchemes();
- schemes = new PasswordStorageScheme[defaultSchemes.size()];
- defaultSchemes.toArray(schemes);
- authPasswordSchemes.put(t, schemes);
- }
- else
- {
- LinkedHashSet<PasswordStorageScheme> newSchemes =
- new LinkedHashSet<PasswordStorageScheme>();
- for (PasswordStorageScheme s : schemes)
- {
- newSchemes.add(s);
- }
-
- for (PasswordStorageScheme s : p.getDefaultStorageSchemes())
- {
- newSchemes.add(s);
- }
-
- schemes = new PasswordStorageScheme[newSchemes.size()];
- newSchemes.toArray(schemes);
- authPasswordSchemes.put(t, schemes);
- }
- }
- else
- {
- PasswordStorageScheme[] schemes = userPasswordSchemes.get(t);
- if (schemes == null)
- {
- CopyOnWriteArrayList<PasswordStorageScheme> defaultSchemes =
- p.getDefaultStorageSchemes();
- schemes = new PasswordStorageScheme[defaultSchemes.size()];
- defaultSchemes.toArray(schemes);
- userPasswordSchemes.put(t, schemes);
- }
- else
- {
- LinkedHashSet<PasswordStorageScheme> newSchemes =
- new LinkedHashSet<PasswordStorageScheme>();
- for (PasswordStorageScheme s : schemes)
- {
- newSchemes.add(s);
- }
-
- for (PasswordStorageScheme s : p.getDefaultStorageSchemes())
- {
- newSchemes.add(s);
- }
-
- schemes = new PasswordStorageScheme[newSchemes.size()];
- newSchemes.toArray(schemes);
- userPasswordSchemes.put(t, schemes);
- }
- }
- }
}
@@ -182,10 +135,14 @@
*/
@Override()
public final void initializePlugin(Set<PluginType> pluginTypes,
- PluginCfg configuration)
+ PasswordPolicyImportPluginCfg configuration)
throws ConfigException
{
- configuration.addChangeListener(this);
+ configuration.addPasswordPolicyImportChangeListener(this);
+
+ customPolicyAttribute =
+ DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_POLICY_DN, true);
+
// Make sure that the plugin has been enabled for the appropriate types.
for (PluginType t : pluginTypes)
@@ -203,6 +160,166 @@
throw new ConfigException(msgID, message);
}
}
+
+
+ // Get the set of default password storage schemes for auth password
+ // attributes.
+ PasswordPolicy defaultPolicy = DirectoryServer.getDefaultPasswordPolicy();
+ Set<String> authSchemesSet =
+ configuration.getDefaultAuthPasswordStorageScheme();
+ if ((authSchemesSet == null) || authSchemesSet.isEmpty())
+ {
+ if (defaultPolicy.usesAuthPasswordSyntax())
+ {
+ CopyOnWriteArrayList<PasswordStorageScheme> schemeList =
+ defaultPolicy.getDefaultStorageSchemes();
+ defaultAuthPasswordSchemes =
+ new PasswordStorageScheme[schemeList.size()];
+ schemeList.toArray(defaultAuthPasswordSchemes);
+ }
+ else
+ {
+ defaultAuthPasswordSchemes = new PasswordStorageScheme[1];
+ defaultAuthPasswordSchemes[0] =
+ DirectoryServer.getAuthPasswordStorageScheme(
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1);
+ if (defaultAuthPasswordSchemes[0] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_AUTH_SCHEMES;
+ String message = getMessage(msgID,
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1);
+ throw new ConfigException(msgID, message);
+ }
+ }
+ }
+ else
+ {
+ defaultAuthPasswordSchemes =
+ new PasswordStorageScheme[authSchemesSet.size()];
+ int i=0;
+ for (String schemeName : authSchemesSet)
+ {
+ defaultAuthPasswordSchemes[i] =
+ DirectoryServer.getAuthPasswordStorageScheme(schemeName);
+ if (defaultAuthPasswordSchemes[i] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_AUTH_SCHEME;
+ String message = getMessage(msgID, schemeName);
+ throw new ConfigException(msgID, message);
+ }
+ i++;
+ }
+ }
+
+
+ // Get the set of default password storage schemes for user password
+ // attributes.
+ Set<String> userSchemeSet =
+ configuration.getDefaultUserPasswordStorageScheme();
+ if ((userSchemeSet == null) || userSchemeSet.isEmpty())
+ {
+ if (! defaultPolicy.usesAuthPasswordSyntax())
+ {
+ CopyOnWriteArrayList<PasswordStorageScheme> schemeList =
+ defaultPolicy.getDefaultStorageSchemes();
+ defaultUserPasswordSchemes =
+ new PasswordStorageScheme[schemeList.size()];
+ schemeList.toArray(defaultUserPasswordSchemes);
+ }
+ else
+ {
+ defaultUserPasswordSchemes = new PasswordStorageScheme[1];
+ defaultUserPasswordSchemes[0] =
+ DirectoryServer.getPasswordStorageScheme(
+ toLowerCase(STORAGE_SCHEME_NAME_SALTED_SHA_1));
+ if (defaultUserPasswordSchemes[0] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_USER_SCHEMES;
+ String message = getMessage(msgID, STORAGE_SCHEME_NAME_SALTED_SHA_1);
+ throw new ConfigException(msgID, message);
+ }
+ }
+ }
+ else
+ {
+ defaultUserPasswordSchemes =
+ new PasswordStorageScheme[userSchemeSet.size()];
+ int i=0;
+ for (String schemeName : userSchemeSet)
+ {
+ defaultUserPasswordSchemes[i] =
+ DirectoryServer.getPasswordStorageScheme(toLowerCase(schemeName));
+ if (defaultUserPasswordSchemes[i] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_USER_SCHEME;
+ String message = getMessage(msgID, schemeName);
+ throw new ConfigException(msgID, message);
+ }
+ i++;
+ }
+ }
+
+ processImportBegin(null, null);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processImportBegin(Backend backend, LDIFImportConfig config)
+ {
+ // Find the set of attribute types with the auth password and user password
+ // syntax defined in the schema.
+ HashSet<AttributeType> authPWTypes = new HashSet<AttributeType>();
+ HashSet<AttributeType> userPWTypes = new HashSet<AttributeType>();
+ for (AttributeType t : DirectoryServer.getAttributeTypes().values())
+ {
+ if (t.getSyntaxOID().equals(SYNTAX_AUTH_PASSWORD_OID))
+ {
+ authPWTypes.add(t);
+ }
+ else if (t.getSyntaxOID().equals(SYNTAX_USER_PASSWORD_OID))
+ {
+ userPWTypes.add(t);
+ }
+ }
+
+
+ // Get the set of password policies defined in the server and get the
+ // attribute types associated with them.
+ HashMap<DN,PasswordStorageScheme[]> schemeMap =
+ new HashMap<DN,PasswordStorageScheme[]>();
+ for (PasswordPolicy p : DirectoryServer.getPasswordPolicies())
+ {
+ CopyOnWriteArrayList<PasswordStorageScheme> schemeList =
+ p.getDefaultStorageSchemes();
+ PasswordStorageScheme[] schemeArray =
+ new PasswordStorageScheme[schemeList.size()];
+ schemeList.toArray(schemeArray);
+ schemeMap.put(p.getConfigEntryDN(), schemeArray);
+ }
+
+
+ AttributeType[] authTypesArray = new AttributeType[authPWTypes.size()];
+ AttributeType[] userTypesArray = new AttributeType[userPWTypes.size()];
+ authPWTypes.toArray(authTypesArray);
+ userPWTypes.toArray(userTypesArray);
+
+ schemesByPolicy = schemeMap;
+ authPasswordTypes = authTypesArray;
+ userPasswordTypes = userTypesArray;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processImportEnd(Backend backend, LDIFImportConfig config,
+ boolean successful)
+ {
+ // No implementation is required.
}
@@ -218,18 +335,157 @@
ArrayList<ByteString> encodedValueList = new ArrayList<ByteString>();
+ // See if the entry explicitly states the password policy that it should
+ // use. If so, then only use it to perform the encoding.
+ List<Attribute> attrList = entry.getAttribute(customPolicyAttribute);
+ if (attrList != null)
+ {
+ DN policyDN = null;
+ PasswordPolicy policy = null;
+policyLoop:
+ for (Attribute a : attrList)
+ {
+ for (AttributeValue v : a.getValues())
+ {
+ try
+ {
+ policyDN = DN.decode(v.getValue());
+ policy = DirectoryServer.getPasswordPolicy(policyDN);
+ if (policy == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_SUCH_POLICY;
+ String message = getMessage(msgID, String.valueOf(entry.getDN()),
+ String.valueOf(policyDN));
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_WARNING,
+ message, msgID);
+ }
+ break policyLoop;
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_CANNOT_DECODE_POLICY_DN;
+ String message = getMessage(msgID, String.valueOf(entry.getDN()),
+ de.getErrorMessage());
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_WARNING,
+ message, msgID);
+ break policyLoop;
+ }
+ }
+ }
+
+ if (policy != null)
+ {
+ PasswordStorageScheme[] schemes = schemesByPolicy.get(policyDN);
+ if (schemes != null)
+ {
+ attrList = entry.getAttribute(policy.getPasswordAttribute());
+ if (attrList == null)
+ {
+ return LDIFPluginResult.SUCCESS;
+ }
+
+ for (Attribute a : attrList)
+ {
+ encodedValueList.clear();
+
+ LinkedHashSet<AttributeValue> values = a.getValues();
+ Iterator<AttributeValue> iterator = values.iterator();
+ while (iterator.hasNext())
+ {
+ AttributeValue v = iterator.next();
+ ByteString value = v.getValue();
+
+ if (policy.usesAuthPasswordSyntax())
+ {
+ if (! AuthPasswordSyntax.isEncoded(value))
+ {
+ try
+ {
+ for (PasswordStorageScheme s : schemes)
+ {
+ encodedValueList.add(s.encodeAuthPassword(value));
+ }
+
+ iterator.remove();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_PLUGIN_PWPIMPORT_ERROR_ENCODING_PASSWORD;
+ String message = getMessage(msgID,
+ policy.getPasswordAttribute().getNameOrOID(),
+ String.valueOf(entry.getDN()),
+ stackTraceToSingleLineString(e));
+ logError(ErrorLogCategory.PLUGIN,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+
+ encodedValueList.clear();
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (! UserPasswordSyntax.isEncoded(value))
+ {
+ try
+ {
+ for (PasswordStorageScheme s : schemes)
+ {
+ encodedValueList.add(s.encodePasswordWithScheme(value));
+ }
+
+ iterator.remove();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_PLUGIN_PWPIMPORT_ERROR_ENCODING_PASSWORD;
+ String message = getMessage(msgID,
+ policy.getPasswordAttribute().getNameOrOID(),
+ String.valueOf(entry.getDN()),
+ stackTraceToSingleLineString(e));
+ logError(ErrorLogCategory.PLUGIN,
+ ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+
+ encodedValueList.clear();
+ break;
+ }
+ }
+ }
+ }
+
+ for (ByteString s : encodedValueList)
+ {
+ values.add(new AttributeValue(policy.getPasswordAttribute(), s));
+ }
+ }
+
+ return LDIFPluginResult.SUCCESS;
+ }
+ }
+ }
+
+
// Iterate through the list of auth password attributes. If any of them
// are present and their values are not encoded, then encode them with all
// appropriate schemes.
- for (AttributeType t : authPasswordSchemes.keySet())
+ for (AttributeType t : authPasswordTypes)
{
- List<Attribute> attrList = entry.getAttribute(t);
+ attrList = entry.getAttribute(t);
if ((attrList == null) || attrList.isEmpty())
{
continue;
}
- PasswordStorageScheme[] schemes = authPasswordSchemes.get(t);
for (Attribute a : attrList)
{
encodedValueList.clear();
@@ -244,7 +500,7 @@
{
try
{
- for (PasswordStorageScheme s : schemes)
+ for (PasswordStorageScheme s : defaultAuthPasswordSchemes)
{
encodedValueList.add(s.encodeAuthPassword(value));
}
@@ -282,15 +538,14 @@
// Iterate through the list of user password attributes. If any of them
// are present and their values are not encoded, then encode them with all
// appropriate schemes.
- for (AttributeType t : userPasswordSchemes.keySet())
+ for (AttributeType t : userPasswordTypes)
{
- List<Attribute> attrList = entry.getAttribute(t);
+ attrList = entry.getAttribute(t);
if ((attrList == null) || attrList.isEmpty())
{
continue;
}
- PasswordStorageScheme[] schemes = userPasswordSchemes.get(t);
for (Attribute a : attrList)
{
encodedValueList.clear();
@@ -305,7 +560,7 @@
{
try
{
- for (PasswordStorageScheme s : schemes)
+ for (PasswordStorageScheme s : defaultUserPasswordSchemes)
{
encodedValueList.add(s.encodePasswordWithScheme(value));
}
@@ -348,7 +603,8 @@
/**
* {@inheritDoc}
*/
- public boolean isConfigurationChangeAcceptable(PluginCfg configuration,
+ public boolean isConfigurationChangeAcceptable(
+ PasswordPolicyImportPluginCfg configuration,
List<String> unacceptableReasons)
{
boolean configAcceptable = true;
@@ -371,6 +627,86 @@
}
}
+
+ // Get the set of default password storage schemes for auth password
+ // attributes.
+ Set<String> authSchemesSet =
+ configuration.getDefaultAuthPasswordStorageScheme();
+ if ((authSchemesSet == null) || authSchemesSet.isEmpty())
+ {
+ PasswordStorageScheme[] defaultAuthSchemes = new PasswordStorageScheme[1];
+ defaultAuthSchemes[0] =
+ DirectoryServer.getAuthPasswordStorageScheme(
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1);
+ if (defaultAuthSchemes[0] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_AUTH_SCHEMES;
+ String message = getMessage(msgID,
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1);
+ unacceptableReasons.add(message);
+ configAcceptable = false;
+ }
+ }
+ else
+ {
+ PasswordStorageScheme[] defaultAuthSchemes =
+ new PasswordStorageScheme[authSchemesSet.size()];
+ int i=0;
+ for (String schemeName : authSchemesSet)
+ {
+ defaultAuthSchemes[i] =
+ DirectoryServer.getAuthPasswordStorageScheme(schemeName);
+ if (defaultAuthSchemes[i] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_AUTH_SCHEME;
+ String message = getMessage(msgID, schemeName);
+ unacceptableReasons.add(message);
+ configAcceptable = false;
+ }
+ i++;
+ }
+ }
+
+
+ // Get the set of default password storage schemes for user password
+ // attributes.
+ Set<String> userSchemeSet =
+ configuration.getDefaultUserPasswordStorageScheme();
+ if ((userSchemeSet == null) || userSchemeSet.isEmpty())
+ {
+ PasswordStorageScheme[] defaultUserSchemes = new PasswordStorageScheme[1];
+ defaultUserSchemes[0] =
+ DirectoryServer.getPasswordStorageScheme(
+ toLowerCase(STORAGE_SCHEME_NAME_SALTED_SHA_1));
+ if (defaultUserSchemes[0] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_USER_SCHEMES;
+ String message = getMessage(msgID, STORAGE_SCHEME_NAME_SALTED_SHA_1);
+ unacceptableReasons.add(message);
+ configAcceptable = false;
+ }
+ }
+ else
+ {
+ PasswordStorageScheme[] defaultUserSchemes =
+ new PasswordStorageScheme[userSchemeSet.size()];
+ int i=0;
+ for (String schemeName : userSchemeSet)
+ {
+ defaultUserSchemes[i] =
+ DirectoryServer.getPasswordStorageScheme(toLowerCase(schemeName));
+ if (defaultUserSchemes[i] == null)
+ {
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_USER_SCHEME;
+ String message = getMessage(msgID, schemeName);
+ unacceptableReasons.add(message);
+ configAcceptable = false;
+ }
+ i++;
+ }
+ }
+
+
return configAcceptable;
}
@@ -379,10 +715,115 @@
/**
* {@inheritDoc}
*/
- public ConfigChangeResult applyConfigurationChange(PluginCfg configuration)
+ public ConfigChangeResult applyConfigurationChange(
+ PasswordPolicyImportPluginCfg configuration)
{
- // No implementation is required.
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ ResultCode resultCode = ResultCode.SUCCESS;
+ boolean adminActionRequired = false;
+ ArrayList<String> messages = new ArrayList<String>();
+
+
+ // Get the set of default password storage schemes for auth password
+ // attributes.
+ PasswordPolicy defaultPolicy = DirectoryServer.getDefaultPasswordPolicy();
+ PasswordStorageScheme[] defaultAuthSchemes;
+ Set<String> authSchemesSet =
+ configuration.getDefaultAuthPasswordStorageScheme();
+ if ((authSchemesSet == null) || authSchemesSet.isEmpty())
+ {
+ if (defaultPolicy.usesAuthPasswordSyntax())
+ {
+ CopyOnWriteArrayList<PasswordStorageScheme> schemeList =
+ defaultPolicy.getDefaultStorageSchemes();
+ defaultAuthSchemes =
+ new PasswordStorageScheme[schemeList.size()];
+ schemeList.toArray(defaultAuthSchemes);
+ }
+ else
+ {
+ defaultAuthSchemes = new PasswordStorageScheme[1];
+ defaultAuthSchemes[0] =
+ DirectoryServer.getAuthPasswordStorageScheme(
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1);
+ if (defaultAuthSchemes[0] == null)
+ {
+ resultCode = DirectoryServer.getServerErrorResultCode();
+
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_AUTH_SCHEMES;
+ messages.add(getMessage(msgID,
+ AUTH_PASSWORD_SCHEME_NAME_SALTED_SHA_1));
+ }
+ }
+ }
+ else
+ {
+ defaultAuthSchemes = new PasswordStorageScheme[authSchemesSet.size()];
+ int i=0;
+ for (String schemeName : authSchemesSet)
+ {
+ defaultAuthSchemes[i] =
+ DirectoryServer.getAuthPasswordStorageScheme(schemeName);
+ if (defaultAuthSchemes[i] == null)
+ {
+ resultCode = DirectoryServer.getServerErrorResultCode();
+
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_AUTH_SCHEME;
+ messages.add(getMessage(msgID, schemeName));
+ }
+ i++;
+ }
+ }
+
+
+ // Get the set of default password storage schemes for user password
+ // attributes.
+ PasswordStorageScheme[] defaultUserSchemes;
+ Set<String> userSchemeSet =
+ configuration.getDefaultUserPasswordStorageScheme();
+ if ((userSchemeSet == null) || userSchemeSet.isEmpty())
+ {
+ if (! defaultPolicy.usesAuthPasswordSyntax())
+ {
+ CopyOnWriteArrayList<PasswordStorageScheme> schemeList =
+ defaultPolicy.getDefaultStorageSchemes();
+ defaultUserSchemes =
+ new PasswordStorageScheme[schemeList.size()];
+ schemeList.toArray(defaultUserSchemes);
+ }
+ else
+ {
+ defaultUserSchemes = new PasswordStorageScheme[1];
+ defaultUserSchemes[0] = DirectoryServer.getPasswordStorageScheme(
+ toLowerCase(STORAGE_SCHEME_NAME_SALTED_SHA_1));
+ if (defaultUserSchemes[0] == null)
+ {
+ resultCode = DirectoryServer.getServerErrorResultCode();
+
+ int msgID = MSGID_PLUGIN_PWIMPORT_NO_DEFAULT_USER_SCHEMES;
+ messages.add(getMessage(msgID, STORAGE_SCHEME_NAME_SALTED_SHA_1));
+ }
+ }
+ }
+ else
+ {
+ defaultUserSchemes = new PasswordStorageScheme[userSchemeSet.size()];
+ int i=0;
+ for (String schemeName : userSchemeSet)
+ {
+ defaultUserSchemes[i] =
+ DirectoryServer.getPasswordStorageScheme(toLowerCase(schemeName));
+ if (defaultUserSchemes[i] == null)
+ {
+ resultCode = DirectoryServer.getServerErrorResultCode();
+
+ int msgID = MSGID_PLUGIN_PWIMPORT_INVALID_DEFAULT_USER_SCHEME;
+ messages.add(getMessage(msgID, schemeName));
+ }
+ i++;
+ }
+ }
+
+ return new ConfigChangeResult(resultCode, adminActionRequired, messages);
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/PasswordPolicyImportPluginTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/PasswordPolicyImportPluginTestCase.java
index 7087eef..4e10d1b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/PasswordPolicyImportPluginTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/PasswordPolicyImportPluginTestCase.java
@@ -35,8 +35,8 @@
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.admin.std.meta.PluginCfgDefn;
-import org.opends.server.admin.std.server.PluginCfg;
+import org.opends.server.admin.std.meta.PasswordPolicyImportPluginCfgDefn;
+import org.opends.server.admin.std.server.PasswordPolicyImportPluginCfg;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
@@ -86,11 +86,59 @@
"dn: cn=Password Policy Import,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
"cn: Password Policy Import",
"ds-cfg-plugin-class: org.opends.server.plugins." +
"PasswordPolicyImportPlugin",
"ds-cfg-plugin-enabled: true",
- "ds-cfg-plugin-type: ldifImport");
+ "ds-cfg-plugin-type: ldifImport",
+ "",
+ "dn: cn=Password Policy Import,cn=Plugins,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
+ "cn: Password Policy Import",
+ "ds-cfg-plugin-class: org.opends.server.plugins." +
+ "PasswordPolicyImportPlugin",
+ "ds-cfg-plugin-enabled: true",
+ "ds-cfg-plugin-type: ldifImport",
+ "ds-cfg-default-user-password-storage-scheme: SSHA",
+ "",
+ "dn: cn=Password Policy Import,cn=Plugins,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
+ "cn: Password Policy Import",
+ "ds-cfg-plugin-class: org.opends.server.plugins." +
+ "PasswordPolicyImportPlugin",
+ "ds-cfg-plugin-enabled: true",
+ "ds-cfg-plugin-type: ldifImport",
+ "ds-cfg-default-user-password-storage-scheme: CRYPT",
+ "ds-cfg-default-user-password-storage-scheme: SSHA",
+ "",
+ "dn: cn=Password Policy Import,cn=Plugins,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
+ "cn: Password Policy Import",
+ "ds-cfg-plugin-class: org.opends.server.plugins." +
+ "PasswordPolicyImportPlugin",
+ "ds-cfg-plugin-enabled: true",
+ "ds-cfg-plugin-type: ldifImport",
+ "ds-cfg-default-auth-password-storage-scheme: SHA1",
+ "",
+ "dn: cn=Password Policy Import,cn=Plugins,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
+ "cn: Password Policy Import",
+ "ds-cfg-plugin-class: org.opends.server.plugins." +
+ "PasswordPolicyImportPlugin",
+ "ds-cfg-plugin-enabled: true",
+ "ds-cfg-plugin-type: ldifImport",
+ "ds-cfg-default-user-password-storage-scheme: SSHA",
+ "ds-cfg-default-auth-password-storage-scheme: SHA1"
+ );
Object[][] array = new Object[entries.size()][1];
for (int i=0; i < array.length; i++)
@@ -124,8 +172,9 @@
}
}
- PluginCfg configuration = AdminTestCaseUtils.getConfiguration(
- PluginCfgDefn.getInstance(), e);
+ PasswordPolicyImportPluginCfg configuration =
+ AdminTestCaseUtils.getConfiguration(
+ PasswordPolicyImportPluginCfgDefn.getInstance(), e);
PasswordPolicyImportPlugin plugin = new PasswordPolicyImportPlugin();
plugin.initializePlugin(pluginTypes, configuration);
@@ -155,6 +204,7 @@
"dn: cn=Password Policy Import,cn=Plugins,cn=config",
"objectClass: top",
"objectClass: ds-cfg-plugin",
+ "objectClass: ds-cfg-password-policy-import-plugin",
"cn: Password Policy Import",
"ds-cfg-plugin-class: org.opends.server.plugins." +
"PasswordPolicyImportPlugin",
@@ -200,9 +250,9 @@
}
- PluginCfg configuration =
+ PasswordPolicyImportPluginCfg configuration =
AdminTestCaseUtils.getConfiguration(
- PluginCfgDefn.getInstance(), e);
+ PasswordPolicyImportPluginCfgDefn.getInstance(), e);
PasswordPolicyImportPlugin plugin = new PasswordPolicyImportPlugin();
plugin.initializePlugin(pluginTypes, configuration);
--
Gitblit v1.10.0