| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.kerby.kerberos.kerb.client.request; |
| |
| import org.apache.kerby.KOptions; |
| import org.apache.kerby.kerberos.kerb.KrbException; |
| import org.apache.kerby.kerberos.kerb.ccache.Credential; |
| import org.apache.kerby.kerberos.kerb.ccache.CredentialCache; |
| import org.apache.kerby.kerberos.kerb.client.KrbOption; |
| import org.apache.kerby.kerberos.kerb.client.preauth.KrbFastRequestState; |
| import org.apache.kerby.kerberos.kerb.common.CheckSumUtil; |
| import org.apache.kerby.kerberos.kerb.common.EncryptionUtil; |
| import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler; |
| import org.apache.kerby.kerberos.kerb.crypto.fast.FastUtil; |
| import org.apache.kerby.kerberos.kerb.type.KerberosTime; |
| import org.apache.kerby.kerberos.kerb.type.ap.ApOptions; |
| import org.apache.kerby.kerberos.kerb.type.ap.ApReq; |
| import org.apache.kerby.kerberos.kerb.type.ap.Authenticator; |
| import org.apache.kerby.kerberos.kerb.type.base.CheckSum; |
| import org.apache.kerby.kerberos.kerb.type.base.CheckSumType; |
| import org.apache.kerby.kerberos.kerb.type.base.EncryptedData; |
| import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey; |
| import org.apache.kerby.kerberos.kerb.type.base.EncryptionType; |
| import org.apache.kerby.kerberos.kerb.type.base.KeyUsage; |
| import org.apache.kerby.kerberos.kerb.type.fast.ArmorType; |
| import org.apache.kerby.kerberos.kerb.type.fast.KrbFastArmor; |
| import org.apache.kerby.kerberos.kerb.type.fast.KrbFastArmoredReq; |
| import org.apache.kerby.kerberos.kerb.type.fast.KrbFastReq; |
| import org.apache.kerby.kerberos.kerb.type.kdc.AsReq; |
| import org.apache.kerby.kerberos.kerb.type.kdc.KdcReq; |
| import org.apache.kerby.kerberos.kerb.type.kdc.KdcReqBody; |
| import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry; |
| import org.apache.kerby.kerberos.kerb.type.pa.PaDataType; |
| import org.apache.kerby.kerberos.kerb.type.ticket.Ticket; |
| |
| import java.io.File; |
| import java.io.IOException; |
| |
| public class ArmoredRequest { |
| |
| private Credential credential; |
| private EncryptionKey subKey; |
| private EncryptionKey armorCacheKey; |
| private KdcRequest kdcRequest; |
| |
| public ArmoredRequest(KdcRequest kdcRequest) { |
| this.kdcRequest = kdcRequest; |
| } |
| |
| public void process() throws KrbException { |
| KdcReq kdcReq = kdcRequest.getKdcReq(); |
| KrbFastRequestState state = kdcRequest.getFastRequestState(); |
| fastAsArmor(state, kdcRequest.getArmorKey(), subKey, credential, kdcReq); |
| kdcRequest.setFastRequestState(state); |
| kdcRequest.setOuterRequestBody(state.getFastOuterRequest().encode()); |
| kdcReq.getPaData().addElement(makeFastEntry(state, kdcReq, |
| kdcRequest.getOuterRequestBody())); |
| } |
| |
| protected void preauth() throws KrbException { |
| KOptions preauthOptions = getPreauthOptions(); |
| String ccache = preauthOptions.getStringOption(KrbOption.ARMOR_CACHE); |
| credential = getCredential(ccache); |
| |
| armorCacheKey = getArmorCacheKey(credential); |
| subKey = getSubKey(armorCacheKey.getKeyType()); |
| EncryptionKey armorKey = makeArmorKey(subKey, armorCacheKey); |
| kdcRequest.getFastRequestState().setArmorKey(armorKey); |
| } |
| |
| public KOptions getPreauthOptions() { |
| KOptions results = new KOptions(); |
| |
| KOptions krbOptions = kdcRequest.getRequestOptions(); |
| results.add(krbOptions.getOption(KrbOption.ARMOR_CACHE)); |
| |
| return results; |
| } |
| |
| public EncryptionKey getClientKey() throws KrbException { |
| return kdcRequest.getFastRequestState().getArmorKey(); |
| } |
| |
| public EncryptionKey getArmorCacheKey() { |
| return armorCacheKey; |
| } |
| |
| private Credential getCredential(String ccache) throws KrbException { |
| File ccacheFile = new File(ccache); |
| CredentialCache cc = null; |
| try { |
| cc = resolveCredCache(ccacheFile); |
| } catch (IOException e) { |
| throw new KrbException("Failed to load armor cache file"); |
| } |
| // TODO: get the right credential. |
| return cc.getCredentials().iterator().next(); |
| } |
| |
| private static CredentialCache resolveCredCache(File ccacheFile) throws IOException { |
| CredentialCache cc = new CredentialCache(); |
| cc.load(ccacheFile); |
| |
| return cc; |
| } |
| |
| private void fastAsArmor(KrbFastRequestState state, |
| EncryptionKey armorKey, EncryptionKey subKey, |
| Credential credential, KdcReq kdcReq) |
| throws KrbException { |
| state.setArmorKey(armorKey); |
| state.setFastArmor(fastArmorApRequest(subKey, credential)); |
| KdcReq fastOuterRequest = new AsReq(); |
| fastOuterRequest.setReqBody(kdcReq.getReqBody()); |
| fastOuterRequest.setPaData(null); |
| state.setFastOuterRequest(fastOuterRequest); |
| } |
| |
| private PaDataEntry makeFastEntry(KrbFastRequestState state, KdcReq kdcReq, |
| byte[] outerRequestBody) throws KrbException { |
| |
| KrbFastReq fastReq = new KrbFastReq(); |
| fastReq.setKdcReqBody(kdcReq.getReqBody()); |
| fastReq.setFastOptions(state.getFastOptions()); |
| |
| KrbFastArmoredReq armoredReq = new KrbFastArmoredReq(); |
| armoredReq.setArmor(state.getFastArmor()); |
| CheckSum reqCheckSum = CheckSumUtil.makeCheckSumWithKey(CheckSumType.NONE, |
| outerRequestBody, state.getArmorKey(), KeyUsage.FAST_REQ_CHKSUM); |
| armoredReq.setReqChecksum(reqCheckSum); |
| armoredReq.setEncryptedFastReq(EncryptionUtil.seal(fastReq, state.getArmorKey(), KeyUsage.FAST_ENC)); |
| |
| PaDataEntry paDataEntry = new PaDataEntry(); |
| paDataEntry.setPaDataType(PaDataType.FX_FAST); |
| paDataEntry.setPaDataValue(armoredReq.encode()); |
| |
| return paDataEntry; |
| } |
| |
| private KrbFastArmor fastArmorApRequest(EncryptionKey subKey, Credential credential) |
| throws KrbException { |
| KrbFastArmor fastArmor = new KrbFastArmor(); |
| fastArmor.setArmorType(ArmorType.ARMOR_AP_REQUEST); |
| ApReq apReq = makeApReq(subKey, credential); |
| fastArmor.setArmorValue(apReq.encode()); |
| return fastArmor; |
| } |
| |
| private ApReq makeApReq(EncryptionKey subKey, Credential credential) |
| throws KrbException { |
| ApReq apReq = new ApReq(); |
| ApOptions apOptions = new ApOptions(); |
| apReq.setApOptions(apOptions); |
| Ticket ticket = credential.getTicket(); |
| apReq.setTicket(ticket); |
| Authenticator authenticator = makeAuthenticator(credential, subKey); |
| apReq.setAuthenticator(authenticator); |
| EncryptedData authnData = EncryptionUtil.seal(authenticator, |
| credential.getKey(), KeyUsage.AP_REQ_AUTH); |
| apReq.setEncryptedAuthenticator(authnData); |
| return apReq; |
| } |
| |
| /** |
| * Prepare FAST armor key. |
| * @return |
| * @throws KrbException |
| */ |
| private EncryptionKey makeArmorKey(EncryptionKey subKey, EncryptionKey armorCacheKey) |
| throws KrbException { |
| EncryptionKey armorKey = FastUtil.cf2(subKey, "subkeyarmor", armorCacheKey, "ticketarmor"); |
| return armorKey; |
| } |
| |
| private EncryptionKey getSubKey(EncryptionType type) throws KrbException { |
| return EncryptionHandler.random2Key(type); |
| } |
| |
| /** |
| * Get armor cache key. |
| * @return armor cache key |
| * @throws KrbException |
| */ |
| private EncryptionKey getArmorCacheKey(Credential credential) throws KrbException { |
| EncryptionKey armorCacheKey = credential.getKey(); |
| |
| return armorCacheKey; |
| } |
| |
| protected Authenticator makeAuthenticator(Credential credential, |
| EncryptionKey subKey) throws KrbException { |
| Authenticator authenticator = new Authenticator(); |
| authenticator.setAuthenticatorVno(5); |
| authenticator.setCname(credential.getClientName()); |
| authenticator.setCrealm(credential.getClientRealm()); |
| authenticator.setCtime(KerberosTime.now()); |
| authenticator.setCusec(0); |
| authenticator.setSubKey(subKey); |
| |
| KdcReqBody reqBody = kdcRequest.getReqBody(); |
| CheckSum checksum = CheckSumUtil.seal(reqBody, null, |
| subKey, KeyUsage.TGS_REQ_AUTH_CKSUM); |
| authenticator.setCksum(checksum); |
| |
| return authenticator; |
| } |
| } |