/// <summary>
        /// decoding the data with security provider
        /// </summary>
        /// <param name="data">
        /// a bytes data that contains the data to be decoded with security provider.
        /// </param>
        /// <returns>
        /// a bytes data that contains the decoded data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when data is null.
        /// </exception>
        public override byte[] Decode(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            // if the ssl stream is authenticated, but user do not want to encrypted data
            // directly return the plaintext data.
            if (this.sslStream.IsAuthenticated && !this.UsingMessageSecurity)
            {
                this.consumedData = false;

                return(data);
            }

            this.streamProxy.AddReceivedData(data);
            this.consumedData   = true;
            this.consumedLength = data.Length;

            // if ssl is not authenticated, and ssl do not need to wait for data
            // that is, data is enough for current ssl, must wait for it to consumed it.
            while (!this.sslStream.IsAuthenticated &&
                   !this.streamProxy.WaitingForDataComing)
            {
                Thread.Sleep(MILLI_SECONDS_TO_WAIT_SSL_CONSUME_DATA);
            }

            AdtsLdapSslTlsSecurityHeader header = new AdtsLdapSslTlsSecurityHeader();

            header.FromBytes(this.streamProxy.ReceivedBuffer.Peek(AdtsLdapSslTlsSecurityHeader.SIZE_OF_HEADER));

            // if data is received enough to decode.
            if (this.sslStream.IsAuthenticated && header.IsValid(this.streamProxy.ReceivedBuffer.Length))
            {
                byte[] decryptedData = new byte[header.Length];
                this.sslStream.Read(decryptedData, 0, decryptedData.Length);

                return(decryptedData);
            }

            return(new byte[0]);
        }
Esempio n. 2
0
        /// <summary>
        /// This method encapsulates LdapV2Decoder and LdapV3Decoder because the incoming packets may be
        /// LDAP v2 or v3 packets, the decoding may require both decoders if the LDAP version that client uses
        /// is not clear.
        /// </summary>
        /// <param name="endPoint">The end point of the client.</param>
        /// <param name="messageBytes">The message bytes that contains the packet data.</param>
        /// <param name="consumedLength">Consumed length.</param>
        /// <param name="expectedLength">
        /// Indicates expected length if the message bytes doesn't all packet data.
        /// </param>
        /// <returns>Decoded packets.</returns>
        internal override StackPacket[] DecodeLdapPacketCallBack(
            object endPoint,
            byte[] messageBytes,
            out int consumedLength,
            out int expectedLength)
        {
            // Get packet data, start decoding.
            IPEndPoint      remote  = (IPEndPoint)endPoint;
            AdtsLdapContext context = GetContext(remote, this.server.IsTcp);

            byte[] data = messageBytes;

            // decode messageBytes if needed
            if (context != null && messageBytes != null)
            {
                // if security is not init, and the package is SslHandshake, init security.
                if (context.Security == null)
                {
                    AdtsLdapSslTlsSecurityHeader header = new AdtsLdapSslTlsSecurityHeader();
                    header.FromBytes(messageBytes);

                    if (header.IsSslHandShake)
                    {
                        this.server.SslStartup(context);
                    }
                }

                // decode messageBytes with security.
                if (context.Security != null)
                {
                    data = this.server.Decrypt(context, messageBytes);
                }
            }

            byte[] packetData = this.GetSinglePacketData(data, out consumedLength, out expectedLength);

            // add the comsumed length of security decorder
            if (context != null && context.Security != null && context.Security.ConsumedData)
            {
                consumedLength = context.Security.ConsumedLength;
            }

            if (packetData == null)
            {
                return(null);
            }

            // New connection. Try both LDAP v2 and v3 decoders. Note that for requests that don't have version
            // context(e.g., UDP search requests), LDAP v3 is used by default.
            AdtsLdapPacket packet = null;

            if (context == null)
            {
                context = new AdtsLdapContext(AdtsLdapVersion.V3, remote);
                packet  = this.decoderv3.ParseAdtsLdapPacket(
                    this.decoderv3.AuthenticateMessage(packetData),
                    context);
                // synchronize the message ID with newly received packet.
                context.MessageId = packet.messageId;

                // Check BindRequestPacket, normally it's the first message from client in which
                // contains the LDAP version. And since LDAP v3 decoder can decode LDAP v2 messages
                // without any exception, we need to check into the 'version' variable in the request.
                AdtsBindRequestPacket bindRequestPacket = packet as AdtsBindRequestPacket;
                if (bindRequestPacket != null)
                {
                    LdapV3.BindRequest bindRequest =
                        (LdapV3.BindRequest)bindRequestPacket.GetInnerRequestOrResponse();
                    // Version doesn't match. Decode again with LDAP v2 decoder and update context version.
                    if ((AdtsLdapVersion)bindRequest.version.Value == AdtsLdapVersion.V2)
                    {
                        packet = this.decoderv2.ParseAdtsLdapPacket(
                            this.decoderv2.AuthenticateMessage(packetData),
                            context);
                        context.ClientVersion = context.ServerVersion = AdtsLdapVersion.V2;
                    }
                }

                // Add context.
                this.server.ContextManager.AddContext(context, this.server.IsTcp);
            }
            else
            {
                if (context.ClientVersion == AdtsLdapVersion.V2)
                {
                    packet = this.decoderv2.ParseAdtsLdapPacket(
                        this.decoderv2.AuthenticateMessage(packetData),
                        context);
                }
                else
                {
                    packet = this.decoderv3.ParseAdtsLdapPacket(
                        this.decoderv3.AuthenticateMessage(packetData),
                        context);
                }
                // synchronize the message ID with newly received packet.
                context.MessageId = packet.messageId;
            }

            return(new StackPacket[] { packet });
        }
        /// <summary>
        /// decoding the data with security provider
        /// </summary>
        /// <param name="data">
        /// a bytes data that contains the data to be decoded with security provider.
        /// </param>
        /// <returns>
        /// a bytes data that contains the decoded data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when data is null.
        /// </exception>
        public override byte[] Decode(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            // if the ssl stream is authenticated, but user do not want to encrypted data
            // directly return the plaintext data.
            if (this.sslStream.IsAuthenticated && !this.UsingMessageSecurity)
            {
                this.consumedData = false;

                return data;
            }

            this.streamProxy.AddReceivedData(data);
            this.consumedData = true;
            this.consumedLength = data.Length;

            // if ssl is not authenticated, and ssl do not need to wait for data
            // that is, data is enough for current ssl, must wait for it to consumed it.
            while (!this.sslStream.IsAuthenticated
                    && !this.streamProxy.WaitingForDataComing)
            {
                Thread.Sleep(MILLI_SECONDS_TO_WAIT_SSL_CONSUME_DATA);
            }

            AdtsLdapSslTlsSecurityHeader header = new AdtsLdapSslTlsSecurityHeader();
            header.FromBytes(this.streamProxy.ReceivedBuffer.Peek(AdtsLdapSslTlsSecurityHeader.SIZE_OF_HEADER));

            // if data is received enough to decode.
            if (this.sslStream.IsAuthenticated && header.IsValid(this.streamProxy.ReceivedBuffer.Length))
            {
                byte[] decryptedData = new byte[header.Length];
                this.sslStream.Read(decryptedData, 0, decryptedData.Length);

                return decryptedData;
            }

            return new byte[0];
        }
        /// <summary>
        /// This method encapsulates LdapV2Decoder and LdapV3Decoder because the incoming packets may be 
        /// LDAP v2 or v3 packets, the decoding may require both decoders if the LDAP version that client uses
        /// is not clear.
        /// </summary>
        /// <param name="endPoint">The end point of the client.</param>
        /// <param name="messageBytes">The message bytes that contains the packet data.</param>
        /// <param name="consumedLength">Consumed length.</param>
        /// <param name="expectedLength">
        /// Indicates expected length if the message bytes doesn't all packet data.
        /// </param>
        /// <returns>Decoded packets.</returns>
        internal override StackPacket[] DecodeLdapPacketCallBack(
            object endPoint,
            byte[] messageBytes,
            out int consumedLength,
            out int expectedLength)
        {
            // Get packet data, start decoding.
            IPEndPoint remote = (IPEndPoint)endPoint;
            AdtsLdapContext context = GetContext(remote, this.server.IsTcp);

            byte[] data = messageBytes;

            // decode messageBytes if needed
            if (context != null && messageBytes != null)
            {
                // if security is not init, and the package is SslHandshake, init security.
                if (context.Security == null)
                {
                    AdtsLdapSslTlsSecurityHeader header = new AdtsLdapSslTlsSecurityHeader();
                    header.FromBytes(messageBytes);

                    if (header.IsSslHandShake)
                    {
                        this.server.SslStartup(context);
                    }
                }

                // decode messageBytes with security.
                if (context.Security != null)
                {
                    data = this.server.Decrypt(context, messageBytes);
                }
            }

            byte[] packetData = this.GetSinglePacketData(data, out consumedLength, out expectedLength);

            // add the comsumed length of security decorder
            if (context != null && context.Security != null && context.Security.ConsumedData)
            {
                consumedLength = context.Security.ConsumedLength;
            }

            if (packetData == null)
            {
                return null;
            }

            // New connection. Try both LDAP v2 and v3 decoders. Note that for requests that don't have version
            // context(e.g., UDP search requests), LDAP v3 is used by default.
            AdtsLdapPacket packet = null;
            if (context == null)
            {
                context = new AdtsLdapContext(AdtsLdapVersion.V3, remote);
                packet = this.decoderv3.ParseAdtsLdapPacket(
                    this.decoderv3.AuthenticateMessage(packetData),
                    context);
                // synchronize the message ID with newly received packet.
                context.MessageId = packet.messageId;

                // Check BindRequestPacket, normally it's the first message from client in which
                // contains the LDAP version. And since LDAP v3 decoder can decode LDAP v2 messages
                // without any exception, we need to check into the 'version' variable in the request.
                AdtsBindRequestPacket bindRequestPacket = packet as AdtsBindRequestPacket;
                if (bindRequestPacket != null)
                {
                    LdapV3.BindRequest bindRequest =
                        (LdapV3.BindRequest)bindRequestPacket.GetInnerRequestOrResponse();
                    // Version doesn't match. Decode again with LDAP v2 decoder and update context version.
                    if ((AdtsLdapVersion)bindRequest.version.Value == AdtsLdapVersion.V2)
                    {
                        packet = this.decoderv2.ParseAdtsLdapPacket(
                            this.decoderv2.AuthenticateMessage(packetData),
                            context);
                        context.ClientVersion = context.ServerVersion = AdtsLdapVersion.V2;
                    }
                }

                // Add context.
                this.server.ContextManager.AddContext(context, this.server.IsTcp);
            }
            else
            {
                if (context.ClientVersion == AdtsLdapVersion.V2)
                {
                    packet = this.decoderv2.ParseAdtsLdapPacket(
                        this.decoderv2.AuthenticateMessage(packetData),
                        context);
                }
                else
                {
                    packet = this.decoderv3.ParseAdtsLdapPacket(
                        this.decoderv3.AuthenticateMessage(packetData),
                        context);
                }
                // synchronize the message ID with newly received packet.
                context.MessageId = packet.messageId;
            }

            return new StackPacket[] { packet };
        }