1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.directory.server.kerberos.changepwd.protocol;
22
23
24 import java.io.UnsupportedEncodingException;
25 import java.net.InetAddress;
26 import java.net.InetSocketAddress;
27 import java.nio.ByteBuffer;
28
29 import javax.security.auth.kerberos.KerberosPrincipal;
30
31 import org.apache.directory.server.i18n.I18n;
32 import org.apache.directory.server.kerberos.changepwd.ChangePasswordServer;
33 import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswdErrorType;
34 import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswordException;
35 import org.apache.directory.server.kerberos.changepwd.messages.ChangePasswordError;
36 import org.apache.directory.server.kerberos.changepwd.messages.ChangePasswordRequest;
37 import org.apache.directory.server.kerberos.changepwd.service.ChangePasswordContext;
38 import org.apache.directory.server.kerberos.changepwd.service.ChangePasswordService;
39 import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
40 import org.apache.directory.shared.kerberos.KerberosTime;
41 import org.apache.directory.shared.kerberos.components.PrincipalName;
42 import org.apache.directory.shared.kerberos.exceptions.ErrorType;
43 import org.apache.directory.shared.kerberos.exceptions.KerberosException;
44 import org.apache.directory.shared.kerberos.messages.KrbError;
45 import org.apache.mina.core.service.IoHandlerAdapter;
46 import org.apache.mina.core.session.IdleStatus;
47 import org.apache.mina.core.session.IoSession;
48 import org.apache.mina.filter.codec.ProtocolCodecFilter;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56 public class ChangePasswordProtocolHandler extends IoHandlerAdapter
57 {
58 private static final Logger LOG = LoggerFactory.getLogger( ChangePasswordProtocolHandler.class );
59
60 private ChangePasswordServer server;
61 private PrincipalStore store;
62 private String contextKey = "context";
63
64
65
66
67
68
69
70
71 public ChangePasswordProtocolHandler( ChangePasswordServer config, PrincipalStore store )
72 {
73 this.server = config;
74 this.store = store;
75 }
76
77
78 @Override
79 public void sessionCreated( IoSession session ) throws Exception
80 {
81 if ( LOG.isDebugEnabled() )
82 {
83 LOG.debug( "{} CREATED: {}", session.getRemoteAddress(), session.getTransportMetadata() );
84 }
85
86 session.getFilterChain().addFirst( "codec",
87 new ProtocolCodecFilter( ChangePasswordProtocolCodecFactory.getInstance() ) );
88 }
89
90
91 @Override
92 public void sessionOpened( IoSession session )
93 {
94 LOG.debug( "{} OPENED", session.getRemoteAddress() );
95 }
96
97
98 @Override
99 public void sessionClosed( IoSession session )
100 {
101 LOG.debug( "{} CLOSED", session.getRemoteAddress() );
102 }
103
104
105 @Override
106 public void sessionIdle( IoSession session, IdleStatus status )
107 {
108 LOG.debug( "{} IDLE ({})", session.getRemoteAddress(), status );
109 }
110
111
112 @Override
113 public void exceptionCaught( IoSession session, Throwable cause )
114 {
115 LOG.debug( session.getRemoteAddress() + " EXCEPTION", cause );
116 session.closeNow();
117 }
118
119
120 @Override
121 public void messageReceived( IoSession session, Object message )
122 {
123 LOG.debug( "{} RCVD: {}", session.getRemoteAddress(), message );
124
125 InetAddress clientAddress = ( ( InetSocketAddress ) session.getRemoteAddress() ).getAddress();
126 ChangePasswordRequest/../org/apache/directory/server/kerberos/changepwd/messages/ChangePasswordRequest.html#ChangePasswordRequest">ChangePasswordRequest request = ( ChangePasswordRequest ) message;
127
128 try
129 {
130 ChangePasswordContextpwd/service/ChangePasswordContext.html#ChangePasswordContext">ChangePasswordContext changepwContext = new ChangePasswordContext();
131 changepwContext.setConfig( server.getConfig() );
132 changepwContext.setStore( store );
133 changepwContext.setClientAddress( clientAddress );
134 changepwContext.setRequest( request );
135 changepwContext.setReplayCache( server.getReplayCache() );
136 session.setAttribute( getContextKey(), changepwContext );
137
138 ChangePasswordService.execute( session, changepwContext );
139
140 session.write( changepwContext.getReply() );
141 }
142 catch ( KerberosException ke )
143 {
144 if ( LOG.isDebugEnabled() )
145 {
146 LOG.warn( ke.getLocalizedMessage(), ke );
147 }
148 else
149 {
150 LOG.warn( ke.getLocalizedMessage() );
151 }
152
153 KrbError errorMessage = getErrorMessage( server.getConfig().getServicePrincipal(), ke );
154
155 session.write( new ChangePasswordError( request.getVersionNumber(), errorMessage ) );
156 }
157 catch ( Exception e )
158 {
159 LOG.error( I18n.err( I18n.ERR_152, e.getLocalizedMessage() ), e );
160
161 KrbError error = getErrorMessage( server.getConfig().getServicePrincipal(), new ChangePasswordException(
162 ChangePasswdErrorType.KRB5_KPASSWD_UNKNOWN_ERROR ) );
163 session.write( new ChangePasswordError( request.getVersionNumber(), error ) );
164 }
165 }
166
167
168 @Override
169 public void messageSent( IoSession session, Object message )
170 {
171 if ( LOG.isDebugEnabled() )
172 {
173 LOG.debug( "{} SENT: {}", session.getRemoteAddress(), message );
174 }
175 }
176
177
178 protected String getContextKey()
179 {
180 return ( this.contextKey );
181 }
182
183
184 private KrbError getErrorMessage( KerberosPrincipal principal, KerberosException exception )
185 {
186 KrbErrorared/kerberos/messages/KrbError.html#KrbError">KrbError krbError = new KrbError();
187
188 KerberosTimehared/kerberos/KerberosTime.html#KerberosTime">KerberosTime now = new KerberosTime();
189
190
191
192 krbError.setErrorCode( ErrorType.KRB_ERR_GENERIC );
193 krbError.setEText( exception.getLocalizedMessage() );
194 krbError.setSName( new PrincipalName( principal ) );
195 krbError.setSTime( now );
196 krbError.setSusec( 0 );
197 krbError.setRealm( principal.getRealm() );
198 krbError.setEData( buildExplanatoryData( exception ) );
199
200 return krbError;
201 }
202
203
204 private byte[] buildExplanatoryData( KerberosException exception )
205 {
206 short resultCode = ( short ) exception.getErrorCode();
207
208 byte[] resultString =
209 { ( byte ) 0x00 };
210
211 if ( exception.getExplanatoryData() == null || exception.getExplanatoryData().length == 0 )
212 {
213 try
214 {
215 resultString = exception.getLocalizedMessage().getBytes( "UTF-8" );
216 }
217 catch ( UnsupportedEncodingException uee )
218 {
219 LOG.error( uee.getLocalizedMessage() );
220 }
221 }
222 else
223 {
224 resultString = exception.getExplanatoryData();
225 }
226
227 ByteBuffer byteBuffer = ByteBuffer.allocate( 2 + resultString.length );
228 byteBuffer.putShort( resultCode );
229 byteBuffer.put( resultString );
230
231 return byteBuffer.array();
232 }
233
234
235 @Override
236 public void inputClosed( IoSession session )
237 {
238 }
239 }