Example #1
0
/* ---------------------------------------------- */
static int fix_header_len(tvbuff_t *tvb, int offset)
{
    int            base_offset, ctrla_offset;
    char          *value;
    int            size;
    fix_parameter *tag;

    base_offset = offset;

    /* get at least the fix version: 8=FIX.x.x */
    if (fix_marker(tvb, offset) != 0) {
        return fix_next_header(tvb, offset);
    }

    /* begin string */
    ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
    if (ctrla_offset == -1) {
        /* it should be there, (minimum size is big enough)
         * if not maybe it's not really
         * a FIX packet but it's too late to bail out.
        */
        return fix_next_header(tvb, offset +MARKER_LEN) +MARKER_LEN;
    }
    offset = ctrla_offset + 1;

    /* msg length */
    if (!(tag = fix_param(tvb, offset)) || tvb_strneql(tvb, offset, "9=", 2)) {
        /* not a tag or not the BodyLength tag, give up */
        return fix_next_header(tvb, offset);
    }

    value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len);
    /* Fix version, msg type, length and checksum aren't in body length.
     * If the packet is big enough find the checksum
    */
    size = atoi(value) +tag->ctrla_offset - base_offset +1;
    if (tvb_length_remaining(tvb, base_offset) > size +4) {
        /* 10= should be there */
        offset = base_offset +size;
        if (tvb_strneql(tvb, offset, "10=", 3) != 0) {
            /* No? bogus packet, try to find the next header */
            return fix_next_header(tvb, base_offset +MARKER_LEN)  +MARKER_LEN;
        }
        ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
        if (ctrla_offset == -1) {
            /* assume checksum is 7 bytes 10=xxx\01 */
            return size+7;
        }
        return size +ctrla_offset -offset +1;
    }
    else {
    }
    /* assume checksum is 7 bytes 10=xxx\01 */
    return size +7;
}
Example #2
0
/* check whether the packet looks like SBUS or not */
static gboolean
is_esio_pdu(tvbuff_t *tvb)
{
       /* we need at least 8 bytes to determine whether this is
          Ether-S-I/O or not*/
       /* minimal length is 20 bytes*/
       if (tvb_captured_length(tvb) < 20) {
              return FALSE;
       }
       /* First four bytes must be "ESIO"*/
       if (tvb_strneql(tvb, 0, "ESIO", 4) != 0) {
              return FALSE;
       }
       /* fifth byte must be 0*/
       if (tvb_get_guint8(tvb, 4) > 0x00) {
              return FALSE;
       }
       /* sixth byte indicates telegram type and must be 0, 1 or 2*/
       if (tvb_get_guint8(tvb, 5) > 0x02) {
              return FALSE;
       }
       /* seventh byte must be 0*/
       if (tvb_get_guint8(tvb, 6) > 0x00) {
              return FALSE;
       }
       /* eight byte indicates telegram version and must be 0 (up to now)*/
       if (tvb_get_guint8(tvb, 7) > 0x00) {
              return FALSE;
       }
       /*header seems to be Ether-S-I/O*/
       return TRUE;
}
/*
 * Unless the first boundary, subsequent boundaries include a line-end sequence
 * before the dashed boundary string.
 *
 * Return the offset to the 1st byte of the boundary delimiter line.
 * Set boundary_line_len to the length of the entire boundary delimiter.
 * Set last_boundary to TRUE if we've seen the last-boundary delimiter.
 */
static gint
find_next_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
        gint boundary_len, gint *boundary_line_len, gboolean *last_boundary)
{
    gint offset = start, next_offset, line_len, boundary_start;

    while (tvb_length_remaining(tvb, offset + 2 + boundary_len) > 0) {
        line_len =  tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
        if (line_len == -1) {
            return -1;
        }
        boundary_start = offset + line_len;
        if (((tvb_strneql(tvb, next_offset, (const guint8 *)"--", 2) == 0)
                    && (tvb_strneql(tvb, next_offset + 2, boundary, boundary_len) == 0)))
        {
            /* Boundary string; now check if last */
            if ((tvb_length_remaining(tvb, next_offset + 2 + boundary_len + 2) >= 0)
                    && (tvb_strneql(tvb, next_offset + 2 + boundary_len,
                            (const guint8 *)"--", 2) == 0)) {
                *last_boundary = TRUE;
            } else {
                *last_boundary = FALSE;
            }
            /* Look for line end of the boundary line */
            line_len =  tvb_find_line_end(tvb, next_offset, -1, &offset, FALSE);
            if (line_len == -1) {
                *boundary_line_len = -1;
            } else {
                *boundary_line_len = offset - boundary_start;
            }
            return boundary_start;
        }
        offset = next_offset;
    }

    return -1;
}
Example #4
0
/* ABNF of line-end:
 * end-line = "-------" transact-id continuation-flag CRLF
 * This code is modeled on the code in packet-multipart.c
 */
static int
find_end_line(tvbuff_t *tvb, gint start)
{
	gint offset = start, next_offset, linelen;

	while (tvb_length_remaining(tvb, offset) > 0) {
		/* 'desegment' is FALSE so will set next_offset to beyond the end of
		   the buffer if no line ending is found */
		linelen =  tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
		if (linelen == -1) {
			return -1;
		}
		if (tvb_strneql(tvb, next_offset, (const gchar *)"-------", 7) == 0)
			return next_offset;
		offset = next_offset;
	}

	return -1;
}
Example #5
0
static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
    int len = wanted->len;
#ifdef TVBPARSE_DEBUG
    if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
#endif

    if ( offset + wanted->len > tt->end_offset )
        return -1;

    if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
        *tok = new_tok(tt,wanted->id,offset,len,wanted);
#ifdef TVBPARSE_DEBUG
        if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
#endif
        return len;
    } else {
        return -1;
    }
}
Example #6
0
/*
 * Unless the first boundary, subsequent boundaries include a line-end sequence
 * before the dashed boundary string.
 *
 * Return the offset to the 1st byte of the boundary delimiter line.
 * Set boundary_line_len to the length of the entire boundary delimiter.
 * Set last_boundary to TRUE if we've seen the last-boundary delimiter.
 */
static gint
find_next_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
                   gint boundary_len, gint *boundary_line_len, gboolean *last_boundary)
{
    gint offset = start, next_offset, line_len, boundary_start;

    while (tvb_offset_exists(tvb, offset + 2 + boundary_len)) {
        line_len =  tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
        if (line_len == -1) {
            return -1;
        }
        boundary_start = offset + line_len;
        if (((tvb_strneql(tvb, next_offset, (const guint8 *)"--", 2) == 0)
                && (tvb_strneql(tvb, next_offset + 2, boundary, boundary_len) == 0)))
        {
            /* Boundary string; now check if last */
            if ((tvb_reported_length_remaining(tvb, next_offset + 2 + boundary_len + 2) >= 0)
                    && (tvb_strneql(tvb, next_offset + 2 + boundary_len,
                                    (const guint8 *)"--", 2) == 0)) {
                *last_boundary = TRUE;
            } else {
                *last_boundary = FALSE;
            }
            /* Look for line end of the boundary line */
            line_len =  tvb_find_line_end(tvb, next_offset, -1, &offset, FALSE);
            if (line_len == -1) {
                *boundary_line_len = -1;
            } else {
                *boundary_line_len = offset - boundary_start;
            }
            return boundary_start;
            /* check if last before CRLF; some ignore the standard, so there is no CRLF before the boundary */
        } else if ((tvb_strneql(tvb, boundary_start - 2, (const guint8 *)"--", 2) == 0)
                   && (tvb_strneql(tvb, boundary_start - (2 + boundary_len), boundary, boundary_len) == 0)
                   && (tvb_strneql(tvb, boundary_start - (2 + boundary_len + 2),
                                   (const guint8 *)"--", 2) == 0)) {
            boundary_start -= 2 + boundary_len + 2;
            *boundary_line_len = next_offset - boundary_start;
            *last_boundary = TRUE;
            return boundary_start;
        }
        offset = next_offset;
    }

    return -1;
}
Example #7
0
static int fix_marker(tvbuff_t *tvb, int offset)
{
    return tvb_strneql(tvb, offset, MARKER_TAG, MARKER_LEN);
}
Example #8
0
static void
dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    int offset = 0;
    int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len;
    guint8 vers_flags;
    guint8 auth_len;
    guint16 tmp1;
    guint8 auth_flags;
    tvbuff_t *next_tvb;

    proto_item *si, *sif;
    proto_tree *sap_tree, *sap_flags_tree;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAP");
    col_clear(pinfo->cinfo, COL_INFO);

    vers_flags = tvb_get_guint8(tvb, offset);
    is_ipv6 = vers_flags&MCAST_SAP_BIT_A;
    is_del = vers_flags&MCAST_SAP_BIT_T;
    is_enc = vers_flags&MCAST_SAP_BIT_E;
    is_comp = vers_flags&MCAST_SAP_BIT_C;

    sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
    addr_len = (is_ipv6) ? sizeof(struct e_in6_addr) : 4;

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
                     (is_del) ? "Deletion" : "Announcement", sap_version);
    }

    if (tree) {
        si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, ENC_NA);
        sap_tree = proto_item_add_subtree(si, ett_sap);

        sif = proto_tree_add_uint(sap_tree, hf_sap_flags, tvb, offset, 1, vers_flags);
        sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags);
        proto_tree_add_uint(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, vers_flags);
        proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, vers_flags);
        proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, vers_flags);
        proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, vers_flags);
        proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, vers_flags);
        proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, vers_flags);
        offset++;

        auth_len = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(sap_tree, tvb, offset, 1, "Authentication Length: %u", auth_len);
        offset++;

        tmp1 = tvb_get_ntohs(tvb, offset);
        proto_tree_add_text(sap_tree, tvb, offset, 2, "Message Identifier Hash: 0x%x", tmp1);
        offset +=2;

        proto_tree_add_text(sap_tree, tvb, offset, addr_len, "Originating Source: %s",
                            (is_ipv6) ? tvb_ip6_to_str(tvb, offset) : tvb_ip_to_str(tvb, offset));
        offset += addr_len;

        /* Authentication data lives in its own subtree */
        if (auth_len > 0) {
            guint32 auth_data_len;
            proto_item *sdi, *sai;
            proto_tree *sa_tree, *saf_tree;
            int has_pad;
            guint8 pad_len = 0;

            auth_data_len = auth_len * sizeof(guint32);

            sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, ENC_NA);
            sa_tree = proto_item_add_subtree(sdi, ett_sap_auth);

            auth_flags = tvb_get_guint8(tvb, offset);
            sai = proto_tree_add_uint(sa_tree, hf_auth_flags, tvb, offset, 1, auth_flags);
            saf_tree = proto_item_add_subtree(sai, ett_sap_authf);
            proto_tree_add_uint(saf_tree, hf_auth_flags_v, tvb, offset, 1, auth_flags);
            proto_tree_add_boolean(saf_tree, hf_auth_flags_p, tvb, offset, 1, auth_flags);
            proto_tree_add_uint(saf_tree, hf_auth_flags_t, tvb, offset, 1, auth_flags);

            has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P;
            if (has_pad)
                pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1);

            if ((int) auth_data_len - pad_len - 1 < 0) {
                proto_tree_add_text(sa_tree, tvb, 0, 0,
                                    "Bogus authentication length (%d) or pad length (%d)",
                                    auth_len, pad_len);
                return;
            }


            proto_tree_add_text(sa_tree, tvb, offset+1, auth_data_len-pad_len-1,
                                "Authentication subheader: (%u byte%s)",
                                auth_data_len-1, plurality(auth_data_len-1, "", "s"));
            if (has_pad) {
                proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-pad_len, pad_len,
                                    "Authentication data padding: (%u byte%s)",
                                    pad_len, plurality(pad_len, "", "s"));
                proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-1, 1,
                                    "Authentication data pad count: %u byte%s",
                                    pad_len, plurality(pad_len, "", "s"));
            }

            offset += auth_data_len;
        }
        if (is_enc || is_comp) {
            const char *mangle;
            if (is_enc && is_comp) mangle = "compressed and encrypted";
            else if (is_enc) mangle = "encrypted";
            else mangle = "compressed";
            proto_tree_add_text(sap_tree, tvb, offset, -1,
                                "The rest of the packet is %s", mangle);
            return;
        }

        /* Do we have the optional payload type aka. MIME content specifier */
        if (tvb_strneql(tvb, offset, "v=", strlen("v="))) {
            gint remaining_len;
            guint32 pt_len;
            int pt_string_len;

            remaining_len = tvb_length_remaining(tvb, offset);
            if (remaining_len == 0) {
                /*
                 * "tvb_strneql()" failed because there was no
                * data left in the packet.
                *
                * Set the remaining length to 1, so that
                * we throw the appropriate exception in
                * "tvb_get_ptr()", rather than displaying
                * the payload type.
                */
                remaining_len = 1;
            }
            pt_string_len = tvb_strnlen(tvb, offset, remaining_len);
            if (pt_string_len == -1) {
                /*
                 * We didn't find a terminating '\0'; run to the
                 * end of the buffer.
                 */
                pt_string_len = remaining_len;
                pt_len = pt_string_len;
            } else {
                /*
                 * Include the '\0' in the total item length.
                 */
                pt_len = pt_string_len + 1;
            }
            proto_tree_add_text(sap_tree, tvb, offset, pt_len,
                                "Payload type: %.*s", pt_string_len,
                                tvb_get_ephemeral_string(tvb, offset, pt_string_len));
            offset += pt_len;
        }
    }

    /* Done with SAP */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(sdp_handle, next_tvb, pinfo, tree);

    return;
}
Example #9
0
/* Dissect OSC bundle */
static int
dissect_osc_bundle(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len)
{
    proto_tree  *bundle_tree;
    gint         end = offset + len;
    guint32      sec;
    guint32      frac;
    nstime_t     ns;

    /* check for valid #bundle */
    if(tvb_strneql(tvb, offset, bundle_str, 8) != 0)
        return -1;

    /* create bundle */
    ti = proto_tree_add_item(osc_tree, hf_osc_bundle_type, tvb, offset, len, ENC_NA);

    bundle_tree = proto_item_add_subtree(ti, ett_osc_bundle);

    offset += 8; /* skip bundle_str */

    /* read timetag */
    sec  = tvb_get_ntohl(tvb, offset);
    frac = tvb_get_ntohl(tvb, offset+4);
    if( (sec == 0) && (frac == 1) )
        proto_tree_add_time_format_value(bundle_tree, hf_osc_bundle_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str);
    else
        proto_tree_add_item(bundle_tree, hf_osc_bundle_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
    offset += 8;

    /* ::read size, read block:: */
    while(offset < end)
    {
        /* peek bundle element size */
        gint32 size = tvb_get_ntohl(tvb, offset);

        /* read bundle element size */
        proto_tree_add_int_format_value(bundle_tree, hf_osc_bundle_element_size_type, tvb, offset, 4, size, "%i bytes", size);
        offset += 4;

        /* check for zero size bundle element */
        if(size == 0)
            continue;

        /* peek first bundle element char */
        switch(tvb_get_guint8(tvb, offset))
        {
            case '#': /* this is a bundle */
                if(dissect_osc_bundle(tvb, ti, bundle_tree, offset, size))
                    return -1;
                else
                    break;
            case '/': /* this is a message */
                if(dissect_osc_message(tvb, ti, bundle_tree, offset, size))
                    return -1;
                else
                    break;
            default:
                return -1; /* neither message nor bundle */
        }

        /* check for integer overflow */
        if(size > G_MAXINT - offset)
            return -1;
        else
            offset += size;
    }

    if(offset != end)
        return -1;
    else
        return 0;
}
Example #10
0
static void
dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  struct smtp_proto_data    *spd_frame_data;
  proto_tree                *smtp_tree = NULL;
  proto_tree                *cmdresp_tree;
  proto_item                *ti, *hidden_item;
  int                       offset = 0;
  int                       request = 0;
  conversation_t            *conversation;
  struct smtp_session_state *session_state;
  const guchar              *line, *linep, *lineend;
  guint32                   code;
  int                       linelen = 0;
  gint                      length_remaining;
  gboolean                  eom_seen = FALSE;
  gint                      next_offset;
  gint                      loffset = 0;
  int                       cmdlen;
  fragment_data             *frag_msg = NULL;
  tvbuff_t                  *next_tvb;

  /* As there is no guarantee that we will only see frames in the
   * the SMTP conversation once, and that we will see them in
   * order - in Wireshark, the user could randomly click on frames
   * in the conversation in any order in which they choose - we
   * have to store information with each frame indicating whether
   * it contains commands or data or an EOM indication.
   *
   * XXX - what about frames that contain *both*?  TCP is a
   * byte-stream protocol, and there are no guarantees that
   * TCP segment boundaries will correspond to SMTP commands
   * or EOM indications.
   *
   * We only need that for the client->server stream; responses
   * are easy to manage.
   *
   * If we have per frame data, use that, else, we must be on the first
   * pass, so we figure it out on the first pass.
   */

  /*
   * Find or create the conversation for this.
   */
  conversation = find_or_create_conversation(pinfo);

  /*
   * Is there a request structure attached to this conversation?
   */
  session_state = conversation_get_proto_data(conversation, proto_smtp);
  if (!session_state) {
    /*
     * No - create one and attach it.
     */
    session_state = se_alloc(sizeof(struct smtp_session_state));
    session_state->smtp_state = SMTP_STATE_READING_CMDS;
    session_state->crlf_seen = FALSE;
    session_state->data_seen = FALSE;
    session_state->msg_read_len = 0;
    session_state->msg_tot_len = 0;
    session_state->msg_last = TRUE;
    session_state->last_nontls_frame = 0;

    conversation_add_proto_data(conversation, proto_smtp, session_state);
  }

  /* Are we doing TLS?
   * FIXME In my understanding of RFC 2487 client and server can send SMTP cmds
   * after a rejected TLS negotiation
   */
  if (session_state->last_nontls_frame != 0 && pinfo->fd->num > session_state->last_nontls_frame) {
    guint16 save_can_desegment;
    guint32 save_last_nontls_frame;

    /* This is TLS, not raw SMTP. TLS can desegment */
    save_can_desegment = pinfo->can_desegment;
    pinfo->can_desegment = pinfo->saved_can_desegment;

    /* Make sure the SSL dissector will not be called again after decryption */
    save_last_nontls_frame = session_state->last_nontls_frame;
    session_state->last_nontls_frame = 0;

    call_dissector(ssl_handle, tvb, pinfo, tree);

    pinfo->can_desegment = save_can_desegment;
    session_state->last_nontls_frame = save_last_nontls_frame;
    return;
  }

  /* Is this a request or a response? */
  request = pinfo->destport == pinfo->match_uint;

  /*
   * Is there any data attached to this frame?
   */
  spd_frame_data = p_get_proto_data(pinfo->fd, proto_smtp);

  if (!spd_frame_data) {

    /*
     * No frame data.
     */
    if(request) {

      /*
       * Create a frame data structure and attach it to the packet.
       */
      spd_frame_data = se_alloc0(sizeof(struct smtp_proto_data));

      spd_frame_data->conversation_id = conversation->index;
      spd_frame_data->more_frags = TRUE;

      p_add_proto_data(pinfo->fd, proto_smtp, spd_frame_data);

    }

    /*
     * Get the first line from the buffer.
     *
     * Note that "tvb_find_line_end()" will, if it doesn't return
     * -1, return a value that is not longer than what's in the buffer,
     * and "tvb_find_line_end()" will always return a value that is not
     * longer than what's in the buffer, so the "tvb_get_ptr()" call
     * won't throw an exception.
     */
    loffset = offset;
    while (tvb_offset_exists(tvb, loffset)) {
      linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset,
                                  smtp_desegment && pinfo->can_desegment);
      if (linelen == -1) {
        if (offset == loffset) {
          /*
           * We didn't find a line ending, and we're doing desegmentation;
           * tell the TCP dissector where the data for this message starts
           * in the data it handed us, and tell it we need more bytes
           */
          pinfo->desegment_offset = loffset;
          pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
          return;
        } else {
          linelen = tvb_length_remaining(tvb, loffset);
          next_offset = loffset + linelen;
        }
      }
      line = tvb_get_ptr(tvb, loffset, linelen);

      /*
       * Check whether or not this packet is an end of message packet
       * We should look for CRLF.CRLF and they may be split.
       * We have to keep in mind that we may see what we want on
       * two passes through here ...
       */
      if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
        /*
         * The order of these is important ... We want to avoid
         * cases where there is a CRLF at the end of a packet and a
         * .CRLF at the begining of the same packet.
         */
        if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) ||
            tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0)
          eom_seen = TRUE;

        length_remaining = tvb_length_remaining(tvb, loffset);
        if (length_remaining == tvb_reported_length_remaining(tvb, loffset) &&
            tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0)
          session_state->crlf_seen = TRUE;
        else
          session_state->crlf_seen = FALSE;
      }

      /*
       * OK, Check if we have seen a DATA request. We do it here for
       * simplicity, but we have to be careful below.
       */
      if (request) {
        if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
          /*
           * This is message data.
           */
          if (eom_seen) { /* Seen the EOM */
            /*
             * EOM.
             * Everything that comes after it is commands.
             */
            spd_frame_data->pdu_type = SMTP_PDU_EOM;
            session_state->smtp_state = SMTP_STATE_READING_CMDS;
            break;
          } else {
            /*
             * Message data with no EOM.
             */
            spd_frame_data->pdu_type = SMTP_PDU_MESSAGE;

            if (session_state->msg_tot_len > 0) {
              /*
               * We are handling a BDAT message.
               * Check if we have reached end of the data chunk.
               */
              session_state->msg_read_len += tvb_length_remaining(tvb, loffset);

              if (session_state->msg_read_len == session_state->msg_tot_len) {
                /*
                 * We have reached end of BDAT data chunk.
                 * Everything that comes after this is commands.
                 */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;

                if (session_state->msg_last) {
                  /*
                   * We have found the LAST data chunk.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }

                break; /* no need to go through the remaining lines */
              }
            }
          }
        } else {
          /*
           * This is commands - unless the capture started in the
           * middle of a session, and we're in the middle of data.
           *
           * Commands are not necessarily 4 characters; look
           * for a space or the end of the line to see where
           * the putative command ends.
           */
          linep = line;
          lineend = line + linelen;
          while (linep < lineend && *linep != ' ')
            linep++;
          cmdlen = (int)(linep - line);
          if (line_is_smtp_command(line, cmdlen)) {
            if (g_ascii_strncasecmp(line, "DATA", 4) == 0) {
              /*
               * DATA command.
               * This is a command, but everything that comes after it,
               * until an EOM, is data.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->smtp_state = SMTP_STATE_READING_DATA;
              session_state->data_seen = TRUE;
            } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) {
              /*
               * BDAT command.
               * This is a command, but everything that comes after it,
               * until given length is received, is data.
               */
              guint32 msg_len;

              msg_len = strtoul (line+5, NULL, 10);

              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->data_seen = TRUE;
              session_state->msg_tot_len += msg_len;

              if (msg_len == 0) {
                /* No data to read, next will be a command */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;
              } else {
                session_state->smtp_state = SMTP_STATE_READING_DATA;
              }

              if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) {
                /*
                 * This is the last data chunk.
                 */
                session_state->msg_last = TRUE;

                if (msg_len == 0) {
                  /*
                   * No more data to expect.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }
              } else {
                session_state->msg_last = FALSE;
              }
            } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) {
              /*
               * STARTTLS command.
               * This is a command, but if the response is 220,
               * everything after the response is TLS.
               */
              session_state->smtp_state = SMTP_STATE_AWAITING_STARTTLS_RESPONSE;
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            } else {
              /*
               * Regular command.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            }
          } else {
            /*
             * Assume it's message data.
             */
            spd_frame_data->pdu_type = session_state->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD;
          }
        }
      }

      /*
       * Step past this line.
       */
      loffset = next_offset;
    }
  }


  /*
   * From here, we simply add items to the tree and info to the info
   * fields ...
   */

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP");

  if (check_col(pinfo->cinfo, COL_INFO)) {  /* Add the appropriate type here */
    col_clear(pinfo->cinfo, COL_INFO);

    /*
     * If it is a request, we have to look things up, otherwise, just
     * display the right things
     */

    if (request) {
      /* We must have frame_data here ... */
      switch (spd_frame_data->pdu_type) {
      case SMTP_PDU_MESSAGE:

        length_remaining = tvb_length_remaining(tvb, offset);
        col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body");
        col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining,
                        plurality (length_remaining, "", "s"));
        break;

      case SMTP_PDU_EOM:
        col_set_str(pinfo->cinfo, COL_INFO, "C: .");
        break;

      case SMTP_PDU_CMD:
        loffset = offset;
        while (tvb_offset_exists(tvb, loffset)) {
          /*
           * Find the end of the line.
           */
          linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
          line = tvb_get_ptr(tvb, loffset, linelen);

          if(loffset == offset)
            col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s",
                            format_text(line, linelen));
          else {
            col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                            format_text(line, linelen));
          }

          loffset = next_offset;
        }
        break;
      }
    } else {
      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
        line = tvb_get_ptr(tvb, loffset, linelen);

        if (loffset == offset)
          col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s",
                          format_text(line, linelen));
        else {
          col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                          format_text(line, linelen));
        }

        loffset = next_offset;
      }
    }
  }

  if (tree) { /* Build the tree info ... */
    ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, ENC_NA);
    smtp_tree = proto_item_add_subtree(ti, ett_smtp);
  }

  if (request) {
    /*
     * Check out whether or not we can see a command in there ...
     * What we are looking for is not data_seen and the word DATA
     * and not eom_seen.
     *
     * We will see DATA and session_state->data_seen when we process the
     * tree view after we have seen a DATA packet when processing
     * the packet list pane.
     *
     * On the first pass, we will not have any info on the packets
     * On second and subsequent passes, we will.
     */
    switch (spd_frame_data->pdu_type) {

    case SMTP_PDU_MESSAGE:
      if (smtp_data_desegment) {
        frag_msg = fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                         smtp_data_segment_table, smtp_data_reassembled_table,
                                         tvb_length(tvb), spd_frame_data->more_frags);
      } else {
        /*
         * Message body.
         * Put its lines into the protocol tree, a line at a time.
         */
        dissect_smtp_data(tvb, offset, smtp_tree);
      }
      break;

    case SMTP_PDU_EOM:
      /*
       * End-of-message-body indicator.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * DATA command this terminates before sending another
       * request, but we should probably handle it.
       */
      proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: .");

      if (smtp_data_desegment) {
        /* add final data segment */
        if (loffset)
          fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                smtp_data_segment_table, smtp_data_reassembled_table,
                                loffset, spd_frame_data->more_frags);

        /* terminate the desegmentation */
        frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                          smtp_data_reassembled_table);
      }
      break;

    case SMTP_PDU_CMD:
      /*
       * Command.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * previous command before sending another request, but we
       * should probably handle it.
       */

      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);

        if (linelen >= 4)
          cmdlen = 4;
        else
          cmdlen = linelen;
        hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb,
                                             0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /*
         * Put the command line into the protocol tree.
         */
        ti =  proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb,
                          loffset, next_offset - loffset, ENC_ASCII|ENC_NA);
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);

        proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
                            loffset, cmdlen, ENC_ASCII|ENC_NA);
        if (linelen > 5) {
          proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
                              loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
        }

        if (smtp_data_desegment && !spd_frame_data->more_frags) {
          /* terminate the desegmentation */
          frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                            smtp_data_reassembled_table);
        }

        /*
         * Step past this line.
         */
        loffset = next_offset;
      }
    }

    if (smtp_data_desegment) {
      next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled SMTP",
                                          frag_msg, &smtp_data_frag_items, NULL, smtp_tree);
      if (next_tvb) {
        /* XXX: this is presumptious - we may have negotiated something else */
        if (imf_handle) {
          call_dissector(imf_handle, next_tvb, pinfo, tree);
        } else {
          /*
           * Message body.
           * Put its lines into the protocol tree, a line at a time.
           */
          dissect_smtp_data(tvb, offset, smtp_tree);
        }

        pinfo->fragmented = FALSE;
      } else {
        pinfo->fragmented = TRUE;
      }
    }
  } else {
    /*
     * Process the response, a line at a time, until we hit a line
     * that doesn't have a continuation indication on it.
     */
    if (tree) {
      hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb,
                                           0, 0, TRUE);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    while (tvb_offset_exists(tvb, offset)) {
      /*
       * Find the end of the line.
       */
      linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

      if (tree) {
        /*
         * Put it into the protocol tree.
         */
        ti =  proto_tree_add_item(smtp_tree, hf_smtp_response, tvb,
                          offset, next_offset - offset, ENC_ASCII|ENC_NA);
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
      } else
        cmdresp_tree = NULL;

      line = tvb_get_ptr(tvb, offset, linelen);
      if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
          && isdigit(line[2])) {
        /*
         * We have a 3-digit response code.
         */
        code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0');

        /*
         * If we're awaiting the response to a STARTTLS code, this
         * is it - if it's 220, all subsequent traffic will
         * be TLS, otherwise we're back to boring old SMTP.
         */
        if (session_state->smtp_state == SMTP_STATE_AWAITING_STARTTLS_RESPONSE) {
          if (code == 220) {
            /* This is the last non-TLS frame. */
            session_state->last_nontls_frame = pinfo->fd->num;
          }
          session_state->smtp_state =  SMTP_STATE_READING_CMDS;
        }

        if (tree) {
          /*
           * Put the response code and parameters into the protocol tree.
           */
          proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3,
                              code);

          if (linelen >= 4) {
            proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
                                offset + 4, linelen - 4, ENC_ASCII|ENC_NA);
          }
        }
      }

      /*
       * Step past this line.
       */
      offset = next_offset;

    }
  }
}
Example #11
0
static gboolean
dissect_clique_rm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint8 version = 0;
  guint8 type = 0;
  int offset = 0;

  if (tvb_length (tvb) < 12)
    return FALSE;

  if (tvb_strneql (tvb, offset, "Clique", 6))
    return FALSE;
  offset += 6;

  version = tvb_get_guint8 (tvb, offset);
  if (version != 1)
    return FALSE;
  offset++;

  type = tvb_get_guint8 (tvb, offset);
  offset++;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "Clique-rm");
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
        val_to_str(type, packet_type_vals, "Unknown (0x%02x)"));

  if (tree) {
    proto_item *ti = NULL;
    proto_tree *clique_rm_tree = NULL;

    /* rewind back to just behind the prefix */
    offset = 6;

    ti = proto_tree_add_item(tree, proto_clique_rm, tvb, 0, -1, ENC_NA);
    clique_rm_tree = proto_item_add_subtree(ti, ett_clique_rm);

    proto_tree_add_item(clique_rm_tree, hf_clique_rm_version, tvb, offset, 1,
        ENC_BIG_ENDIAN);
    offset++;

    proto_tree_add_item(clique_rm_tree, hf_clique_rm_type, tvb, offset, 1,
        ENC_BIG_ENDIAN);
    offset++;

   if (check_col(pinfo->cinfo, COL_INFO))
     col_append_fstr(pinfo->cinfo, COL_INFO, ", sender: 0x%x",
       tvb_get_ntohl (tvb, offset));

    proto_tree_add_item(clique_rm_tree, hf_clique_rm_sender, tvb, offset,
        4, ENC_BIG_ENDIAN);
    offset += 4;

    if (IS_RELIABLE(type)) {
      if (check_col(pinfo->cinfo, COL_INFO))
        col_append_fstr(pinfo->cinfo, COL_INFO, ", id: 0x%x",
          tvb_get_ntohl (tvb, offset));

      dissect_reliable_packet(clique_rm_tree, type, tvb, offset);
    } else {
      dissect_unreliable_packet(clique_rm_tree, type, tvb, offset);
    }
  }

  return TRUE;
}
static int
dissect_beep_tree(tvbuff_t *tvb, int offset, packet_info *pinfo,
                  proto_tree *tree, struct beep_request_val *request_val,
                  struct beep_proto_data *beep_frame_data)
{
  proto_tree     *ti = NULL, *hdr = NULL;
  /*proto_item     *hidden_item;*/
  int            st_offset, msgno, ansno, seqno, size, channel, ackno, window, cc,
                 more;

  const char * cmd_temp = NULL;
  int is_ANS = 0;
  st_offset = offset;

  if (tvb_strneql(tvb, offset, "MSG ", 4) == 0)
    cmd_temp = "Command: MSG";
  if (tvb_strneql(tvb, offset, "RPY ", 4) == 0)
    cmd_temp = "Command: RPY";
  if (tvb_strneql(tvb, offset, "ERR ", 4) == 0)
    cmd_temp = "Command: ERR";
  if (tvb_strneql(tvb, offset, "NUL ", 4) == 0)
    cmd_temp = "Command: NUL";
  if (tvb_strneql(tvb, offset, "ANS ", 4) == 0) {
    cmd_temp = "Command: ANS";
    is_ANS = 1;
  }

  if (cmd_temp != NULL) {

    if (tree) {
      hdr = proto_tree_add_subtree(tree, tvb, offset, header_len(tvb, offset) + 2,
            ett_header, NULL, "Header");

      ti = proto_tree_add_item(hdr, hf_beep_cmd, tvb, offset, 3, ENC_NA|ENC_ASCII);
      /* Include space */
      proto_item_set_len(ti, 4);

      proto_tree_add_boolean(hdr, hf_beep_req, tvb, offset, 3, TRUE);
    }

    offset += 4;

    /* Get the channel */
    offset += dissect_beep_int(tvb, offset, hdr, hf_beep_channel, &channel, req_chan_hfa);
    offset += 1; /* Skip the space */

    /* Dissect the message number */
    offset += dissect_beep_int(tvb, offset, hdr, hf_beep_msgno, &msgno, req_msgno_hfa);
    offset += 1; /* skip the space */

    /* Insert the more elements ... */
    if ((more = dissect_beep_more(tvb, pinfo, offset, hdr)) >= 0) {
      /* Figure out which direction this is in and what mime_hdr flag to
       * add to the beep_frame_data. If there are missing segments, this code
       * will get it wrong!
       */
      set_mime_hdr_flags(more, request_val, beep_frame_data, pinfo);
    }
    else {  /* Protocol violation, so dissect rest as undisectable */
      if (tree && (tvb_length_remaining(tvb, offset) > 0)) {
        proto_tree_add_item(tree, hf_beep_payload_undissected, tvb, offset,
                            tvb_length_remaining(tvb, offset), ENC_NA|ENC_ASCII);
      }
      return -1;
    }

    offset += 2; /* Skip the flag and the space ... */

    /* now for the seqno */
    offset += dissect_beep_int(tvb, offset, hdr, hf_beep_seqno, &seqno, req_seqno_hfa);
    offset += 1; /* skip the space */

    offset += dissect_beep_int(tvb, offset, hdr, hf_beep_size, &size, req_size_hfa);
    if (request_val)   /* FIXME, is this the right order ... */
      request_val -> size = size;  /* Stash this away */
    else if (beep_frame_data) {
      beep_frame_data->pl_size = size;
      if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0; /* FIXME: OK? */
    }
    /* offset += 1; skip the space */

    if (is_ANS) { /* We need to put in the ansno */
        offset += 1; /* skip the space */
        /* Dissect the message number */
        offset += dissect_beep_int(tvb, offset, hdr, hf_beep_ansno, &ansno, req_ansno_hfa);
    }

    if ((cc = check_term(tvb, pinfo, offset, hdr)) <= 0) {

      /* We dissect the rest as data and bail ... */

      if (tree && (tvb_length_remaining(tvb, offset) > 0)) {
        proto_tree_add_item(tree, hf_beep_payload_undissected, tvb, offset,
                            tvb_length_remaining(tvb, offset), ENC_NA|ENC_ASCII);
      }

      return -1;

    }

    offset += cc;

    /* Insert MIME header ... */

    if (beep_frame_data && beep_frame_data->mime_hdr)
      offset += dissect_beep_mime_header(tvb, pinfo, offset, beep_frame_data, hdr);

    /* Now for the payload, if any */

    if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect what is left as payload */

      int pl_size = MIN(size, tvb_length_remaining(tvb, offset));

      /* Except, check the payload length, and only dissect that much */

      /* We need to keep track, in the conversation, of how much is left
       * so in the next packet, we can figure out what is part of the payload
       * and what is the next message
       */

      if (tree) {
        proto_tree_add_item(tree, hf_beep_payload, tvb, offset, pl_size, ENC_NA|ENC_ASCII);
      }

      offset += pl_size;

      if (request_val) {
        request_val->size -= pl_size;
        if (request_val->size < 0) request_val->size = 0;
      }
      else if (beep_frame_data) {
        beep_frame_data->pl_size -= pl_size;
        if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0;
      }
    }

    /* If anything else left, dissect it ... */

    if (tvb_length_remaining(tvb, offset) > 0)
      offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, beep_frame_data);

  } else if (tvb_strneql(tvb, offset, "SEQ ", 4) == 0) {

    if (tree) {
      ti = proto_tree_add_item(hdr, hf_beep_cmd, tvb, offset, 3, ENC_NA|ENC_ASCII);
      /* Include space */
      proto_item_set_len(ti, 4);
    }

    offset += 3;

    /* Now check the space: FIXME */

    offset += 1;

    offset += dissect_beep_int(tvb, offset, tree, hf_beep_channel, &channel, seq_chan_hfa);

    /* Check the space: FIXME */

    offset += 1;

    offset += dissect_beep_int(tvb, offset, tree, hf_beep_ackno, &ackno, seq_ackno_hfa);

    /* Check the space: FIXME */

    offset += 1;

    offset += dissect_beep_int(tvb, offset, tree, hf_beep_window, &window, seq_window_hfa);

    if ((cc = check_term(tvb, pinfo, offset, tree)) <= 0) {

      /* We dissect the rest as data and bail ... */

      if (tree && (tvb_length_remaining(tvb, offset) > 0)) {
        proto_tree_add_item(tree, hf_beep_payload_undissected, tvb, offset,
                            tvb_length_remaining(tvb, offset), ENC_NA|ENC_ASCII);
      }

      return -1;

    }

    offset += cc;

  } else if (tvb_strneql(tvb, offset, "END", 3) == 0) {

    proto_tree *tr = NULL;

    if (tree) {
      tr = proto_tree_add_subtree(tree, tvb, offset, MIN(5, MAX(0, tvb_length_remaining(tvb, offset))),
                                    ett_trailer, NULL, "Trailer");

      proto_tree_add_item(hdr, hf_beep_cmd, tvb, offset, 3, ENC_NA|ENC_ASCII);
    }

    offset += 3;

    if ((cc = check_term(tvb, pinfo, offset, tr)) <= 0) {

      /* We dissect the rest as data and bail ... */

      if (tree && (tvb_length_remaining(tvb, offset) > 0)) {
        proto_tree_add_item(tree, hf_beep_payload_undissected, tvb, offset,
                            tvb_length_remaining(tvb, offset), ENC_NA|ENC_ASCII);
      }

      return -1;

    }

    offset += cc;

  }

  if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect anything left over */

    int pl_size = 0;

    if (request_val) {

      pl_size = MIN(request_val->size, tvb_length_remaining(tvb, offset));

      if (pl_size == 0) { /* The whole of the rest must be payload */

        pl_size = tvb_length_remaining(tvb, offset); /* Right place ? */

      }

    } else if (beep_frame_data) {
      pl_size = MIN(beep_frame_data->pl_size, tvb_length_remaining(tvb, offset));
    } else { /* Just in case */
      pl_size = tvb_length_remaining(tvb, offset);
    }

    /* Take care here to handle the payload correctly, and if there is
     * another message here, then handle it correctly as well.
     */

    /* If the pl_size == 0 and the offset == 0?, then we have not processed
     * anything in this frame above, so we better treat all this data as
     * payload to avoid recursion loops
     */

    if (pl_size == 0 && offset == st_offset)
      pl_size = tvb_length_remaining(tvb, offset);

    if (pl_size > 0) {

      if (tree) {
        proto_tree_add_item(tree, hf_beep_payload, tvb, offset, pl_size, ENC_NA|ENC_ASCII);
      }

      offset += pl_size;            /* Advance past the payload */

      if (request_val){
        request_val->size -= pl_size; /* Reduce payload by what we added */
        if (request_val->size < 0) request_val->size = 0;
      }
      else if (beep_frame_data) {
        beep_frame_data->pl_size -= pl_size;
        if (beep_frame_data->pl_size < 0) beep_frame_data->pl_size = 0;
      }
    }

    if (tvb_length_remaining(tvb, offset) > 0) {
      offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, beep_frame_data);
    }
  }

  return offset - st_offset;

}
static int
dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		    gboolean is_verifier)
{
	proto_item *volatile item;
	proto_tree *volatile subtree;
	volatile int return_offset = 0;
	gssapi_conv_info_t *volatile gss_info;
	gssapi_oid_value *oidvalue;
	dissector_handle_t handle;
	conversation_t *conversation;
	tvbuff_t *oid_tvb;
	int len, start_offset, oid_start_offset;
	volatile int offset;
	gint8 appclass;
	gboolean pc, ind_field;
	gint32 tag;
	guint32 len1;
	const char *oid;
	fragment_data *fd_head=NULL;
	gssapi_frag_info_t *fi;
	tvbuff_t *volatile gss_tvb=NULL;
	asn1_ctx_t asn1_ctx;
	void *pd_save;

	start_offset=0;
	offset=0;
	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
	/*
	 * We don't know whether the data is encrypted, so say it's
	 * not, for now.  The subdissector must set gssapi_data_encrypted
	 * if it is.
	 */
	pinfo->gssapi_data_encrypted = FALSE;


	/*
	 * We need a conversation for later
	 */
	conversation = find_or_create_conversation(pinfo);

	gss_info = (gssapi_conv_info_t *)conversation_get_proto_data(conversation, proto_gssapi);
	if (!gss_info) {
		gss_info = se_new(gssapi_conv_info_t);
		gss_info->oid=NULL;
		gss_info->do_reassembly=FALSE;
		gss_info->frags=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "gssapi_frags");

		conversation_add_proto_data(conversation, proto_gssapi, gss_info);
	}

	item = proto_tree_add_item(
		tree, proto_gssapi, tvb, offset, -1, ENC_NA);

	subtree = proto_item_add_subtree(item, ett_gssapi);

	/*
	 * Catch the ReportedBoundsError exception; the stuff we've been
	 * handed doesn't necessarily run to the end of the packet, it's
	 * an item inside a packet, so if it happens to be malformed (or
	 * we, or a dissector we call, has a bug), so that an exception
	 * is thrown, we want to report the error, but return and let
	 * our caller dissect the rest of the packet.
	 *
	 * If it gets a BoundsError, we can stop, as there's nothing more
	 * in the packet after our blob to see, so we just re-throw the
	 * exception.
	 */
	pd_save = pinfo->private_data;
	TRY {
		gss_tvb=tvb;


		/* First of all, if it's the first time we see this packet
		 * then check whether we are in the middle of reassembly or not
		 */
		if( (!pinfo->fd->flags.visited)
		&&  (gss_info->do_reassembly)
		&&  (gssapi_reassembly) ){
			fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, gss_info->first_frame);
			if(!fi){
				goto done;
			}
			se_tree_insert32(gss_info->frags, pinfo->fd->num, fi);
			fd_head=fragment_add(&gssapi_reassembly_table,
				tvb, 0, pinfo, fi->first_frame, NULL,
				gss_info->frag_offset,
				tvb_length(tvb), TRUE);
			gss_info->frag_offset+=tvb_length(tvb);

			/* we need more fragments */
			if(!fd_head){
				goto done;
			}

			/* this blob is now fully reassembled */
			gss_info->do_reassembly=FALSE;
			fi->reassembled_in=pinfo->fd->num;

			gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
			add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI");
		}
		/* We have seen this packet before.
		 * Is this blob part of reassembly or a normal blob ?
		 */
		if( (pinfo->fd->flags.visited)
		&&  (gssapi_reassembly) ){
			fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, pinfo->fd->num);
			if(fi){
				fd_head=fragment_get(&gssapi_reassembly_table,
					pinfo, fi->first_frame, NULL);
				if(fd_head && (fd_head->flags&FD_DEFRAGMENTED)){
					if(pinfo->fd->num==fi->reassembled_in){
					        proto_item *frag_tree_item;
						gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
						add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI");
						show_fragment_tree(fd_head, &gssapi_frag_items, tree, pinfo, tvb, &frag_tree_item);
					} else {
						proto_item *it;
						it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in);
					        PROTO_ITEM_SET_GENERATED(it);
						goto done;
					}
				}
			}
		}

		/* Read header */
		offset = get_ber_identifier(gss_tvb, offset, &appclass, &pc, &tag);
		offset = get_ber_length(gss_tvb, offset, &len1, &ind_field);


		if (!(appclass == BER_CLASS_APP && pc && tag == 0)) {
		  /* It could be NTLMSSP, with no OID.  This can happen
		     for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */
			if ((tvb_length_remaining(gss_tvb, start_offset)>7) && (tvb_strneql(gss_tvb, start_offset, "NTLMSSP", 7) == 0)) {
				return_offset = call_dissector(ntlmssp_handle,
							tvb_new_subset_remaining(gss_tvb, start_offset),
							pinfo, subtree);
				goto done;
			}
			/* Maybe it's new NTLMSSP payload */
			if ((tvb_length_remaining(gss_tvb, start_offset)>16) &&
			   ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
				return_offset = call_dissector(ntlmssp_payload_handle,
							tvb_new_subset_remaining(gss_tvb, start_offset),
							pinfo, subtree);
				pinfo->gssapi_data_encrypted = TRUE;
				goto done;
			}
			if ((tvb_length_remaining(gss_tvb, start_offset)==16) &&
			   ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
				if( is_verifier ) {
					return_offset = call_dissector(ntlmssp_verf_handle,
									tvb_new_subset_remaining(gss_tvb, start_offset),
									pinfo, subtree);
				}
				else if( pinfo->gssapi_encrypted_tvb ) {
					return_offset = call_dissector(ntlmssp_data_only_handle,
									tvb_new_subset_remaining(pinfo->gssapi_encrypted_tvb, 0),
									pinfo, subtree);
					pinfo->gssapi_data_encrypted = TRUE;
				}
		   		goto done;
		  	}

		  /* Maybe it's new GSSKRB5 CFX Wrapping */
		  if ((tvb_length_remaining(gss_tvb, start_offset)>2) &&
		      ((tvb_memeql(gss_tvb, start_offset, "\04\x04", 2) == 0) ||
		       (tvb_memeql(gss_tvb, start_offset, "\05\x04", 2) == 0))) {
		    return_offset = call_dissector(spnego_krb5_wrap_handle,
						   tvb_new_subset_remaining(gss_tvb, start_offset),
						   pinfo, subtree);
		    goto done;
		  }

		  /*
		   * If we do not recognise an Application class,
		   * then we are probably dealing with an inner context
		   * token or a wrap token, and we should retrieve the
		   * gssapi_oid_value pointer from the per-frame data or,
		   * if there is no per-frame data (as would be the case
		   * the first time we dissect this frame), from the
		   * conversation that exists or that we created from
		   * pinfo (and then make it per-frame data).
		   * We need to make it per-frame data as there can be
		   * more than one GSS-API negotiation in a conversation.
		   *
		   * Note! We "cheat". Since we only need the pointer,
		   * we store that as the data.  (That's not really
		   * "cheating" - the per-frame data and per-conversation
		   * data code doesn't care what you supply as a data
		   * pointer; it just treats it as an opaque pointer, it
		   * doesn't dereference it or free what it points to.)
		   */
		  oidvalue = (gssapi_oid_value *)p_get_proto_data(pinfo->fd, proto_gssapi, 0);
		  if (!oidvalue && !pinfo->fd->flags.visited)
		  {
		    /* No handle attached to this frame, but it's the first */
		    /* pass, so it'd be attached to the conversation. */
		    oidvalue = gss_info->oid;
		    if (gss_info->oid)
		      p_add_proto_data(pinfo->fd, proto_gssapi, 0, gss_info->oid);
		  }
		  if (!oidvalue)
		  {
                    proto_tree_add_text(subtree, gss_tvb, start_offset, 0,
					  "Unknown header (class=%d, pc=%d, tag=%d)",
					  appclass, pc, tag);
		    return_offset = tvb_length(gss_tvb);
		    goto done;
		  } else {
		    tvbuff_t *oid_tvb_local;

		    oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset);
		    if (is_verifier)
			handle = oidvalue->wrap_handle;
		    else
			handle = oidvalue->handle;
		    len = call_dissector(handle, oid_tvb_local, pinfo, subtree);
		    if (len == 0)
			return_offset = tvb_length(gss_tvb);
		    else
			return_offset = start_offset + len;
		    goto done; /* We are finished here */
		  }
		}

		/* Read oid */
		oid_start_offset=offset;
		offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, gss_tvb, offset, hf_gssapi_oid, &oid);
		oidvalue = gssapi_lookup_oid_str(oid);


		/* Check if we need reassembly of this blob.
		 * Only try reassembly for OIDs we recognize
		 * and when we have the entire tvb
		 *
		 * SMB will sometimes split one large GSSAPI blob
		 * across multiple SMB/SessionSetup commands.
		 * While we should look at the uid returned in the response
		 * to the first SessionSetup and use that as a key
		 * instead for simplicity we assume there will not be several
		 * such authentication at once on a single tcp session
		 */
		if( (!pinfo->fd->flags.visited)
		&&  (oidvalue)
		&&  (tvb_length(gss_tvb)==tvb_reported_length(gss_tvb))
		&&  (len1>(guint32)tvb_length_remaining(gss_tvb, oid_start_offset))
		&&  (gssapi_reassembly) ){
			fi=se_new(gssapi_frag_info_t);
			fi->first_frame=pinfo->fd->num;
			fi->reassembled_in=0;
			se_tree_insert32(gss_info->frags, pinfo->fd->num, fi);

			fragment_add(&gssapi_reassembly_table,
				gss_tvb, 0, pinfo, pinfo->fd->num, NULL,
				0, tvb_length(gss_tvb), TRUE);
			fragment_set_tot_len(&gssapi_reassembly_table,
				pinfo, pinfo->fd->num, NULL, len1+oid_start_offset);

			gss_info->do_reassembly=TRUE;
			gss_info->first_frame=pinfo->fd->num;
			gss_info->frag_offset=tvb_length(gss_tvb);
			goto done;
		}


		/*
		 * Hand off to subdissector.
		 */

		if ((oidvalue == NULL) ||
		    !proto_is_protocol_enabled(oidvalue->proto)) {
			/* No dissector for this oid */
			proto_tree_add_text(subtree, gss_tvb, oid_start_offset, -1,
					    "Token object");

			return_offset = tvb_length(gss_tvb);
			goto done;
		}

		/* Save a pointer to the data for the OID for the
		 * GSSAPI protocol for this conversation.
		 */

		/*
		 * Now add the proto data ...
		 * but only if it is not already there.
		 */
		if(!gss_info->oid){
		  gss_info->oid=oidvalue;
		}

		if (is_verifier) {
			handle = oidvalue->wrap_handle;
			if (handle != NULL) {
				oid_tvb = tvb_new_subset_remaining(gss_tvb, offset);
				len = call_dissector(handle, oid_tvb, pinfo,
				    subtree);
				if (len == 0)
					return_offset = tvb_length(gss_tvb);
				else
					return_offset = offset + len;
			} else {
				proto_tree_add_text(subtree, gss_tvb, offset, -1,
				    "Authentication verifier");
				return_offset = tvb_length(gss_tvb);
			}
		} else {
			handle = oidvalue->handle;
			if (handle != NULL) {
				oid_tvb = tvb_new_subset_remaining(gss_tvb, offset);
				len = call_dissector(handle, oid_tvb, pinfo,
				    subtree);
				if (len == 0)
					return_offset = tvb_length(gss_tvb);
				else
					return_offset = offset + len;
			} else {
				proto_tree_add_text(subtree, gss_tvb, offset, -1,
				    "Authentication credentials");
				return_offset = tvb_length(gss_tvb);
			}
		}

	 done:
		;
	} CATCH_NONFATAL_ERRORS {
		/*
		 * Somebody threw an exception that means that there
		 * was a problem dissecting the payload; that means
		 * that a dissector was found, so we don't need to
		 * dissect the payload as data or update the protocol
		 * or info columns.
		 *
		 * Just show the exception and then drive on to show
		 * the trailer, after noting that a dissector was found
		 * and restoring the protocol value that was in effect
		 * before we called the subdissector.
		 *
		 * Restore the private_data structure in case one of the
		 * called dissectors modified it (and, due to the exception,
		 * was unable to restore it).
		 */
		pinfo->private_data = pd_save;
		show_exception(gss_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
	} ENDTRY;

	proto_item_set_len(item, return_offset);
	return return_offset;
}
Example #14
0
static int
dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
    proto_tree *hdrs_tree   = NULL;
    proto_tree *hdr_tree    = NULL;
    proto_item *hdr         = NULL;
    proto_item *handle_item;
    gint        item_length = -1;
    guint8      hdr_id, i;

    if (tvb_length_remaining(tvb, offset) > 0) {
        proto_item *hdrs;
        hdrs      = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
        hdrs_tree = proto_item_add_subtree(hdrs, ett_btobex_hdrs);
    }
    else {
        return offset;
    }

    while (tvb_length_remaining(tvb, offset) > 0) {
        hdr_id = tvb_get_guint8(tvb, offset);

        switch(0xC0 & hdr_id)
        {
            case 0x00: /* null terminated unicode */
                item_length = tvb_get_ntohs(tvb, offset+1);
                break;
            case 0x40:  /* byte sequence */
                item_length = tvb_get_ntohs(tvb, offset+1);
                break;
            case 0x80:  /* 1 byte */
                item_length = 2;
                break;
            case 0xc0:  /* 4 bytes */
                item_length = 5;
                break;
        }

        hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s",
                                  val_to_str_ext_const(hdr_id, &header_id_vals_ext, "Unknown"));
        hdr_tree = proto_item_add_subtree(hdr, ett_btobex_hdr);

        proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN);

        offset++;

        switch(0xC0 & hdr_id)
        {
            case 0x00: /* null terminated unicode */
                {
                    proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;

                    if ((item_length - 3) > 0) {
                        char *str;

                        display_unicode_string(tvb, hdr_tree, offset, &str);
                        proto_item_append_text(hdr_tree, " (\"%s\")", str);
                        col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
                    }
                    else {
                        col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
                    }

                    offset += item_length - 3;
                }
                break;
            case 0x40:  /* byte sequence */
                proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;

                handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA);

                if (((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19)) { /* target or who */
                    for(i=0; target_vals[i].strptr != NULL; i++) {
                        if (tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0) {
                            proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
                            proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
                            col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
                        }
                    }
                }

                if (!tvb_strneql(tvb, offset, "<?xml", 5))
                {
                    tvbuff_t* next_tvb = tvb_new_subset_remaining(tvb, offset);

                    call_dissector(xml_handle, next_tvb, pinfo, tree);
                }
                else if (is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
                {
                    proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
                    col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
                }

                offset += item_length - 3;
                break;
            case 0x80:  /* 1 byte */
                proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
                proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset++;
                break;
            case 0xc0:  /* 4 bytes */
                proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
                proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            default:
                break;
        }
    }

    return offset;
}
Example #15
0
static void
dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    int offset = 0;
    int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len;
    guint8 vers_flags;
    guint8 auth_len;
    guint8 auth_flags;
    tvbuff_t *next_tvb;

    proto_item *si, *sif;
    proto_tree *sap_tree = NULL, *sap_flags_tree;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAP");
    col_clear(pinfo->cinfo, COL_INFO);

    vers_flags = tvb_get_guint8(tvb, offset);
    is_ipv6 = vers_flags&MCAST_SAP_BIT_A;
    is_del = vers_flags&MCAST_SAP_BIT_T;
    is_enc = vers_flags&MCAST_SAP_BIT_E;
    is_comp = vers_flags&MCAST_SAP_BIT_C;

    sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
    addr_len = (is_ipv6) ? (int)sizeof(struct e_in6_addr) : 4;

    col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
                            (is_del) ? "Deletion" : "Announcement", sap_version);

    if (tree) {
        si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, ENC_NA);
        sap_tree = proto_item_add_subtree(si, ett_sap);

        sif = proto_tree_add_item(sap_tree, hf_sap_flags, tvb, offset, 1, ENC_NA);
        sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, ENC_NA);
    }

    offset++;

    auth_len = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(sap_tree, hf_sap_auth_len, tvb, offset, 1, ENC_NA);
    offset++;

    proto_tree_add_item(sap_tree, hf_sap_message_identifier_hash, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset +=2;

    if (is_ipv6)
        proto_tree_add_item(sap_tree, hf_sap_originating_source_ipv6, tvb, offset, addr_len, ENC_NA);
    else
        proto_tree_add_item(sap_tree, hf_sap_originating_source_ipv4, tvb, offset, addr_len, ENC_BIG_ENDIAN);
    offset += addr_len;

    /* Authentication data lives in its own subtree */
    if (auth_len > 0) {
        guint32 auth_data_len;
        proto_item *sdi, *sai;
        proto_tree *sa_tree, *saf_tree;
        int has_pad;
        guint8 pad_len = 0;

        auth_data_len = (guint32)(auth_len * sizeof(guint32));

        sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, ENC_NA);
        sa_tree = proto_item_add_subtree(sdi, ett_sap_auth);

        auth_flags = tvb_get_guint8(tvb, offset);
        sai = proto_tree_add_item(sa_tree, hf_auth_flags, tvb, offset, 1, ENC_NA);
        saf_tree = proto_item_add_subtree(sai, ett_sap_authf);
        proto_tree_add_item(saf_tree, hf_auth_flags_v, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(saf_tree, hf_auth_flags_p, tvb, offset, 1, ENC_NA);
        proto_tree_add_item(saf_tree, hf_auth_flags_t, tvb, offset, 1, ENC_NA);

        has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P;
        if (has_pad) {
            pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1);
        }

        if ((int) auth_data_len - pad_len - 1 < 0) {
            expert_add_info_format(pinfo, sai, &ei_sap_bogus_authentication_or_pad_length,
                                        "Bogus authentication length (%d) or pad length (%d)", auth_len, pad_len);
            return;
        }


        proto_tree_add_item(sa_tree, hf_sap_auth_subheader, tvb, offset+1, auth_data_len-pad_len-1, ENC_NA);
        if (has_pad) {
            proto_tree_add_item(sa_tree, hf_sap_auth_data_padding_len, tvb, offset+auth_data_len-1, 1, ENC_NA);
            proto_tree_add_item(sa_tree, hf_sap_auth_data_padding, tvb, offset+auth_data_len-pad_len, pad_len, ENC_NA);
        }

        offset += auth_data_len;
    }

    if (is_enc || is_comp) {
        expert_field *mangle;
        if (is_enc && is_comp)
            mangle = &ei_sap_compressed_and_encrypted;
        else if (is_enc)
            mangle = &ei_sap_encrypted;
        else
            mangle = &ei_sap_compressed;

        proto_tree_add_expert(sap_tree, pinfo, mangle, tvb, offset, -1);
        return;
    }

    if (tree) {
        /* Do we have the optional payload type aka. MIME content specifier */
        if (tvb_strneql(tvb, offset, "v=", strlen("v="))) {
            gint remaining_len;
            guint32 pt_len;
            int pt_string_len;
            guint8* pt_str;

            remaining_len = tvb_captured_length_remaining(tvb, offset);
            if (remaining_len == 0) {
                /*
                    * "tvb_strneql()" failed because there was no
                    * data left in the packet.
                    *
                    * Set the remaining length to 1, so that
                    * we throw the appropriate exception in
                    * "tvb_get_ptr()", rather than displaying
                    * the payload type.
                    */
                remaining_len = 1;
            }

            pt_string_len = tvb_strnlen(tvb, offset, remaining_len);
            if (pt_string_len == -1) {
                /*
                 * We didn't find a terminating '\0'; run to the
                 * end of the buffer.
                 */
                pt_string_len = remaining_len;
                pt_len = pt_string_len;
            } else {
                /*
                 * Include the '\0' in the total item length.
                 */
                pt_len = pt_string_len + 1;
            }

            pt_str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, pt_string_len, ENC_ASCII);
            proto_tree_add_string_format_value(sap_tree, hf_sap_payload_type, tvb, offset, pt_len,
                pt_str, "%.*s", pt_string_len, pt_str);
            offset += pt_len;
        }
    }

    /* Done with SAP */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(sdp_handle, next_tvb, pinfo, tree);
}