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.changepwd; 021 022 023import java.io.IOException; 024 025import net.sf.ehcache.Cache; 026 027import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 028import org.apache.directory.api.ldap.model.name.Dn; 029import org.apache.directory.server.kerberos.ChangePasswordConfig; 030import org.apache.directory.server.kerberos.changepwd.protocol.ChangePasswordProtocolHandler; 031import org.apache.directory.server.kerberos.kdc.DirectoryPrincipalStore; 032import org.apache.directory.server.kerberos.shared.replay.ReplayCache; 033import org.apache.directory.server.kerberos.shared.replay.ReplayCacheImpl; 034import org.apache.directory.server.kerberos.shared.store.PrincipalStore; 035import org.apache.directory.server.protocol.shared.DirectoryBackedService; 036import org.apache.directory.server.protocol.shared.transport.TcpTransport; 037import org.apache.directory.server.protocol.shared.transport.Transport; 038import org.apache.directory.server.protocol.shared.transport.UdpTransport; 039import org.apache.mina.core.service.IoAcceptor; 040import org.apache.mina.transport.socket.DatagramSessionConfig; 041import org.apache.mina.transport.socket.SocketAcceptor; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045 046/** 047 * Contains the configuration parameters for the Change Password protocol provider. 048 * 049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 050 */ 051public class ChangePasswordServer extends DirectoryBackedService 052{ 053 /** logger for this class */ 054 private static final Logger LOG = LoggerFactory.getLogger( ChangePasswordServer.class ); 055 056 /** The default change password port. */ 057 private static final int DEFAULT_IP_PORT = 464; 058 059 /** The default change password password policy for password length. */ 060 public static final int DEFAULT_PASSWORD_LENGTH = 6; 061 062 /** The default change password password policy for category count. */ 063 public static final int DEFAULT_CATEGORY_COUNT = 3; 064 065 /** The default change password password policy for token size. */ 066 public static final int DEFAULT_TOKEN_SIZE = 3; 067 068 private ChangePasswordConfig config; 069 070 /** the cache used for storing change password requests */ 071 private ReplayCache replayCache; 072 073 074 /** 075 * Creates a new instance of ChangePasswordConfiguration. 076 */ 077 public ChangePasswordServer() 078 { 079 this( new ChangePasswordConfig() ); 080 } 081 082 083 public ChangePasswordServer( ChangePasswordConfig config ) 084 { 085 this.config = config; 086 } 087 088 089 /** 090 * @throws IOException if we cannot bind to the specified ports 091 */ 092 public void start() throws IOException, LdapInvalidDnException 093 { 094 PrincipalStore store = new DirectoryPrincipalStore( getDirectoryService(), new Dn( this.getSearchBaseDn() ) ); 095 096 LOG.debug( "initializing the changepassword replay cache" ); 097 098 Cache cache = getDirectoryService().getCacheService().getCache( "changePwdReplayCache" ); 099 replayCache = new ReplayCacheImpl( cache ); 100 101 for ( Transport transport : transports ) 102 { 103 IoAcceptor acceptor = transport.getAcceptor(); 104 105 // Disable the disconnection of the clients on unbind 106 acceptor.setCloseOnDeactivation( false ); 107 108 if ( transport instanceof UdpTransport ) 109 { 110 // Allow the port to be reused even if the socket is in TIME_WAIT state 111 ( ( DatagramSessionConfig ) acceptor.getSessionConfig() ).setReuseAddress( true ); 112 } 113 else 114 { 115 // Allow the port to be reused even if the socket is in TIME_WAIT state 116 ( ( SocketAcceptor ) acceptor ).setReuseAddress( true ); 117 118 // No Nagle's algorithm 119 ( ( SocketAcceptor ) acceptor ).getSessionConfig().setTcpNoDelay( true ); 120 } 121 122 // Set the handler 123 acceptor.setHandler( new ChangePasswordProtocolHandler( this, store ) ); 124 125 // Bind 126 acceptor.bind(); 127 } 128 129 LOG.info( "ChangePassword service started." ); 130 //System.out.println( "ChangePassword service started." ); 131 } 132 133 134 public void stop() 135 { 136 for ( Transport transport : getTransports() ) 137 { 138 IoAcceptor acceptor = transport.getAcceptor(); 139 140 if ( acceptor != null ) 141 { 142 acceptor.dispose(); 143 } 144 } 145 146 replayCache.clear(); 147 148 LOG.info( "ChangePassword service stopped." ); 149 //System.out.println( "ChangePassword service stopped." ); 150 } 151 152 153 /** 154 * @return the replayCache 155 */ 156 public ReplayCache getReplayCache() 157 { 158 return replayCache; 159 } 160 161 162 public ChangePasswordConfig getConfig() 163 { 164 return config; 165 } 166 167 168 public int getTcpPort() 169 { 170 for ( Transport t : getTransports() ) 171 { 172 if ( t instanceof TcpTransport ) 173 { 174 return t.getPort(); 175 } 176 } 177 178 throw new IllegalStateException( "TCP transport is not enabled" ); 179 } 180 181 182 /** 183 * @see Object#toString() 184 */ 185 public String toString() 186 { 187 StringBuilder sb = new StringBuilder(); 188 189 sb.append( "ChangePasswordServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' ); 190 191 if ( getTransports() != null ) 192 { 193 for ( Transport transport : getTransports() ) 194 { 195 sb.append( " " ).append( transport ).append( '\n' ); 196 } 197 } 198 199 return sb.toString(); 200 } 201}