001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.server.kerberos.kdc; 021 022 023import javax.security.auth.kerberos.KerberosPrincipal; 024 025import org.apache.directory.api.ldap.model.constants.AuthenticationLevel; 026import org.apache.directory.api.ldap.model.constants.SchemaConstants; 027import org.apache.directory.api.ldap.model.entry.Attribute; 028import org.apache.directory.api.ldap.model.entry.DefaultAttribute; 029import org.apache.directory.api.ldap.model.entry.DefaultModification; 030import org.apache.directory.api.ldap.model.entry.Entry; 031import org.apache.directory.api.ldap.model.entry.Modification; 032import org.apache.directory.api.ldap.model.entry.ModificationOperation; 033import org.apache.directory.api.ldap.model.exception.LdapException; 034import org.apache.directory.api.ldap.model.name.Dn; 035import org.apache.directory.api.ldap.model.schema.SchemaManager; 036import org.apache.directory.api.util.Strings; 037import org.apache.directory.server.constants.ServerDNConstants; 038import org.apache.directory.server.core.api.CoreSession; 039import org.apache.directory.server.core.api.DirectoryService; 040import org.apache.directory.server.core.api.LdapPrincipal; 041import org.apache.directory.server.core.shared.DefaultCoreSession; 042import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswdErrorType; 043import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswordException; 044import org.apache.directory.server.kerberos.shared.store.PrincipalStore; 045import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry; 046import org.apache.directory.server.protocol.shared.kerberos.GetPrincipal; 047import org.apache.directory.server.protocol.shared.kerberos.StoreUtils; 048import org.apache.directory.shared.kerberos.KerberosAttribute; 049 050 051/** 052 * A PrincipalStore backing entries in a DirectoryService. 053 * 054 * 055 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 056 */ 057public class DirectoryPrincipalStore implements PrincipalStore 058{ 059 /** The directory service backing store for this PrincipalStore. */ 060 private final DirectoryService directoryService; 061 private final Dn searchBaseDn; 062 063 private CoreSession adminSession; 064 065 066 /** 067 * Creates a new instance of DirectoryPrincipalStore. 068 * 069 * @param directoryService backing store for this PrincipalStore 070 * @param searchBaseDn The Search Base DN 071 */ 072 public DirectoryPrincipalStore( DirectoryService directoryService, Dn searchBaseDn ) 073 { 074 this.directoryService = directoryService; 075 this.adminSession = directoryService.getAdminSession(); 076 this.searchBaseDn = searchBaseDn; 077 } 078 079 080 /** 081 * {@inheritDoc} 082 */ 083 public void changePassword( KerberosPrincipal byPrincipal, KerberosPrincipal forPrincipal, String newPassword, 084 boolean isInitialTicket ) throws ChangePasswordException 085 { 086 try 087 { 088 Entry ebyPrincipalEntry = null; 089 090 ebyPrincipalEntry = StoreUtils.findPrincipalEntry( adminSession, searchBaseDn, byPrincipal.getName() ); 091 092 if ( ebyPrincipalEntry == null ) 093 { 094 throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_HARDERROR, 095 Strings.getBytesUtf8( ( "No such principal " + byPrincipal ) ) ); 096 } 097 098 SchemaManager schemaManager = directoryService.getSchemaManager(); 099 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 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}