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 */
020 package org.apache.directory.server.kerberos.sam;
021
022
023 import java.util.HashMap;
024 import java.util.Hashtable;
025 import java.util.Map;
026
027 import javax.naming.NamingException;
028 import javax.naming.directory.DirContext;
029 import javax.security.auth.kerberos.KerberosKey;
030
031 import org.apache.directory.server.i18n.I18n;
032 import org.apache.directory.server.kerberos.shared.messages.value.SamType;
033 import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
034
035
036 /**
037 * The Subsystem that enables the Kerberos server to use plugable Single-use
038 * Authentication mechanisms.
039 *
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 * @version $Rev: 902547 $
042 */
043 public final class SamSubsystem
044 {
045 /** the property key base used for SAM algorithm verifiers */
046 public static final String PROPKEY_BASE = "kerberos.sam.type.";
047
048 /** the SAM subsystem instance */
049 public static SamSubsystem instance;
050
051 /** a map of verifiers so we do not need to create a new one every time */
052 private final Map<SamType, SamVerifier> verifiers = new HashMap<SamType, SamVerifier>();
053
054 /** the key integrity checker used by the subsystem for all sam types */
055 private KeyIntegrityChecker keyChecker;
056
057 /** the user context the SamSubsystem would use to verify passwords */
058 private DirContext userContext;
059 private String userBaseRdn;
060
061
062 /**
063 * Gets the singleton instance of the SamSubsystem.
064 *
065 * @return the singleton for the SamSubsystem
066 */
067 public static SamSubsystem getInstance()
068 {
069 if ( instance == null )
070 {
071 instance = new SamSubsystem();
072 }
073
074 return instance;
075 }
076
077
078 /**
079 * Sets the KeyIntegrityChecker used by the entire SamSubsystem.
080 *
081 * @param keyChecker the KeyIntegrityChecker used by the entire SamSubsystem
082 */
083 public void setIntegrityChecker( KeyIntegrityChecker keyChecker )
084 {
085 this.keyChecker = keyChecker;
086 }
087
088
089 /**
090 * Uses the principal entry information to load the approapriate SamVerifier
091 * and verify the Single-use password.
092 *
093 * @param entry the store entry for the Kerberos principal
094 * @param sad the single-use authentication data encrypted timestamp payload
095 * @return true if verification passed, false otherwise
096 * @throws SamException thrown when there is a failure within the verifier
097 * or a verifier cannot be found.
098 */
099 public KerberosKey verify( PrincipalStoreEntry entry, byte[] sad ) throws SamException
100 {
101 SamVerifier verifier = null;
102
103 if ( keyChecker == null )
104 {
105 throw new IllegalStateException( I18n.err( I18n.ERR_651 ) );
106 }
107
108 if ( entry.getSamType() == null )
109 {
110 throw new SamException( entry.getSamType(), I18n.err( I18n.ERR_652 ) );
111 }
112
113 if ( verifiers.containsKey( entry.getSamType() ) )
114 {
115 verifier = verifiers.get( entry.getSamType() );
116
117 return verifier.verify( entry.getPrincipal(), sad );
118 }
119
120 String key = PROPKEY_BASE + entry.getSamType().getOrdinal();
121
122 Hashtable<Object, Object> env = new Hashtable<Object, Object>();
123
124 try
125 {
126 env.putAll( userContext.getEnvironment() );
127 }
128 catch ( NamingException e )
129 {
130 e.printStackTrace();
131 }
132
133 if ( !env.containsKey( key ) )
134 {
135 String msg = I18n.err( I18n.ERR_653, key );
136
137 throw new SamException( entry.getSamType(), msg );
138 }
139
140 String fqcn = ( String ) env.get( key );
141
142 try
143 {
144 Class c = Class.forName( fqcn );
145
146 verifier = ( SamVerifier ) c.newInstance();
147
148 try
149 {
150 verifier.setUserContext( ( DirContext ) userContext.lookup( userBaseRdn ) );
151 }
152 catch ( NamingException e )
153 {
154 e.printStackTrace();
155
156 }
157
158 verifier.setIntegrityChecker( keyChecker );
159
160 verifier.startup();
161
162 if ( !verifier.getSamType().equals( entry.getSamType() ) )
163 {
164 String msg = I18n.err( I18n.ERR_654, verifier.getSamType(), entry.getSamType() );
165
166 throw new SamException( entry.getSamType(), msg );
167 }
168
169 verifiers.put( verifier.getSamType(), verifier );
170
171 return verifier.verify( entry.getPrincipal(), sad );
172 }
173 catch ( ClassNotFoundException e )
174 {
175 String msg = I18n.err( I18n.ERR_655, fqcn, entry.getSamType() );
176
177 throw new SamException( entry.getSamType(), msg, e );
178 }
179 catch ( IllegalAccessException e )
180 {
181 String msg = I18n.err( I18n.ERR_656, fqcn, entry.getSamType() );
182
183 throw new SamException( entry.getSamType(), msg, e );
184 }
185 catch ( InstantiationException e )
186 {
187 String msg = I18n.err( I18n.ERR_657, fqcn, entry.getSamType() );
188
189 throw new SamException( entry.getSamType(), msg, e );
190 }
191 }
192
193
194 /**
195 * Sets the context under which user entries can be found.
196 *
197 * @param userContext the jndi context under which users can be found.
198 * @param userBaseRdn the container with users
199 */
200 public void setUserContext( DirContext userContext, String userBaseRdn )
201 {
202 this.userContext = userContext;
203 this.userBaseRdn = userBaseRdn;
204 }
205 }