package org.apache.kerberos.kerb.server.request; import org.apache.kerberos.kerb.KrbErrorCode; import org.apache.kerberos.kerb.codec.KrbCodec; import org.apache.kerberos.kerb.common.EncryptionUtil; import org.apache.kerberos.kerb.server.KdcContext; import org.apache.kerberos.kerb.KrbConstant; import org.apache.kerberos.kerb.KrbException; import org.apache.kerberos.kerb.spec.KerberosTime; import org.apache.kerberos.kerb.spec.ap.ApOption; import org.apache.kerberos.kerb.spec.ap.ApReq; import org.apache.kerberos.kerb.spec.ap.Authenticator; import org.apache.kerberos.kerb.spec.common.*; import org.apache.kerberos.kerb.spec.kdc.*; import org.apache.kerberos.kerb.spec.pa.PaDataEntry; import org.apache.kerberos.kerb.spec.ticket.EncTicketPart; import org.apache.kerberos.kerb.spec.ticket.Ticket; import org.apache.kerberos.kerb.spec.ticket.TicketFlag; import java.nio.ByteBuffer; public class TgsRequest extends KdcRequest { private EncryptionKey tgtSessionKey; public TgsRequest(TgsReq tgsReq, KdcContext kdcContext) { super(tgsReq, kdcContext); setPreauthRequired(true); } public EncryptionKey getTgtSessionKey() { return tgtSessionKey; } public void setTgtSessionKey(EncryptionKey tgtSessionKey) { this.tgtSessionKey = tgtSessionKey; } 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); } EncryptionType encType = getKdcReq().getReqBody().getEtypes().listIterator().next(); EncryptionKey tgsKey = getTgsEntry().getKeys().get(encType); Ticket ticket = apReq.getTicket(); if (ticket.getTktvno() != KrbConstant.KRB_V5) { throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADVERSION); } EncTicketPart encPart = EncryptionUtil.unseal(ticket.getEncryptedEncPart(), tgsKey, KeyUsage.KDC_REP_TICKET, EncTicketPart.class); ticket.setEncPart(encPart); EncryptionKey encKey = null; //if (apReq.getApOptions().isFlagSet(ApOptions.USE_SESSION_KEY)) { encKey = ticket.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(ticket.getEncPart().getCname())) { throw new KrbException(KrbErrorCode.KRB_AP_ERR_BADMATCH); } HostAddresses hostAddresses = ticket.getEncPart().getClientAddresses(); if (hostAddresses == null || hostAddresses.isEmpty()) { if (!kdcContext.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 = ticket.getSname(); serverPrincipal.setRealm(ticket.getRealm()); PrincipalName clientPrincipal = authenticator.getCname(); clientPrincipal.setRealm(authenticator.getCrealm()); if (!authenticator.getCtime().isInClockSkew( kdcContext.getConfig().getAllowableClockSkew() * 1000)) { throw new KrbException(KrbErrorCode.KRB_AP_ERR_SKEW); } KerberosTime now = KerberosTime.now(); KerberosTime startTime = ticket.getEncPart().getStartTime(); if (startTime == null) { startTime = ticket.getEncPart().getAuthTime(); } if (! startTime.lessThan(now)) { throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_NYV); } KerberosTime endTime = ticket.getEncPart().getEndTime(); if (! endTime.greaterThan(now)) { throw new KrbException(KrbErrorCode.KRB_AP_ERR_TKT_EXPIRED); } apReq.getApOptions().setFlag(ApOption.MUTUAL_REQUIRED); setTgtSessionKey(ticket.getEncPart().getKey()); } @Override protected void makeReply() throws KrbException { Ticket ticket = getTicket(); TgsRep reply = new TgsRep(); reply.setCname(getClientEntry().getPrincipal()); reply.setCrealm(kdcContext.getServerRealm()); reply.setTicket(ticket); EncKdcRepPart encKdcRepPart = makeEncKdcRepPart(); reply.setEncPart(encKdcRepPart); EncryptionKey sessionKey = getTgtSessionKey(); EncryptedData encryptedData = EncryptionUtil.seal(encKdcRepPart, sessionKey, KeyUsage.TGS_REP_ENCPART_SESSKEY); reply.setEncryptedEncPart(encryptedData); setReply(reply); } private EncKdcRepPart makeEncKdcRepPart() { KdcReq request = getKdcReq(); Ticket ticket = getTicket(); EncKdcRepPart encKdcRepPart = new EncTgsRepPart(); //session key encKdcRepPart.setKey(ticket.getEncPart().getKey()); LastReq lastReq = new LastReq(); LastReqEntry entry = new LastReqEntry(); entry.setLrType(LastReqType.THE_LAST_INITIAL); entry.setLrValue(new KerberosTime()); lastReq.add(entry); encKdcRepPart.setLastReq(lastReq); encKdcRepPart.setNonce(request.getReqBody().getNonce()); encKdcRepPart.setFlags(ticket.getEncPart().getFlags()); encKdcRepPart.setAuthTime(ticket.getEncPart().getAuthTime()); encKdcRepPart.setStartTime(ticket.getEncPart().getStartTime()); encKdcRepPart.setEndTime(ticket.getEncPart().getEndTime()); if (ticket.getEncPart().getFlags().isFlagSet(TicketFlag.RENEWABLE)) { encKdcRepPart.setRenewTill(ticket.getEncPart().getRenewtill()); } encKdcRepPart.setSname(ticket.getSname()); encKdcRepPart.setSrealm(ticket.getRealm()); encKdcRepPart.setCaddr(ticket.getEncPart().getClientAddresses()); return encKdcRepPart; } public ByteBuffer getRequestBody() throws KrbException { return null; } public EncryptionKey getArmorKey() throws KrbException { return null; } }