/* jcifs smb client library in Java * Copyright (C) 2004 "Michael B. Allen" <jcifs at samba dot org> * "Eric Glass" <jcifs at samba dot org> * * 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.spnego; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; import jcifs.spnego.asn1.ASN1EncodableVector; import jcifs.spnego.asn1.ASN1OctetString; import jcifs.spnego.asn1.ASN1Sequence; import jcifs.spnego.asn1.ASN1TaggedObject; import jcifs.spnego.asn1.DERBitString; import jcifs.spnego.asn1.DERInputStream; import jcifs.spnego.asn1.DERObject; import jcifs.spnego.asn1.DERObjectIdentifier; import jcifs.spnego.asn1.DEROctetString; import jcifs.spnego.asn1.DEROutputStream; import jcifs.spnego.asn1.DERSequence; import jcifs.spnego.asn1.DERTaggedObject; import jcifs.spnego.asn1.DERTags; import jcifs.spnego.asn1.DERUnknownTag; public class NegTokenInit extends SpnegoToken { public static final int DELEGATION = 0x40; public static final int MUTUAL_AUTHENTICATION = 0x20; public static final int REPLAY_DETECTION = 0x10; public static final int SEQUENCE_CHECKING = 0x08; public static final int ANONYMITY = 0x04; public static final int CONFIDENTIALITY = 0x02; public static final int INTEGRITY = 0x01; private String[] mechanisms; private int contextFlags; public NegTokenInit() { } public NegTokenInit(String[] mechanisms, int contextFlags, byte[] mechanismToken, byte[] mechanismListMIC) { setMechanisms(mechanisms); setContextFlags(contextFlags); setMechanismToken(mechanismToken); setMechanismListMIC(mechanismListMIC); } public NegTokenInit(byte[] token) throws IOException { parse(token); } public int getContextFlags() { return contextFlags; } public void setContextFlags(int contextFlags) { this.contextFlags = contextFlags; } public boolean getContextFlag(int flag) { return (getContextFlags() & flag) == flag; } public void setContextFlag(int flag, boolean value) { setContextFlags(value ? (getContextFlags() | flag) : (getContextFlags() & (0xffffffff ^ flag))); } public String[] getMechanisms() { return mechanisms; } public void setMechanisms(String[] mechanisms) { this.mechanisms = mechanisms; } public byte[] toByteArray() { try { ByteArrayOutputStream collector = new ByteArrayOutputStream(); DEROutputStream der = new DEROutputStream(collector); der.writeObject(new DERObjectIdentifier( SpnegoConstants.SPNEGO_MECHANISM)); ASN1EncodableVector fields = new ASN1EncodableVector(); String[] mechanisms = getMechanisms(); if (mechanisms != null) { ASN1EncodableVector vector = new ASN1EncodableVector(); for (int i = 0; i < mechanisms.length; i++) { vector.add(new DERObjectIdentifier(mechanisms[i])); } fields.add(new DERTaggedObject(true, 0, new DERSequence(vector))); } int contextFlags = getContextFlags(); if (contextFlags != 0) { fields.add(new DERTaggedObject(true, 1, new DERBitString(contextFlags))); } byte[] mechanismToken = getMechanismToken(); if (mechanismToken != null) { fields.add(new DERTaggedObject(true, 2, new DEROctetString(mechanismToken))); } byte[] mechanismListMIC = getMechanismListMIC(); if (mechanismListMIC != null) { fields.add(new DERTaggedObject(true, 3, new DEROctetString(mechanismListMIC))); } der.writeObject(new DERTaggedObject(true, 0, new DERSequence(fields))); DERObject token = new DERUnknownTag(DERTags.CONSTRUCTED | DERTags.APPLICATION, collector.toByteArray()); der = new DEROutputStream(collector = new ByteArrayOutputStream()); der.writeObject(token); return collector.toByteArray(); } catch (IOException ex) { throw new IllegalStateException(ex.getMessage()); } } protected void parse(byte[] token) throws IOException { ByteArrayInputStream tokenStream = new ByteArrayInputStream(token); DERInputStream der = new DERInputStream(tokenStream); DERUnknownTag constructed = (DERUnknownTag) der.readObject(); if (constructed.getTag() != (DERTags.CONSTRUCTED | DERTags.APPLICATION)) { throw new IOException("Malformed NegTokenInit."); } tokenStream = new ByteArrayInputStream(constructed.getData()); der = new DERInputStream(tokenStream); DERObjectIdentifier spnego = (DERObjectIdentifier) der.readObject(); ASN1TaggedObject tagged = (ASN1TaggedObject) der.readObject(); ASN1Sequence sequence = ASN1Sequence.getInstance(tagged, true); Enumeration fields = sequence.getObjects(); while (fields.hasMoreElements()) { tagged = (ASN1TaggedObject) fields.nextElement(); switch (tagged.getTagNo()) { case 0: sequence = ASN1Sequence.getInstance(tagged, true); String[] mechanisms = new String[sequence.size()]; for (int i = mechanisms.length - 1; i >= 0; i--) { DERObjectIdentifier mechanism = (DERObjectIdentifier) sequence.getObjectAt(i); mechanisms[i] = mechanism.getId(); } setMechanisms(mechanisms); break; case 1: DERBitString contextFlags = DERBitString.getInstance(tagged, true); setContextFlags(contextFlags.getBytes()[0] & 0xff); break; case 2: ASN1OctetString mechanismToken = ASN1OctetString.getInstance(tagged, true); setMechanismToken(mechanismToken.getOctets()); break; case 3: ASN1OctetString mechanismListMIC = ASN1OctetString.getInstance(tagged, true); setMechanismListMIC(mechanismListMIC.getOctets()); break; default: throw new IOException("Malformed token field."); } } } }