/// <summary>
        ///     Decodes the specified region of the buffer into an unadjusted frame length.  The default implementation is
        ///     capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer.  Override this method to
        ///     decode the length field encoded differently.
        ///     Note that this method must not modify the state of the specified buffer (e.g.
        ///     <see cref="IByteBuffer.ReaderIndex" />,
        ///     <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.)
        /// </summary>
        /// <param name="buffer">The buffer we'll be extracting the frame length from.</param>
        /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param>
        /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param>
        /// <param name="order">The preferred <see cref="ByteOrder" /> of buffer.</param>
        /// <returns>A long integer that represents the unadjusted length of the next frame.</returns>
        protected virtual long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order)
        {
            long frameLength;

            switch (length)
            {
            case 1:
                frameLength = buffer.GetByte(offset);
                break;

            case 2:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedShort(offset) : buffer.GetUnsignedShortLE(offset);
                break;

            case 3:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedMedium(offset) : buffer.GetUnsignedMediumLE(offset);
                break;

            case 4:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetInt(offset) : buffer.GetIntLE(offset);
                break;

            case 8:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetLong(offset) : buffer.GetLongLE(offset);
                break;

            default:
                throw new DecoderException("unsupported lengthFieldLength: " + this.lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)");
            }
            return(frameLength);
        }
 /// <summary>
 ///     Decodes the specified region of the buffer into an unadjusted frame length.  The default implementation is
 ///     capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer.  Override this method to
 ///     decode the length field encoded differently.
 ///     Note that this method must not modify the state of the specified buffer (e.g.
 ///     <see cref="IByteBuffer.ReaderIndex" />,
 ///     <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.)
 /// </summary>
 /// <param name="buffer">The buffer we'll be extracting the frame length from.</param>
 /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param>
 /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param>
 /// <returns>A long integer that represents the unadjusted length of the next frame.</returns>
 protected static long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length)
 {
     return(length switch
     {
         1 => buffer.GetByte(offset),
         2 => buffer.GetUnsignedShort(offset),
         3 => buffer.GetUnsignedMedium(offset),
         4 => buffer.GetInt(offset),
         8 => buffer.GetLong(offset),
         _ => CThrowHelper.ThrowDecoderException(length),
     });
        public static int GetMedium(this IByteBuffer buf, int index)
        {
            uint value = (uint)buf.GetUnsignedMedium(index);

            if ((value & 0x800000) != 0)
            {
                value |= 0xff000000;
            }

            return((int)value);
        }
Exemple #4
0
        /// <summary>
        ///     Decodes the specified region of the buffer into an unadjusted frame length.  The default implementation is
        ///     capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer.  Override this method to
        ///     decode the length field encoded differently.
        ///     Note that this method must not modify the state of the specified buffer (e.g.
        ///     <see cref="IByteBuffer.ReaderIndex" />,
        ///     <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.)
        /// </summary>
        /// <param name="buffer">The buffer we'll be extracting the frame length from.</param>
        /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param>
        /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param>
        /// <param name="order">The preferred <see cref="ByteOrder" /> of buffer.</param>
        /// <returns>A long integer that represents the unadjusted length of the next frame.</returns>
        protected long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order)
        {
            long frameLength;

            switch (length)
            {
            case 1:
                frameLength = buffer.GetByte(offset);
                break;

            case 2:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedShort(offset) : buffer.GetUnsignedShortLE(offset);
                break;

            case 3:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedMedium(offset) : buffer.GetUnsignedMediumLE(offset);
                break;

            case 4:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetInt(offset) : buffer.GetIntLE(offset);
                break;

            case 8:
                frameLength = order == ByteOrder.BigEndian ? buffer.GetLong(offset) : buffer.GetLongLE(offset);
                break;

            default:
                throw new DecoderException("unsupported lengthFieldLength: " + this.lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)");
            }
            byte[] bytes = BitConverter.GetBytes(frameLength);

            string slength = Encoding.UTF8.GetString(bytes);

            frameLength = long.Parse(slength);

            return(frameLength);
        }
Exemple #5
0
 public virtual int GetUnsignedMedium(int index) => Buf.GetUnsignedMedium(index);
Exemple #6
0
 public int GetUnsignedMedium(int index)
 {
     CheckIndex(index, 3);
     return(_buffer.GetUnsignedMedium(index));
 }
Exemple #7
0
        protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output)
        {
            if (!_suppressRead && !_handshakeFailed)
            {
                Exception error = null;
                try
                {
                    int readerIndex     = input.ReaderIndex;
                    int readableBytes   = input.ReadableBytes;
                    int handshakeLength = -1;

                    // Check if we have enough data to determine the record type and length.
                    while (readableBytes >= TlsUtils.SSL_RECORD_HEADER_LENGTH)
                    {
                        int contentType = input.GetByte(readerIndex);
                        // tls, but not handshake command
                        switch (contentType)
                        {
                        case TlsUtils.SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
                        // fall-through
                        case TlsUtils.SSL_CONTENT_TYPE_ALERT:
                            int len = TlsUtils.GetEncryptedPacketLength(input, readerIndex);

                            // Not an SSL/TLS packet
                            if (len == TlsUtils.NOT_ENCRYPTED)
                            {
                                _handshakeFailed = true;
                                var e = new NotSslRecordException(
                                    "not an SSL/TLS record: " + ByteBufferUtil.HexDump(input));
                                _ = input.SkipBytes(input.ReadableBytes);
                                _ = context.FireUserEventTriggered(new SniCompletionEvent(e));
                                TlsUtils.NotifyHandshakeFailure(context, e, true);
                                throw e;
                            }
                            if (len == TlsUtils.NOT_ENOUGH_DATA)
                            {
                                // Not enough data
                                return;
                            }
                            // SNI can't be present in an ALERT or CHANGE_CIPHER_SPEC record, so we'll fall back and
                            // assume no SNI is present. Let's let the actual TLS implementation sort this out.
                            // Just select the default SslContext
                            goto SelectDefault;

                        case TlsUtils.SSL_CONTENT_TYPE_HANDSHAKE:
                            int majorVersion = input.GetByte(readerIndex + 1);

                            // SSLv3 or TLS
                            if (majorVersion == 3)
                            {
                                int packetLength = input.GetUnsignedShort(readerIndex + 3) + TlsUtils.SSL_RECORD_HEADER_LENGTH;

                                if (readableBytes < packetLength)
                                {
                                    // client hello incomplete; try again to decode once more data is ready.
                                    return;
                                }
                                else if (packetLength == TlsUtils.SSL_RECORD_HEADER_LENGTH)
                                {
                                    goto SelectDefault;
                                }


                                int endOffset = readerIndex + packetLength;

                                // Let's check if we already parsed the handshake length or not.
                                if (handshakeLength == -1)
                                {
                                    if (readerIndex + 4 > endOffset)
                                    {
                                        // Need more data to read HandshakeType and handshakeLength (4 bytes)
                                        return;
                                    }

                                    int handshakeType = input.GetByte(readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH);

                                    // Check if this is a clientHello(1)
                                    // See https://tools.ietf.org/html/rfc5246#section-7.4
                                    if (handshakeType != 1)
                                    {
                                        goto SelectDefault;
                                    }

                                    // Read the length of the handshake as it may arrive in fragments
                                    // See https://tools.ietf.org/html/rfc5246#section-7.4
                                    handshakeLength = input.GetUnsignedMedium(readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH + 1);

                                    // Consume handshakeType and handshakeLength (this sums up as 4 bytes)
                                    readerIndex  += 4;
                                    packetLength -= 4;

                                    if (handshakeLength + 4 + TlsUtils.SSL_RECORD_HEADER_LENGTH <= packetLength)
                                    {
                                        // We have everything we need in one packet.
                                        // Skip the record header
                                        readerIndex += TlsUtils.SSL_RECORD_HEADER_LENGTH;
                                        Select(context, ExtractSniHostname(input, readerIndex, readerIndex + handshakeLength));
                                        return;
                                    }
                                    else
                                    {
                                        if (_handshakeBuffer is null)
                                        {
                                            _handshakeBuffer = context.Allocator.Buffer(handshakeLength);
                                        }
                                        else
                                        {
                                            // Clear the buffer so we can aggregate into it again.
                                            _ = _handshakeBuffer.Clear();
                                        }
                                    }
                                }

                                // Combine the encapsulated data in one buffer but not include the SSL_RECORD_HEADER
                                _ = _handshakeBuffer.WriteBytes(input, readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH,
                                                                packetLength - TlsUtils.SSL_RECORD_HEADER_LENGTH);
                                readerIndex   += packetLength;
                                readableBytes -= packetLength;
                                if (handshakeLength <= _handshakeBuffer.ReadableBytes)
                                {
                                    Select(context, ExtractSniHostname(_handshakeBuffer, 0, handshakeLength));
                                    return;
                                }
                            }
                            break;

                        default:
                            //not tls, ssl or application data, do not try sni
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    error = e;

                    // unexpected encoding, ignore sni and use default
                    if (Logger.WarnEnabled)
                    {
                        Logger.UnexpectedClientHelloPacket(input, e);
                    }
                }

SelectDefault:
                if (_serverTlsSniSettings.DefaultServerHostName is object)
                {
                    // Just select the default server TLS setting
                    Select(context, _serverTlsSniSettings.DefaultServerHostName);
                }
                else
                {
                    ReleaseHandshakeBuffer();

                    _handshakeFailed = true;
                    var e = new DecoderException($"failed to get the server TLS setting {error}");
                    TlsUtils.NotifyHandshakeFailure(context, e, true);
                    throw e;
                }
            }
        }