1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.kerberos.protocol;
21
22
23 import java.io.IOException;
24 import java.net.InetSocketAddress;
25 import java.net.SocketAddress;
26 import java.security.SecureRandom;
27
28 import javax.security.auth.kerberos.KerberosKey;
29 import javax.security.auth.kerberos.KerberosPrincipal;
30
31 import junit.framework.TestCase;
32
33 import org.apache.directory.server.kerberos.shared.KerberosConstants;
34 import org.apache.directory.server.kerberos.shared.KerberosMessageType;
35 import org.apache.directory.server.kerberos.shared.crypto.checksum.ChecksumHandler;
36 import org.apache.directory.server.kerberos.shared.crypto.checksum.ChecksumType;
37 import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
38 import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
39 import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
40 import org.apache.directory.server.kerberos.shared.crypto.encryption.RandomKeyFactory;
41 import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
42 import org.apache.directory.server.kerberos.shared.io.encoder.ApplicationRequestEncoder;
43 import org.apache.directory.server.kerberos.shared.io.encoder.KdcRequestEncoder;
44 import org.apache.directory.server.kerberos.shared.messages.ApplicationRequest;
45 import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
46 import org.apache.directory.server.kerberos.shared.messages.components.Authenticator;
47 import org.apache.directory.server.kerberos.shared.messages.components.AuthenticatorModifier;
48 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPart;
49 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPartModifier;
50 import org.apache.directory.server.kerberos.shared.messages.components.Ticket;
51 import org.apache.directory.server.kerberos.shared.messages.value.ApOptions;
52 import org.apache.directory.server.kerberos.shared.messages.value.Checksum;
53 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
54 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
55 import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
56 import org.apache.directory.server.kerberos.shared.messages.value.PaData;
57 import org.apache.directory.server.kerberos.shared.messages.value.PrincipalName;
58 import org.apache.directory.server.kerberos.shared.messages.value.RequestBody;
59 import org.apache.directory.server.kerberos.shared.messages.value.TransitedEncoding;
60 import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlag;
61 import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlags;
62 import org.apache.directory.server.kerberos.shared.messages.value.types.PaDataType;
63 import org.apache.directory.server.kerberos.shared.messages.value.types.PrincipalNameType;
64 import org.apache.mina.common.IoFilterChain;
65 import org.apache.mina.common.IoHandler;
66 import org.apache.mina.common.IoService;
67 import org.apache.mina.common.IoServiceConfig;
68 import org.apache.mina.common.IoSessionConfig;
69 import org.apache.mina.common.TransportType;
70 import org.apache.mina.common.WriteFuture;
71 import org.apache.mina.common.support.BaseIoSession;
72
73
74
75
76
77
78
79
80
81
82
83 public abstract class AbstractTicketGrantingServiceTest extends TestCase
84 {
85 protected CipherTextHandler lockBox;
86 protected static final SecureRandom random = new SecureRandom();
87
88
89 protected EncryptionKey sessionKey;
90 protected EncryptionKey subSessionKey;
91 protected int sequenceNumber;
92 protected KerberosTime now;
93 protected int clientMicroSeconds = 0;
94
95
96 protected Ticket getTgt( KerberosPrincipal clientPrincipal, KerberosPrincipal serverPrincipal, String serverPassword )
97 throws Exception
98 {
99 EncryptionKey serverKey = getEncryptionKey( serverPrincipal, serverPassword );
100 return getTicket( clientPrincipal, serverPrincipal, serverKey );
101 }
102
103
104
105
106
107
108
109
110
111 protected EncryptionKey getEncryptionKey( KerberosPrincipal principal, String passPhrase )
112 {
113 KerberosKey kerberosKey = new KerberosKey( principal, passPhrase.toCharArray(), "DES" );
114 byte[] keyBytes = kerberosKey.getEncoded();
115 return new EncryptionKey( EncryptionType.DES_CBC_MD5, keyBytes );
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 protected Ticket getTicket( KerberosPrincipal clientPrincipal, KerberosPrincipal serverPrincipal,
134 EncryptionKey serverKey ) throws KerberosException
135 {
136 EncTicketPartModifier encTicketModifier = new EncTicketPartModifier();
137
138 TicketFlags ticketFlags = new TicketFlags();
139 ticketFlags.setFlag( TicketFlag.RENEWABLE );
140 encTicketModifier.setFlags( ticketFlags );
141
142 EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( EncryptionType.DES_CBC_MD5 );
143
144 encTicketModifier.setSessionKey( sessionKey );
145 encTicketModifier.setClientPrincipal( clientPrincipal );
146 encTicketModifier.setTransitedEncoding( new TransitedEncoding() );
147 encTicketModifier.setAuthTime( new KerberosTime() );
148
149 long now = System.currentTimeMillis();
150 KerberosTime endTime = new KerberosTime( now + KerberosTime.DAY );
151 encTicketModifier.setEndTime( endTime );
152
153 KerberosTime renewTill = new KerberosTime( now + KerberosTime.WEEK );
154 encTicketModifier.setRenewTill( renewTill );
155
156 EncTicketPart encTicketPart = encTicketModifier.getEncTicketPart();
157
158 EncryptedData encryptedTicketPart = lockBox.seal( serverKey, encTicketPart, KeyUsage.NUMBER2 );
159
160 Ticket ticket = new Ticket( KerberosConstants.KERBEROS_V5, serverPrincipal, encryptedTicketPart );
161
162 ticket.setEncTicketPart( encTicketPart );
163
164 return ticket;
165 }
166
167
168 protected EncTicketPartModifier getTicketArchetype( KerberosPrincipal clientPrincipal ) throws KerberosException
169 {
170 EncTicketPartModifier encTicketModifier = new EncTicketPartModifier();
171
172 TicketFlags ticketFlags = new TicketFlags();
173 ticketFlags.setFlag( TicketFlag.RENEWABLE );
174 encTicketModifier.setFlags( ticketFlags );
175
176 EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( EncryptionType.DES_CBC_MD5 );
177
178 encTicketModifier.setSessionKey( sessionKey );
179 encTicketModifier.setClientPrincipal( clientPrincipal );
180 encTicketModifier.setTransitedEncoding( new TransitedEncoding() );
181 encTicketModifier.setAuthTime( new KerberosTime() );
182
183 long now = System.currentTimeMillis();
184 KerberosTime endTime = new KerberosTime( now + KerberosTime.DAY );
185 encTicketModifier.setEndTime( endTime );
186
187 KerberosTime renewTill = new KerberosTime( now + KerberosTime.WEEK );
188 encTicketModifier.setRenewTill( renewTill );
189
190 return encTicketModifier;
191 }
192
193
194 protected Ticket getTicket( EncTicketPartModifier encTicketModifier, KerberosPrincipal serverPrincipal,
195 EncryptionKey serverKey ) throws KerberosException
196 {
197 EncTicketPart encTicketPart = encTicketModifier.getEncTicketPart();
198
199 EncryptedData encryptedTicketPart = lockBox.seal( serverKey, encTicketPart, KeyUsage.NUMBER2 );
200
201 Ticket ticket = new Ticket();
202 ticket.setTktVno( 5 );
203 ticket.setServerPrincipal( serverPrincipal );
204 ticket.setEncPart( encryptedTicketPart );
205
206 ticket.setEncTicketPart( encTicketPart );
207
208 return ticket;
209 }
210
211
212 protected KdcRequest getKdcRequest( Ticket tgt, RequestBody requestBody ) throws Exception
213 {
214 return getKdcRequest( tgt, requestBody, ChecksumType.RSA_MD5 );
215 }
216
217
218
219
220
221 protected KdcRequest getKdcRequest( Ticket tgt, RequestBody requestBody, ChecksumType checksumType )
222 throws Exception
223 {
224
225 sessionKey = tgt.getEncTicketPart().getSessionKey();
226
227
228 sequenceNumber = random.nextInt();
229 now = new KerberosTime();
230
231 EncryptedData authenticator = getAuthenticator( tgt.getEncTicketPart().getClientPrincipal(), requestBody, checksumType );
232
233 PaData[] paData = getPreAuthenticationData( tgt, authenticator );
234
235 return new KdcRequest( 5, KerberosMessageType.TGS_REQ, paData, requestBody );
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249 protected EncryptedData getAuthenticator( KerberosPrincipal clientPrincipal, RequestBody requestBody,
250 ChecksumType checksumType ) throws IOException, KerberosException
251 {
252 AuthenticatorModifier authenticatorModifier = new AuthenticatorModifier();
253
254 clientMicroSeconds = random.nextInt();
255
256 authenticatorModifier.setVersionNumber( 5 );
257 authenticatorModifier.setClientPrincipal( clientPrincipal );
258 authenticatorModifier.setClientTime( now );
259 authenticatorModifier.setClientMicroSecond( clientMicroSeconds );
260 authenticatorModifier.setSubSessionKey( subSessionKey );
261 authenticatorModifier.setSequenceNumber( sequenceNumber );
262
263 Checksum checksum = getBodyChecksum( requestBody, checksumType );
264 authenticatorModifier.setChecksum( checksum );
265
266 Authenticator authenticator = authenticatorModifier.getAuthenticator();
267
268 EncryptedData encryptedAuthenticator = lockBox.seal( sessionKey, authenticator, KeyUsage.NUMBER7 );
269
270 return encryptedAuthenticator;
271 }
272
273
274 protected Checksum getBodyChecksum( RequestBody requestBody, ChecksumType checksumType ) throws IOException,
275 KerberosException
276 {
277 KdcRequestEncoder bodyEncoder = new KdcRequestEncoder();
278 byte[] bodyBytes = bodyEncoder.encodeRequestBody( requestBody );
279
280 ChecksumHandler checksumHandler = new ChecksumHandler();
281 return checksumHandler.calculateChecksum( checksumType, bodyBytes, null, KeyUsage.NUMBER8 );
282 }
283
284
285
286
287
288
289
290
291
292
293 protected PaData[] getPreAuthenticationData( Ticket ticket, EncryptedData authenticator )
294 throws IOException
295 {
296 ApplicationRequest applicationRequest = new ApplicationRequest();
297 applicationRequest.setMessageType( KerberosMessageType.AP_REQ );
298 applicationRequest.setProtocolVersionNumber( 5 );
299 applicationRequest.setApOptions( new ApOptions() );
300 applicationRequest.setTicket( ticket );
301 applicationRequest.setEncPart( authenticator );
302
303 ApplicationRequestEncoder encoder = new ApplicationRequestEncoder();
304 byte[] encodedApReq = encoder.encode( applicationRequest );
305
306 PaData[] paData = new PaData[1];
307
308 PaData preAuth = new PaData();
309 preAuth.setPaDataType( PaDataType.PA_TGS_REQ );
310 preAuth.setPaDataValue( encodedApReq );
311
312 paData[0] = preAuth;
313
314 return paData;
315 }
316
317
318 protected PrincipalName getPrincipalName( String name )
319 {
320 PrincipalName principalName = new PrincipalName();
321 principalName.addName( name );
322 principalName.setNameType( PrincipalNameType.KRB_NT_PRINCIPAL );
323
324 return principalName;
325 }
326
327 protected static class DummySession extends BaseIoSession
328 {
329 Object message;
330
331
332 @Override
333 public WriteFuture write( Object message )
334 {
335 this.message = message;
336
337 return super.write( message );
338 }
339
340
341 protected Object getMessage()
342 {
343 return message;
344 }
345
346
347 protected void updateTrafficMask()
348 {
349
350 }
351
352
353 public IoService getService()
354 {
355 return null;
356 }
357
358
359 public IoHandler getHandler()
360 {
361 return null;
362 }
363
364
365 public IoFilterChain getFilterChain()
366 {
367 return null;
368 }
369
370
371 public TransportType getTransportType()
372 {
373 return null;
374 }
375
376
377 public SocketAddress getRemoteAddress()
378 {
379 return new InetSocketAddress( 10088 );
380 }
381
382
383 public SocketAddress getLocalAddress()
384 {
385 return null;
386 }
387
388
389 public IoSessionConfig getConfig()
390 {
391 return null;
392 }
393
394
395 public int getScheduledWriteRequests()
396 {
397 return 0;
398 }
399
400
401 public SocketAddress getServiceAddress()
402 {
403 return null;
404 }
405
406
407 public IoServiceConfig getServiceConfig()
408 {
409 return null;
410 }
411
412
413 public int getScheduledWriteBytes()
414 {
415 return 0;
416 }
417 }
418 }