| | |
| | | |
| | | |
| | | |
| | | import org.opends.server.types.DN; |
| | | import static org.opends.messages.CoreMessages.*; |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; |
| | | |
| | | import java.util.List; |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.loggers.debug.DebugLogger; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.TimeThread; |
| | | |
| | | |
| | | |
| | |
| | | public abstract class AuthenticationPolicy |
| | | { |
| | | /** |
| | | * The tracer object for the debug logger. |
| | | */ |
| | | private static final DebugTracer TRACER = DebugLogger.getTracer(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the authentication policy for the user provided user. The following |
| | | * algorithm is used in order to obtain the appropriate authentication policy: |
| | | * <ul> |
| | | * <li>if the user entry contains the {@code ds-pwp-password-policy-dn} |
| | | * attribute (whether real or virtual), then the referenced authentication |
| | | * policy will be returned |
| | | * <li>otherwise, a search is performed in order to find the nearest |
| | | * applicable password policy sub-entry to the user entry, |
| | | * <li>otherwise, the default password policy will be returned. |
| | | * </ul> |
| | | * |
| | | * @param userEntry |
| | | * The user entry. |
| | | * @param useDefaultOnError |
| | | * Indicates whether the server should fall back to using the default |
| | | * password policy if there is a problem with the configured policy |
| | | * for the user. |
| | | * @return The password policy for the user. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while attempting to determine the password |
| | | * policy for the user. |
| | | */ |
| | | public final static AuthenticationPolicy forUser(Entry userEntry, |
| | | boolean useDefaultOnError) throws DirectoryException |
| | | { |
| | | // First check to see if the ds-pwp-password-policy-dn is present. |
| | | String userDNString = userEntry.getDN().toString(); |
| | | AttributeType type = DirectoryServer.getAttributeType( |
| | | OP_ATTR_PWPOLICY_POLICY_DN, true); |
| | | List<Attribute> attrList = userEntry.getAttribute(type); |
| | | |
| | | if (attrList != null) |
| | | { |
| | | for (Attribute a : attrList) |
| | | { |
| | | if (a.isEmpty()) continue; |
| | | |
| | | AttributeValue v = a.iterator().next(); |
| | | DN subentryDN; |
| | | try |
| | | { |
| | | subentryDN = DN.decode(v.getValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugError("Could not parse password policy subentry " |
| | | + "DN %s for user %s: %s", v.getValue().toString(), |
| | | userDNString, stackTraceToSingleLineString(e)); |
| | | } |
| | | |
| | | Message message = ERR_PWPSTATE_CANNOT_DECODE_SUBENTRY_VALUE_AS_DN |
| | | .get(v.getValue().toString(), userDNString, e.getMessage()); |
| | | if (useDefaultOnError) |
| | | { |
| | | logError(message); |
| | | return DirectoryServer.getDefaultPasswordPolicy(); |
| | | } |
| | | else |
| | | { |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, message, |
| | | e); |
| | | } |
| | | } |
| | | |
| | | AuthenticationPolicy policy = DirectoryServer |
| | | .getAuthenticationPolicy(subentryDN); |
| | | if (policy == null) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugError("Password policy subentry %s for user %s " |
| | | + "is not defined in the Directory Server.", |
| | | String.valueOf(subentryDN), userDNString); |
| | | } |
| | | |
| | | Message message = ERR_PWPSTATE_NO_SUCH_POLICY.get(userDNString, |
| | | String.valueOf(subentryDN)); |
| | | if (useDefaultOnError) |
| | | { |
| | | logError(message); |
| | | return DirectoryServer.getDefaultPasswordPolicy(); |
| | | } |
| | | else |
| | | { |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), message); |
| | | } |
| | | } |
| | | |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugInfo("Using password policy subentry %s for user %s.", |
| | | String.valueOf(subentryDN), userDNString); |
| | | } |
| | | |
| | | return policy; |
| | | } |
| | | } |
| | | |
| | | // The ds-pwp-password-policy-dn attribute was not present, so instead |
| | | // search for the nearest applicable sub-entry. |
| | | List<SubEntry> pwpSubEntries = DirectoryServer.getSubentryManager() |
| | | .getSubentries(userEntry); |
| | | if ((pwpSubEntries != null) && (!pwpSubEntries.isEmpty())) |
| | | { |
| | | for (SubEntry subentry : pwpSubEntries) |
| | | { |
| | | try |
| | | { |
| | | if (subentry.getEntry().isPasswordPolicySubentry()) |
| | | { |
| | | AuthenticationPolicy policy = DirectoryServer |
| | | .getAuthenticationPolicy(subentry.getDN()); |
| | | if (policy == null) |
| | | { |
| | | // This shouldn't happen but if it does debug log |
| | | // this problem and fall back to default policy. |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugError("Found unknown password policy subentry " |
| | | + "DN %s for user %s", subentry.getDN().toString(), |
| | | userDNString); |
| | | } |
| | | break; |
| | | } |
| | | return policy; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugError("Could not parse password policy subentry " |
| | | + "DN %s for user %s: %s", subentry.getDN().toString(), |
| | | userDNString, stackTraceToSingleLineString(e)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // No authentication policy found, so use the global default. |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugInfo("Using the default password policy for user %s", |
| | | userDNString); |
| | | } |
| | | |
| | | return DirectoryServer.getDefaultPasswordPolicy(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new abstract authentication policy. |
| | | */ |
| | | protected AuthenticationPolicy() |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if this authentication policy is a password policy and |
| | | * the methods {@link #createAuthenticationPolicyState(Entry)} and |
| | | * {@link #createAuthenticationPolicyState(Entry, long)} will return a |
| | | * {@code PasswordPolicyState}. |
| | | * <p> |
| | | * The default implementation is to return {@code false}. |
| | | * |
| | | * @return {@code true} if this authentication policy is a password policy, |
| | | * otherwise {@code false}. |
| | | */ |
| | | public boolean isPasswordPolicy() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the authentication policy state object for the provided user using |
| | | * the current time as the basis for all time-based state logic (such as |
| | | * expiring passwords). |
| | | * <p> |
| | | * The default implementation is to call |
| | | * {@link #createAuthenticationPolicyState(Entry, long)} with the current |
| | | * time. |
| | | * |
| | | * @param userEntry |
| | | * The user's entry. |
| | | * @return The authentication policy state object for the provided user. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while attempting to initialize the state |
| | | * object from the provided user entry. |
| | | */ |
| | | public AuthenticationPolicyState createAuthenticationPolicyState( |
| | | Entry userEntry) throws DirectoryException |
| | | { |
| | | return createAuthenticationPolicyState(userEntry, TimeThread.getTime()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns an authentication policy state object for the provided user using |
| | | * the specified time as the basis for all time-based state logic (such as |
| | | * expiring passwords). |
| | | * |
| | | * @param userEntry |
| | | * The user's entry. |
| | | * @param time |
| | | * The time since the epoch to use for all time-based state logic |
| | | * (such as expiring passwords). |
| | | * @return The authentication policy state object for the provided user. |
| | | * @throws DirectoryException |
| | | * If a problem occurs while attempting to initialize the state |
| | | * object from the provided user entry. |
| | | */ |
| | | public abstract AuthenticationPolicyState createAuthenticationPolicyState( |
| | | Entry userEntry, long time) throws DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary work to finalize this authentication policy. |
| | | * <p> |
| | | * The default implementation is to do nothing. |