All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kerb4j.server.marshall.pac.Pac Maven / Gradle / Ivy

There is a newer version: 0.2.0
Show newest version
package com.kerb4j.server.marshall.pac;

import com.kerb4j.server.marshall.Kerb4JException;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.crypto.CheckSumHandler;
import org.apache.kerby.kerberos.kerb.type.base.CheckSumType;
import org.apache.kerby.kerberos.kerb.type.base.KeyUsage;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.security.Key;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

// https://msdn.microsoft.com/en-us/library/cc237917.aspx
public class Pac {

    private PacLogonInfo logonInfo;
    private PacCredentialType credentialType;
    private List delegationInfos = new ArrayList<>();
    private List delegationInfosReadOnly = Collections.unmodifiableList(delegationInfos);

    private PacSignature serverSignature;
    private PacSignature kdcSignature;

    public Pac(byte[] data, Key key) throws Kerb4JException {
        byte[] checksumData = data.clone();
        try {
            PacDataInputStream pacStream = new PacDataInputStream(new DataInputStream(
                    new ByteArrayInputStream(data)));

            if (data.length <= 8)
                throw new Kerb4JException("pac.token.empty", null, null);

            int bufferCount = pacStream.readInt();
            int version = pacStream.readInt();

            if (version != PacConstants.PAC_VERSION) {
                Object[] args = new Object[]{version};
                throw new Kerb4JException("pac.version.invalid", args, null);
            }

            for (int bufferIndex = 0; bufferIndex < bufferCount; bufferIndex++) {
                final int sigTypeLength = 4;

                int bufferType = pacStream.readInt();
                int bufferSize = pacStream.readInt();
                long bufferOffset = pacStream.readLong();
                byte[] bufferData = new byte[bufferSize];
                System.arraycopy(data, (int) bufferOffset, bufferData, 0, bufferSize);

                switch (bufferType) {
                    case PacConstants.LOGON_INFO:
                        // PAC Credential Information
                        logonInfo = new PacLogonInfo(bufferData);
                        break;
                    case PacConstants.CREDENTIAL_TYPE:
                        // PAC Credential Type
                        credentialType = new PacCredentialType(bufferData);
                        break;
                    case PacConstants.S4U_DELEGATION_INFO:
                        // PAC S4U Delegation Info Type, according to [MS-PAC] �2.9, can "be used multiple times"
                        delegationInfos.add(new PacDelegationInfo(bufferData));
                        break;
                    case PacConstants.SERVER_CHECKSUM:
                        // PAC Server Signature
                        serverSignature = new PacSignature(bufferData);
                        // Clear signature from checksum copy
                        for (int i = 0; i < bufferSize - sigTypeLength; i++)
                            checksumData[(int) bufferOffset + sigTypeLength + i] = 0;
                        break;
                    case PacConstants.PRIVSVR_CHECKSUM:
                        // PAC KDC Signature
                        kdcSignature = new PacSignature(bufferData);
                        // Clear signature from checksum copy
                        for (int i = 0; i < bufferSize - sigTypeLength; i++)
                            checksumData[(int) bufferOffset + sigTypeLength + i] = 0;
                        break;
                    default:
                }
            }
        } catch (IOException e) {
            throw new Kerb4JException("pac.token.malformed", null, e);
        }

        byte[] checksum;

        try {
            checksum = CheckSumHandler.getCheckSumHandler(CheckSumType.fromValue(serverSignature.getType())).
                    checksumWithKey(checksumData, key.getEncoded(), KeyUsage.APP_DATA_CKSUM.getValue());
        } catch (KrbException e) {
            throw new Kerb4JException("pac.check.fail", null, e);
        }

        if (!Arrays.equals(serverSignature.getChecksum(), checksum))
            throw new Kerb4JException("pac.signature.invalid", null, null);
    }

    public PacLogonInfo getLogonInfo() {
        return logonInfo;
    }

    public PacCredentialType getCredentialType() {
        return credentialType;
    }

    public PacSignature getServerSignature() {
        return serverSignature;
    }

    public PacSignature getKdcSignature() {
        return kdcSignature;
    }

    public List getDelegationInfos(){
    	return delegationInfosReadOnly;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy