001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010 Sun Microsystems, Inc.
015 * Portions Copyright 2011-2016 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import org.forgerock.i18n.LocalizableMessage;
020import org.forgerock.i18n.slf4j.LocalizedLogger;
021import org.forgerock.opendj.ldap.ResultCode;
022import org.forgerock.opendj.server.config.server.
023        PasswordPolicySubentryVirtualAttributeCfg;
024import org.opends.server.api.AuthenticationPolicy;
025import org.opends.server.api.VirtualAttributeProvider;
026import org.opends.server.core.SearchOperation;
027import org.opends.server.types.*;
028import static org.opends.messages.ExtensionMessages.*;
029
030/**
031 * This class implements a virtual attribute provider to serve
032 * the pwdPolicySubentry operational attribute as described in
033 * Password Policy for LDAP Directories Internet-Draft.
034 */
035public class PasswordPolicySubentryVirtualAttributeProvider
036        extends VirtualAttributeProvider<
037        PasswordPolicySubentryVirtualAttributeCfg>
038{
039  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
040
041  /** Creates a new instance of this pwdPolicySubentry virtual attribute provider. */
042  public PasswordPolicySubentryVirtualAttributeProvider()
043  {
044    super();
045
046    // All initialization should be performed in the
047    // initializeVirtualAttributeProvider method.
048  }
049
050  @Override
051  public boolean isMultiValued()
052  {
053    return false;
054  }
055
056  @Override
057  public Attribute getValues(Entry entry, VirtualAttributeRule rule)
058  {
059    if (!entry.isSubentry() && !entry.isLDAPSubentry())
060    {
061      AuthenticationPolicy policy = null;
062
063      try
064      {
065        policy = AuthenticationPolicy.forUser(entry, false);
066      }
067      catch (DirectoryException de)
068      {
069        // Something went wrong while trying to
070        // retrieve password policy, log this.
071        logger.error(de.getMessageObject());
072
073        logger.traceException(de, "Failed to retrieve password policy for user %s",
074            entry.getName());
075      }
076
077      if (policy == null)
078      {
079        // No authentication policy: debug log this as an error since all
080        // entries should have at least the default password policy.
081        logger.trace("No applicable password policy for user %s", entry.getName());
082      }
083      else if (policy.isPasswordPolicy())
084      {
085        return Attributes.create(rule.getAttributeType(),
086            policy.getDN().toString());
087      }
088      else
089      {
090        // Not a password policy, could be PTA, etc.
091        if (logger.isTraceEnabled())
092        {
093          logger.trace("Authentication policy %s found for user %s is "
094              + "not a password policy", policy.getDN(), entry.getName());
095        }
096      }
097    }
098
099    return Attributes.empty(rule.getAttributeType());
100  }
101
102  @Override
103  public boolean isSearchable(VirtualAttributeRule rule,
104                              SearchOperation searchOperation,
105                              boolean isPreIndexed)
106  {
107    return false;
108  }
109
110  @Override
111  public void processSearch(VirtualAttributeRule rule,
112                            SearchOperation searchOperation)
113  {
114    searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
115
116    LocalizableMessage message =
117            ERR_PASSWORDPOLICYSUBENTRY_VATTR_NOT_SEARCHABLE.get(
118            rule.getAttributeType().getNameOrOID());
119    searchOperation.appendErrorMessage(message);
120  }
121}