protected static string?ReadHints(byte[] buffer, ref int offset, out byte[]?hintAddress)
        {
            string?hintName = null;

            hintAddress = null;
            _           = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.Sequence)
            {
                throw new InvalidDataException();
            }
            int sequenceLength    = DerEncodingHelper.ReadLength(buffer, ref offset);
            int sequenceEndOffset = offset + sequenceLength;

            while (offset < sequenceEndOffset)
            {
                tag = ByteReader.ReadByte(buffer, ref offset);
                switch (tag)
                {
                case HintNameTag:
                    hintName = ReadHintName(buffer, ref offset);
                    break;

                case HintAddressTag:
                    hintAddress = ReadHintAddress(buffer, ref offset);
                    break;

                default:
                    throw new InvalidDataException();
                }
            }
            return(hintName);
        }
        protected static List <byte[]> ReadMechanismTypeList(byte[] buffer, ref int offset)
        {
            List <byte[]> result = new List <byte[]>();

            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.Sequence)
            {
                throw new InvalidDataException();
            }
            int sequenceLength    = DerEncodingHelper.ReadLength(buffer, ref offset);
            int sequenceEndOffset = offset + sequenceLength;

            while (offset < sequenceEndOffset)
            {
                tag = ByteReader.ReadByte(buffer, ref offset);
                if (tag != (byte)DerEncodingTag.ObjectIdentifier)
                {
                    throw new InvalidDataException();
                }
                int    mechanismTypeLength = DerEncodingHelper.ReadLength(buffer, ref offset);
                byte[] mechanismType       = ByteReader.ReadBytes(buffer, ref offset, mechanismTypeLength);
                result.Add(mechanismType);
            }
            return(result);
        }
예제 #3
0
        private static NegState ReadNegState(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.Enum)
            {
                throw new InvalidDataException();
            }
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            return((NegState)ByteReader.ReadByte(buffer, ref offset));
        }
        protected static byte[] ReadHintAddress(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.ByteArray)
            {
                throw new InvalidDataException();
            }
            int hintLength = DerEncodingHelper.ReadLength(buffer, ref offset);

            return(ByteReader.ReadBytes(buffer, ref offset, hintLength));
        }
예제 #5
0
        private static byte[] ReadMechanismListMIC(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.ByteArray)
            {
                throw new InvalidDataException();
            }
            int length = DerEncodingHelper.ReadLength(buffer, ref offset);

            return(ByteReader.ReadBytes(buffer, ref offset, length));
        }
예제 #6
0
        private static byte[] ReadSupportedMechanism(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.ObjectIdentifier)
            {
                throw new InvalidDataException();
            }
            int length = DerEncodingHelper.ReadLength(buffer, ref offset);

            return(ByteReader.ReadBytes(buffer, ref offset, length));
        }
        protected static string ReadHintName(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.GeneralString)
            {
                throw new InvalidDataException();
            }
            int hintLength = DerEncodingHelper.ReadLength(buffer, ref offset);

            byte[] hintNameBytes = ByteReader.ReadBytes(buffer, ref offset, hintLength);
            return(DerEncodingHelper.DecodeGeneralString(hintNameBytes));
        }
        protected static byte[] ReadMechanismToken(byte[] buffer, ref int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.ByteArray)
            {
                throw new InvalidDataException();
            }
            int mechanismTokenLength = DerEncodingHelper.ReadLength(buffer, ref offset);

            byte[] token = ByteReader.ReadBytes(buffer, ref offset, mechanismTokenLength);
            return(token);
        }
        /// <summary>
        /// https://tools.ietf.org/html/rfc2743
        /// </summary>
        /// <exception cref="System.IO.InvalidDataException"></exception>
        public static SimpleProtectedNegotiationToken?ReadToken(byte[] tokenBytes, int offset, bool serverInitiatedNegotiation)
        {
            byte tag = ByteReader.ReadByte(tokenBytes, ref offset);

            if (tag == ApplicationTag)
            {
                // https://msdn.microsoft.com/en-us/library/ms995330.aspx
                // when an InitToken is sent, it is prepended by an Application Constructed Object specifier (0x60),
                // and the OID for SPNEGO. This is the generic GSSAPI header.

                // [RFC 2743] The use of the Mechanism-Independent Token Format is required for initial context
                // establishment tokens, use in non-initial tokens is optional.
                _   = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
                tag = ByteReader.ReadByte(tokenBytes, ref offset);
                if (tag == (byte)DerEncodingTag.ObjectIdentifier)
                {
                    int    objectIdentifierLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
                    byte[] objectIdentifier       = ByteReader.ReadBytes(tokenBytes, ref offset, objectIdentifierLength);
                    if (ByteUtils.AreByteArraysEqual(objectIdentifier, SPNEGOIdentifier))
                    {
                        tag = ByteReader.ReadByte(tokenBytes, ref offset);
                        if (tag == SimpleProtectedNegotiationTokenInit.NegTokenInitTag)
                        {
                            if (serverInitiatedNegotiation)
                            {
                                // [MS-SPNG] Standard GSS has a strict notion of client (initiator) and server (acceptor).
                                // If the client has not sent a negTokenInit ([RFC4178] section 4.2.1) message, no context establishment token is expected from the server.
                                // The [NegTokenInit2] SPNEGO extension allows the server to generate a context establishment token message [..] and send it to the client.
                                return(new SimpleProtectedNegotiationTokenInit2(tokenBytes, offset));
                            }

                            return(new SimpleProtectedNegotiationTokenInit(tokenBytes, offset));
                        }

                        if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
                        {
                            return(new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset));
                        }
                    }
                }
            }
            else if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
            {
                return(new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset));
            }
            return(null);
        }
        /// <summary></summary>
        /// <param name="buffer">A buffer object to write to</param>
        /// <param name="offset">The offset following the NegTokenInit2 tag</param>
        /// <exception cref="InvalidDataException"></exception>
        public SimpleProtectedNegotiationTokenInit2(byte[] buffer, int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.Sequence)
            {
                throw new InvalidDataException();
            }
            int sequenceLength    = DerEncodingHelper.ReadLength(buffer, ref offset);
            int sequenceEndOffset = offset + sequenceLength;

            while (offset < sequenceEndOffset)
            {
                tag = ByteReader.ReadByte(buffer, ref offset);
                if (tag == MechanismTypeListTag)
                {
                    MechanismTypeList = ReadMechanismTypeList(buffer, ref offset);
                }
                else if (tag == RequiredFlagsTag)
                {
                    throw new NotImplementedException("negTokenInit.ReqFlags is not implemented");
                }
                else if (tag == MechanismTokenTag)
                {
                    MechanismToken = ReadMechanismToken(buffer, ref offset);
                }
                else if (tag == NegHintsTag)
                {
                    HintName = ReadHints(buffer, ref offset, out HintAddress);
                }
                else if (tag == MechanismListMICTag)
                {
                    MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
                }
                else
                {
                    throw new InvalidDataException("Invalid negTokenInit structure");
                }
            }
        }
예제 #11
0
        /// <param name="buffer"></param>
        /// <param name="offset">The offset following the NegTokenResp tag</param>
        /// <exception cref="InvalidDataException"></exception>
        public SimpleProtectedNegotiationTokenResponse(byte[] buffer, int offset)
        {
            _ = DerEncodingHelper.ReadLength(buffer, ref offset);
            byte tag = ByteReader.ReadByte(buffer, ref offset);

            if (tag != (byte)DerEncodingTag.Sequence)
            {
                throw new InvalidDataException();
            }
            int sequenceLength    = DerEncodingHelper.ReadLength(buffer, ref offset);
            int sequenceEndOffset = offset + sequenceLength;

            while (offset < sequenceEndOffset)
            {
                tag = ByteReader.ReadByte(buffer, ref offset);
                if (tag == NegStateTag)
                {
                    NegState = ReadNegState(buffer, ref offset);
                }
                else if (tag == SupportedMechanismTag)
                {
                    SupportedMechanism = ReadSupportedMechanism(buffer, ref offset);
                }
                else if (tag == ResponseTokenTag)
                {
                    ResponseToken = ReadResponseToken(buffer, ref offset);
                }
                else if (tag == MechanismListMICTag)
                {
                    MechanismListMic = ReadMechanismListMIC(buffer, ref offset);
                }
                else
                {
                    throw new InvalidDataException("Invalid negTokenResp structure");
                }
            }
        }