diff options
Diffstat (limited to 'epan/dissectors/packet-rpc.c')
-rw-r--r-- | epan/dissectors/packet-rpc.c | 398 |
1 files changed, 222 insertions, 176 deletions
diff --git a/epan/dissectors/packet-rpc.c b/epan/dissectors/packet-rpc.c index 0c8d118e28..d12b9e9d2f 100644 --- a/epan/dissectors/packet-rpc.c +++ b/epan/dissectors/packet-rpc.c @@ -13,7 +13,7 @@ #include "config.h" -#include <stdio.h> +#include <stdio.h> /* fprintf() */ #include <epan/packet.h> #include <epan/expert.h> #include <epan/exceptions.h> @@ -29,8 +29,8 @@ #include "packet-rpc.h" #include "packet-tcp.h" +#include "packet-tls.h" #include "packet-nfs.h" -#include "packet-dcerpc.h" #include "packet-gssapi.h" /* @@ -52,13 +52,17 @@ * RFC 5531, "Appendix C: Current Number Assignments" defines AUTH_RSA. * AUTH_RSA is not implemented for any known RPC-protocols. The Gluster * protocols (ab)use AUTH_RSA for their own AUTH-flavor. AUTH_RSA is - * therefore dissected as the inofficial AUTH_GLUSTER. + * therefore dissected as the unofficial AUTH_GLUSTER. */ void proto_register_rpc(void); void proto_reg_handoff_rpc(void); #define RPC_TCP_PORT 111 +#define RPC_UDP 0 +#define RPC_TCP 1 +#define RPC_TLS 2 + /* desegmentation of RPC over TCP */ static gboolean rpc_desegment = TRUE; @@ -75,7 +79,7 @@ static gboolean rpc_dissect_unknown_programs = FALSE; */ static gboolean rpc_find_fragment_start = FALSE; -static int rpc_tap = -1; +static int rpc_tap; static dissector_handle_t spnego_krb5_wrap_handle = NULL; @@ -98,6 +102,7 @@ const value_string rpc_auth_flavor[] = { { AUTH_DES, "AUTH_DES" }, { AUTH_RSA, "AUTH_RSA/Gluster" }, { RPCSEC_GSS, "RPCSEC_GSS" }, + { AUTH_TLS, "AUTH_TLS" }, { AUTH_GSSAPI, "AUTH_GSSAPI" }, { RPCSEC_GSS_KRB5, "RPCSEC_GSS_KRB5" }, { RPCSEC_GSS_KRB5I, "RPCSEC_GSS_KRB5I" }, @@ -109,6 +114,7 @@ const value_string rpc_auth_flavor[] = { { RPCSEC_GSS_SPKM3I, "RPCSEC_GSS_SPKM3I" }, { RPCSEC_GSS_SPKM3P, "RPCSEC_GSS_SPKM3P" }, { AUTH_GLUSTERFS, "AUTH_GLUSTERFS" }, + { AUTH_GLUSTERFS_V3, "AUTH_GLUSTERFS_V3" }, { 0, NULL } }; @@ -170,113 +176,114 @@ static const value_string rpc_authdes_namekind[] = { }; /* the protocol number */ -static int proto_rpc = -1; -static int hf_rpc_reqframe = -1; -static int hf_rpc_repframe = -1; -static int hf_rpc_lastfrag = -1; -static int hf_rpc_fraglen = -1; -static int hf_rpc_xid = -1; -static int hf_rpc_msgtype = -1; -static int hf_rpc_version = -1; -static int hf_rpc_version_min = -1; -static int hf_rpc_version_max = -1; -static int hf_rpc_program = -1; -static int hf_rpc_programversion = -1; -static int hf_rpc_programversion_min = -1; -static int hf_rpc_programversion_max = -1; -static int hf_rpc_procedure = -1; -static int hf_rpc_auth_flavor = -1; -static int hf_rpc_auth_length = -1; -static int hf_rpc_auth_machinename = -1; -static int hf_rpc_auth_stamp = -1; -static int hf_rpc_auth_lk_owner = -1; -static int hf_rpc_auth_pid = -1; -static int hf_rpc_auth_uid = -1; -static int hf_rpc_auth_gid = -1; -static int hf_rpc_auth_flags = -1; -static int hf_rpc_auth_ctime = -1; -static int hf_rpc_authgss_v = -1; -static int hf_rpc_authgss_proc = -1; -static int hf_rpc_authgss_seq = -1; -static int hf_rpc_authgss_svc = -1; -static int hf_rpc_authgss_ctx = -1; -static int hf_rpc_authgss_ctx_create_frame = -1; -static int hf_rpc_authgss_ctx_destroy_frame = -1; -static int hf_rpc_authgss_ctx_len = -1; -static int hf_rpc_authgss_major = -1; -static int hf_rpc_authgss_minor = -1; -static int hf_rpc_authgss_window = -1; -static int hf_rpc_authgss_token_length = -1; -static int hf_rpc_authgss_data_length = -1; -static int hf_rpc_authgss_data = -1; -static int hf_rpc_authgss_token = -1; -static int hf_rpc_authgss_checksum = -1; -static int hf_rpc_authgssapi_v = -1; -static int hf_rpc_authgssapi_msg = -1; -static int hf_rpc_authgssapi_msgv = -1; -static int hf_rpc_authgssapi_handle = -1; -static int hf_rpc_authgssapi_isn = -1; -static int hf_rpc_authdes_namekind = -1; -static int hf_rpc_authdes_netname = -1; -static int hf_rpc_authdes_convkey = -1; -static int hf_rpc_authdes_window = -1; -static int hf_rpc_authdes_nickname = -1; -static int hf_rpc_authdes_timestamp = -1; -static int hf_rpc_authdes_windowverf = -1; -static int hf_rpc_authdes_timeverf = -1; -static int hf_rpc_state_accept = -1; -static int hf_rpc_state_reply = -1; -static int hf_rpc_state_reject = -1; -static int hf_rpc_state_auth = -1; -static int hf_rpc_dup = -1; -static int hf_rpc_call_dup = -1; -static int hf_rpc_reply_dup = -1; -static int hf_rpc_value_follows = -1; -static int hf_rpc_array_len = -1; -static int hf_rpc_time = -1; -static int hf_rpc_fragments = -1; -static int hf_rpc_fragment = -1; -static int hf_rpc_fragment_overlap = -1; -static int hf_rpc_fragment_overlap_conflict = -1; -static int hf_rpc_fragment_multiple_tails = -1; -static int hf_rpc_fragment_too_long_fragment = -1; -static int hf_rpc_fragment_error = -1; -static int hf_rpc_fragment_count = -1; -static int hf_rpc_reassembled_length = -1; -static int hf_rpc_unknown_body = -1; +static int proto_rpc; +static int hf_rpc_reqframe; +static int hf_rpc_repframe; +static int hf_rpc_lastfrag; +static int hf_rpc_fraglen; +static int hf_rpc_xid; +static int hf_rpc_msgtype; +static int hf_rpc_version; +static int hf_rpc_version_min; +static int hf_rpc_version_max; +static int hf_rpc_program; +static int hf_rpc_programversion; +static int hf_rpc_programversion_min; +static int hf_rpc_programversion_max; +static int hf_rpc_procedure; +static int hf_rpc_auth_flavor; +static int hf_rpc_auth_length; +static int hf_rpc_auth_machinename; +static int hf_rpc_auth_stamp; +static int hf_rpc_auth_lk_owner; +static int hf_rpc_auth_pid; +static int hf_rpc_auth_uid; +static int hf_rpc_auth_gid; +static int hf_rpc_auth_flags; +static int hf_rpc_auth_ctime; +static int hf_rpc_authgss_v; +static int hf_rpc_authgss_proc; +static int hf_rpc_authgss_seq; +static int hf_rpc_authgss_svc; +static int hf_rpc_authgss_ctx; +static int hf_rpc_authgss_ctx_create_frame; +static int hf_rpc_authgss_ctx_destroy_frame; +static int hf_rpc_authgss_ctx_len; +static int hf_rpc_authgss_major; +static int hf_rpc_authgss_minor; +static int hf_rpc_authgss_window; +static int hf_rpc_authgss_token_length; +static int hf_rpc_authgss_data_length; +static int hf_rpc_authgss_data; +static int hf_rpc_authgss_token; +static int hf_rpc_authgss_checksum; +static int hf_rpc_authgssapi_v; +static int hf_rpc_authgssapi_msg; +static int hf_rpc_authgssapi_msgv; +static int hf_rpc_authgssapi_handle; +static int hf_rpc_authgssapi_isn; +static int hf_rpc_authdes_namekind; +static int hf_rpc_authdes_netname; +static int hf_rpc_authdes_convkey; +static int hf_rpc_authdes_window; +static int hf_rpc_authdes_nickname; +static int hf_rpc_authdes_timestamp; +static int hf_rpc_authdes_windowverf; +static int hf_rpc_authdes_timeverf; +static int hf_rpc_state_accept; +static int hf_rpc_state_reply; +static int hf_rpc_state_reject; +static int hf_rpc_state_auth; +static int hf_rpc_dup; +static int hf_rpc_call_dup; +static int hf_rpc_reply_dup; +static int hf_rpc_value_follows; +static int hf_rpc_array_len; +static int hf_rpc_time; +static int hf_rpc_fragments; +static int hf_rpc_fragment; +static int hf_rpc_fragment_overlap; +static int hf_rpc_fragment_overlap_conflict; +static int hf_rpc_fragment_multiple_tails; +static int hf_rpc_fragment_too_long_fragment; +static int hf_rpc_fragment_error; +static int hf_rpc_fragment_count; +static int hf_rpc_reassembled_length; +static int hf_rpc_unknown_body; /* Generated from convert_proto_tree_add_text.pl */ -static int hf_rpc_opaque_data = -1; -static int hf_rpc_no_values = -1; -static int hf_rpc_continuation_data = -1; -static int hf_rpc_fill_bytes = -1; -static int hf_rpc_argument_length = -1; -static int hf_rpc_fragment_data = -1; -static int hf_rpc_opaque_length = -1; - -static gint ett_rpc = -1; -static gint ett_rpc_unknown_program = -1; -static gint ett_rpc_fragments = -1; -static gint ett_rpc_fragment = -1; -static gint ett_rpc_fraghdr = -1; -static gint ett_rpc_string = -1; -static gint ett_rpc_cred = -1; -static gint ett_rpc_verf = -1; -static gint ett_rpc_gids = -1; -static gint ett_rpc_gss_token = -1; -static gint ett_rpc_gss_data = -1; -static gint ett_rpc_array = -1; -static gint ett_rpc_authgssapi_msg = -1; -static gint ett_gss_context = -1; -static gint ett_gss_wrap = -1; - -static expert_field ei_rpc_cannot_dissect = EI_INIT; -static expert_field ei_rpc_segment_needed = EI_INIT; +static int hf_rpc_opaque_data; +static int hf_rpc_no_values; +static int hf_rpc_continuation_data; +static int hf_rpc_fill_bytes; +static int hf_rpc_argument_length; +static int hf_rpc_fragment_data; +static int hf_rpc_opaque_length; + +static gint ett_rpc; +static gint ett_rpc_unknown_program; +static gint ett_rpc_fragments; +static gint ett_rpc_fragment; +static gint ett_rpc_fraghdr; +static gint ett_rpc_string; +static gint ett_rpc_cred; +static gint ett_rpc_verf; +static gint ett_rpc_gids; +static gint ett_rpc_gss_token; +static gint ett_rpc_gss_data; +static gint ett_rpc_array; +static gint ett_rpc_authgssapi_msg; +static gint ett_gss_context; +static gint ett_gss_wrap; + +static expert_field ei_rpc_cannot_dissect; +static expert_field ei_rpc_segment_needed; static dissector_handle_t rpc_tcp_handle; static dissector_handle_t rpc_handle; static dissector_handle_t gssapi_handle; static dissector_handle_t data_handle; +static dissector_handle_t rpc_tls_handle; static dissector_table_t subdissector_call_table; static dissector_table_t subdissector_reply_table; @@ -306,7 +313,7 @@ static const fragment_items rpc_frag_items = { GHashTable *rpc_progs = NULL; typedef gboolean (*rec_dissector_t)(tvbuff_t *, packet_info *, proto_tree *, - tvbuff_t *, fragment_head *, gboolean, guint32, gboolean, gboolean); + tvbuff_t *, fragment_head *, int, guint32, gboolean, gboolean); static void show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree, guint32 rpc_rm, fragment_head *ipfd_head, packet_info *pinfo); @@ -356,7 +363,7 @@ rpcstat_init(struct register_srt* srt, GArray* srt_array) hf_index=rpc_prog_hf(tap_data->program, tap_data->version); hfi=proto_registrar_get_nth(hf_index); - g_snprintf(table_name, sizeof(table_name), "%s Version %u", tap_data->prog, tap_data->version); + snprintf(table_name, sizeof(table_name), "%s Version %u", tap_data->prog, tap_data->version); rpc_srt_table = init_srt_table(table_name, NULL, srt_array, tap_data->num_procedures, NULL, hfi->abbrev, tap_data); for (i = 0; i < rpc_srt_table->num_procs; i++) { @@ -367,7 +374,7 @@ rpcstat_init(struct register_srt* srt, GArray* srt_array) } static tap_packet_status -rpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv) +rpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv, tap_flags_t flags _U_) { srt_stat_table *rpc_srt_table; srt_data_t *data = (srt_data_t *)pss; @@ -422,7 +429,7 @@ rpcstat_param(register_srt_t* srt, const char* opt_arg, char** err) tap_data->num_procedures = rpc_max_proc+1; if (rpc_min_proc == -1) { - *err = g_strdup_printf("Program:%u version:%u isn't supported", rpc_program, rpc_version); + *err = ws_strdup_printf("Program:%u version:%u isn't supported", rpc_program, rpc_version); } } else @@ -477,6 +484,7 @@ rpc_proc_name_internal(wmem_allocator_t *allocator, guint32 prog, guint32 vers, key.proc = proc; /* Look at both tables for possible procedure names */ + /* XXX - dissector name, or protocol name? */ if ((dissect_function = dissector_get_custom_table_handle(subdissector_call_table, &key)) != NULL) procname = wmem_strdup(allocator, dissector_handle_get_dissector_name(dissect_function)); else if ((dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key)) != NULL) @@ -713,7 +721,8 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, /* int string_item_offset; */ char *string_buffer = NULL; - const char *string_buffer_print = NULL; + uint8_t *bytes_buffer; + const char *formatted_text = NULL; if (fixed_length) { string_length = length; @@ -779,9 +788,9 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, if (string_data) { string_buffer = tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset, string_length_copy, ENC_ASCII); } else { - string_buffer = (char *)tvb_memcpy(tvb, wmem_alloc(wmem_packet_scope(), string_length_copy+1), data_offset, string_length_copy); + bytes_buffer = tvb_memcpy(tvb, wmem_alloc(wmem_packet_scope(), string_length_copy), data_offset, string_length_copy); } - string_buffer[string_length_copy] = '\0'; + /* calculate a nice printable string */ if (string_length) { if (string_length != string_length_copy) { @@ -790,25 +799,25 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, formatted = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer)); /* copy over the data and append <TRUNCATED> */ - string_buffer_print=wmem_strdup_printf(wmem_packet_scope(), "%s%s", formatted, RPC_STRING_TRUNCATED); + formatted_text=wmem_strdup_printf(wmem_packet_scope(), "%s%s", formatted, RPC_STRING_TRUNCATED); } else { - string_buffer_print=RPC_STRING_DATA RPC_STRING_TRUNCATED; + formatted_text=RPC_STRING_DATA RPC_STRING_TRUNCATED; } } else { if (string_data) { - string_buffer_print = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer)); + formatted_text = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer)); } else { - string_buffer_print=RPC_STRING_DATA; + formatted_text=RPC_STRING_DATA; } } } else { - string_buffer_print=RPC_STRING_EMPTY; + formatted_text=RPC_STRING_EMPTY; } /* string_item_offset = offset; */ string_tree = proto_tree_add_subtree_format(tree, tvb,offset, -1, ett_rpc_string, &string_item, "%s: %s", proto_registrar_get_name(hfindex), - string_buffer_print); + formatted_text); if (!fixed_length) { proto_tree_add_uint(string_tree, hf_rpc_opaque_length, tvb,offset, 4, string_length); @@ -820,12 +829,12 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, proto_tree_add_string_format(string_tree, hfindex, tvb, offset, string_length_copy, string_buffer, - "contents: %s", string_buffer_print); + "contents: %s", formatted_text); } else { proto_tree_add_bytes_format(string_tree, hfindex, tvb, offset, string_length_copy, - string_buffer, - "contents: %s", string_buffer_print); + bytes_buffer, + "contents: %s", formatted_text); } } @@ -846,7 +855,7 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, proto_item_set_end(string_item, tvb, offset); if (string_buffer_ret != NULL) - *string_buffer_ret = string_buffer_print; + *string_buffer_ret = formatted_text; /* * If the data was truncated, throw the appropriate exception, @@ -1227,11 +1236,11 @@ dissect_rpc_authglusterfs_v3_cred(tvbuff_t* tvb, proto_tree* tree, int offset) offset = dissect_rpc_uint32(tvb, tree, hf_rpc_auth_gid, offset); offset = dissect_rpc_uint32(tvb, tree, hf_rpc_auth_flags, offset); timestamp.secs = tvb_get_ntohl(tvb, offset); - timestamp.nsecs = tvb_get_ntohl(tvb, offset + 4); + timestamp.nsecs = (int)tvb_get_ntohi64(tvb, offset + 4); if (tree) proto_tree_add_time(tree, hf_rpc_auth_ctime, tvb, - offset, 8, ×tamp); - offset += 8; + offset, 12, ×tamp); + offset += 12; offset = dissect_rpc_authunix_groups(tvb, tree, offset); @@ -1687,18 +1696,18 @@ get_conversation_for_call(packet_info *pinfo) * if you use NO_ADDR_B. */ conversation = find_conversation(pinfo->num, - &pinfo->src, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), + &pinfo->src, &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->destport, 0, NO_ADDR_B|NO_PORT_B); } if (conversation == NULL) { if (pinfo->ptype == PT_TCP || pinfo->ptype == PT_IBQP || pinfo->ptype == PT_IWARP_MPA) { conversation = conversation_new(pinfo->num, - &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), + &pinfo->src, &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport, pinfo->destport, 0); } else { conversation = conversation_new(pinfo->num, - &pinfo->src, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), + &pinfo->src, &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->destport, 0, NO_ADDR2|NO_PORT2); } } @@ -1739,7 +1748,7 @@ find_conversation_for_reply(packet_info *pinfo) * if you use NO_ADDR_B. */ conversation = find_conversation(pinfo->num, - &pinfo->dst, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), + &pinfo->dst, &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport, 0, NO_ADDR_B|NO_PORT_B); } return conversation; @@ -1754,22 +1763,22 @@ new_conversation_for_reply(packet_info *pinfo) { case PT_TCP: conversation = conversation_new(pinfo->num, - &pinfo->src, &pinfo->dst, ENDPOINT_TCP, + &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0); break; case PT_IBQP: conversation = conversation_new(pinfo->num, - &pinfo->src, &pinfo->dst, ENDPOINT_IBQP, + &pinfo->src, &pinfo->dst, CONVERSATION_IBQP, pinfo->srcport, pinfo->destport, 0); break; case PT_IWARP_MPA: conversation = conversation_new(pinfo->num, - &pinfo->src, &pinfo->dst, ENDPOINT_IWARP_MPA, + &pinfo->src, &pinfo->dst, CONVERSATION_IWARP_MPA, pinfo->srcport, pinfo->destport, 0); break; default: conversation = conversation_new(pinfo->num, - &pinfo->dst, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype), + &pinfo->dst, &null_address, conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport, 0, NO_ADDR2|NO_PORT2); break; } @@ -1937,6 +1946,7 @@ dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key); if (dissect_function != NULL) { + /* XXX - dissector name, or protocol name? */ procname = dissector_handle_get_dissector_name(dissect_function); } else { @@ -2203,7 +2213,7 @@ looks_like_rpc_reply(tvbuff_t *tvb, packet_info *pinfo, int offset) static gboolean dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - tvbuff_t *frag_tvb, fragment_head *ipfd_head, gboolean is_tcp, + tvbuff_t *frag_tvb, fragment_head *ipfd_head, int tp_type, guint32 rpc_rm, gboolean first_pdu, gboolean can_defragment) { guint32 msg_type; @@ -2216,6 +2226,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned int prog = 0; unsigned int vers = 0; unsigned int proc = 0; + unsigned int cred_flavor = 0; flavor_t flavor = FLAVOR_UNKNOWN; unsigned int gss_proc = 0; unsigned int gss_svc = 0; @@ -2242,7 +2253,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *pitem = NULL; proto_tree *ptree = NULL; - int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0; + int offset = (tp_type != RPC_UDP && tvb == frag_tvb) ? 4 : 0; rpc_proc_info_key key; conversation_t* conversation; @@ -2290,7 +2301,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, return FALSE; } - if (is_tcp) { + if (tp_type != RPC_UDP) { /* * This is RPC-over-TCP; check if this is the last * fragment. @@ -2314,7 +2325,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ENC_NA); rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc); - if (is_tcp) { + if (tp_type != RPC_UDP) { show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm, ipfd_head, pinfo); } @@ -2371,6 +2382,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, key.proc = proc; if ((dissect_function = dissector_get_custom_table_handle(subdissector_call_table, &key)) != NULL) { + /* XXX - dissector name, or protocol name? */ procname = dissector_handle_get_dissector_name(dissect_function); } else { @@ -2383,7 +2395,8 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /* Check for RPCSEC_GSS and AUTH_GSSAPI */ if (tvb_bytes_exist(tvb, offset+16, 4)) { - switch (tvb_get_ntohl(tvb, offset+16)) { + cred_flavor = tvb_get_ntohl(tvb, offset+16); + switch (cred_flavor) { case RPCSEC_GSS: /* @@ -2472,8 +2485,10 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /* Make the dissector for this conversation the non-heuristic RPC dissector. */ - conversation_set_dissector(conversation, - (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle); + if (tp_type != RPC_TLS && cred_flavor != AUTH_TLS) { + conversation_set_dissector(conversation, + (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle); + } /* look up the request */ rpc_call = (rpc_call_info_value *)wmem_tree_lookup32(rpc_conv_info->xids, xid); @@ -2531,16 +2546,11 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, offset += 16; offset = dissect_rpc_cred(tvb, rpc_tree, offset, pinfo, rpc_conv_info); + offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo); + /* pass rpc_info to subdissectors */ rpc_call->request=TRUE; - if (gss_proc == RPCSEC_GSS_DESTROY) { - /* there is no verifier for GSS destroy packets */ - break; - } - - offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo); - /* go to the next dissector */ break; /* end of RPC call */ @@ -2557,6 +2567,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key); if (dissect_function != NULL) { + /* XXX - dissector name, or protocol name? */ procname = dissector_handle_get_dissector_name(dissect_function); } else { @@ -3014,7 +3025,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, tvb_new_subset_remaining(tvb, offset), pinfo, ptree); } - /* XXX this should really loop over all fhandles registred for the frame */ + /* XXX this should really loop over all fhandles registered for the frame */ if(nfs_fhandle_reqrep_matching){ switch (msg_type) { case RPC_CALL: @@ -3038,14 +3049,14 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, static gboolean dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0, + return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, RPC_UDP, 0, TRUE, FALSE); } static int dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0, + if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, RPC_UDP, 0, TRUE, FALSE)) { if (tvb_reported_length(tvb) != 0) dissect_rpc_continuation(tvb, pinfo, tree); @@ -3177,8 +3188,8 @@ show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree, static gboolean call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo, proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector, - fragment_head *ipfd_head, guint32 rpc_rm, gboolean first_pdu, - gboolean can_defragment) + fragment_head *ipfd_head, int tp_type, guint32 rpc_rm, + gboolean first_pdu, gboolean can_defragment) { const char *saved_proto; volatile gboolean rpc_succeeded; @@ -3187,7 +3198,7 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo, rpc_succeeded = FALSE; TRY { rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree, - frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu, + frag_tvb, ipfd_head, tp_type, rpc_rm, first_pdu, can_defragment); } CATCH_NONFATAL_ERRORS { @@ -3216,13 +3227,14 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo, } static int -dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, rec_dissector_t dissector, gboolean is_heur, - int proto, int ett, gboolean first_pdu, struct tcpinfo *tcpinfo) +dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, + rec_dissector_t dissector, gboolean is_heur, int proto, int ett, + gboolean first_pdu, struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo) { guint32 seq; guint32 rpc_rm; guint32 len; + int tp_type; gint tvb_len, tvb_reported_len; tvbuff_t *frag_tvb; conversation_t *conversation = NULL; @@ -3233,11 +3245,12 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, fragment_head *ipfd_head; tvbuff_t *rec_tvb; - if (pinfo == NULL || tcpinfo == NULL) { + if (pinfo == NULL || (tcpinfo == NULL && tlsinfo == NULL)) { return 0; } - seq = tcpinfo->seq + offset; + seq = (tcpinfo != NULL ? tcpinfo->seq : tlsinfo->seq) + offset; + tp_type = (tcpinfo != NULL ? RPC_TCP : RPC_TLS); /* * Get the record mark. @@ -3322,8 +3335,9 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, dissector for it the non-heuristic RPC dissector for RPC-over-TCP. */ conversation = find_or_create_conversation(pinfo); - conversation_set_dissector(conversation, - rpc_tcp_handle); + if (tcpinfo != NULL) { + conversation_set_dissector(conversation, rpc_tcp_handle); + } } /* OK, we think it is RPC. Can we desegment? */ @@ -3376,8 +3390,8 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo, - tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu, - can_defragment); + tree, frag_tvb, dissector, ipfd_head, tp_type, rpc_rm, + first_pdu, can_defragment); pinfo->fragmented = save_fragmented; if (!rpc_succeeded) return 0; /* not RPC */ @@ -3424,7 +3438,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, * an exception. */ if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb, - NULL, TRUE, rpc_rm, first_pdu, can_defragment)) + NULL, tp_type, rpc_rm, first_pdu, can_defragment)) return 0; /* not valid */ /* @@ -3609,8 +3623,8 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, * dissector. */ if (!call_message_dissector(tvb, rec_tvb, pinfo, tree, - frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu, - can_defragment)) + frag_tvb, dissector, ipfd_head, tp_type, rpc_rm, + first_pdu, can_defragment)) return 0; /* not RPC */ return len; } /* end of dissect_rpc_fragment() */ @@ -3766,8 +3780,8 @@ find_rpc_over_tcp_reply_start(tvbuff_t *tvb, int offset) static int find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rec_dissector_t dissector, - gboolean is_heur, - int proto, int ett, struct tcpinfo* tcpinfo) + gboolean is_heur, int proto, int ett, + struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo) { int offReply; @@ -3782,7 +3796,7 @@ find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, len = dissect_rpc_fragment(tvb, offReply, pinfo, tree, dissector, is_heur, proto, ett, - TRUE /* force first-pdu state */, tcpinfo); + TRUE /* force first-pdu state */, tcpinfo, tlsinfo); /* misses are reported as-is */ if (len == 0) @@ -3813,7 +3827,7 @@ find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, */ static gboolean dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - gboolean is_heur, struct tcpinfo* tcpinfo) + gboolean is_heur, struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo) { int offset = 0; gboolean saw_rpc = FALSE; @@ -3826,7 +3840,7 @@ dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, */ len = dissect_rpc_fragment(tvb, offset, pinfo, tree, dissect_rpc_message, is_heur, proto_rpc, ett_rpc, - first_pdu, tcpinfo); + first_pdu, tcpinfo, tlsinfo); if ((len == 0) && first_pdu && rpc_find_fragment_start) { /* @@ -3835,7 +3849,7 @@ dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, */ len = find_and_dissect_rpc_fragment(tvb, offset, pinfo, tree, dissect_rpc_message, is_heur, proto_rpc, ett_rpc, - tcpinfo); + tcpinfo, tlsinfo); } first_pdu = FALSE; @@ -3893,7 +3907,7 @@ dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * { struct tcpinfo* tcpinfo = (struct tcpinfo *)data; - return dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, tcpinfo); + return dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, tcpinfo, NULL); } static int @@ -3901,12 +3915,42 @@ dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { struct tcpinfo* tcpinfo = (struct tcpinfo *)data; - if (!dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, tcpinfo)) + if (!dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, tcpinfo, NULL)) dissect_rpc_continuation(tvb, pinfo, tree); return tvb_reported_length(tvb); } +static gboolean +dissect_rpc_tls_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + struct tlsinfo *tlsinfo = (struct tlsinfo *)data; + + if (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, NULL, tlsinfo)) { + if (tlsinfo != NULL) { + *(tlsinfo->app_handle) = rpc_tls_handle; + } + return TRUE; + } + return FALSE; +} + +static int +dissect_rpc_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + struct tlsinfo* tlsinfo = (struct tlsinfo *)data; + + col_set_writable(pinfo->cinfo, COL_PROTOCOL, TRUE); + if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, NULL, tlsinfo)) { + col_set_writable(pinfo->cinfo, COL_PROTOCOL, FALSE); + col_set_writable(pinfo->cinfo, COL_INFO, FALSE); + } else { + dissect_rpc_continuation(tvb, pinfo, tree); + } + + return tvb_reported_length(tvb); +} + /* Tap statistics */ typedef enum { @@ -3948,7 +3992,7 @@ static void rpc_prog_stat_init(stat_tap_table_ui* new_stat) } static tap_packet_status -rpc_prog_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rciv_ptr) +rpc_prog_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rciv_ptr, tap_flags_t flags _U_) { stat_data_t* stat_data = (stat_data_t*)tapdata; const rpc_call_info_value *ri = (const rpc_call_info_value *)rciv_ptr; @@ -4342,7 +4386,7 @@ proto_register_rpc(void) }; static stat_tap_table_ui rpc_prog_stat_table = { - REGISTER_STAT_GROUP_UNSORTED, + REGISTER_PACKET_STAT_GROUP_UNSORTED, "ONC-RPC Programs", "rpc", "rpc,programs", @@ -4359,8 +4403,8 @@ proto_register_rpc(void) proto_rpc = proto_register_protocol("Remote Procedure Call", "RPC", "rpc"); - subdissector_call_table = register_custom_dissector_table("rpc.call", "RPC Call Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal); - subdissector_reply_table = register_custom_dissector_table("rpc.reply", "RPC Reply Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal); + subdissector_call_table = register_custom_dissector_table("rpc.call", "RPC Call Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal, g_free); + subdissector_reply_table = register_custom_dissector_table("rpc.reply", "RPC Reply Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal, g_free); /* this is a dummy dissector for all those unknown rpc programs */ proto_register_field_array(proto_rpc, hf, array_length(hf)); @@ -4401,6 +4445,7 @@ proto_register_rpc(void) rpc_handle = register_dissector("rpc", dissect_rpc, proto_rpc); rpc_tcp_handle = register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc); + rpc_tls_handle = register_dissector("rpc-with-tls", dissect_rpc_tls, proto_rpc); rpc_tap = register_tap("rpc"); register_srt_table(proto_rpc, NULL, 1, rpcstat_packet, rpcstat_init, rpcstat_param); @@ -4441,6 +4486,7 @@ proto_reg_handoff_rpc(void) heur_dissector_add("tcp", dissect_rpc_tcp_heur, "RPC over TCP", "rpc_tcp", proto_rpc, HEURISTIC_ENABLE); heur_dissector_add("udp", dissect_rpc_heur, "RPC over UDP", "rpc_udp", proto_rpc, HEURISTIC_ENABLE); + heur_dissector_add("tls", dissect_rpc_tls_heur, "RPC with TLS", "rpc_tls", proto_rpc, HEURISTIC_ENABLE); gssapi_handle = find_dissector_add_dependency("gssapi", proto_rpc); spnego_krb5_wrap_handle = find_dissector_add_dependency("spnego-krb5-wrap", proto_rpc); data_handle = find_dissector("data"); |