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  package org.apache.directory.server.kerberos.kdc;
21  
22  
23  import javax.security.auth.kerberos.KerberosPrincipal;
24  
25  import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
26  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
27  import org.apache.directory.api.ldap.model.entry.Attribute;
28  import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
29  import org.apache.directory.api.ldap.model.entry.DefaultModification;
30  import org.apache.directory.api.ldap.model.entry.Entry;
31  import org.apache.directory.api.ldap.model.entry.Modification;
32  import org.apache.directory.api.ldap.model.entry.ModificationOperation;
33  import org.apache.directory.api.ldap.model.exception.LdapException;
34  import org.apache.directory.api.ldap.model.name.Dn;
35  import org.apache.directory.api.ldap.model.schema.SchemaManager;
36  import org.apache.directory.api.util.Strings;
37  import org.apache.directory.server.constants.ServerDNConstants;
38  import org.apache.directory.server.core.api.CoreSession;
39  import org.apache.directory.server.core.api.DirectoryService;
40  import org.apache.directory.server.core.api.LdapPrincipal;
41  import org.apache.directory.server.core.shared.DefaultCoreSession;
42  import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswdErrorType;
43  import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswordException;
44  import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
45  import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
46  import org.apache.directory.server.protocol.shared.kerberos.GetPrincipal;
47  import org.apache.directory.server.protocol.shared.kerberos.StoreUtils;
48  import org.apache.directory.shared.kerberos.KerberosAttribute;
49  
50  
51  /**
52   * A PrincipalStore backing entries in a DirectoryService.
53   * 
54   *
55   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
56   */
57  public class DirectoryPrincipalStore implements PrincipalStore
58  {
59      /** The directory service backing store for this PrincipalStore. */
60      private final DirectoryService directoryService;
61      private final Dn searchBaseDn;
62  
63      private CoreSession adminSession;
64  
65  
66      /**
67       * Creates a new instance of DirectoryPrincipalStore.
68       *
69       * @param directoryService backing store for this PrincipalStore
70       * @param searchBaseDn The Search Base DN
71       */
72      public DirectoryPrincipalStore( DirectoryService directoryService, Dn searchBaseDn )
73      {
74          this.directoryService = directoryService;
75          this.adminSession = directoryService.getAdminSession();
76          this.searchBaseDn = searchBaseDn;
77      }
78  
79  
80      /**
81       * {@inheritDoc}
82       */
83      public void changePassword( KerberosPrincipal byPrincipal, KerberosPrincipal forPrincipal, String newPassword,
84          boolean isInitialTicket ) throws ChangePasswordException
85      {
86          try
87          {
88              Entry ebyPrincipalEntry = null;
89  
90              ebyPrincipalEntry = StoreUtils.findPrincipalEntry( adminSession, searchBaseDn, byPrincipal.getName() );
91  
92              if ( ebyPrincipalEntry == null )
93              {
94                  throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_HARDERROR,
95                      Strings.getBytesUtf8( ( "No such principal " + byPrincipal ) ) );
96              }
97  
98              SchemaManager schemaManager = directoryService.getSchemaManager();
99  
100             CoreSession bySession = null;
101 
102             boolean isAdmin = ebyPrincipalEntry.getDn()
103                 .equals( ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
104 
105             if ( !isInitialTicket && !isAdmin )
106             {
107                 throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_INITIAL_FLAG_NEEDED );
108             }
109 
110             // if admin assign the admin session
111             if ( isAdmin )
112             {
113                 bySession = adminSession;
114             }
115             // otherwise create a new session for the user with 'byPrincipal' who is trying to change the password for 'forPrincipal' 
116             else
117             {
118                 LdapPrincipaldapPrincipal.html#LdapPrincipal">LdapPrincipal byLdapPrincipal = new LdapPrincipal( schemaManager, ebyPrincipalEntry.getDn(),
119                     AuthenticationLevel.SIMPLE );
120 
121                 bySession = new DefaultCoreSession( byLdapPrincipal, directoryService );
122             }
123 
124             Attribute newPasswordAttribute = new DefaultAttribute(
125                 schemaManager.lookupAttributeTypeRegistry( SchemaConstants.USER_PASSWORD_AT ),
126                 Strings.getBytesUtf8( newPassword ) );
127             Modification passwordMod = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
128                 newPasswordAttribute );
129 
130             Attribute principalAttribute = new DefaultAttribute(
131                 schemaManager.lookupAttributeTypeRegistry( KerberosAttribute.KRB5_PRINCIPAL_NAME_AT ),
132                 forPrincipal.getName() );
133             Modification principalMod = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
134                 principalAttribute );
135 
136             Entry forPrincipalEntry = StoreUtils.findPrincipalEntry( bySession, searchBaseDn, forPrincipal.getName() );
137 
138             adminSession.modify( forPrincipalEntry.getDn(), passwordMod, principalMod );
139         }
140         catch ( LdapException e )
141         {
142             throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_ACCESSDENIED, e );
143         }
144         catch ( Exception e )
145         {
146             throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_HARDERROR, e );
147         }
148     }
149 
150 
151     /**
152      * {@inheritDoc}
153      */
154     public PrincipalStoreEntry getPrincipal( KerberosPrincipal principal ) throws Exception
155     {
156         return ( PrincipalStoreEntry ) new GetPrincipal( principal ).execute( adminSession, searchBaseDn );
157     }
158 }