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 }