static gboolean dissect_credssp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { asn1_ctx_t asn1_ctx; int offset = 0; gint8 class; gboolean pc; gint32 tag; guint32 length; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* Look for SEQUENCE, CONTEXT 0, and INTEGER 2 */ if(tvb_length(tvb) > 7) { offset = get_ber_identifier(tvb, offset, &class, &pc, &tag); if((class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_SEQUENCE) && (pc == TRUE)) { offset = get_ber_length(tvb, offset, NULL, NULL); offset = get_ber_identifier(tvb, offset, &class, &pc, &tag); if((class == BER_CLASS_CON) && (tag == 0)) { offset = get_ber_length(tvb, offset, NULL, NULL); offset = get_ber_identifier(tvb, offset, &class, &pc, &tag); if((class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_INTEGER)) { offset = get_ber_length(tvb, offset, &length, NULL); if((length == 1) && (tvb_get_guint8(tvb, offset) == 2)) { dissect_credssp(tvb, pinfo, parent_tree); return TRUE; } } } } }
static void dissect_ss_info_ie(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint len, proto_tree *tree) { guint saved_offset; gint8 appclass; gboolean pc; gboolean ind = FALSE; guint32 component_len = 0; guint32 header_end_offset; guint32 header_len; asn1_ctx_t asn1_ctx; tvbuff_t *ss_tvb = NULL; static gint comp_type_tag; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); saved_offset = offset; col_append_str(pinfo->cinfo, COL_PROTOCOL, "/"); col_set_fence(pinfo->cinfo, COL_PROTOCOL); while (len > (offset - saved_offset)) { /* get the length of the component. there can be multiple components in one message */ header_end_offset = get_ber_identifier(tvb, offset, &appclass, &pc, &comp_type_tag); header_end_offset = get_ber_length(tvb, header_end_offset, &component_len, &ind); header_len = header_end_offset -offset; component_len += header_len; ss_tvb = tvb_new_subset_length(tvb, offset, component_len); col_append_str(pinfo->cinfo, COL_INFO, "(GSM MAP) "); col_set_fence(pinfo->cinfo, COL_INFO); call_dissector(gsm_map_handle, ss_tvb, pinfo, tree); offset += component_len; } }
static gboolean dissect_mms_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { /* must check that this really is an mms packet */ int offset = 0; guint32 length = 0 ; guint32 oct; gint idx = 0 ; gint8 tmp_class; gboolean tmp_pc; gint32 tmp_tag; /* first, check do we have at least 2 bytes (pdu) */ if (!tvb_bytes_exist(tvb, 0, 2)) return FALSE; /* no */ /* can we recognize MMS PDU ? Return FALSE if not */ /* get MMS PDU type */ offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag); /* check MMS type */ /* Class should be constructed */ if (tmp_class!=BER_CLASS_CON) return FALSE; /* see if the tag is a valid MMS PDU */ match_strval_idx(tmp_tag, mms_MMSpdu_vals, &idx); if (idx == -1) { return FALSE; /* no, it isn't an MMS PDU */ } /* check MMS length */ oct = tvb_get_guint8(tvb, offset)& 0x7F; if (oct==0) /* MMS requires length after tag so not MMS if indefinite length*/ return FALSE; offset = get_ber_length(tvb, offset, &length, NULL); /* do we have enough bytes? */ if (!tvb_bytes_exist(tvb, offset, length)) return FALSE; dissect_mms(tvb, pinfo, parent_tree); return TRUE; }
static int strip_octet_string(tvbuff_t *tvb) { gint8 ber_class; gboolean pc, ind; gint32 tag; guint32 len; int offset = 0; /* PKCS#7 encodes the content as OCTET STRING, whereas CMS is just any ANY */ /* if we use CMS (rather than PKCS#7) - which we are - we need to strip the OCTET STRING tag */ /* before proceeding */ offset = get_ber_identifier(tvb, 0, &ber_class, &pc, &tag); offset = get_ber_length(tvb, offset, &len, &ind); if((ber_class == BER_CLASS_UNI) && (tag == BER_UNI_TAG_OCTETSTRING)) return offset; return 0; }
/*--- dissect_q932_facility_ie -------------------------------------------------------*/ static void dissect_q932_facility_ie(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int length) { gint8 appclass; gboolean pc; gint32 tag; guint32 len; int hoffset, eoffset; int ie_end; tvbuff_t *next_tvb; ie_end = offset + length; proto_tree_add_item(tree, hf_q932_pp, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; while (offset < ie_end) { hoffset = offset; offset = get_ber_identifier(tvb, offset, &appclass, &pc, &tag); offset = get_ber_length(tvb, offset, &len, NULL); eoffset = offset + len; next_tvb = tvb_new_subset_length(tvb, hoffset, eoffset - hoffset); switch (appclass) { case BER_CLASS_CON: switch (tag) { case 10 : /* Network Facility Extension */ dissect_NetworkFacilityExtension_PDU(next_tvb, pinfo, tree, NULL); break; case 18 : /* Network Protocol Profile */ dissect_NetworkProtocolProfile_PDU(next_tvb, pinfo, tree, NULL); break; case 11 : /* Interpretation Component */ dissect_InterpretationComponent_PDU(next_tvb, pinfo, tree, NULL); break; /* ROSE APDU */ case 1 : /* invoke */ case 2 : /* returnResult */ case 3 : /* returnError */ case 4 : /* reject */ q932_rose_ctx.apdu_depth = 1; call_dissector_with_data(q932_ros_handle, next_tvb, pinfo, tree, &q932_rose_ctx); break; /* DSE APDU */ case 12 : /* begin */ case 14 : /* end */ case 15 : /* continue */ case 17 : /* abort */ offset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL); offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL); proto_tree_add_expert(tree, pinfo, &ei_q932_dse_not_supported, tvb, offset, len); break; default: offset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL); offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL); proto_tree_add_expert(tree, pinfo, &ei_q932_unknown_component, tvb, offset, len); } break; case BER_CLASS_APP: switch (tag) { /* ACSE APDU */ case 0 : /* aarq */ case 1 : /* aare */ case 2 : /* rlrq */ case 3 : /* rlre */ case 4 : /* abrt */ offset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL); offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL); proto_tree_add_expert(tree, pinfo, &ei_q932_acse_not_supported, tvb, offset, len); break; default: offset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL); offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL); proto_tree_add_expert(tree, pinfo, &ei_q932_unknown_component, tvb, offset, len); } break; default: offset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL); offset = dissect_ber_length(pinfo, tree, tvb, offset, NULL, NULL); proto_tree_add_expert(tree, pinfo, &ei_q932_unknown_component, tvb, offset, len); } offset = eoffset; } }
static int dissect_tcap_param(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset) { gint tag_offset, saved_offset, len_offset; tvbuff_t *next_tvb; proto_tree *subtree; proto_item *pi; gint8 class; gboolean pc; gint32 tag; guint32 len; guint32 tag_length; guint32 len_length; gboolean ind_field; while (tvb_reported_length_remaining(tvb, offset) > 0) { saved_offset = offset; offset = get_ber_identifier(tvb, offset, &class, &pc, &tag); tag_offset = offset; offset = get_ber_length(tvb, offset, &len, &ind_field); len_offset = offset; tag_length = tag_offset - saved_offset; len_length = len_offset - tag_offset; if (pc) { pi = proto_tree_add_text(tree, tvb, saved_offset, len + (len_offset - saved_offset), "CONSTRUCTOR"); subtree = proto_item_add_subtree(pi, ett_param); proto_tree_add_uint_format(subtree, hf_tcap_tag, tvb, saved_offset, tag_length, tag, "CONSTRUCTOR Tag"); proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset, tag_length, class); proto_tree_add_uint(subtree, hf_tcap_length, tvb, tag_offset, len_length, len); if (len-(2*ind_field)) /*should always be positive unless we get an empty contructor pointless? */ { next_tvb = tvb_new_subset(tvb, offset, len-(2*ind_field), len-(2*ind_field)); dissect_tcap_param(actx, subtree,next_tvb,0); } if (ind_field) proto_tree_add_text(subtree, tvb, offset+len-2, 2, "CONSTRUCTOR EOC"); offset += len; } else { pi = proto_tree_add_text(tree, tvb, saved_offset, len + (len_offset - saved_offset), "Parameter (0x%.2x)", tag); subtree = proto_item_add_subtree(pi, ett_param); proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset, tag_length, tag); proto_tree_add_uint(subtree, hf_tcap_length, tvb, saved_offset+tag_length, len_length, len); if (len) /* check for NULLS */ { next_tvb = tvb_new_subset(tvb, offset, len, len); dissect_ber_octet_string(TRUE, actx, tree, next_tvb, 0, hf_tcap_data, NULL); } offset += len; } }
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; }