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