예제 #1
0
static int
dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ws_tree, guint8 opcode, guint64 payload_length, guint8 mask, const guint8* masking_key)
{
  int offset = 0;
  int payload_length_32bit;
  proto_item *ti_unmask, *ti;
  proto_tree *pl_tree, *mask_tree = NULL;
  tvbuff_t  *unmask_tvb    = NULL;

  /* Wireshark does not handle packets larger than 2^31-1 bytes. */
  payload_length_32bit = (int)payload_length;
  if (payload_length != (guint64)payload_length_32bit) {
    proto_tree_add_text(ws_tree, tvb, offset, -1, "Payload length %" G_GINT64_MODIFIER "u is too large to dissect",
                        payload_length);
    return tvb_length(tvb);
  }

  /* Payload */
  ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length_32bit, ENC_NA);
  pl_tree = proto_item_add_subtree(ti, ett_ws_pl);
  if(mask){
    unmask_tvb = tvb_unmasked(tvb, offset, payload_length_32bit, masking_key);
    tvb_set_child_real_data_tvbuff(tvb, unmask_tvb);
    add_new_data_source(pinfo, unmask_tvb, payload_length_32bit > (int) tvb_length(unmask_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data");
    ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
    mask_tree = proto_item_add_subtree(ti, ett_ws_mask);
  }

  /* Extension Data */
  /* TODO: Add dissector of Extension (not extension available for the moment...) */

  /* Application Data */
  switch(opcode){

    case WS_CONTINUE: /* Continue */
      proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length_32bit, ENC_NA);
      /* TODO: Add Fragmentation support... */
    break;

    case WS_TEXT: /* Text */
    if(mask){

      proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, unmask_tvb, offset, payload_length_32bit,  ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, unmask_tvb, offset, payload_length_32bit,  ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length_32bit, ENC_UTF_8|ENC_NA);

    }
    offset += payload_length_32bit;
    break;

    case WS_BINARY: /* Binary */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    case WS_CLOSE: /* Close */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, unmask_tvb, offset, 2, ENC_BIG_ENDIAN);
      PROTO_ITEM_SET_GENERATED(ti_unmask);

      if(payload_length_32bit > 2){
        ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, unmask_tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA);
        PROTO_ITEM_SET_GENERATED(ti_unmask);
      }
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length_32bit, ENC_NA);
      proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN);
      if(payload_length_32bit > 2){
        proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA);
      }
    }
    offset += payload_length_32bit;
    break;

    case WS_PING: /* Ping */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    case WS_PONG: /* Pong */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    default: /* Unknown */
      ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length_32bit, ENC_NA);
      expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_NOTE, "Dissector for Websocket Opcode (%d)"
                                       " code not implemented, Contact Wireshark developers"
                                       " if you want this supported", opcode);
    break;
  }
  return offset;
}
예제 #2
0
static int
dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, guint8 mask, const guint8* masking_key)
{
  guint offset = 0;
  proto_item *ti_unmask, *ti;
  dissector_handle_t handle;
  proto_tree *pl_tree, *mask_tree = NULL;
  tvbuff_t *payload_tvb = NULL;

  /* Payload */
  ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length, ENC_NA);
  pl_tree = proto_item_add_subtree(ti, ett_ws_pl);
  if(mask){
    payload_tvb = tvb_unmasked(tvb, offset, payload_length, masking_key);
    tvb_set_child_real_data_tvbuff(tvb, payload_tvb);
    add_new_data_source(pinfo, payload_tvb, payload_length > tvb_length(payload_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data");
    ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, payload_tvb, offset, payload_length, ENC_NA);
    mask_tree = proto_item_add_subtree(ti, ett_ws_mask);
  }else{
    payload_tvb = tvb_new_subset(tvb, offset, payload_length, -1);
  }

  handle = dissector_get_uint_handle(port_subdissector_table, pinfo->match_uint);
  if(handle != NULL){
    call_dissector_only(handle, payload_tvb, pinfo, tree, NULL);
  }else{
    dissector_try_heuristic(heur_subdissector_list, payload_tvb, pinfo, tree, NULL);
  }

  /* Extension Data */
  /* TODO: Add dissector of Extension (not extension available for the moment...) */

  /* Application Data */
  switch(opcode){

    case WS_CONTINUE: /* Continue */
      proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length, ENC_NA);
      /* TODO: Add Fragmentation support... */
    break;

    case WS_TEXT: /* Text */
    if(mask){

      proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      const gchar  *saved_match_string = pinfo->match_string;
      void *save_private_data = pinfo->private_data;

      pinfo->match_string = NULL;
      pinfo->private_data = NULL;
      switch(pref_text_type){
      case WEBSOCKET_TEXT:
          call_dissector(text_lines_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_JSON:
          call_dissector(json_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_NONE:
          /* falltrough */
      default:
          proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
          break;
      }
      pinfo->match_string = saved_match_string;
      pinfo->private_data = save_private_data;
    }
    offset += payload_length;
    break;

    case WS_BINARY: /* Binary */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_CLOSE: /* Close */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
      PROTO_ITEM_SET_GENERATED(ti_unmask);

      if(payload_length > 2){
        ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, payload_tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
        PROTO_ITEM_SET_GENERATED(ti_unmask);
      }
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length, ENC_NA);
      proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN);
      if(payload_length > 2){
        proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
      }
    }
    offset += payload_length;
    break;

    case WS_PING: /* Ping */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_PONG: /* Pong */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    default: /* Unknown */
      ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length, ENC_NA);
      expert_add_info_format(pinfo, ti, &ei_ws_payload_unknown, "Dissector for Websocket Opcode (%d)"
        " code not implemented, Contact Wireshark developers"
        " if you want this supported", opcode);
    break;
  }
  return offset;
}