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.net.InetAddress;
24 import java.nio.ByteBuffer;
25 import java.util.Date;
26 import java.util.List;
27 import java.util.Set;
28
29 import javax.security.auth.kerberos.KerberosKey;
30 import javax.security.auth.kerberos.KerberosPrincipal;
31
32 import org.apache.directory.api.asn1.EncoderException;
33 import org.apache.directory.api.ldap.model.constants.Loggers;
34 import org.apache.directory.server.i18n.I18n;
35 import org.apache.directory.server.kerberos.KerberosConfig;
36 import org.apache.directory.server.kerberos.kdc.KdcContext;
37 import org.apache.directory.server.kerberos.sam.SamException;
38 import org.apache.directory.server.kerberos.sam.SamSubsystem;
39 import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
40 import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
41 import org.apache.directory.server.kerberos.shared.crypto.encryption.RandomKeyFactory;
42 import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
43 import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
44 import org.apache.directory.shared.kerberos.KerberosConstants;
45 import org.apache.directory.shared.kerberos.KerberosTime;
46 import org.apache.directory.shared.kerberos.KerberosUtils;
47 import org.apache.directory.shared.kerberos.codec.KerberosDecoder;
48 import org.apache.directory.shared.kerberos.codec.options.KdcOptions;
49 import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
50 import org.apache.directory.shared.kerberos.codec.types.LastReqType;
51 import org.apache.directory.shared.kerberos.codec.types.PaDataType;
52 import org.apache.directory.shared.kerberos.components.ETypeInfo;
53 import org.apache.directory.shared.kerberos.components.ETypeInfo2;
54 import org.apache.directory.shared.kerberos.components.ETypeInfo2Entry;
55 import org.apache.directory.shared.kerberos.components.ETypeInfoEntry;
56 import org.apache.directory.shared.kerberos.components.EncKdcRepPart;
57 import org.apache.directory.shared.kerberos.components.EncTicketPart;
58 import org.apache.directory.shared.kerberos.components.EncryptedData;
59 import org.apache.directory.shared.kerberos.components.EncryptionKey;
60 import org.apache.directory.shared.kerberos.components.KdcReq;
61 import org.apache.directory.shared.kerberos.components.KdcReqBody;
62 import org.apache.directory.shared.kerberos.components.LastReq;
63 import org.apache.directory.shared.kerberos.components.LastReqEntry;
64 import org.apache.directory.shared.kerberos.components.MethodData;
65 import org.apache.directory.shared.kerberos.components.PaData;
66 import org.apache.directory.shared.kerberos.components.PaEncTsEnc;
67 import org.apache.directory.shared.kerberos.components.PrincipalName;
68 import org.apache.directory.shared.kerberos.components.TransitedEncoding;
69 import org.apache.directory.shared.kerberos.exceptions.ErrorType;
70 import org.apache.directory.shared.kerberos.exceptions.KerberosException;
71 import org.apache.directory.shared.kerberos.flags.TicketFlag;
72 import org.apache.directory.shared.kerberos.flags.TicketFlags;
73 import org.apache.directory.shared.kerberos.messages.AsRep;
74 import org.apache.directory.shared.kerberos.messages.EncAsRepPart;
75 import org.apache.directory.shared.kerberos.messages.Ticket;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
78
79
80
81
82
83
84
85 public final class AuthenticationService
86 {
87
88 private static final Logger LOG_KRB = LoggerFactory.getLogger( Loggers.KERBEROS_LOG.getName() );
89
90
91 private static final CipherTextHandler/crypto/encryption/CipherTextHandler.html#CipherTextHandler">CipherTextHandler CIPHER_TEXT_HANDLER = new CipherTextHandler();
92
93
94 private static final String SERVICE_NAME = "Authentication Service (AS)";
95
96
97 private AuthenticationService()
98 {
99 }
100
101
102
103
104
105
106
107
108 public static void execute( AuthenticationContext authContext ) throws Exception
109 {
110 if ( LOG_KRB.isDebugEnabled() )
111 {
112 monitorRequest( authContext );
113 }
114
115 authContext.setCipherTextHandler( CIPHER_TEXT_HANDLER );
116
117 int kerberosVersion = authContext.getRequest().getProtocolVersionNumber();
118
119 if ( kerberosVersion != KerberosConstants.KERBEROS_V5 )
120 {
121 LOG_KRB.error( "Kerberos V{} is not supported", kerberosVersion );
122 throw new KerberosException( ErrorType.KDC_ERR_BAD_PVNO );
123 }
124
125 selectEncryptionType( authContext );
126 getClientEntry( authContext );
127 verifyPolicy( authContext );
128 verifySam( authContext );
129 verifyEncryptedTimestamp( authContext );
130
131 getServerEntry( authContext );
132 generateTicket( authContext );
133 buildReply( authContext );
134 }
135
136
137
138
139
140
141
142 private static void selectEncryptionType( AuthenticationContext authContext ) throws KerberosException
143 {
144
145 LOG_KRB.debug( "--> Selecting the EncryptionType" );
146 KdcContext kdcContext = authContext;
147 KerberosConfig config = kdcContext.getConfig();
148
149 Set<EncryptionType> requestedTypes = kdcContext.getRequest().getKdcReqBody().getEType();
150 LOG_KRB.debug( "Encryption types requested by client {}.", requestedTypes );
151
152 EncryptionType bestType = KerberosUtils.getBestEncryptionType( requestedTypes, config.getEncryptionTypes() );
153
154 LOG_KRB.debug( "Session will use encryption type {}.", bestType );
155
156 if ( bestType == null )
157 {
158 LOG_KRB.error( "No encryptionType selected !" );
159 throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP );
160 }
161
162 kdcContext.setEncryptionType( bestType );
163 }
164
165
166 private static void getClientEntry( AuthenticationContext authContext ) throws KerberosException
167 {
168 LOG_KRB.debug( "--> Getting the client Entry" );
169 KdcReqBody kdcReqBody = authContext.getRequest().getKdcReqBody();
170 KerberosPrincipal principal = KerberosUtils.getKerberosPrincipal(
171 kdcReqBody.getCName(),
172 kdcReqBody.getRealm() );
173 PrincipalStore store = authContext.getStore();
174
175 try
176 {
177 PrincipalStoreEntry storeEntry = KerberosUtils.getEntry( principal, store,
178 ErrorType.KDC_ERR_C_PRINCIPAL_UNKNOWN );
179 authContext.setClientEntry( storeEntry );
180
181 LOG_KRB.debug( "Found entry {} for principal {}", storeEntry.getDistinguishedName(), principal );
182 }
183 catch ( KerberosException ke )
184 {
185 LOG_KRB.error( "Error while searching for client {} : {}", principal, ke.getMessage() );
186 throw ke;
187 }
188 }
189
190
191 private static void verifyPolicy( AuthenticationContext authContext ) throws KerberosException
192 {
193 LOG_KRB.debug( "--> Verifying the policy" );
194 PrincipalStoreEntry entry = authContext.getClientEntry();
195
196 if ( entry.isDisabled() )
197 {
198 LOG_KRB.error( "The entry {} is disabled", entry.getDistinguishedName() );
199 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
200 }
201
202 if ( entry.isLockedOut() )
203 {
204 LOG_KRB.error( "The entry {} is locked out", entry.getDistinguishedName() );
205 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
206 }
207
208 if ( entry.getExpiration().getTime() < new Date().getTime() )
209 {
210 LOG_KRB.error( "The entry {} has been revoked", entry.getDistinguishedName() );
211 throw new KerberosException( ErrorType.KDC_ERR_CLIENT_REVOKED );
212 }
213 }
214
215
216 private static void verifySam( AuthenticationContext authContext ) throws KerberosException
217 {
218 LOG_KRB.debug( "--> Verifying using SAM subsystem." );
219 KdcReq request = authContext.getRequest();
220 KerberosConfig config = authContext.getConfig();
221
222 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
223 String clientName = clientEntry.getPrincipal().getName();
224
225 EncryptionKey clientKey = null;
226
227 if ( clientEntry.getSamType() != null )
228 {
229 if ( LOG_KRB.isDebugEnabled() )
230 {
231 LOG_KRB
232 .debug(
233 "Entry for client principal {} has a valid SAM type. Invoking SAM subsystem for pre-authentication.",
234 clientName );
235 }
236
237 List<PaData> preAuthData = request.getPaData();
238
239 if ( ( preAuthData == null ) || preAuthData.isEmpty() )
240 {
241 LOG_KRB.debug( "No PreAuth Data" );
242 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED, preparePreAuthenticationError(
243 authContext.getEncryptionType(), config
244 .getEncryptionTypes() ) );
245 }
246
247 try
248 {
249 for ( PaData paData : preAuthData )
250 {
251 if ( paData.getPaDataType().equals( PaDataType.PA_ENC_TIMESTAMP ) )
252 {
253 KerberosKey samKey = SamSubsystem.getInstance().verify( clientEntry,
254 paData.getPaDataValue() );
255 clientKey = new EncryptionKey( EncryptionType.getTypeByValue( samKey.getKeyType() ), samKey
256 .getEncoded() );
257 }
258 }
259 }
260 catch ( SamException se )
261 {
262 LOG_KRB.error( "Error : {}", se.getMessage() );
263 throw new KerberosException( ErrorType.KRB_ERR_GENERIC, se );
264 }
265
266 authContext.setClientKey( clientKey );
267 authContext.setPreAuthenticated( true );
268
269 if ( LOG_KRB.isDebugEnabled() )
270 {
271 LOG_KRB.debug( "Pre-authentication using SAM subsystem successful for {}.", clientName );
272 }
273 }
274 }
275
276
277 private static void verifyEncryptedTimestamp( AuthenticationContext authContext ) throws KerberosException
278 {
279 LOG_KRB.debug( "--> Verifying using encrypted timestamp." );
280
281 KerberosConfig config = authContext.getConfig();
282 KdcReq request = authContext.getRequest();
283 CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
284 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
285 String clientName = clientEntry.getPrincipal().getName();
286
287 EncryptionKey clientKey = null;
288
289 if ( clientEntry.getSamType() == null )
290 {
291 LOG_KRB.debug(
292 "Entry for client principal {} has no SAM type. Proceeding with standard pre-authentication.",
293 clientName );
294
295 EncryptionType encryptionType = authContext.getEncryptionType();
296 clientKey = clientEntry.getKeyMap().get( encryptionType );
297
298 if ( clientKey == null )
299 {
300 LOG_KRB.error( "No key for client {}", clientEntry.getDistinguishedName() );
301 throw new KerberosException( ErrorType.KDC_ERR_NULL_KEY );
302 }
303
304 if ( config.isPaEncTimestampRequired() )
305 {
306 List<PaData> preAuthData = request.getPaData();
307
308 if ( preAuthData == null )
309 {
310 LOG_KRB.debug( "PRE_AUTH required..." );
311 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED,
312 preparePreAuthenticationError( authContext.getEncryptionType(), config.getEncryptionTypes() ) );
313 }
314
315 PaEncTsEnc timestamp = null;
316
317 for ( PaData paData : preAuthData )
318 {
319 if ( paData.getPaDataType().equals( PaDataType.PA_ENC_TIMESTAMP ) )
320 {
321 EncryptedData dataValue = KerberosDecoder.decodeEncryptedData( paData.getPaDataValue() );
322 byte[] decryptedData = cipherTextHandler.decrypt( clientKey, dataValue,
323 KeyUsage.AS_REQ_PA_ENC_TIMESTAMP_WITH_CKEY );
324 timestamp = KerberosDecoder.decodePaEncTsEnc( decryptedData );
325 }
326 }
327
328 if ( timestamp == null )
329 {
330 LOG_KRB.error( "No timestamp found" );
331 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_REQUIRED,
332 preparePreAuthenticationError( authContext.getEncryptionType(), config.getEncryptionTypes() ) );
333 }
334
335 if ( !timestamp.getPaTimestamp().isInClockSkew( config.getAllowableClockSkew() ) )
336 {
337 LOG_KRB.error( "Timestamp not in delay" );
338
339 throw new KerberosException( ErrorType.KDC_ERR_PREAUTH_FAILED );
340 }
341 }
342 }
343
344 authContext.setClientKey( clientKey );
345 authContext.setPreAuthenticated( true );
346
347 if ( LOG_KRB.isDebugEnabled() )
348 {
349 LOG_KRB.debug( "Pre-authentication by encrypted timestamp successful for {}.", clientName );
350 }
351 }
352
353
354 private static void getServerEntry( AuthenticationContext authContext ) throws KerberosException
355 {
356 PrincipalName principal = authContext.getRequest().getKdcReqBody().getSName();
357 PrincipalStore store = authContext.getStore();
358
359 LOG_KRB.debug( "--> Getting the server entry for {}", principal );
360
361 KerberosPrincipal principalWithRealm = new KerberosPrincipal( principal.getNameString() + "@"
362 + authContext.getRequest().getKdcReqBody().getRealm() );
363 authContext.setServerEntry( KerberosUtils.getEntry( principalWithRealm, store,
364 ErrorType.KDC_ERR_S_PRINCIPAL_UNKNOWN ) );
365 }
366
367
368 private static void generateTicket( AuthenticationContext authContext ) throws KerberosException
369 {
370 KdcReq request = authContext.getRequest();
371 CipherTextHandler cipherTextHandler = authContext.getCipherTextHandler();
372 PrincipalName serverPrincipal = request.getKdcReqBody().getSName();
373
374 LOG_KRB.debug( "--> Generating ticket for {}", serverPrincipal );
375
376 EncryptionType encryptionType = authContext.getEncryptionType();
377 EncryptionKey serverKey = authContext.getServerEntry().getKeyMap().get( encryptionType );
378
379 PrincipalName ticketPrincipal = request.getKdcReqBody().getSName();
380
381 EncTicketPartros/components/EncTicketPart.html#EncTicketPart">EncTicketPart encTicketPart = new EncTicketPart();
382 KerberosConfig config = authContext.getConfig();
383
384
385 TicketFlagserberos/flags/TicketFlags.html#TicketFlags">TicketFlags ticketFlags = new TicketFlags();
386 encTicketPart.setFlags( ticketFlags );
387 ticketFlags.setFlag( TicketFlag.INITIAL );
388
389
390 if ( authContext.isPreAuthenticated() )
391 {
392 ticketFlags.setFlag( TicketFlag.PRE_AUTHENT );
393 }
394
395 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.FORWARDABLE ) )
396 {
397 if ( !config.isForwardableAllowed() )
398 {
399 LOG_KRB.error( "Ticket cannot be generated, because Forwadable is not allowed" );
400 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
401 }
402
403 ticketFlags.setFlag( TicketFlag.FORWARDABLE );
404 }
405
406 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.PROXIABLE ) )
407 {
408 if ( !config.isProxiableAllowed() )
409 {
410 LOG_KRB.error( "Ticket cannot be generated, because proxyiable is not allowed" );
411 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
412 }
413
414 ticketFlags.setFlag( TicketFlag.PROXIABLE );
415 }
416
417 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.ALLOW_POSTDATE ) )
418 {
419 if ( !config.isPostdatedAllowed() )
420 {
421 LOG_KRB.error( "Ticket cannot be generated, because Posdate is not allowed" );
422 throw new KerberosException( ErrorType.KDC_ERR_POLICY );
423 }
424
425 ticketFlags.setFlag( TicketFlag.MAY_POSTDATE );
426 }
427
428 KdcOptions kdcOptions = request.getKdcReqBody().getKdcOptions();
429
430 if ( kdcOptions.get( KdcOptions.RENEW )
431 || kdcOptions.get( KdcOptions.VALIDATE )
432 || kdcOptions.get( KdcOptions.PROXY )
433 || kdcOptions.get( KdcOptions.FORWARDED )
434 || kdcOptions.get( KdcOptions.ENC_TKT_IN_SKEY ) )
435 {
436 String msg = "";
437
438 if ( kdcOptions.get( KdcOptions.RENEW ) )
439 {
440 msg = "Ticket cannot be generated, as it's a renew";
441 }
442
443 if ( kdcOptions.get( KdcOptions.VALIDATE ) )
444 {
445 msg = "Ticket cannot be generated, as it's a validate";
446 }
447
448 if ( kdcOptions.get( KdcOptions.PROXY ) )
449 {
450 msg = "Ticket cannot be generated, as it's a proxy";
451 }
452
453 if ( kdcOptions.get( KdcOptions.FORWARDED ) )
454 {
455 msg = "Ticket cannot be generated, as it's forwarded";
456 }
457
458 if ( kdcOptions.get( KdcOptions.ENC_TKT_IN_SKEY ) )
459 {
460 msg = "Ticket cannot be generated, as it's a user-to-user ";
461 }
462
463 if ( LOG_KRB.isDebugEnabled() )
464 {
465 LOG_KRB.debug( msg );
466 }
467
468 throw new KerberosException( ErrorType.KDC_ERR_BADOPTION, msg );
469 }
470
471 EncryptionKey sessionKey = RandomKeyFactory.getRandomKey( authContext.getEncryptionType() );
472 encTicketPart.setKey( sessionKey );
473
474 encTicketPart.setCName( request.getKdcReqBody().getCName() );
475 encTicketPart.setCRealm( request.getKdcReqBody().getRealm() );
476 encTicketPart.setTransited( new TransitedEncoding() );
477 String serverRealm = request.getKdcReqBody().getRealm();
478
479 KerberosTimehared/kerberos/KerberosTime.html#KerberosTime">KerberosTime now = new KerberosTime();
480
481 encTicketPart.setAuthTime( now );
482
483 KerberosTime startTime = request.getKdcReqBody().getFrom();
484
485
486
487
488
489
490
491 if ( startTime == null || startTime.lessThan( now ) || startTime.isInClockSkew( config.getAllowableClockSkew() )
492 && !request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
493 {
494 startTime = now;
495 }
496
497
498
499
500
501
502 if ( ( startTime != null ) && startTime.greaterThan( now )
503 && !startTime.isInClockSkew( config.getAllowableClockSkew() )
504 && !request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
505 {
506 String msg = "Ticket cannot be generated, as it's in the future and the POSTDATED option is not set in the request";
507 LOG_KRB.error( msg );
508 throw new KerberosException( ErrorType.KDC_ERR_CANNOT_POSTDATE, msg );
509 }
510
511
512
513
514
515
516 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.POSTDATED ) )
517 {
518 if ( !config.isPostdatedAllowed() )
519 {
520 String msg = "Ticket cannot be generated, cause issuing POSTDATED tickets is not allowed";
521 LOG_KRB.error( msg );
522 throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
523 }
524
525 ticketFlags.setFlag( TicketFlag.POSTDATED );
526 ticketFlags.setFlag( TicketFlag.INVALID );
527 }
528
529 encTicketPart.setStartTime( startTime );
530
531 long till = 0;
532
533 if ( request.getKdcReqBody().getTill().getTime() == 0 )
534 {
535 till = Long.MAX_VALUE;
536 }
537 else
538 {
539 till = request.getKdcReqBody().getTill().getTime();
540 }
541
542
543
544
545
546 long endTime = Math.min( till, startTime.getTime() + config.getMaximumTicketLifetime() );
547 KerberosTimeos/KerberosTime.html#KerberosTime">KerberosTime kerberosEndTime = new KerberosTime( endTime );
548 encTicketPart.setEndTime( kerberosEndTime );
549
550
551
552
553
554
555 if ( kerberosEndTime.lessThan( startTime ) )
556 {
557 String msg = "Ticket cannot be generated, as the endTime is below the startTime";
558 LOG_KRB.error( msg );
559 throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID, msg );
560 }
561
562 long ticketLifeTime = Math.abs( startTime.getTime() - kerberosEndTime.getTime() );
563
564 if ( ticketLifeTime < config.getMinimumTicketLifetime() )
565 {
566 String msg = "Ticket cannot be generated, as the Lifetime is too small";
567 LOG_KRB.error( msg );
568 throw new KerberosException( ErrorType.KDC_ERR_NEVER_VALID, msg );
569 }
570
571
572
573
574
575
576
577 KerberosTime tempRtime = request.getKdcReqBody().getRTime();
578
579 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.RENEWABLE_OK )
580 && request.getKdcReqBody().getTill().greaterThan( kerberosEndTime ) )
581 {
582 if ( !config.isRenewableAllowed() )
583 {
584 String msg = "Ticket cannot be generated, as the renew date is exceeded";
585 LOG_KRB.error( msg );
586 throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
587 }
588
589 request.getKdcReqBody().getKdcOptions().set( KdcOptions.RENEWABLE );
590 tempRtime = request.getKdcReqBody().getTill();
591 }
592
593 if ( request.getKdcReqBody().getKdcOptions().get( KdcOptions.RENEWABLE ) )
594 {
595 if ( !config.isRenewableAllowed() )
596 {
597 String msg = "Ticket cannot be generated, as Renewable is not allowed";
598 LOG_KRB.error( msg );
599 throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
600 }
601
602 ticketFlags.setFlag( TicketFlag.RENEWABLE );
603
604 if ( tempRtime == null || tempRtime.isZero() )
605 {
606 tempRtime = KerberosTime.INFINITY;
607 }
608
609
610
611
612
613
614 long renewTill = Math.min( tempRtime.getTime(), startTime.getTime() + config.getMaximumRenewableLifetime() );
615 encTicketPart.setRenewTill( new KerberosTime( renewTill ) );
616 }
617
618 if ( request.getKdcReqBody().getAddresses() != null
619 && request.getKdcReqBody().getAddresses().getAddresses() != null
620 && request.getKdcReqBody().getAddresses().getAddresses().length > 0 )
621 {
622 encTicketPart.setClientAddresses( request.getKdcReqBody().getAddresses() );
623 }
624 else
625 {
626 if ( !config.isEmptyAddressesAllowed() )
627 {
628 String msg = "Ticket cannot be generated, as the addresses are null, and it's not allowed";
629 LOG_KRB.error( msg );
630 throw new KerberosException( ErrorType.KDC_ERR_POLICY, msg );
631 }
632 }
633
634 EncryptedData encryptedData = cipherTextHandler.seal( serverKey, encTicketPart,
635 KeyUsage.AS_OR_TGS_REP_TICKET_WITH_SRVKEY );
636
637 Tickethared/kerberos/messages/Ticket.html#Ticket">Ticket newTicket = new Ticket( ticketPrincipal, encryptedData );
638
639 newTicket.setRealm( serverRealm );
640 newTicket.setEncTicketPart( encTicketPart );
641
642 if ( LOG_KRB.isDebugEnabled() )
643 {
644 LOG_KRB.debug( "Ticket will be issued for access to {}.", serverPrincipal );
645 }
646
647 authContext.setTicket( newTicket );
648 }
649
650
651 private static void buildReply( AuthenticationContext authContext ) throws KerberosException
652 {
653 LOG_KRB.debug( "--> Building reply" );
654 KdcReq request = authContext.getRequest();
655 Ticket ticket = authContext.getTicket();
656
657 AsRepory/shared/kerberos/messages/AsRep.html#AsRep">AsRep reply = new AsRep();
658
659 reply.setCName( request.getKdcReqBody().getCName() );
660 reply.setCRealm( request.getKdcReqBody().getRealm() );
661 reply.setTicket( ticket );
662
663 EncKdcRepPartros/components/EncKdcRepPart.html#EncKdcRepPart">EncKdcRepPart encKdcRepPart = new EncKdcRepPart();
664
665 encKdcRepPart.setKey( ticket.getEncTicketPart().getKey() );
666
667
668
669 LastReqshared/kerberos/components/LastReq.html#LastReq">LastReq lastReq = new LastReq();
670 lastReq.addEntry( new LastReqEntry( LastReqType.TIME_OF_INITIAL_REQ, new KerberosTime() ) );
671 encKdcRepPart.setLastReq( lastReq );
672
673
674 encKdcRepPart.setNonce( request.getKdcReqBody().getNonce() );
675
676 encKdcRepPart.setFlags( ticket.getEncTicketPart().getFlags() );
677 encKdcRepPart.setAuthTime( ticket.getEncTicketPart().getAuthTime() );
678 encKdcRepPart.setStartTime( ticket.getEncTicketPart().getStartTime() );
679 encKdcRepPart.setEndTime( ticket.getEncTicketPart().getEndTime() );
680
681 if ( ticket.getEncTicketPart().getFlags().isRenewable() )
682 {
683 encKdcRepPart.setRenewTill( ticket.getEncTicketPart().getRenewTill() );
684 }
685
686 encKdcRepPart.setSName( ticket.getSName() );
687 encKdcRepPart.setSRealm( ticket.getRealm() );
688 encKdcRepPart.setClientAddresses( ticket.getEncTicketPart().getClientAddresses() );
689
690 EncAsRepPartberos/messages/EncAsRepPart.html#EncAsRepPart">EncAsRepPart encAsRepPart = new EncAsRepPart();
691 encAsRepPart.setEncKdcRepPart( encKdcRepPart );
692
693 if ( LOG_KRB.isDebugEnabled() )
694 {
695 monitorContext( authContext );
696 monitorReply( reply, encKdcRepPart );
697 }
698
699 EncryptionKey clientKey = authContext.getClientKey();
700 EncryptedData encryptedData = CIPHER_TEXT_HANDLER.seal( clientKey, encAsRepPart,
701 KeyUsage.AS_REP_ENC_PART_WITH_CKEY );
702 reply.setEncPart( encryptedData );
703
704 reply.setEncKdcRepPart( encKdcRepPart );
705
706 authContext.setReply( reply );
707 }
708
709
710 private static void monitorRequest( KdcContext kdcContext )
711 {
712 KdcReq request = kdcContext.getRequest();
713
714 if ( LOG_KRB.isDebugEnabled() )
715 {
716 try
717 {
718 String clientAddress = kdcContext.getClientAddress().getHostAddress();
719
720 StringBuilder sb = new StringBuilder();
721
722 sb.append( "Received " ).append( SERVICE_NAME ).append( " request:" );
723 sb.append( "\n\tmessageType: " ).append( request.getMessageType() );
724 sb.append( "\n\tprotocolVersionNumber: " ).append( request.getProtocolVersionNumber() );
725 sb.append( "\n\tclientAddress: " ).append( clientAddress );
726 sb.append( "\n\tnonce: " ).append( request.getKdcReqBody().getNonce() );
727 sb.append( "\n\tkdcOptions: " ).append( request.getKdcReqBody().getKdcOptions() );
728 sb.append( "\n\tclientPrincipal: " ).append( request.getKdcReqBody().getCName() );
729 sb.append( "\n\tserverPrincipal: " ).append( request.getKdcReqBody().getSName() );
730 sb.append( "\n\tencryptionType: "
731 + KerberosUtils.getEncryptionTypesString( request.getKdcReqBody().getEType() ) );
732 sb.append( "\n\trealm: " ).append( request.getKdcReqBody().getRealm() );
733 sb.append( "\n\tfrom time: " ).append( request.getKdcReqBody().getFrom() );
734 sb.append( "\n\ttill time: " ).append( request.getKdcReqBody().getTill() );
735 sb.append( "\n\trenew-till time: " ).append( request.getKdcReqBody().getRTime() );
736 sb.append( "\n\thostAddresses: " ).append( request.getKdcReqBody().getAddresses() );
737
738 String message = sb.toString();
739 LOG_KRB.debug( message );
740 }
741 catch ( Exception e )
742 {
743
744 LOG_KRB.error( I18n.err( I18n.ERR_153 ), e );
745 }
746 }
747 }
748
749
750 private static void monitorContext( AuthenticationContext authContext )
751 {
752 if ( LOG_KRB.isDebugEnabled() )
753 {
754 try
755 {
756 long clockSkew = authContext.getConfig().getAllowableClockSkew();
757 InetAddress clientAddress = authContext.getClientAddress();
758
759 StringBuilder sb = new StringBuilder();
760
761 sb.append( "Monitoring " ).append( SERVICE_NAME ).append( " context:" );
762
763 sb.append( "\n\tclockSkew " ).append( clockSkew );
764 sb.append( "\n\tclientAddress " ).append( clientAddress );
765
766 KerberosPrincipal clientPrincipal = authContext.getClientEntry().getPrincipal();
767 PrincipalStoreEntry clientEntry = authContext.getClientEntry();
768
769 sb.append( "\n\tprincipal " ).append( clientPrincipal );
770 sb.append( "\n\tcn " ).append( clientEntry.getCommonName() );
771 sb.append( "\n\trealm " ).append( clientEntry.getRealmName() );
772 sb.append( "\n\tprincipal " ).append( clientEntry.getPrincipal() );
773 sb.append( "\n\tSAM type " ).append( clientEntry.getSamType() );
774
775 PrincipalName serverPrincipal = authContext.getRequest().getKdcReqBody().getSName();
776 PrincipalStoreEntry serverEntry = authContext.getServerEntry();
777
778 sb.append( "\n\tprincipal " ).append( serverPrincipal );
779 sb.append( "\n\tcn " ).append( serverEntry.getCommonName() );
780 sb.append( "\n\trealm " ).append( serverEntry.getRealmName() );
781 sb.append( "\n\tprincipal " ).append( serverEntry.getPrincipal() );
782 sb.append( "\n\tSAM type " ).append( serverEntry.getSamType() );
783
784 EncryptionType encryptionType = authContext.getEncryptionType();
785 int clientKeyVersion = clientEntry.getKeyMap().get( encryptionType ).getKeyVersion();
786 int serverKeyVersion = serverEntry.getKeyMap().get( encryptionType ).getKeyVersion();
787 sb.append( "\n\tRequest key type " ).append( encryptionType );
788 sb.append( "\n\tClient key version " ).append( clientKeyVersion );
789 sb.append( "\n\tServer key version " ).append( serverKeyVersion );
790
791 String message = sb.toString();
792
793 LOG_KRB.debug( message );
794 }
795 catch ( Exception e )
796 {
797
798 LOG_KRB.error( I18n.err( I18n.ERR_154 ), e );
799 }
800 }
801 }
802
803
804 private static void monitorReply( AsRep reply, EncKdcRepPart part )
805 {
806 if ( LOG_KRB.isDebugEnabled() )
807 {
808 try
809 {
810 StringBuilder sb = new StringBuilder();
811
812 sb.append( "Responding with " ).append( SERVICE_NAME ).append( " reply:" );
813 sb.append( "\n\tmessageType: " ).append( reply.getMessageType() );
814 sb.append( "\n\tprotocolVersionNumber: " ).append( reply.getProtocolVersionNumber() );
815 sb.append( "\n\tnonce: " ).append( part.getNonce() );
816 sb.append( "\n\tclientPrincipal: " ).append( reply.getCName() );
817 sb.append( "\n\tclient realm: " ).append( reply.getCRealm() );
818 sb.append( "\n\tserverPrincipal: " ).append( part.getSName() );
819 sb.append( "\n\tserver realm: " ).append( part.getSRealm() );
820 sb.append( "\n\tauth time: " ).append( part.getAuthTime() );
821 sb.append( "\n\tstart time: " ).append( part.getStartTime() );
822 sb.append( "\n\tend time: " ).append( part.getEndTime() );
823 sb.append( "\n\trenew-till time: " ).append( part.getRenewTill() );
824 sb.append( "\n\thostAddresses: " ).append( part.getClientAddresses() );
825
826 String message = sb.toString();
827
828 LOG_KRB.debug( message );
829 }
830 catch ( Exception e )
831 {
832
833 LOG_KRB.error( I18n.err( I18n.ERR_155 ), e );
834 }
835 }
836 }
837
838
839
840
841
842
843
844
845
846 private static byte[] preparePreAuthenticationError( EncryptionType requestedType,
847 Set<EncryptionType> encryptionTypes )
848 {
849 boolean isNewEtype = KerberosUtils.isNewEncryptionType( requestedType );
850
851 ETypeInfo2/kerberos/components/ETypeInfo2.html#ETypeInfo2">ETypeInfo2 eTypeInfo2 = new ETypeInfo2();
852
853 ETypeInfoed/kerberos/components/ETypeInfo.html#ETypeInfo">ETypeInfo eTypeInfo = new ETypeInfo();
854
855 for ( EncryptionType encryptionType : encryptionTypes )
856 {
857 if ( !isNewEtype )
858 {
859 ETypeInfoEntrys/components/ETypeInfoEntry.html#ETypeInfoEntry">ETypeInfoEntry etypeInfoEntry = new ETypeInfoEntry( encryptionType, null );
860 eTypeInfo.addETypeInfoEntry( etypeInfoEntry );
861 }
862
863 ETypeInfo2Entrycomponents/ETypeInfo2Entry.html#ETypeInfo2Entry">ETypeInfo2Entry etypeInfo2Entry = new ETypeInfo2Entry( encryptionType );
864 eTypeInfo2.addETypeInfo2Entry( etypeInfo2Entry );
865 }
866
867 byte[] encTypeInfo = null;
868 byte[] encTypeInfo2 = null;
869 try
870 {
871 if ( !isNewEtype )
872 {
873 ByteBuffer buffer = ByteBuffer.allocate( eTypeInfo.computeLength() );
874 encTypeInfo = eTypeInfo.encode( buffer ).array();
875 }
876
877 ByteBuffer buffer = ByteBuffer.allocate( eTypeInfo2.computeLength() );
878 encTypeInfo2 = eTypeInfo2.encode( buffer ).array();
879 }
880 catch ( EncoderException ioe )
881 {
882 return null;
883 }
884
885 MethodData/kerberos/components/MethodData.html#MethodData">MethodData methodData = new MethodData();
886
887 methodData.addPaData( new PaData( PaDataType.PA_ENC_TIMESTAMP, null ) );
888
889 if ( !isNewEtype )
890 {
891 methodData.addPaData( new PaData( PaDataType.PA_ENCTYPE_INFO, encTypeInfo ) );
892 }
893
894 methodData.addPaData( new PaData( PaDataType.PA_ENCTYPE_INFO2, encTypeInfo2 ) );
895
896 try
897 {
898 ByteBuffer buffer = ByteBuffer.allocate( methodData.computeLength() );
899 return methodData.encode( buffer ).array();
900 }
901 catch ( EncoderException ee )
902 {
903 LOG_KRB.warn( "Failed to encode the etype information", ee );
904 return null;
905 }
906 }
907 }