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

com.hierynomus.spnego.NegTokenInit Maven / Gradle / Ivy

There is a newer version: 0.13.0
Show newest version
/*
 * Copyright (C)2016 - SMBJ Contributors
 *
 * Licensed 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 com.hierynomus.spnego;

import com.hierynomus.protocol.commons.buffer.Buffer;
import com.hierynomus.protocol.commons.buffer.Endian;
import org.bouncycastle.asn1.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import static com.hierynomus.spnego.ObjectIdentifiers.SPNEGO;

/**
 * This class can encode and decode the SPNEGO negTokenInit Token.
 * 

* The entire token is an ASN.1 DER encoded sequence of bytes in little endian byte encoding. *

* The following is the full ASN.1 specification of the token: *

*

 * GSSAPI          ::=  [APPLICATION 0] IMPLICIT SEQUENCE {
 *   mech                MechType,
 *   negTokenInit        NegotiationToken
 * }
 *
 * NegotiationToken ::=  CHOICE {
 *   negTokenInit   [0]  NegTokenInit,
 *   negTokenTarg   [1]  NegTokenTarg
 * }
 *
 * NegTokenInit     ::=  SEQUENCE {
 *   mechTypes      [0]  MechTypeList  OPTIONAL,
 *   reqFlags       [1]  ContextFlags  OPTIONAL,
 *   mechToken      [2]  OCTET STRING  OPTIONAL,
 *   mechListMIC    [3]  OCTET STRING  OPTIONAL
 * }
 *
 * MechTypeList     ::=  SEQUENCE of MechType
 *
 * ContextFlags     ::=  BIT_STRING {
 *   delegFlag      (0),
 *   mutualFlag     (1),
 *   replayFlag     (2),
 *   sequenceFlag   (3),
 *   anonFlag       (4),
 *   confFlag       (5),
 *   integFlag      (6)
 * }
 *
 * MechType         ::=  OBJECT IDENTIFIER
 * 
*

* In the context of this class only the NegTokenInit is covered. *

*

    *
  • When an InitToken is sent, it is prepended by the generic GSSAPI header.
  • *
  • The "mech" field of the GSSAPI header is always set to the SPNEGO OID (1.3.6.1.5.5.2)
  • *
  • The negTokenInit will have a lead byte of 0xa0 (the CHOICE tagged object).
  • *
*/ public class NegTokenInit extends SpnegoToken { private static final String ADS_IGNORE_PRINCIPAL = "not_defined_in_RFC4178@please_ignore"; private List mechTypes = new ArrayList<>(); private byte[] mechToken; public NegTokenInit() { super(0x0, "NegTokenInit"); } public void write(Buffer buffer) throws SpnegoException { try { ASN1EncodableVector negTokenInit = new ASN1EncodableVector(); addMechTypeList(negTokenInit); addMechToken(negTokenInit); writeGss(buffer, negTokenInit); } catch (IOException e) { throw new SpnegoException("Unable to write NegTokenInit", e); } } public NegTokenInit read(byte[] bytes) throws SpnegoException { return read(new Buffer.PlainBuffer(bytes, Endian.LE)); } private NegTokenInit read(Buffer buffer) throws SpnegoException { try (ASN1InputStream is = new ASN1InputStream(buffer.asInputStream())) { ASN1Primitive applicationSpecific = is.readObject(); if (!(applicationSpecific instanceof BERApplicationSpecific || applicationSpecific instanceof DERApplicationSpecific)) { throw new SpnegoException("Incorrect GSS-API ASN.1 token received, expected to find an [APPLICATION 0], not: " + applicationSpecific); } ASN1Sequence implicitSequence = (ASN1Sequence) ((ASN1ApplicationSpecific) applicationSpecific).getObject(BERTags.SEQUENCE); ASN1Encodable spnegoOid = implicitSequence.getObjectAt(0); if (!(spnegoOid instanceof ASN1ObjectIdentifier)) { throw new SpnegoException("Expected to find the SPNEGO OID (" + SPNEGO + "), not: " + spnegoOid); } parseSpnegoToken(implicitSequence.getObjectAt(1)); } catch (IOException ioe) { throw new SpnegoException("Could not read NegTokenInit from buffer", ioe); } return this; } @Override protected void parseTagged(ASN1TaggedObject asn1TaggedObject) throws SpnegoException { if (asn1TaggedObject.getObject().toString().contains(ADS_IGNORE_PRINCIPAL)) { // Ignore return; } switch (asn1TaggedObject.getTagNo()) { case 0: readMechTypeList(asn1TaggedObject.getObject()); break; case 1: // Ignore reqFlags for now... break; case 2: readMechToken(asn1TaggedObject.getObject()); break; case 3: // Ignore mechListMIC for now... break; default: throw new SpnegoException("Unknown Object Tag " + asn1TaggedObject.getTagNo() + " encountered."); } } private void readMechToken(ASN1Primitive mechToken) throws SpnegoException { if (!(mechToken instanceof ASN1OctetString)) { throw new SpnegoException("Expected the MechToken (OCTET_STRING) contents, not: " + mechToken); } this.mechToken = ((ASN1OctetString) mechToken).getOctets(); } private void readMechTypeList(ASN1Primitive sequence) throws SpnegoException { if (!(sequence instanceof ASN1Sequence)) { throw new SpnegoException("Expected the MechTypeList (SEQUENCE) contents, not: " + sequence); } Enumeration mechTypeElems = ((ASN1Sequence) sequence).getObjects(); while (mechTypeElems.hasMoreElements()) { ASN1Encodable mechType = (ASN1Encodable) mechTypeElems.nextElement(); if (!(mechType instanceof ASN1ObjectIdentifier)) { throw new SpnegoException("Expected a MechType (OBJECT IDENTIFIER) as contents of the MechTypeList, not: " + mechType); } mechTypes.add((ASN1ObjectIdentifier) mechType); } } private void addMechToken(ASN1EncodableVector negTokenInit) { if (mechToken != null && mechToken.length > 0) { ASN1Primitive token = new DERTaggedObject(true, 0x02, new DEROctetString(mechToken)); negTokenInit.add(token); } } private void addMechTypeList(ASN1EncodableVector negTokenInit) { if (mechTypes.size() > 0) { ASN1EncodableVector supportedMechVector = new ASN1EncodableVector(); for (ASN1ObjectIdentifier mechType : mechTypes) { supportedMechVector.add(mechType); } ASN1Primitive asn1Encodables1 = new DERTaggedObject(true, 0x0, new DERSequence(supportedMechVector)); negTokenInit.add(asn1Encodables1); } } public void addSupportedMech(ASN1ObjectIdentifier oid) { this.mechTypes.add(oid); } public void setMechToken(byte[] mechToken) { this.mechToken = mechToken; } public List getSupportedMechTypes() { return mechTypes; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy