
jcifs.pac.Pac Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs Show documentation
Show all versions of jcifs Show documentation
JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java
/*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.pac;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Map;
import javax.security.auth.kerberos.KerberosKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jcifs.util.Hexdump;
@SuppressWarnings ( "javadoc" )
public class Pac {
private static final Logger log = LoggerFactory.getLogger(Pac.class);
private PacLogonInfo logonInfo;
private PacCredentialType credentialType;
private PacSignature serverSignature;
private PacSignature kdcSignature;
public Pac ( byte[] data, Map keys ) throws PACDecodingException {
byte[] checksumData = data.clone();
try {
PacDataInputStream pacStream = new PacDataInputStream(new DataInputStream(new ByteArrayInputStream(data)));
if ( data.length <= 8 )
throw new PACDecodingException("Empty PAC");
int bufferCount = pacStream.readInt();
int version = pacStream.readInt();
if ( version != PacConstants.PAC_VERSION ) {
throw new PACDecodingException("Unrecognized PAC version " + version);
}
for ( int bufferIndex = 0; bufferIndex < bufferCount; bufferIndex++ ) {
int bufferType = pacStream.readInt();
int bufferSize = pacStream.readInt();
long bufferOffset = pacStream.readLong();
if ( bufferOffset % 8 != 0 ) {
throw new PACDecodingException("Unaligned buffer " + bufferType);
}
byte[] bufferData = new byte[bufferSize];
System.arraycopy(data, (int) bufferOffset, bufferData, 0, bufferSize);
switch ( bufferType ) {
case PacConstants.LOGON_INFO:
// PAC Credential Information
if ( this.logonInfo == null ) {
this.logonInfo = new PacLogonInfo(bufferData);
}
break;
case PacConstants.CREDENTIAL_TYPE:
// PAC Credential Type
this.credentialType = new PacCredentialType(bufferData);
break;
case PacConstants.SERVER_CHECKSUM:
// PAC Server Signature
if ( this.serverSignature == null ) {
this.serverSignature = new PacSignature(bufferData);
if ( log.isDebugEnabled() ) {
log.debug(
String.format("Server signature is type %d @ %d len %d", this.serverSignature.getType(), bufferOffset, bufferSize));
}
// Clear signature from checksum copy
for ( int i = 0; i < this.serverSignature.getChecksum().length; i++ )
checksumData[ (int) bufferOffset + 4 + i ] = 0;
}
break;
case PacConstants.PRIVSVR_CHECKSUM:
// PAC KDC Signature
if ( this.kdcSignature == null ) {
this.kdcSignature = new PacSignature(bufferData);
if ( log.isDebugEnabled() ) {
log.debug(String.format("KDC signature is type %d @ %d len %d", this.kdcSignature.getType(), bufferOffset, bufferSize));
}
// Clear signature from checksum copy
for ( int i = 0; i < this.kdcSignature.getChecksum().length; i++ )
checksumData[ (int) bufferOffset + 4 + i ] = 0;
}
break;
default:
if ( log.isDebugEnabled() ) {
log.debug("Found unhandled PAC buffer " + bufferType);
}
}
}
}
catch ( IOException e ) {
throw new PACDecodingException("Malformed PAC", e);
}
if ( this.serverSignature == null || this.kdcSignature == null || this.logonInfo == null ) {
throw new PACDecodingException("Missing required buffers");
}
if ( log.isTraceEnabled() ) {
log.trace(
String.format(
"Checksum data %s type %d signature %s",
Hexdump.toHexString(checksumData),
this.serverSignature.getType(),
Hexdump.toHexString(this.serverSignature.getChecksum())));
}
byte checksum[] = PacMac.calculateMac(this.serverSignature.getType(), keys, checksumData);
if ( !MessageDigest.isEqual(this.serverSignature.getChecksum(), checksum) ) {
if ( log.isDebugEnabled() ) {
log.debug(
String.format(
"PAC signature validation failed, have: %s expected: %s type: %d len: %d",
Hexdump.toHexString(checksum),
Hexdump.toHexString(this.serverSignature.getChecksum()),
this.serverSignature.getType(),
data.length));
}
if ( log.isTraceEnabled() ) {
log.trace(String.format("Checksum data %s", Hexdump.toHexString(checksumData)));
}
throw new PACDecodingException("Invalid PAC signature");
}
}
public PacLogonInfo getLogonInfo () {
return this.logonInfo;
}
public PacCredentialType getCredentialType () {
return this.credentialType;
}
public PacSignature getServerSignature () {
return this.serverSignature;
}
public PacSignature getKdcSignature () {
return this.kdcSignature;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy