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.kdc.authentication;
21
22
23 import java.io.IOException;
24 import java.net.InetAddress;
25 import java.util.Date;
26 import java.util.Set;
27
28 import javax.security.auth.kerberos.KerberosKey;
29 import javax.security.auth.kerberos.KerberosPrincipal;
30
31 import org.apache.directory.server.kerberos.kdc.KdcContext;
32 import org.apache.directory.server.kerberos.kdc.KdcServer;
33 import org.apache.directory.server.kerberos.sam.SamException;
34 import org.apache.directory.server.kerberos.sam.SamSubsystem;
35 import org.apache.directory.server.kerberos.shared.KerberosConstants;
36 import org.apache.directory.server.kerberos.shared.KerberosUtils;
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.ErrorType;
42 import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
43 import org.apache.directory.server.kerberos.shared.io.decoder.EncryptedDataDecoder;
44 import org.apache.directory.server.kerberos.shared.io.encoder.EncryptionTypeInfoEncoder;
45 import org.apache.directory.server.kerberos.shared.io.encoder.PreAuthenticationDataEncoder;
46 import org.apache.directory.server.kerberos.shared.messages.AuthenticationReply;
47 import org.apache.directory.server.kerberos.shared.messages.KdcReply;
48 import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
49 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPart;
50 import org.apache.directory.server.kerberos.shared.messages.components.EncTicketPartModifier;
51 import org.apache.directory.server.kerberos.shared.messages.components.InvalidTicketException;
52 import org.apache.directory.server.kerberos.shared.messages.components.Ticket;
53 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
54 import org.apache.directory.server.kerberos.shared.messages.value.EncryptedTimeStamp;
55 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
56 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionTypeInfoEntry;
57 import org.apache.directory.server.kerberos.shared.messages.value.KdcOptions;
58 import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
59 import org.apache.directory.server.kerberos.shared.messages.value.LastRequest;
60 import org.apache.directory.server.kerberos.shared.messages.value.PaData;
61 import org.apache.directory.server.kerberos.shared.messages.value.TransitedEncoding;
62 import org.apache.directory.server.kerberos.shared.messages.value.flags.TicketFlag;
63 import org.apache.directory.server.kerberos.shared.messages.value.types.PaDataType;
64 import org.apache.directory.server.kerberos.shared.replay.InMemoryReplayCache;
65 import org.apache.directory.server.kerberos.shared.replay.ReplayCache;
66 import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
67 import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71
72
73
74
75
76 public class AuthenticationService
77 {
78
79 private static final Logger LOG = LoggerFactory.getLogger( AuthenticationService.class );
80
81 private static final ReplayCache replayCache = new InMemoryReplayCache();
82 private static final CipherTextHandler cipherTextHandler = new CipherTextHandler();
83
84 private static final String SERVICE_NAME = "Authentication Service (AS)";
85
86
87 public static void execute( AuthenticationContext authContext ) throws Exception
88 {
89 if ( LOG.isDebugEnabled() )
90 {
91 monitorRequest( authContext );
92 }
93
94 authContext.setReplayCache( replayCache );
95 authContext.setCipherTextHandler( cipherTextHandler );
96
97 if ( authContext.getRequest().getProtocolVersionNumber() != KerberosConstants.KERBEROS_V5 )
98 {
99 throw new KerberosException( ErrorType.KDC_ERR_BAD_PVNO );
100 }
101
102 selectEncryptionType( authContext );
103 getClientEntry( authContext );
104 verifyPolicy( authContext );
105 verifySam( authContext );
106 verifyEncryptedTimestamp( authContext );
107
108 if ( authContext.getClientKey() == null )
109 {
110 verifyEncryptedTimestamp( authContext );
111 }
112
113 getServerEntry( authContext );
114 generateTicket( authContext );
115 buildReply( authContext );
116
117 if ( LOG.isDebugEnabled() )
118 {
119 monitorContext( authContext );
120 monitorReply( ( KdcContext ) authContext );
121 }
122
123 sealReply( authContext );
124 }
125
126
127 private static void selectEncryptionType( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
128 {
129 KdcContext kdcContext = ( KdcContext ) authContext;
130 KdcServer config = kdcContext.getConfig();
131
132 Set<EncryptionType> requestedTypes = kdcContext.getRequest().getEType();
133
134 EncryptionType bestType = KerberosUtils.getBestEncryptionType( requestedTypes, config.getEncryptionTypes() );
135
136 LOG.debug( "Session will use encryption type {}.", bestType );
137
138 if ( bestType == null )
139 {
140 throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP );
141 }
142
143 kdcContext.setEncryptionType( bestType );
144 }
145
146
147 private static void getClientEntry( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
148 {
149 KerberosPrincipal principal = authContext.getRequest().getClientPrincipal();
150 PrincipalStore store = authContext.getStore();
151
152 PrincipalStoreEntry storeEntry = getEntry( principal, store, ErrorType.KDC_ERR_C_PRINCIPAL_UNKNOWN );
153 authContext.setClientEntry( storeEntry );
154 }
155
156
157 private static void verifyPolicy( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
158 {
159 PrincipalStoreEntry entry = authContext.getClientEntry();
160
161 if ( entry.isDisabled() )
162 {
163 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
164 }
165
166 if ( entry.isLockedOut() )
167 {
168 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
169 }
170
171 if ( entry.getExpiration().getTime() < new Date().getTime() )
172 {
173 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
174 }
175 }
176
177
178 private static void verifySam( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
179 {
180 LOG.debug( "Verifying using SAM subsystem." );
181 KdcRequest request = authContext.getRequest();
182 KdcServer config = authContext.getConfig();
183
184 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
185 String clientName = clientEntry.getPrincipal().getName();
186
187 EncryptionKey clientKey = null;
188
189 if ( clientEntry.getSamType() != null )
190 {
191 if ( LOG.isDebugEnabled() )
192 {
193 LOG.debug( "Entry for client principal {} has a valid SAM type. Invoking SAM subsystem for pre-authentication.", clientName );
194 }
195
196 PaData[] preAuthData = request.getPreAuthData();
197
198 if ( preAuthData == null || preAuthData.length == 0 )
199 {
200 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED, preparePreAuthenticationError( config
201 .getEncryptionTypes() ) );
202 }
203
204 try
205 {
206 for ( int ii = 0; ii < preAuthData.length; ii++ )
207 {
208 if ( preAuthData[ii].getPaDataType().equals( PaDataType.PA_ENC_TIMESTAMP ) )
209 {
210 KerberosKey samKey = SamSubsystem.getInstance().verify( clientEntry,
211 preAuthData[ii].getPaDataValue() );
212 clientKey = new EncryptionKey( EncryptionType.getTypeByOrdinal( samKey.getKeyType() ), samKey
213 .getEncoded() );
214 }
215 }
216 }
217 catch ( SamException se )
218 {
219 throw new KerberosException( ErrorType.KRB_ERR_GENERIC, se );
220 }
221
222 authContext.setClientKey( clientKey );
223 authContext.setPreAuthenticated( true );
224
225 if ( LOG.isDebugEnabled() )
226 {
227 LOG.debug( "Pre-authentication using SAM subsystem successful for {}.", clientName );
228 }
229 }
230 }
231
232
233 private static void verifyEncryptedTimestamp( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
234 {
235 LOG.debug( "Verifying using encrypted timestamp." );
236
237 KdcServer config = authContext.getConfig();
238 KdcRequest request = authContext.getRequest();
239 CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
240 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
241 String clientName = clientEntry.getPrincipal().getName();
242
243 EncryptionKey clientKey = null;
244
245 if ( clientEntry.getSamType() == null )
246 {
247 if ( LOG.isDebugEnabled() )
248 {
249 LOG.debug(
250 "Entry for client principal {} has no SAM type. Proceeding with standard pre-authentication.",
251 clientName );
252 }
253
254 EncryptionType encryptionType = authContext.getEncryptionType();
255 clientKey = clientEntry.getKeyMap().get( encryptionType );
256
257 if ( clientKey == null )
258 {
259 throw new KerberosException( ErrorType.KDC_ERR_NULL_KEY );
260 }
261
262 if ( config.isPaEncTimestampRequired() )
263 {
264 PaData[] preAuthData = request.getPreAuthData();
265
266 if ( preAuthData == null )
267 {
268 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED,
269 preparePreAuthenticationError( config.getEncryptionTypes() ) );
270 }
271
272 EncryptedTimeStamp timestamp = null;
273
274 for ( int ii = 0; ii < preAuthData.length; ii++ )
275 {
276 if ( preAuthData[ii].getPaDataType().equals( PaDataType.PA_ENC_TIMESTAMP ) )
277 {
278 EncryptedData dataValue;
279
280 try
281 {
282 dataValue = EncryptedDataDecoder.decode( preAuthData[ii].getPaDataValue() );
283 }
284 catch ( IOException ioe )
285 {
286 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, ioe );
287 }
288 catch ( ClassCastException cce )
289 {
290 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, cce );
291 }
292
293 timestamp = ( EncryptedTimeStamp ) cipherTextHandler.unseal( EncryptedTimeStamp.class,
294 clientKey, dataValue, KeyUsage.NUMBER1 );
295 }
296 }
297
298 if ( preAuthData.length > 0 && timestamp == null )
299 {
300 throw new KerberosException( ErrorType.KDC_ERR_PADATA_TYPE_NOSUPP );
301 }
302
303 if ( timestamp == null )
304 {
305 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED,
306 preparePreAuthenticationError( config.getEncryptionTypes() ) );
307 }
308
309 if ( !timestamp.getTimeStamp().isInClockSkew( config.getAllowableClockSkew() ) )
310 {
311 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_FAILED );
312 }
313
314
315
316
317
318
319
320
321 }
322 }
323
324 authContext.setClientKey( clientKey );
325 authContext.setPreAuthenticated( true );
326
327 if ( LOG.isDebugEnabled() )
328 {
329 LOG.debug( "Pre-authentication by encrypted timestamp successful for {}.", clientName );
330 }
331 }
332
333
334 private static void getServerEntry( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
335 {
336 KerberosPrincipal principal = authContext.getRequest().getServerPrincipal();
337 PrincipalStore store = authContext.getStore();
338
339 authContext.setServerEntry( getEntry( principal, store, ErrorType.KDC_ERR_S_PRINCIPAL_UNKNOWN ) );
340 }
341
342
343 private static void generateTicket( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
344 {
345 KdcRequest request = authContext.getRequest();
346 CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
347 KerberosPrincipal serverPrincipal = request.getServerPrincipal();
348
349 EncryptionType encryptionType = authContext.getEncryptionType();
350 EncryptionKey serverKey = authContext.getServerEntry().getKeyMap().get( encryptionType );
351
352 KerberosPrincipal ticketPrincipal = request.getServerPrincipal();
353 EncTicketPartModifier newTicketBody = new EncTicketPartModifier();
354 KdcServer config = authContext.getConfig();
355
356
357 newTicketBody.setFlag( TicketFlag.INITIAL );
358
359
360 if ( authContext.isPreAuthenticated() )
361 {
362 newTicketBody.setFlag( TicketFlag.PRE_AUTHENT );
363 }
364
365 if ( request.getOption( KdcOptions.FORWARDABLE ) )
366 {
367 if ( !config.isForwardableAllowed() )
368 {
369 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
370 }
371
372 newTicketBody.setFlag( TicketFlag.FORWARDABLE );
373 }
374
375 if ( request.getOption( KdcOptions.PROXIABLE ) )
376 {
377 if ( !config.isProxiableAllowed() )
378 {
379 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
380 }
381
382 newTicketBody.setFlag( TicketFlag.PROXIABLE );
383 }
384
385 if ( request.getOption( KdcOptions.ALLOW_POSTDATE ) )
386 {
387 if ( !config.isPostdatedAllowed() )
388 {
389 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
390 }
391
392 newTicketBody.setFlag( TicketFlag.MAY_POSTDATE );
393 }
394
395 if ( request.getOption( KdcOptions.RENEW ) || request.getOption( KdcOptions.VALIDATE )
396 || request.getOption( KdcOptions.PROXY ) || request.getOption( KdcOptions.FORWARDED )
397 || request.getOption( KdcOptions.ENC_TKT_IN_SKEY ) )
398 {
399 throw new KerberosException( ErrorType.KDC_ERR_BADOPTION );
400 }
401
402 EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( authContext.getEncryptionType() );
403 newTicketBody.setSessionKey( sessionKey );
404
405 newTicketBody.setClientPrincipal( request.getClientPrincipal() );
406 newTicketBody.setTransitedEncoding( new TransitedEncoding() );
407
408 KerberosTime now = new KerberosTime();
409
410 newTicketBody.setAuthTime( now );
411
412 KerberosTime startTime = request.getFrom();
413
414
415
416
417
418
419
420 if ( startTime == null || startTime.lessThan( now ) || startTime.isInClockSkew( config.getAllowableClockSkew() )
421 && !request.getOption( KdcOptions.POSTDATED ) )
422 {
423 startTime = now;
424 }
425
426
427
428
429
430
431 if ( startTime != null && startTime.greaterThan( now )
432 && !startTime.isInClockSkew( config.getAllowableClockSkew() ) && !request.getOption( KdcOptions.POSTDATED ) )
433 {
434 throw new KerberosException( ErrorType.KDC_ERR_CANNOT_POSTDATE );
435 }
436
437
438
439
440
441
442 if ( request.getOption( KdcOptions.POSTDATED ) )
443 {
444 if ( !config.isPostdatedAllowed() )
445 {
446 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
447 }
448
449 newTicketBody.setFlag( TicketFlag.POSTDATED );
450 newTicketBody.setFlag( TicketFlag.INVALID );
451 newTicketBody.setStartTime( startTime );
452 }
453
454 long till = 0;
455
456 if ( request.getTill().getTime() == 0 )
457 {
458 till = Long.MAX_VALUE;
459 }
460 else
461 {
462 till = request.getTill().getTime();
463 }
464
465
466
467
468
469 long endTime = Math.min( till, startTime.getTime() + config.getMaximumTicketLifetime() );
470 KerberosTime kerberosEndTime = new KerberosTime( endTime );
471 newTicketBody.setEndTime( kerberosEndTime );
472
473
474
475
476
477
478 if ( kerberosEndTime.lessThan( startTime ) )
479 {
480 throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID );
481 }
482
483 long ticketLifeTime = Math.abs( startTime.getTime() - kerberosEndTime.getTime() );
484
485 if ( ticketLifeTime < config.getAllowableClockSkew() )
486 {
487 throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID );
488 }
489
490
491
492
493
494
495
496 KerberosTime tempRtime = request.getRtime();
497
498 if ( request.getOption( KdcOptions.RENEWABLE_OK ) && request.getTill().greaterThan( kerberosEndTime ) )
499 {
500 if ( !config.isRenewableAllowed() )
501 {
502 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
503 }
504
505 request.setOption( KdcOptions.RENEWABLE );
506 tempRtime = request.getTill();
507 }
508
509 if ( request.getOption( KdcOptions.RENEWABLE ) )
510 {
511 if ( !config.isRenewableAllowed() )
512 {
513 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
514 }
515
516 newTicketBody.setFlag( TicketFlag.RENEWABLE );
517
518 if ( tempRtime == null || tempRtime.isZero() )
519 {
520 tempRtime = KerberosTime.INFINITY;
521 }
522
523
524
525
526
527
528 long renewTill = Math.min( tempRtime.getTime(), startTime.getTime() + config.getMaximumRenewableLifetime() );
529 newTicketBody.setRenewTill( new KerberosTime( renewTill ) );
530 }
531
532 if ( request.getAddresses() != null && request.getAddresses().getAddresses() != null
533 && request.getAddresses().getAddresses().length > 0 )
534 {
535 newTicketBody.setClientAddresses( request.getAddresses() );
536 }
537 else
538 {
539 if ( !config.isEmptyAddressesAllowed() )
540 {
541 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
542 }
543 }
544
545 EncTicketPart ticketPart = newTicketBody.getEncTicketPart();
546
547 EncryptedData encryptedData = cipherTextHandler.seal( serverKey, ticketPart, KeyUsage.NUMBER2 );
548
549 Ticket newTicket = new Ticket( ticketPrincipal, encryptedData );
550 newTicket.setEncTicketPart( ticketPart );
551
552 if ( LOG.isDebugEnabled() )
553 {
554 LOG.debug( "Ticket will be issued for access to {}.", serverPrincipal.toString() );
555 }
556
557 authContext.setTicket( newTicket );
558 }
559
560
561 private static void buildReply( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
562 {
563 KdcRequest request = authContext.getRequest();
564 Ticket ticket = authContext.getTicket();
565
566 AuthenticationReply reply = new AuthenticationReply();
567
568 reply.setClientPrincipal( request.getClientPrincipal() );
569 reply.setTicket( ticket );
570 reply.setKey( ticket.getEncTicketPart().getSessionKey() );
571
572
573 reply.setLastRequest( new LastRequest() );
574
575
576 reply.setNonce( request.getNonce() );
577
578 reply.setFlags( ticket.getEncTicketPart().getFlags() );
579 reply.setAuthTime( ticket.getEncTicketPart().getAuthTime() );
580 reply.setStartTime( ticket.getEncTicketPart().getStartTime() );
581 reply.setEndTime( ticket.getEncTicketPart().getEndTime() );
582
583 if ( ticket.getEncTicketPart().getFlags().isRenewable() )
584 {
585 reply.setRenewTill( ticket.getEncTicketPart().getRenewTill() );
586 }
587
588 reply.setServerPrincipal( ticket.getServerPrincipal() );
589 reply.setClientAddresses( ticket.getEncTicketPart().getClientAddresses() );
590
591 authContext.setReply( reply );
592 }
593
594
595 private static void sealReply( AuthenticationContext authContext ) throws KerberosException, InvalidTicketException
596 {
597 AuthenticationReply reply = ( AuthenticationReply ) authContext.getReply();
598 EncryptionKey clientKey = authContext.getClientKey();
599 CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
600
601 EncryptedData encryptedData = cipherTextHandler.seal( clientKey, reply, KeyUsage.NUMBER3 );
602 reply.setEncPart( encryptedData );
603 }
604
605
606 private static void monitorRequest( KdcContext kdcContext )
607 {
608 KdcRequest request = kdcContext.getRequest();
609
610 if ( LOG.isDebugEnabled() )
611 {
612 try
613 {
614 String clientAddress = kdcContext.getClientAddress().getHostAddress();
615
616 StringBuffer sb = new StringBuffer();
617
618 sb.append( "Received " + SERVICE_NAME + " request:" );
619 sb.append( "\n\t" + "messageType: " + request.getMessageType() );
620 sb.append( "\n\t" + "protocolVersionNumber: " + request.getProtocolVersionNumber() );
621 sb.append( "\n\t" + "clientAddress: " + clientAddress );
622 sb.append( "\n\t" + "nonce: " + request.getNonce() );
623 sb.append( "\n\t" + "kdcOptions: " + request.getKdcOptions() );
624 sb.append( "\n\t" + "clientPrincipal: " + request.getClientPrincipal() );
625 sb.append( "\n\t" + "serverPrincipal: " + request.getServerPrincipal() );
626 sb.append( "\n\t" + "encryptionType: " + KerberosUtils.getEncryptionTypesString( request.getEType() ) );
627 sb.append( "\n\t" + "realm: " + request.getRealm() );
628 sb.append( "\n\t" + "from time: " + request.getFrom() );
629 sb.append( "\n\t" + "till time: " + request.getTill() );
630 sb.append( "\n\t" + "renew-till time: " + request.getRtime() );
631 sb.append( "\n\t" + "hostAddresses: " + request.getAddresses() );
632
633 LOG.debug( sb.toString() );
634 }
635 catch ( Exception e )
636 {
637
638 LOG.error( "Error in request monitor", e );
639 }
640 }
641 }
642
643 private static void monitorContext( AuthenticationContext authContext )
644 {
645 try
646 {
647 long clockSkew = authContext.getConfig().getAllowableClockSkew();
648 InetAddress clientAddress = authContext.getClientAddress();
649
650 StringBuilder sb = new StringBuilder();
651
652 sb.append( "Monitoring " + SERVICE_NAME + " context:" );
653
654 sb.append( "\n\t" + "clockSkew " + clockSkew );
655 sb.append( "\n\t" + "clientAddress " + clientAddress );
656
657 KerberosPrincipal clientPrincipal = authContext.getClientEntry().getPrincipal();
658 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
659
660 sb.append( "\n\t" + "principal " + clientPrincipal );
661 sb.append( "\n\t" + "cn " + clientEntry.getCommonName() );
662 sb.append( "\n\t" + "realm " + clientEntry.getRealmName() );
663 sb.append( "\n\t" + "principal " + clientEntry.getPrincipal() );
664 sb.append( "\n\t" + "SAM type " + clientEntry.getSamType() );
665
666 KerberosPrincipal serverPrincipal = authContext.getRequest().getServerPrincipal();
667 PrincipalStoreEntry serverEntry = authContext.getServerEntry();
668
669 sb.append( "\n\t" + "principal " + serverPrincipal );
670 sb.append( "\n\t" + "cn " + serverEntry.getCommonName() );
671 sb.append( "\n\t" + "realm " + serverEntry.getRealmName() );
672 sb.append( "\n\t" + "principal " + serverEntry.getPrincipal() );
673 sb.append( "\n\t" + "SAM type " + serverEntry.getSamType() );
674
675 EncryptionType encryptionType = authContext.getEncryptionType();
676 int clientKeyVersion = clientEntry.getKeyMap().get( encryptionType ).getKeyVersion();
677 int serverKeyVersion = serverEntry.getKeyMap().get( encryptionType ).getKeyVersion();
678 sb.append( "\n\t" + "Request key type " + encryptionType );
679 sb.append( "\n\t" + "Client key version " + clientKeyVersion );
680 sb.append( "\n\t" + "Server key version " + serverKeyVersion );
681
682 LOG.debug( sb.toString() );
683 }
684 catch ( Exception e )
685 {
686
687 LOG.error( "Error in context monitor", e );
688 }
689 }
690
691
692 private static void monitorReply( KdcContext kdcContext )
693 {
694 Object reply = kdcContext.getReply();
695
696 if ( LOG.isDebugEnabled() )
697 {
698 if ( reply instanceof KdcReply )
699 {
700 KdcReply success = ( KdcReply ) reply;
701
702 try
703 {
704 StringBuffer sb = new StringBuffer();
705
706 sb.append( "Responding with " + SERVICE_NAME + " reply:" );
707 sb.append( "\n\t" + "messageType: " + success.getMessageType() );
708 sb.append( "\n\t" + "protocolVersionNumber: " + success.getProtocolVersionNumber() );
709 sb.append( "\n\t" + "nonce: " + success.getNonce() );
710 sb.append( "\n\t" + "clientPrincipal: " + success.getClientPrincipal() );
711 sb.append( "\n\t" + "client realm: " + success.getClientRealm() );
712 sb.append( "\n\t" + "serverPrincipal: " + success.getServerPrincipal() );
713 sb.append( "\n\t" + "server realm: " + success.getServerRealm() );
714 sb.append( "\n\t" + "auth time: " + success.getAuthTime() );
715 sb.append( "\n\t" + "start time: " + success.getStartTime() );
716 sb.append( "\n\t" + "end time: " + success.getEndTime() );
717 sb.append( "\n\t" + "renew-till time: " + success.getRenewTill() );
718 sb.append( "\n\t" + "hostAddresses: " + success.getClientAddresses() );
719
720 LOG.debug( sb.toString() );
721 }
722 catch ( Exception e )
723 {
724
725 LOG.error( "Error in reply monitor", e );
726 }
727 }
728 }
729 }
730
731
732
733
734
735
736 private static PrincipalStoreEntry getEntry( KerberosPrincipal principal, PrincipalStore store, ErrorType errorType )
737 throws KerberosException
738 {
739 PrincipalStoreEntry entry = null;
740
741 try
742 {
743 entry = store.getPrincipal( principal );
744 }
745 catch ( Exception e )
746 {
747 throw new KerberosException( errorType, e );
748 }
749
750 if ( entry == null )
751 {
752 throw new KerberosException( errorType );
753 }
754
755 if ( entry.getKeyMap() == null || entry.getKeyMap().isEmpty() )
756 {
757 throw new KerberosException( ErrorType.KDC_ERR_NULL_KEY );
758 }
759
760 return entry;
761 }
762
763
764
765
766
767
768
769
770
771 private static byte[] preparePreAuthenticationError( Set<EncryptionType> encryptionTypes )
772 {
773 PaData[] paDataSequence = new PaData[2];
774
775 PaData paData = new PaData();
776 paData.setPaDataType( PaDataType.PA_ENC_TIMESTAMP );
777 paData.setPaDataValue( new byte[0] );
778
779 paDataSequence[0] = paData;
780
781 EncryptionTypeInfoEntry[] entries = new EncryptionTypeInfoEntry[ encryptionTypes.size() ];
782 int i = 0;
783
784 for ( EncryptionType encryptionType:encryptionTypes )
785 {
786 entries[i++] = new EncryptionTypeInfoEntry( encryptionType, null );
787 }
788
789 byte[] encTypeInfo = null;
790
791 try
792 {
793 encTypeInfo = EncryptionTypeInfoEncoder.encode( entries );
794 }
795 catch ( IOException ioe )
796 {
797 return null;
798 }
799
800 PaData encType = new PaData();
801 encType.setPaDataType( PaDataType.PA_ENCTYPE_INFO );
802 encType.setPaDataValue( encTypeInfo );
803
804 paDataSequence[1] = encType;
805
806 try
807 {
808 return PreAuthenticationDataEncoder.encode( paDataSequence );
809 }
810 catch ( IOException ioe )
811 {
812 return null;
813 }
814 }
815 }