Ethereal-dev: [Ethereal-dev] [PATCH] decouple dcerpc authentication from packet-dcerpc.c
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Tim Potter <tpot@xxxxxxxxx>
Date: Tue, 15 Jul 2003 15:21:49 +1000
This is something I've been wanting to do for a while. The attached patch decouples dissection of DCERPC authentication verifiers and payloads from packet-dcerpc.c by allowing dissector modules to register a table of handler functions for dissecting the verifiers in bind, bind ack, auth3, request and response PDUs. The patch modifies the NTLMSSP dissector to use the new interface. Also it adds a small bit of extra functionality which I don't think ethereal supported before - NTLMSSP signing of DCERPC. Previously we only supported NTLMSSP encryption (sign&seal). Caveats: - There are still a few issues to work out with the value_string for the DCE_C_RPC_AUTHN_PROTOCOL_* constants. - SPNEGO and secure channel dissections are broken but should be easy to convert to the new interface. Again I'm putting this out there for anyone (probably Guy (-:) to comment on. I'm not 100% happy with the naming of some of the members of the subdissector_fns structure but that's pretty easy to fix. Tim.
Index: packet-dcerpc.c =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.c,v retrieving revision 1.133 diff -u -r1.133 packet-dcerpc.c --- packet-dcerpc.c 26 Jun 2003 04:30:31 -0000 1.133 +++ packet-dcerpc.c 15 Jul 2003 05:12:50 -0000 @@ -1,6 +1,7 @@ /* packet-dcerpc.c * Routines for DCERPC packet disassembly * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx> + * Copyright 2003, Tim Potter <tpot@xxxxxxxxx> * * $Id: packet-dcerpc.c,v 1.133 2003/06/26 04:30:31 tpot Exp $ * @@ -38,7 +39,6 @@ #include "reassemble.h" #include "tap.h" #include "packet-frame.h" -#include "packet-ntlmssp.h" #include "packet-dcerpc-nt.h" static int dcerpc_tap = -1; @@ -98,7 +98,6 @@ #define DCE_C_RPC_AUTHN_PROTOCOL_NONE 0 #define DCE_C_RPC_AUTHN_PROTOCOL_KRB5 1 #define DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO 9 -#define DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP 10 #define DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN 68 static const value_string authn_protocol_vals[] = { @@ -117,8 +116,6 @@ #define DCE_C_AUTHN_LEVEL_CONNECT 2 #define DCE_C_AUTHN_LEVEL_CALL 3 #define DCE_C_AUTHN_LEVEL_PKT 4 -#define DCE_C_AUTHN_LEVEL_PKT_INTEGRITY 5 -#define DCE_C_AUTHN_LEVEL_PKT_PRIVACY 6 static const value_string authn_level_vals[] = { { DCE_C_AUTHN_LEVEL_NONE, "None" }, @@ -416,8 +413,6 @@ static gint ett_dcerpc_krb5_auth_verf = -1; static gint ett_sec_chan = -1; -static dissector_handle_t ntlmssp_handle, ntlmssp_verf_handle, - ntlmssp_enc_payload_handle; static dissector_handle_t gssapi_handle, gssapi_verf_handle; static const fragment_items dcerpc_frag_items = { @@ -464,6 +459,132 @@ } /* + * Authentication subdissectors. Used to dissect authentication blobs in + * DCERPC binds, requests and responses. + */ + +typedef struct _dcerpc_auth_subdissector { + guint8 auth_level; + guint8 auth_type; + dcerpc_auth_subdissector_fns auth_fns; +} dcerpc_auth_subdissector; + +static GSList *dcerpc_auth_subdissector_list; + +static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns( + guint8 auth_level, guint8 auth_type) +{ + gpointer data; + int i; + + for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) { + dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data; + + if (asd->auth_level == auth_level && + asd->auth_type == auth_type) + return &asd->auth_fns; + } + + return NULL; +} + +void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type, + dcerpc_auth_subdissector_fns *fns) +{ + dcerpc_auth_subdissector *d; + + if (get_auth_subdissector_fns(auth_level, auth_type)) + return; + + d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector)); + + d->auth_level = auth_level; + d->auth_type = auth_type; + memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns)); + + dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d); +} + +/* Hand off verifier data to a registered dissector */ + +static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo, + proto_tree *tree, + dcerpc_auth_subdissector_fns *auth_fns, + e_dce_cn_common_hdr_t *hdr, + dcerpc_auth_info *auth_info) +{ + dcerpc_dissect_fnct_t *fn = NULL; + + switch (hdr->ptype) { + case PDU_BIND: + fn = auth_fns->bind_fn; + break; + case PDU_BIND_ACK: + fn = auth_fns->bind_ack_fn; + break; + case PDU_AUTH3: + fn = auth_fns->auth3_fn; + break; + case PDU_REQ: + fn = auth_fns->req_verf_fn; + break; + case PDU_RESP: + fn = auth_fns->resp_verf_fn; + break; + + /* Don't know how to handle authentication data in this + pdu type. */ + + default: + g_warning("attempt to dissect %s pdu authentication data", + val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)")); + break; + } + + if (fn) + fn(auth_tvb, 0, pinfo, tree, hdr->drep); + else + proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len, + "%s Auth Credentials", + val_to_str(auth_info->auth_type, + authn_protocol_vals, + "Unknown (%u)")); +} + +/* Hand off payload data to a registered dissector */ + +static void dissect_encrypted_data(tvbuff_t *enc_tvb, packet_info *pinfo, + proto_tree *tree, + dcerpc_auth_subdissector_fns *auth_fns, + guint8 ptype, dcerpc_auth_info *auth_info, + char *drep) +{ + dcerpc_dissect_fnct_t *fn = NULL; + + switch (ptype) { + case PDU_REQ: + fn = auth_fns->req_data_fn; + break; + case PDU_RESP: + fn = auth_fns->resp_data_fn; + break; + default: + g_warning("attempt to dissect %s pdu encrypted data", + val_to_str(ptype, pckt_vals, "Unknown (%u)")); + break; + } + + if (fn) + fn(enc_tvb, 0, pinfo, tree, drep); + else + proto_tree_add_text(tree, enc_tvb, 0, tvb_length(enc_tvb), + "%s Auth Credentials", + val_to_str(auth_info->auth_type, + authn_protocol_vals, + "Unknown (%u)")); +} + +/* * Subdissectors */ @@ -1692,66 +1813,46 @@ */ if (auth_info != NULL && auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) { - length = tvb_length_remaining (tvb, offset); - if (length > 0) { - proto_tree_add_text(sub_tree, tvb, offset, length, - "Encrypted stub data (%d byte%s)", - length, plurality(length, "", "s")); + length = tvb_length_remaining (tvb, offset); - switch (auth_info->auth_type) { - - case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: { - /* NTLMSSP */ - tvbuff_t *ntlmssp_tvb; - ntlmssp_tvb = tvb_new_subset(tvb, offset, length, length); - pinfo->decrypted_data=NULL; - - call_dissector(ntlmssp_enc_payload_handle, ntlmssp_tvb, pinfo, - sub_tree); - - if(pinfo->decrypted_data){ - ntlmssp_decrypted_info_t *ndi=pinfo->decrypted_data; - - - sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp; - if (sub_dissect) { - saved_proto = pinfo->current_proto; - saved_private_data = pinfo->private_data; - pinfo->current_proto = sub_proto->name; - pinfo->private_data = (void *)info; - - init_ndr_pointer_list(pinfo); - - /* - * Catch ReportedBoundsError, as that could - * be due to the decryption being bad, - * and doesn't mean that the tvbuff we were - * handed has a malformed packet. - */ - TRY { - offset = sub_dissect (ndi->decr_tvb, 0, pinfo, ndi->decr_tree, drep); - } CATCH(BoundsError) { - RETHROW; - } CATCH(ReportedBoundsError) { - show_reported_bounds_error(tvb, pinfo, tree); - } ENDTRY; - - pinfo->current_proto = saved_proto; - pinfo->private_data = saved_private_data; - } - } - break; - } + if (length > 0) { + dcerpc_auth_subdissector_fns *auth_fns; + decrypted_info_t *dit; + tvbuff_t *enc_tvb; + + enc_tvb = tvb_new_subset(tvb, offset, length, length); + + proto_tree_add_text(sub_tree, enc_tvb, 0, length, + "Encrypted stub data (%d byte%s)", + length, plurality(length, "", "s")); + + pinfo->decrypted_data = NULL; + + if ((auth_fns = get_auth_subdissector_fns( + auth_info->auth_level, auth_info->auth_type))) + dissect_encrypted_data( + enc_tvb, pinfo, sub_tree, auth_fns, + info->request ? PDU_REQ : PDU_RESP, + auth_info, drep); + + /* No decrypted data so don't try and call a subdissector */ + + if (!pinfo->decrypted_data) + goto done; + + dit = (decrypted_info_t *)pinfo->decrypted_data; + tvb = dit->decr_tvb; + sub_tree = dit->decr_tree; } - } - } else { - sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp; - if (sub_dissect) { + } + + sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp; + if (sub_dissect) { saved_proto = pinfo->current_proto; saved_private_data = pinfo->private_data; pinfo->current_proto = sub_proto->name; pinfo->private_data = (void *)info; - + init_ndr_pointer_list(pinfo); /* * Catch ReportedBoundsError, so that even if the stub @@ -1786,7 +1887,8 @@ plurality(length, "", "s")); } } - } + + done: tap_queue_packet(dcerpc_tap, pinfo, info); return 0; } @@ -1799,63 +1901,21 @@ int auth_offset; if (auth_info->auth_size != 0) { - auth_offset = hdr->frag_len - hdr->auth_len; - switch (auth_info->auth_type) { - - case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: { - /* NTLMSSP */ - tvbuff_t *ntlmssp_tvb; - - ntlmssp_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len, - hdr->auth_len); - - call_dissector(ntlmssp_verf_handle, ntlmssp_tvb, pinfo, - dcerpc_tree); - - break; - } - - case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: { - /* SPNEGO (rfc2478) */ - tvbuff_t *gssapi_tvb; - - gssapi_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len, - hdr->auth_len); - - call_dissector(gssapi_verf_handle, gssapi_tvb, pinfo, dcerpc_tree); - - break; - } - - case DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN: { - proto_item *vf = NULL; - proto_tree *volatile sec_chan_tree = NULL; - /* - * Create a new tree, and split into 4 components ... - */ - vf = proto_tree_add_item(dcerpc_tree, hf_dcerpc_sec_chan, tvb, - auth_offset, -1, FALSE); - sec_chan_tree = proto_item_add_subtree(vf, ett_sec_chan); - - proto_tree_add_item(sec_chan_tree, hf_dcerpc_sec_chan_sig, tvb, - auth_offset, 8, FALSE); - - proto_tree_add_item(sec_chan_tree, hf_dcerpc_sec_chan_unk, tvb, - auth_offset + 8, 8, FALSE); + dcerpc_auth_subdissector_fns *auth_fns; + tvbuff_t *auth_tvb; - proto_tree_add_item(sec_chan_tree, hf_dcerpc_sec_chan_seq, tvb, - auth_offset + 16, 8, FALSE); + auth_offset = hdr->frag_len - hdr->auth_len; - proto_tree_add_item(sec_chan_tree, hf_dcerpc_sec_chan_nonce, tvb, - auth_offset + 24, 8, FALSE); + auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len, + hdr->auth_len); - break; - } - - default: - proto_tree_add_text (dcerpc_tree, tvb, auth_offset, hdr->auth_len, - "Auth Verifier"); - } + if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level, + auth_info->auth_type))) + dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns, + hdr, auth_info); + else + proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len, + "Auth Verifier"); } return hdr->auth_len; @@ -1907,49 +1967,19 @@ * Dissect the authentication data. */ if (are_credentials) { - /* - * The authentication data are credentials. - */ - switch (auth_info->auth_type) { - - case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: { - /* NTLMSSP */ - tvbuff_t *ntlmssp_tvb; - - ntlmssp_tvb = tvb_new_subset(tvb, offset, hdr->auth_len, - hdr->auth_len); - - call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, - dcerpc_tree); - - break; - } + tvbuff_t *auth_tvb; + dcerpc_auth_subdissector_fns *auth_fns; - case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: { - /* SPNEGO (rfc2478) */ - tvbuff_t *gssapi_tvb; + auth_tvb = tvb_new_subset( + tvb, offset, hdr->auth_len, hdr->auth_len); - gssapi_tvb = tvb_new_subset(tvb, offset, hdr->auth_len, - hdr->auth_len); - - call_dissector(gssapi_handle, gssapi_tvb, pinfo, dcerpc_tree); - - break; - } - - case DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN: { - - /* TODO: Fill me in when we know what goes here */ - - proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, - "Secure Channel Auth Credentials"); - break; - } - - default: - proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, - "Auth Credentials"); - } + if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level, + auth_info->auth_type))) + dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns, + hdr, auth_info); + else + proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, + "Auth Credentials"); } /* figure out where the auth padding starts */ @@ -4208,7 +4238,7 @@ { &hf_dcerpc_dg_if_ver, { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_dcerpc_krb5_av_prot_level, - { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, "", HFILL }}, + { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, "", HFILL }}, { &hf_dcerpc_krb5_av_key_vers_num, { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_dcerpc_krb5_av_key_auth_verifier, @@ -4356,9 +4386,6 @@ heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc); heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc); heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc); - ntlmssp_handle = find_dissector("ntlmssp"); - ntlmssp_verf_handle = find_dissector("ntlmssp_verf"); - ntlmssp_enc_payload_handle = find_dissector("ntlmssp_encrypted_payload"); gssapi_handle = find_dissector("gssapi"); gssapi_verf_handle = find_dissector("gssapi_verf"); dcerpc_smb_init(proto_dcerpc); Index: packet-dcerpc.h =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.h,v retrieving revision 1.32 diff -u -r1.32 packet-dcerpc.h --- packet-dcerpc.h 26 Jun 2003 04:30:31 -0000 1.32 +++ packet-dcerpc.h 15 Jul 2003 05:12:50 -0000 @@ -1,5 +1,6 @@ /* packet-dcerpc.h * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx> + * Copyright 2003, Tim Potter <tpot@xxxxxxxxx> * * $Id: packet-dcerpc.h,v 1.32 2003/06/26 04:30:31 tpot Exp $ * @@ -279,5 +280,32 @@ int opnum_hf; } dcerpc_uuid_value; +/* Authenticated pipe registration functions and miscellanea */ + +typedef struct _decrpc_auth_subdissector_fns { + dcerpc_dissect_fnct_t *bind_fn; + dcerpc_dissect_fnct_t *bind_ack_fn; + dcerpc_dissect_fnct_t *auth3_fn; + dcerpc_dissect_fnct_t *req_verf_fn; + dcerpc_dissect_fnct_t *resp_verf_fn; + dcerpc_dissect_fnct_t *req_data_fn; + dcerpc_dissect_fnct_t *resp_data_fn; +} dcerpc_auth_subdissector_fns; + +void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type, + dcerpc_auth_subdissector_fns *fns); + +/* Yuck - have to dynamically add these to the authn_protocol_vals + value_string */ + +#define DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP 10 + +#define DCE_C_AUTHN_LEVEL_PKT_INTEGRITY 5 +#define DCE_C_AUTHN_LEVEL_PKT_PRIVACY 6 + +typedef struct _decrypted_info_t { + tvbuff_t *decr_tvb; + proto_tree *decr_tree; +} decrypted_info_t; #endif /* packet-dcerpc.h */ Index: packet-ntlmssp.c =================================================================== RCS file: /cvsroot/ethereal/packet-ntlmssp.c,v retrieving revision 1.40 diff -u -r1.40 packet-ntlmssp.c --- packet-ntlmssp.c 9 May 2003 01:41:28 -0000 1.40 +++ packet-ntlmssp.c 15 Jul 2003 05:12:51 -0000 @@ -1,6 +1,7 @@ /* packet-ntlmssp.c * Routines for NTLM Secure Service Provider * Devin Heitmueller <dheitmueller@xxxxxxxxxxx> + * Copyright 2003, Tim Potter <tpot@xxxxxxxxx> * * $Id: packet-ntlmssp.c,v 1.40 2003/05/09 01:41:28 tpot Exp $ * @@ -38,7 +39,7 @@ #include "crypt-rc4.h" #include "crypt-md4.h" #include "crypt-des.h" -#include "packet-ntlmssp.h" +#include "packet-dcerpc.h" /* Message types */ @@ -1186,7 +1187,7 @@ ntlmssp_info *conv_ntlmssp_info = NULL; ntlmssp_packet_info *packet_ntlmssp_info = NULL; proto_item *it; - static ntlmssp_decrypted_info_t ndi; + static decrypted_info_t ndi; encrypted_block_length = tvb_length_remaining (tvb, offset); @@ -1503,6 +1504,45 @@ dissect_ntlmssp_encrypted_payload, proto_ntlmssp); } +static int dissect_auth_verf(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, char *drep _U_) +{ + dissect_ntlmssp(tvb, pinfo, tree); + return tvb_length_remaining(tvb, offset); +} + +static int dissect_auth_call(tvbuff_t *tvb, int offset _U_, packet_info *pinfo, + proto_tree *tree, char *drep _U_) +{ + return dissect_ntlmssp_verf(tvb, pinfo, tree); +} + +static int dissect_data_call(tvbuff_t *tvb, int offset _U_, packet_info *pinfo, + proto_tree *tree, char *drep _U_) +{ + return dissect_ntlmssp_encrypted_payload(tvb, pinfo, tree); +} + +static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = { + dissect_auth_verf, /* Bind */ + dissect_auth_verf, /* Bind ACK */ + dissect_auth_verf, /* AUTH3 */ + dissect_auth_call, /* Request verifier */ + dissect_auth_call, /* Response verifier */ + NULL, /* Request data */ + NULL /* Response data */ +}; + +static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = { + dissect_auth_verf, /* Bind */ + dissect_auth_verf, /* Bind ACK */ + dissect_auth_verf, /* AUTH3 */ + dissect_auth_call, /* Request verifier */ + dissect_auth_call, /* Response verifier */ + dissect_data_call, /* Request data */ + dissect_data_call /* Response data */ +}; + void proto_reg_handoff_ntlmssp(void) { @@ -1515,4 +1555,14 @@ gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp, ntlmssp_handle, ntlmssp_wrap_handle, "NTLMSSP - Microsoft NTLM Security Support Provider"); + + /* Register authenticated pipe dissector */ + + register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, + DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, + &ntlmssp_sign_fns); + + register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY, + DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, + &ntlmssp_seal_fns); } Index: packet-ntlmssp.h =================================================================== RCS file: packet-ntlmssp.h diff -N packet-ntlmssp.h --- packet-ntlmssp.h 6 Jan 2003 11:28:02 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,27 +0,0 @@ -/* packet-ntlmssp.h - * - * $Id: packet-ntlmssp.h,v 1.1 2003/01/06 11:28:02 sahlberg Exp $ - * - * Ethereal - Network traffic analyzer - * By Gerald Combs <gerald@xxxxxxxxxxxx> - * Copyright 1998 Gerald Combs - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -typedef struct _ntlmssp_decrypted_info_t { - tvbuff_t *decr_tvb; - proto_tree *decr_tree; -} ntlmssp_decrypted_info_t;
- Follow-Ups:
- Prev by Date: Re: [Ethereal-dev] make-register-dotc & make-tapreg-dotc
- Next by Date: [Ethereal-dev] Please add to the wish-list - deflate gzipped HTTP sreams.
- Previous by thread: Re: [Ethereal-dev] [patch] fixed - packet-radius.c
- Next by thread: Re: [Ethereal-dev] [PATCH] decouple dcerpc authentication from packet-dcerpc.c
- Index(es):