/// <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); }
/// <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); }
public virtual int GetUnsignedMedium(int index) => Buf.GetUnsignedMedium(index);
public int GetUnsignedMedium(int index) { CheckIndex(index, 3); return(_buffer.GetUnsignedMedium(index)); }
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; } } }