/**
   * Make padata entry.
   *
   * @param kdcRequest The kdc request
   * @return PaDataEntry to be made.
   */
  private PaDataEntry makeEntry(KdcRequest kdcRequest) throws KrbException {

    TgsRequestWithTgt tgsRequest = (TgsRequestWithTgt) kdcRequest;

    PaDataEntry paEntry = new PaDataEntry();
    paEntry.setPaDataType(PaDataType.TGS_REQ);
    paEntry.setPaDataValue(tgsRequest.getApReq().encode());

    return paEntry;
  }
  /**
   * Verify authenticator.
   *
   * @throws org.apache.kerby.kerberos.kerb.KrbException e
   * @param paDataEntry preauthentication data entry
   */
  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();
    EncryptionType encType = tgtTicket.getEncryptedEncPart().getEType();
    EncryptionKey tgsKey = getTgsEntry().getKeys().get(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());
    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());
  }