View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.server.config.listener;
22  
23  
24  import static org.apache.directory.server.core.api.InterceptorEnum.AUTHENTICATION_INTERCEPTOR;
25  
26  import org.apache.directory.api.ldap.model.entry.Attribute;
27  import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
28  import org.apache.directory.api.ldap.model.entry.Entry;
29  import org.apache.directory.api.ldap.model.exception.LdapException;
30  import org.apache.directory.api.ldap.model.name.Dn;
31  import org.apache.directory.api.ldap.model.schema.AttributeType;
32  import org.apache.directory.api.ldap.model.schema.SchemaManager;
33  import org.apache.directory.server.config.ConfigPartitionReader;
34  import org.apache.directory.server.config.beans.PasswordPolicyBean;
35  import org.apache.directory.server.config.builder.ServiceBuilder;
36  import org.apache.directory.server.core.api.DirectoryService;
37  import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
38  import org.apache.directory.server.core.api.event.DirectoryListenerAdapter;
39  import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
40  import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
41  import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
42  import org.apache.directory.server.core.authn.AuthenticationInterceptor;
43  import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  
48  /**
49   * A listener for handling the config partition changes.
50   * 
51   * Note: currently handles password policy related configuration changes only.
52   * 
53   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
54   */
55  public class ConfigChangeListener extends DirectoryListenerAdapter
56  {
57      /** the config parition reader */
58      private ConfigPartitionReader cpReader;
59  
60      /** container holding the current active password policy configurations */
61      private PpolicyConfigContainer ppolicyConfigContainer;
62  
63      /** the root DN of password policy configurations */
64      private Dn ppolicyConfigDnRoot;
65  
66      private static final String PPOLICY_OC_NAME = "ads-passwordPolicy";
67  
68      // attribute holding the value of #PPOLICY_OC_NAME
69      private Attribute passwordPolicyObjectClassAttribute;
70      
71      
72      /** The logger for this class */
73      private static final Logger LOG = LoggerFactory.getLogger( ConfigChangeListener.class );
74  
75      /**
76       * 
77       * Creates a new instance of ConfigChangeListener.
78       *
79       * @param cpReader the configuration reader
80       * @param directoryService the DirectoryService instance
81       * @throws LdapException If the instance cannot be created
82       */
83      public ConfigChangeListener( ConfigPartitionReader cpReader, DirectoryService directoryService )
84          throws LdapException
85      {
86          this.cpReader = cpReader;
87  
88          SchemaManager schemaManager = directoryService.getSchemaManager();
89  
90          ppolicyConfigDnRoot = new Dn( schemaManager,
91              "ou=passwordPolicies,ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config" );
92  
93          AuthenticationInterceptordirectory/server/core/authn/AuthenticationInterceptor.html#AuthenticationInterceptor">AuthenticationInterceptor authInterceptor = ( AuthenticationInterceptor ) directoryService
94              .getInterceptor( AUTHENTICATION_INTERCEPTOR.getName() );
95          ppolicyConfigContainer = authInterceptor.getPwdPolicyContainer();
96  
97          AttributeType ocType = directoryService.getAtProvider().getObjectClass();
98          passwordPolicyObjectClassAttribute = new DefaultAttribute( ocType, PPOLICY_OC_NAME );
99      }
100 
101 
102     @Override
103     public void entryAdded( AddOperationContext addContext )
104     {
105         Entry entry = addContext.getEntry();
106         updatePasswordPolicy( entry, false );
107     }
108 
109 
110     @Override
111     public void entryDeleted( DeleteOperationContext deleteContext )
112     {
113         Entry entry = deleteContext.getEntry();
114         updatePasswordPolicy( entry, true );
115     }
116 
117 
118     @Override
119     public void entryModified( ModifyOperationContext modifyContext )
120     {
121         Entry entry = modifyContext.getAlteredEntry();
122         updatePasswordPolicy( entry, false );
123     }
124 
125 
126     /**
127      * Updates the password policy represented by the given configuration entry
128      * 
129      * @param entry the password policy configuration entry
130      * @param deleted flag to detect if this is a deleted entry
131      */
132     private void updatePasswordPolicy( Entry entry, boolean deleted )
133     {
134         Dn dn = entry.getDn();
135 
136         if ( !dn.isDescendantOf( ppolicyConfigDnRoot ) )
137         {
138             return;
139         }
140 
141         if ( !entry.contains( passwordPolicyObjectClassAttribute ) )
142         {
143             return;
144         }
145 
146         if ( deleted )
147         {
148             LOG.debug( "Deleting ppolicy config {}", dn );
149             ppolicyConfigContainer.removePolicyConfig( dn );
150             return;
151         }
152         
153         PasswordPolicyBean bean = null;
154         
155         try
156         {
157             bean = ( PasswordPolicyBean ) cpReader.readConfig( entry );
158         }
159         catch ( Exception e )
160         {
161             LOG.warn( "Failed to read the updated ppolicy configuration from {}", dn );
162             LOG.warn( "", e );
163             return;
164         }
165 
166         if ( bean.isDisabled() )
167         {
168             LOG.debug( "Deleting disabled ppolicy config {}", dn );
169             ppolicyConfigContainer.removePolicyConfig( dn );
170         }
171         else
172         {
173             PasswordPolicyConfiguration updated = ServiceBuilder.createPwdPolicyConfig( bean );
174             
175             PasswordPolicyConfiguration existing = ppolicyConfigContainer.getPolicyConfig( dn );
176             
177             if ( existing == null )
178             {
179                 LOG.debug( "Adding ppolicy config {}", dn );
180             }
181             else
182             {
183                 LOG.debug( "Updating ppolicy config {}", dn );
184             }
185             
186             ppolicyConfigContainer.addPolicy( dn, updated );
187         }
188     }
189 }