body.setKdcOptions( clientTgtReq.getOptions() );
List<HostAddress> lstAddresses = clientTgtReq.getHostAddresses();
if ( !lstAddresses.isEmpty() )
{
HostAddresses addresses = new HostAddresses();
for( HostAddress h : lstAddresses )
{
addresses.addHostAddress( h );
}
body.setAddresses( addresses );
}
EncryptionType encryptionType = clientTgtReq.getETypes().iterator().next();
EncryptionKey clientKey = KerberosKeyFactory.string2Key( clientTgtReq.getClientPrincipal(), clientTgtReq.getPassword(), encryptionType );
AsReq req = new AsReq();
req.setKdcReqBody( body );
if ( clientTgtReq.isPreAuthEnabled() )
{
PaEncTsEnc tmstmp = new PaEncTsEnc();
tmstmp.setPaTimestamp( new KerberosTime() );
EncryptedData paDataValue = cipherTextHandler.encrypt( clientKey, getEncoded( tmstmp ), KeyUsage.AS_REQ_PA_ENC_TIMESTAMP_WITH_CKEY );
PaData paEncTstmp = new PaData();
paEncTstmp.setPaDataType( PaDataType.PA_ENC_TIMESTAMP );
paEncTstmp.setPaDataValue( getEncoded( paDataValue ) );
req.addPaData( paEncTstmp );
}
// Get the result from the future
try
{
connect();
// Read the response, waiting for it if not available immediately
// Get the response, blocking
KerberosMessage kdcRep = sendAndReceiveKrbMsg( req );
if ( kdcRep == null )
{
// We didn't received anything : this is an error
LOG.error( "Authentication failed : timeout occured" );
throw new KerberosException( ErrorType.KRB_ERR_GENERIC, TIME_OUT_ERROR );
}
if ( kdcRep instanceof KrbError )
{
// We have an error
LOG.debug( "Authentication failed : {}", kdcRep );
throw new KerberosException( ( KrbError ) kdcRep );
}
AsRep rep = ( AsRep ) kdcRep;
if ( !cName.getNameString().equals( rep.getCName().getNameString() ) )
{
throw new KerberosException( ErrorType.KDC_ERR_CLIENT_NAME_MISMATCH );
}
if ( !realm.equals( rep.getCRealm() ) )
{
throw new KerberosException( ErrorType.KRB_ERR_WRONG_REALM );
}
if ( encryptionType != rep.getEncPart().getEType() )
{
encryptionType = rep.getEncPart().getEType();
clientKey = KerberosKeyFactory.string2Key( clientTgtReq.getClientPrincipal(), clientTgtReq.getPassword(), encryptionType );
}
byte[] decryptedEncAsRepPart = cipherTextHandler.decrypt( clientKey, rep.getEncPart(), KeyUsage.AS_REP_ENC_PART_WITH_CKEY );
EncKdcRepPart encKdcRepPart = null;
try
{
EncAsRepPart encAsRepPart = KerberosDecoder.decodeEncAsRepPart( decryptedEncAsRepPart );
encKdcRepPart = encAsRepPart.getEncKdcRepPart();
}
catch( KerberosException e )
{
LOG.info("Trying an encTgsRepPart instead");
EncTgsRepPart encTgsRepPart = KerberosDecoder.decodeEncTgsRepPart( decryptedEncAsRepPart );
encKdcRepPart = encTgsRepPart.getEncKdcRepPart();
}
if ( currentNonce != encKdcRepPart.getNonce() )
{
throw new KerberosException( ErrorType.KRB_ERR_GENERIC, "received nonce didn't match with the nonce sent in the request" );
}
if ( !encKdcRepPart.getSName().getNameString().equals( clientTgtReq.getSName() ) )
{
throw new KerberosException( ErrorType.KDC_ERR_SERVER_NOMATCH );
}
if ( !encKdcRepPart.getSRealm().equals( clientTgtReq.getRealm() ) )
{
throw new KerberosException( ErrorType.KRB_ERR_GENERIC, "received server realm does not match with requested server realm" );
}
List<HostAddress> hosts = clientTgtReq.getHostAddresses();
if( !hosts.isEmpty() )
{
HostAddresses addresses = encKdcRepPart.getClientAddresses();
for( HostAddress h : hosts )
{
if ( !addresses.contains( h ) )
{
throw new KerberosException( ErrorType.KRB_ERR_GENERIC, "requested client address" + h + " is not found in the ticket" );
}
}
}