5 * Routines to modify dcerpc bindings on the fly.
7 * Copyright 2004 Ulf Lamping
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/packet.h>
30 #include <epan/epan_dissect.h>
31 #include <epan/dissectors/packet-dcerpc.h>
33 #include "ui/gtk/decode_as_dlg.h"
34 #include "ui/gtk/dlg_utils.h"
35 #include "ui/gtk/gui_utils.h"
36 #include "ui/gtk/decode_as_dcerpc.h"
39 /**************************************************/
40 /* Typedefs & Enums */
41 /**************************************************/
43 /* list of dcerpc "Decode As" bindings */
44 GSList
*decode_dcerpc_bindings
= NULL
;
46 /**************************************************/
47 /* Global Functions */
48 /**************************************************/
50 /* inject one of our bindings into the dcerpc binding table */
52 decode_dcerpc_inject_binding(gpointer data
, gpointer user_data _U_
)
54 dcerpc_add_conv_to_bind_table((decode_dcerpc_bind_values_t
*) data
);
58 /* inject all of our bindings into the dcerpc binding table */
60 decode_dcerpc_inject_bindings(gpointer data _U_
) {
61 g_slist_foreach(decode_dcerpc_bindings
, decode_dcerpc_inject_binding
, NULL
/* user_data */);
67 decode_dcerpc_init(void) {
68 GHook
* hook_init_proto
;
71 /* add a hook function to the dcerpc init_protocols hook */
72 hook_init_proto
= g_hook_alloc(&dcerpc_hooks_init_protos
);
73 hook_init_proto
->func
= decode_dcerpc_inject_bindings
;
74 g_hook_prepend(&dcerpc_hooks_init_protos
, hook_init_proto
);
78 /* clone a binding (uses g_malloc) */
79 static decode_dcerpc_bind_values_t
*
80 decode_dcerpc_binding_clone(decode_dcerpc_bind_values_t
*binding_in
)
82 decode_dcerpc_bind_values_t
*stored_binding
;
84 stored_binding
= g_new(decode_dcerpc_bind_values_t
,1);
85 *stored_binding
= *binding_in
;
86 COPY_ADDRESS(&stored_binding
->addr_a
, &binding_in
->addr_a
);
87 COPY_ADDRESS(&stored_binding
->addr_b
, &binding_in
->addr_b
);
88 stored_binding
->ifname
= g_string_new(binding_in
->ifname
->str
);
90 return stored_binding
;
96 decode_dcerpc_binding_free(void *binding_in
)
98 decode_dcerpc_bind_values_t
*binding
= (decode_dcerpc_bind_values_t
*)binding_in
;
100 g_free((void *) binding
->addr_a
.data
);
101 g_free((void *) binding
->addr_b
.data
);
103 g_string_free(binding
->ifname
, TRUE
);
108 /* compare two bindings (except the interface related things, e.g. uuid) */
110 decode_dcerpc_binding_cmp(gconstpointer a
, gconstpointer b
)
112 const decode_dcerpc_bind_values_t
*binding_a
= (const decode_dcerpc_bind_values_t
*)a
;
113 const decode_dcerpc_bind_values_t
*binding_b
= (const decode_dcerpc_bind_values_t
*)b
;
116 /* don't compare uuid and ver! */
118 ADDRESSES_EQUAL(&binding_a
->addr_a
, &binding_b
->addr_a
) &&
119 ADDRESSES_EQUAL(&binding_a
->addr_b
, &binding_b
->addr_b
) &&
120 binding_a
->ptype
== binding_b
->ptype
&&
121 binding_a
->port_a
== binding_b
->port_a
&&
122 binding_a
->port_b
== binding_b
->port_b
&&
123 binding_a
->ctx_id
== binding_b
->ctx_id
&&
124 binding_a
->smb_fid
== binding_b
->smb_fid
)
135 /**************************************************/
136 /* Show Changed Bindings */
137 /**************************************************/
140 /* add a single binding to the Show list */
142 decode_dcerpc_add_show_list_single(gpointer data
, gpointer user_data
)
147 decode_dcerpc_bind_values_t
*binding
= (decode_dcerpc_bind_values_t
*)data
;
149 g_snprintf(string1
, sizeof(string1
), "ctx_id: %u", binding
->ctx_id
);
151 decode_add_to_show_list (
156 binding
->ifname
->str
);
160 /* add all bindings to the Show list */
162 decode_dcerpc_add_show_list(gpointer user_data
)
164 g_slist_foreach(decode_dcerpc_bindings
, decode_dcerpc_add_show_list_single
, user_data
);
168 /**************************************************/
169 /* Modify the binding routines */
170 /**************************************************/
173 /* removes all bindings */
175 decode_dcerpc_reset_all(void)
177 decode_dcerpc_bind_values_t
*binding
;
179 while(decode_dcerpc_bindings
) {
180 binding
= (decode_dcerpc_bind_values_t
*)decode_dcerpc_bindings
->data
;
182 decode_dcerpc_binding_free(binding
);
183 decode_dcerpc_bindings
= g_slist_remove(
184 decode_dcerpc_bindings
,
185 decode_dcerpc_bindings
->data
);
190 /* remove a binding (looking the same way as the given one) */
192 decode_dcerpc_binding_reset(
193 const gchar
*table_name _U_
,
194 decode_dcerpc_bind_values_t
*binding
)
197 decode_dcerpc_bind_values_t
*old_binding
;
200 /* find the old binding (if it exists) */
201 le
= g_slist_find_custom(decode_dcerpc_bindings
,
203 decode_dcerpc_binding_cmp
);
207 old_binding
= (decode_dcerpc_bind_values_t
*)le
->data
;
209 decode_dcerpc_bindings
= g_slist_remove(decode_dcerpc_bindings
, le
->data
);
211 g_free((void *) old_binding
->addr_a
.data
);
212 g_free((void *) old_binding
->addr_b
.data
);
213 g_string_free(old_binding
->ifname
, TRUE
);
218 /* a binding has changed (remove a previously existing one) */
220 decode_dcerpc_binding_change(
221 const gchar
*table_name
,
222 decode_dcerpc_bind_values_t
*binding
)
225 decode_dcerpc_bind_values_t
*stored_binding
;
227 /* remove a probably existing old binding */
228 decode_dcerpc_binding_reset(table_name
, binding
);
230 /* clone the new binding and append it to the list */
231 stored_binding
= decode_dcerpc_binding_clone(binding
);
232 decode_dcerpc_bindings
= g_slist_append (decode_dcerpc_bindings
, stored_binding
);
236 /* a binding has changed (add/replace/remove it) */
238 decode_change_one_dcerpc_binding(const gchar
*table_name
, decode_dcerpc_bind_values_t
*binding
, GtkWidget
*list
)
240 dcerpc_uuid_key
*key
;
242 GtkTreeSelection
*selection
;
246 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list
));
247 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
) == FALSE
)
252 gtk_tree_model_get(model
, &iter
, E_LIST_S_PROTO_NAME
, &abbrev
,
253 E_LIST_S_TABLE
+1, &key
, -1);
256 if (key
== NULL
|| (abbrev
!= NULL
&& strcmp(abbrev
, "(default)") == 0) ) {
257 decode_dcerpc_binding_reset(table_name
, binding
);
259 binding
->ifname
= g_string_new(abbrev
);
260 binding
->uuid
= key
->uuid
;
261 binding
->ver
= key
->ver
;
262 decode_dcerpc_binding_change(table_name
, binding
);
269 /**************************************************/
270 /* Action routines for the "Decode As..." dialog */
271 /* - called when the OK button pressed */
272 /**************************************************/
275 * This routine is called when the user clicks the "OK" button in the
276 * "Decode As..." dialog window and the DCE-RPC page is foremost.
277 * This routine takes care of making any changes requested to the DCE-RPC
280 * @param notebook_pg A pointer to the "DCE-RPC" notebook page.
283 decode_dcerpc(GtkWidget
*notebook_pg
)
286 const gchar
*table_name
;
287 decode_dcerpc_bind_values_t
*binding
;
290 list
= (GtkWidget
*)g_object_get_data(G_OBJECT(notebook_pg
), E_PAGE_LIST
);
291 if (requested_action
== E_DECODE_NO
)
292 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list
)));
294 binding
= (decode_dcerpc_bind_values_t
*)g_object_get_data(G_OBJECT(notebook_pg
), E_PAGE_BINDING
);
296 /*table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);*/
297 table_name
= "DCE-RPC";
298 decode_change_one_dcerpc_binding(table_name
, binding
, list
);
302 /**************************************************/
304 /**************************************************/
307 /* add an interface to the list */
309 decode_dcerpc_add_to_list(gpointer key
, gpointer value
, gpointer user_data
)
311 /*dcerpc_uuid_key *k = key;*/
312 dcerpc_uuid_value
*v
= (dcerpc_uuid_value
*)value
;
314 if(strcmp(v
->name
, "(none)"))
315 decode_add_to_list("DCE-RPC", v
->name
, key
, user_data
);
319 /* add all interfaces to the list */
321 decode_add_dcerpc_menu (GtkWidget
*page
, const gchar
*table_name _U_
)
323 GtkWidget
*scrolled_window
;
326 decode_list_menu_start(page
, &list
, &scrolled_window
);
327 g_hash_table_foreach(dcerpc_uuids
, decode_dcerpc_add_to_list
, list
);
328 decode_list_menu_finish(list
);
329 return(scrolled_window
);
333 /* add a DCE-RPC page to the notebook */
335 decode_dcerpc_add_page (packet_info
*pinfo
)
337 GtkWidget
*page_hb
, *info_vb
, *label
, *scrolled_window
;
338 GString
*gs
= g_string_new("");
339 GString
*gs2
= g_string_new("");
340 decode_dcerpc_bind_values_t
*binding
;
344 binding
= g_new(decode_dcerpc_bind_values_t
,1);
345 COPY_ADDRESS(&binding
->addr_a
, &pinfo
->src
);
346 COPY_ADDRESS(&binding
->addr_b
, &pinfo
->dst
);
347 binding
->ptype
= pinfo
->ptype
;
348 binding
->port_a
= pinfo
->srcport
;
349 binding
->port_b
= pinfo
->destport
;
350 binding
->ctx_id
= pinfo
->dcectxid
;
351 binding
->smb_fid
= dcerpc_get_transport_salt(pinfo
);
352 binding
->ifname
= NULL
;
353 /*binding->uuid = NULL;*/
356 /* create page content */
357 page_hb
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 5, FALSE
);
358 g_object_set_data(G_OBJECT(page_hb
), E_PAGE_ACTION
, decode_dcerpc
);
359 g_object_set_data(G_OBJECT(page_hb
), E_PAGE_TABLE
, (gpointer
)"DCE-RPC");
360 g_object_set_data(G_OBJECT(page_hb
), E_PAGE_TITLE
, (gpointer
)"DCE-RPC");
361 g_object_set_data(G_OBJECT(page_hb
), E_PAGE_BINDING
, binding
);
363 info_vb
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 5, FALSE
);
364 gtk_box_pack_start(GTK_BOX(page_hb
), info_vb
, TRUE
, TRUE
, 0);
367 label
= gtk_label_new("Replace binding between:");
368 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
370 switch(binding
->ptype
) {
372 g_string_printf(gs2
, "TCP port");
375 g_string_printf(gs2
, "UDP port");
378 g_string_printf(gs2
, "Unknown port type");
381 /* XXX - how to print the address binding->addr_a? */
382 g_string_printf(gs
, "Address: ToBeDone %s: %u", gs2
->str
, binding
->port_a
);
383 label
= gtk_label_new(gs
->str
);
384 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
386 label
= gtk_label_new("&");
387 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
389 /* XXX - how to print the address binding->addr_b? */
390 g_string_printf(gs
, "Address: ToBeDone %s: %u", gs2
->str
, binding
->port_b
);
391 label
= gtk_label_new(gs
->str
);
392 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
394 label
= gtk_label_new("&");
395 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
397 g_string_printf(gs
, "Context ID: %u", binding
->ctx_id
);
398 label
= gtk_label_new(gs
->str
);
399 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
401 label
= gtk_label_new("&");
402 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
403 gtk_widget_set_sensitive(label
, binding
->smb_fid
);
405 g_string_printf(gs
, "SMB FID: %u", binding
->smb_fid
);
406 label
= gtk_label_new(gs
->str
);
407 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
408 gtk_widget_set_sensitive(label
, binding
->smb_fid
);
410 /* Conditionally enabled - only when decoding packets */
411 label
= gtk_label_new("with:");
412 gtk_box_pack_start(GTK_BOX(info_vb
), label
, TRUE
, TRUE
, 0);
414 decode_dimmable
= g_slist_prepend(decode_dimmable
, label
);
415 scrolled_window
= decode_add_dcerpc_menu(page_hb
, "dcerpc" /*table_name*/);
416 gtk_box_pack_start(GTK_BOX(page_hb
), scrolled_window
, TRUE
, TRUE
, 0);
417 decode_dimmable
= g_slist_prepend(decode_dimmable
, scrolled_window
);
419 g_string_free(gs
, TRUE
);