Websocket masking error

Discussion of open issues, suggestions and bugs regarding network security and data protection solution - SecureBridge
Post Reply
alexacolor
Posts: 3
Joined: Wed 08 May 2019 08:25

Websocket masking error

Post by alexacolor » Mon 19 Aug 2019 08:53

Unit ScWebSocketClient, function MaskData always set offset = 0
If Options.MaxFragmentSize < data size, client always send only first fragment
Please fix, for example like this:

Code: Select all

procedure MaskData(const Data: PByteArray; Count: integer; FrameType: TScWebSocketFrameType; IsFinal: boolean; VAR Offset: INTEGER);
var
  Mask: array[0..3] of byte;
  MaskBit: byte;
  MaskedDataCount, BlockCount: integer;
  i: integer;
begin
  if Count > $FFFF then
    MaskedDataCount := 8 + 2
  else
  if Count > 125 then
    MaskedDataCount := 2 + 2
  else
    MaskedDataCount := 0 + 2;

  if FIsMasked then begin
    MaskBit := $80;
    Inc(MaskedDataCount, 4);
  end
  else
    MaskBit := 0;

  Inc(MaskedDataCount, Count);

  if MaskedDataCount > Length(FSendData) then
    SetLength(FSendData, MaskedDataCount);

  if IsFinal then
    FSendData[FSendDataOffset] := $80 or FRAME_TYPE_CODES[FrameType]
  else
    FSendData[FSendDataOffset] := FRAME_TYPE_CODES[FrameType];

  if Count > $FFFF then begin
    FSendData[FSendDataOffset + 1] := MaskBit or 127;
    FSendData[FSendDataOffset + 2] := 0;
    FSendData[FSendDataOffset + 3] := 0;
    FSendData[FSendDataOffset + 4] := 0;
    FSendData[FSendDataOffset + 5] := 0;
    FSendData[FSendDataOffset + 6] := Byte(Count shr 24);
    FSendData[FSendDataOffset + 7] := Byte(Count shr 16);
    FSendData[FSendDataOffset + 8] := Byte(Count shr 8);
    FSendData[FSendDataOffset + 9] := Byte(Count);
    Inc(FSendDataOffset, 10);
  end
  else
  if Count > 125 then begin
    FSendData[FSendDataOffset + 1] := MaskBit or 126;
    FSendData[FSendDataOffset + 2] := Byte(Count shr 8);
    FSendData[FSendDataOffset + 3] := Byte(Count);
    Inc(FSendDataOffset, 4);
  end
  else begin
    FSendData[FSendDataOffset + 1] := MaskBit or byte(Count);
    Inc(FSendDataOffset, 2);
  end;

  if FIsMasked then begin
    Random.Random(@Mask, 4);
    Move(Mask[0], FSendData[FSendDataOffset], 4);
    Inc(FSendDataOffset, 4);

   //!!!  Offset := 0;
    BlockCount := Count shr 2; // div 4
    for i := 0 to BlockCount - 1 do begin
      FSendData[FSendDataOffset] := Data[Offset] xor Mask[0];
      FSendData[FSendDataOffset + 1] := Data[Offset + 1] xor Mask[1];
      FSendData[FSendDataOffset + 2] := Data[Offset + 2] xor Mask[2];
      FSendData[FSendDataOffset + 3] := Data[Offset + 3] xor Mask[3];
      Inc(FSendDataOffset, 4);
      Inc(Offset, 4);
    end;

    Count := Count and 3;
    if Count = 3 then begin
      FSendData[FSendDataOffset] := Data[Offset] xor Mask[0];
      FSendData[FSendDataOffset + 1] := Data[Offset + 1] xor Mask[1];
      FSendData[FSendDataOffset + 2] := Data[Offset + 2] xor Mask[2];
      Inc(FSendDataOffset, 3);
    end
    else
    if Count = 2 then begin
      FSendData[FSendDataOffset] := Data[Offset] xor Mask[0];
      FSendData[FSendDataOffset + 1] := Data[Offset + 1] xor Mask[1];
      Inc(FSendDataOffset, 2);
    end
    else
    if Count = 1 then begin
      FSendData[FSendDataOffset] := Data[Offset] xor Mask[0];
      Inc(FSendDataOffset);
    end;
  end
  else
    if Count > 0 then begin
      Move(Data[0], FSendData[FSendDataOffset], Count);
      Inc(FSendDataOffset, Count);
    end;
end;

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Websocket masking error

Post by ViktorV » Mon 19 Aug 2019 11:42

Thank you for the information. We'll fix this behavior in the upcoming release of SecureBridge.

Post Reply