public void verifyAuthenticator()

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.");
            }
        }
    }