in kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/TgsRequest.java [128:264]
public void verifyAuthenticator(PaDataEntry paDataEntry) throws KrbException {
ApReq apReq = KrbCodec.decode(paDataEntry.getPaDataValue(), ApReq.class);
if (apReq.getPvno() != KrbConstant.KRB_V5) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADVERSION);
}
if (apReq.getMsgType() != KrbMessageType.AP_REQ) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_MSG_TYPE);
}
tgtTicket = apReq.getTicket();
EncryptionKey tgsKey;
EncryptionType encType = tgtTicket.getEncryptedEncPart().getEType();
String remoteRealm = tgtTicket.getRealm();
if (checkCrossRealm(remoteRealm)) {
KrbIdentity tgs = getCrossRealmTgsEntry(remoteRealm);
if (tgs != null) {
tgsKey = tgs.getKey(encType);
} else {
throw new KrbException("Failed to get the tgs entry for remote realm: " + remoteRealm);
}
} else {
tgsKey = getTgsEntry().getKeys().get(encType);
}
if (tgsKey == null) {
throw new KrbException("Failed to get the tgs key for the type: " + encType);
}
if (tgtTicket.getTktvno() != KrbConstant.KRB_V5) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADVERSION);
}
EncTicketPart encPart = EncryptionUtil.unseal(tgtTicket.getEncryptedEncPart(),
tgsKey, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
tgtTicket.setEncPart(encPart);
EncryptionKey encKey = null;
//if (apReq.getApOptions().isFlagSet(ApOptions.USE_SESSION_KEY)) {
encKey = tgtTicket.getEncPart().getKey();
if (encKey == null) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_NOKEY);
}
Authenticator authenticator = EncryptionUtil.unseal(apReq.getEncryptedAuthenticator(),
encKey, KeyUsage.TGS_REQ_AUTH, Authenticator.class);
if (!authenticator.getCname().equals(tgtTicket.getEncPart().getCname())) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADMATCH);
}
HostAddresses hostAddresses = tgtTicket.getEncPart().getClientAddresses();
if (hostAddresses == null || hostAddresses.isEmpty()) {
if (!getKdcContext().getConfig().isEmptyAddressesAllowed()) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADADDR);
}
} else if (!hostAddresses.contains(getClientAddress())) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADADDR);
}
PrincipalName serverPrincipal = tgtTicket.getSname();
serverPrincipal.setRealm(tgtTicket.getRealm());
/* The client principal does not exist in backend when it's a cross realm request */
if (authenticator.getCrealm() != null
&& authenticator.getCrealm().equals(getKdcContext().getKdcRealm())) {
PrincipalName clientPrincipal = authenticator.getCname();
clientPrincipal.setRealm(authenticator.getCrealm());
KrbIdentity clientEntry = getEntry(clientPrincipal.getName());
setClientEntry(clientEntry);
}
if (!authenticator.getCtime().isInClockSkew(
getKdcContext().getConfig().getAllowableClockSkew() * 1000)) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_SKEW);
}
KerberosTime now = KerberosTime.now();
KerberosTime startTime = tgtTicket.getEncPart().getStartTime();
if (startTime == null) {
startTime = tgtTicket.getEncPart().getAuthTime();
}
if (!startTime.lessThan(now)) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_NYV);
}
KerberosTime endTime = tgtTicket.getEncPart().getEndTime();
if (!endTime.greaterThan(now)) {
throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_EXPIRED);
}
apReq.getApOptions().setFlag(ApOption.MUTUAL_REQUIRED);
setTgtSessionKey(tgtTicket.getEncPart().getKey());
CheckSum checkSum = authenticator.getCksum();
if (checkSum != null) {
byte[] reqBody;
try {
reqBody = KrbCodec.encode(getKdcReq().getReqBody());
} catch (KrbException e) {
String errMessage = "Encode the ReqBody failed. " + e.getMessage();
LOG.error(errMessage);
throw new KrbException(errMessage);
}
boolean success;
switch (checkSum.getCksumtype()) {
case RSA_MD5_DES:
case RSA_MD4_DES:
case DES_MAC:
case DES_CBC:
case HMAC_SHA1_DES3:
case HMAC_SHA1_96_AES256:
case HMAC_SHA1_96_AES128:
case CMAC_CAMELLIA128:
case CMAC_CAMELLIA256:
case MD5_HMAC_ARCFOUR:
case HMAC_MD5_ARCFOUR:
success = CheckSumHandler.verifyWithKey(checkSum, reqBody,
getTgtSessionKey().getKeyData(), KeyUsage.TGS_REQ_AUTH_CKSUM);
break;
case RSA_MD5:
case NIST_SHA:
case CRC32:
case RSA_MD4:
default:
success = CheckSumHandler.verify(checkSum, reqBody);
}
if (!success) {
LOG.error("Verify the KdcReqBody failed.");
throw new KrbException("Verify the KdcReqBody failed.");
}
}
}