1 /*
2 ettercap -- GTK+ GUI
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_gtk3.h>
24 #include <ec_redirect.h>
25
26 /* proto */
27
28 static void gtkui_sslredir_close(void);
29 static void gtkui_sslredir_detach(GtkWidget *child);
30 static void gtkui_sslredir_attach(void);
31 static void gtkui_sslredir_add(GtkWidget *widget, gpointer data);
32 static void gtkui_sslredir_del(GtkWidget *widget, gpointer data);
33 static void gtkui_sslredir_del_all(GtkWidget *widget, gpointer data);
34 static void gtkui_sslredir_add_list(struct redir_entry *re);
35 static void gtkui_sslredir_add_service(struct serv_entry *se);
36 static void gtkui_sslredir_create_lists(void);
37 static void gtkui_sslredir_af_changed(GtkWidget *widget, gpointer data);
38 static gboolean gtkui_sslredir_key_pressed(GtkWidget *widget,
39 GdkEventKey *event, gpointer data);
40
41 /* globals */
42
43 static GtkWidget *sslredir_window = NULL;
44 static GtkWidget *treeview = NULL;
45 static GtkListStore *redirrules = NULL;
46 static GtkListStore *proto_list = NULL;
47 static GtkListStore *af_list = NULL;
48 static GtkTreeSelection *selection = NULL;
49
50
51
52 /*******************************************/
53
54
55 /*
56 * tab to configure traffic redirection for SSL interception
57 * - no redirect of any interceptable traffic at startup
58 * - selective redirect avoids SSL errors for destinations
59 * not being subject of interception
60 *
61 */
gtkui_sslredir_show(GSimpleAction * action,GVariant * value,gpointer data)62 void gtkui_sslredir_show(GSimpleAction *action, GVariant *value, gpointer data)
63 {
64 GtkWidget *scrolled, *vbox, *hbox, *button, *context_menu, *items;
65 GtkTreeModel *model;
66 GtkCellRenderer *renderer;
67 GtkTreeViewColumn *column;
68
69 (void) action;
70 (void) value;
71 (void) data;
72
73 DEBUG_MSG("gtk_sslredir_show()");
74
75 /* if the object already exist, set the focus to it */
76 if (sslredir_window) {
77 if(GTK_IS_WINDOW (sslredir_window))
78 gtk_window_present(GTK_WINDOW (sslredir_window));
79 else
80 gtkui_page_present(sslredir_window);
81 return;
82 }
83
84 sslredir_window = gtkui_page_new("SSL Intercept",
85 >kui_sslredir_close,
86 >kui_sslredir_detach);
87
88 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
89 gtk_container_add(GTK_CONTAINER(sslredir_window), vbox);
90
91 /* rules list */
92 scrolled = gtk_scrolled_window_new(NULL, NULL);
93 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
94 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
95 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
96 GTK_SHADOW_IN);
97 gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
98
99 treeview = gtk_tree_view_new();
100 gtk_container_add(GTK_CONTAINER(scrolled), treeview);
101
102
103 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
104 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
105
106 renderer = gtk_cell_renderer_text_new();
107 column = gtk_tree_view_column_new_with_attributes("IP Version", renderer,
108 "text", 1, NULL);
109 gtk_tree_view_column_set_sort_column_id(column, 1);
110 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
111
112 renderer = gtk_cell_renderer_text_new();
113 column = gtk_tree_view_column_new_with_attributes("Server IP", renderer,
114 "text", 2, NULL);
115 gtk_tree_view_column_set_sort_column_id(column, 2);
116 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
117
118 renderer = gtk_cell_renderer_text_new();
119 column = gtk_tree_view_column_new_with_attributes("Service", renderer,
120 "text", 6, NULL);
121 gtk_tree_view_column_set_sort_column_id(column, 6);
122 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
123
124 gtkui_sslredir_create_lists();
125
126 model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(redirrules));
127 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), model);
128
129 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
130 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
131
132
133 button = gtk_button_new_with_mnemonic("_Insert new redirect");
134 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
135 if (proto_list)
136 g_signal_connect(G_OBJECT(button), "clicked",
137 G_CALLBACK(gtkui_sslredir_add), model);
138 else
139 gtk_widget_set_sensitive(button, FALSE);
140
141
142 button = gtk_button_new_with_mnemonic("_Remove redirect");
143 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
144 if (proto_list)
145 g_signal_connect(G_OBJECT(button), "clicked",
146 G_CALLBACK(gtkui_sslredir_del), model);
147 else
148 gtk_widget_set_sensitive(button, FALSE);
149
150 /* context menu */
151 context_menu = gtk_menu_new();
152 items = gtk_menu_item_new_with_label("Remove redirect");
153 gtk_menu_shell_append(GTK_MENU_SHELL(context_menu), items);
154 g_signal_connect(G_OBJECT(items), "activate",
155 G_CALLBACK(gtkui_sslredir_del), model);
156 gtk_widget_show(items);
157
158 items = gtk_menu_item_new_with_label("Remove all redirects");
159 gtk_menu_shell_append(GTK_MENU_SHELL(context_menu), items);
160 g_signal_connect(G_OBJECT(items), "activate",
161 G_CALLBACK(gtkui_sslredir_del_all), model);
162 gtk_widget_show(items);
163
164 g_signal_connect(G_OBJECT(treeview), "button-press-event",
165 G_CALLBACK(gtkui_context_menu), context_menu);
166
167 /* remove entries if delete key is pressed */
168 g_signal_connect(G_OBJECT(treeview), "key-press-event",
169 G_CALLBACK(gtkui_sslredir_key_pressed), model);
170
171 gtk_widget_show_all(sslredir_window);
172
173 }
174
175 /* Add a new line to the Rules list */
gtkui_sslredir_add(GtkWidget * widget,gpointer data)176 static void gtkui_sslredir_add(GtkWidget *widget, gpointer data)
177 {
178
179 GtkWidget *dialog, *content, *grid, *destination, *label, *frame;
180 GtkWidget *proto, *af;
181 GtkTreeModel *model;
182 GtkTreeIter iter;
183 GtkCellRenderer *cell1, *cell2;
184 GVariant *gv_from_port, *gv_to_port;
185 int ret = 0;
186 guint16 from_port, to_port;
187 gchar *name;
188 const gchar *server;
189 ec_redir_proto_t ip_ver;
190
191 /* unused variabled */
192 (void) widget;
193 (void) data;
194
195
196 DEBUG_MSG("gtkui_sslredir_add()");
197
198 /* compile IP protocol family list if not already done */
199 if (af_list == NULL) {
200 af_list = gtk_list_store_new(2,
201 G_TYPE_STRING, /* human friendly name */
202 G_TYPE_UINT); /* protocol number for redirect */
203
204 gtk_list_store_append(af_list, &iter);
205 gtk_list_store_set(af_list, &iter,
206 0, "IPv4", 1, EC_REDIR_PROTO_IPV4, -1);
207 #ifdef WITH_IPV6
208 gtk_list_store_append(af_list, &iter);
209 gtk_list_store_set(af_list, &iter,
210 0, "IPv6", 1, EC_REDIR_PROTO_IPV6, -1);
211 #endif
212 }
213
214 dialog = gtk_dialog_new_with_buttons("Create new redirect rule",
215 GTK_WINDOW(window),
216 GTK_DIALOG_MODAL |
217 GTK_DIALOG_DESTROY_WITH_PARENT |
218 GTK_DIALOG_USE_HEADER_BAR,
219 "_Cancel", GTK_RESPONSE_CANCEL,
220 "_Insert", GTK_RESPONSE_OK,
221 NULL);
222
223 content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
224 gtk_container_set_border_width(GTK_CONTAINER(content), 20);
225
226 frame = gtk_frame_new("Redirect specification");
227 gtk_container_add(GTK_CONTAINER(content), frame);
228 gtk_widget_set_margin_bottom(frame, 10);
229
230 grid = gtk_grid_new();
231 gtk_grid_set_row_spacing(GTK_GRID(grid), 5);
232 gtk_grid_set_column_spacing(GTK_GRID(grid), 5);
233 gtk_widget_set_halign(grid, GTK_ALIGN_CENTER);
234 gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
235 gtk_container_add(GTK_CONTAINER(frame), grid);
236
237 label = gtk_label_new("IP Version:");
238 gtk_widget_set_halign(label, GTK_ALIGN_START);
239 gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP, 1, 1);
240
241 af = gtk_combo_box_new();
242 gtk_combo_box_set_model(GTK_COMBO_BOX(af), GTK_TREE_MODEL(af_list));
243 gtk_combo_box_set_active(GTK_COMBO_BOX(af), 0);
244
245 cell1 = gtk_cell_renderer_text_new();
246 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(af), cell1, TRUE);
247 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(af), cell1,
248 "text", 0, NULL);
249 gtk_grid_attach(GTK_GRID(grid), af, GTK_POS_LEFT+1, GTK_POS_TOP, 1, 1);
250
251 label = gtk_label_new("Server IP:");
252 gtk_widget_set_halign(label, GTK_ALIGN_START);
253 gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+1, 1, 1);
254
255 destination = gtk_entry_new();
256 gtk_entry_set_text(GTK_ENTRY(destination), "0.0.0.0/0");
257 gtk_grid_attach(GTK_GRID(grid), destination, GTK_POS_LEFT+1, GTK_POS_TOP+1, 1, 1);
258
259 label = gtk_label_new("Service:");
260 gtk_widget_set_halign(label, GTK_ALIGN_START);
261 gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+2, 1, 1);
262
263 proto = gtk_combo_box_new();
264 gtk_combo_box_set_model(GTK_COMBO_BOX(proto), GTK_TREE_MODEL(proto_list));
265 gtk_combo_box_set_active(GTK_COMBO_BOX(proto), 0);
266
267 cell2 = gtk_cell_renderer_text_new();
268 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(proto), cell2, TRUE);
269 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(proto), cell2,
270 "text", 1, NULL);
271 gtk_grid_attach(GTK_GRID(grid), proto, GTK_POS_LEFT+1, GTK_POS_TOP+2, 1, 1);
272
273 g_signal_connect(G_OBJECT(af), "changed",
274 G_CALLBACK(gtkui_sslredir_af_changed), destination);
275
276 gtk_widget_show_all(dialog);
277 gtk_widget_grab_focus(destination);
278
279 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
280 gtk_widget_hide(dialog);
281
282 /* extract information from widgets */
283 model = gtk_combo_box_get_model(GTK_COMBO_BOX(af));
284 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(af), &iter);
285 gtk_tree_model_get(model, &iter, 1, &ip_ver, -1);
286
287 model = gtk_combo_box_get_model(GTK_COMBO_BOX(proto));
288 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(proto), &iter);
289 gtk_tree_model_get(model, &iter, 0, &name,
290 2, &gv_from_port, 3, &gv_to_port, -1);
291
292 /* convert back from GVariant to uint16 */
293 from_port = g_variant_get_uint16(gv_from_port);
294 to_port = g_variant_get_uint16(gv_to_port);
295
296 server = gtk_entry_get_text(GTK_ENTRY(destination));
297
298 /* execute redirect action */
299 ret = ec_redirect(EC_REDIR_ACTION_INSERT, name, ip_ver,
300 server, from_port, to_port);
301
302
303 /* inform user if redirect execution wasn't successful */
304 if (ret != E_SUCCESS)
305 gtkui_infobar_show(GTK_MESSAGE_ERROR,
306 "Insertion of redirect rule failed.");
307 else { /* otherwise add rule to rules list */
308
309 gtk_list_store_append(redirrules, &iter);
310 gtk_list_store_set(redirrules, &iter,
311 0, ip_ver,
312 1, (ip_ver == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"),
313 2, server,
314 3, gv_from_port,
315 4, gv_to_port,
316 5, ec_strlc(name),
317 6, ec_struc(name),
318 -1);
319 }
320
321
322 }
323
324 gtk_widget_destroy(dialog);
325
326
327 }
328
329 /*
330 * remove selected redirect rules
331 */
gtkui_sslredir_del(GtkWidget * widget,gpointer data)332 void gtkui_sslredir_del(GtkWidget *widget, gpointer data)
333 {
334 GList *list;
335 GtkTreeIter iter, iter_unsorted;
336 GtkTreeModel *model;
337 GVariant *gv_from_port, *gv_to_port;
338 int ret;
339 gchar *name;
340 const gchar *server;
341 guint16 from_port, to_port;
342 ec_redir_proto_t ip_ver;
343
344 /* variable not used */
345 (void) widget;
346
347 DEBUG_MSG("gtkui_sslredir_del()");
348
349 model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(data));
350
351 /* get selected entries */
352 if (gtk_tree_selection_count_selected_rows(selection) > 0) {
353 list = gtk_tree_selection_get_selected_rows(selection, &model);
354 for (list = g_list_last(list); list; list = g_list_previous(list)) {
355 /* extract parameters from GtkTreeView model */
356 gtk_tree_model_get_iter(model, &iter, list->data);
357 gtk_tree_model_get(model, &iter,
358 0, &ip_ver,
359 2, &server,
360 3, &gv_from_port,
361 4, &gv_to_port,
362 5, &name,
363 -1);
364
365 /* convert back from GVariant to uint16 */
366 from_port = g_variant_get_uint16(gv_from_port);
367 to_port = g_variant_get_uint16(gv_to_port);
368
369 /* execute redirect action */
370 ret = ec_redirect(EC_REDIR_ACTION_REMOVE, name, ip_ver,
371 server, from_port, to_port);
372
373 /* inform user if redirect execution wasn't successful */
374 if (ret != E_SUCCESS)
375 gtkui_infobar_show(GTK_MESSAGE_ERROR,
376 "Removal of redirect rule failed.");
377 else { /* otherwise remove from list */
378 gtk_tree_model_sort_convert_iter_to_child_iter(
379 GTK_TREE_MODEL_SORT(data), &iter_unsorted, &iter);
380 gtk_list_store_remove(GTK_LIST_STORE(redirrules), &iter_unsorted);
381 }
382 }
383
384 /* free the list of selection */
385 g_list_free_full(list, (GDestroyNotify)gtk_tree_path_free);
386 }
387
388 }
389
390 /*
391 * select all entries in TreeModel then then call gtkui_sslredir_del
392 */
gtkui_sslredir_del_all(GtkWidget * widget,gpointer data)393 void gtkui_sslredir_del_all(GtkWidget *widget, gpointer data)
394 {
395
396 DEBUG_MSG("gtkui_sslredir_del_all():");
397
398 gtk_tree_selection_select_all(selection);
399 gtkui_sslredir_del(widget, data);
400
401 }
402
403 /* detach ssl redir tab */
gtkui_sslredir_detach(GtkWidget * child)404 static void gtkui_sslredir_detach(GtkWidget *child)
405 {
406 sslredir_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
407 gtk_window_set_title(GTK_WINDOW(sslredir_window), "SSL Intercept");
408 gtk_window_set_default_size(GTK_WINDOW(sslredir_window), 500, 250);
409 g_signal_connect(G_OBJECT(sslredir_window), "delete_event",
410 G_CALLBACK(gtkui_sslredir_close), NULL);
411
412 gtkui_page_attach_shortcut(sslredir_window, gtkui_sslredir_attach);
413
414 gtk_container_add(GTK_CONTAINER(sslredir_window), child);
415 gtk_window_present(GTK_WINDOW(sslredir_window));
416
417 }
418
419 /* callback for reattaching the detached ssl redir tab */
gtkui_sslredir_attach(void)420 static void gtkui_sslredir_attach(void)
421 {
422 gtkui_sslredir_close();
423 gtkui_sslredir_show(NULL, NULL, NULL);
424 }
425
426
427 /* close ssl redir tab */
gtkui_sslredir_close(void)428 static void gtkui_sslredir_close(void)
429 {
430 DEBUG_MSG("gtk_sslredir_close");
431
432 gtk_widget_destroy(sslredir_window);
433 sslredir_window = NULL;
434 }
435
436 /*
437 * create the list for the list of interceptable protocols
438 */
gtkui_sslredir_create_lists(void)439 static void gtkui_sslredir_create_lists(void)
440 {
441 int res;
442
443 DEBUG_MSG("gtk_sslredir_create_lists()");
444
445 /* populate redirect rules */
446 if (redirrules == NULL) {
447 redirrules = gtk_list_store_new(7,
448 G_TYPE_UINT, /* IP address family */
449 G_TYPE_STRING, /* IP address family human readable */
450 G_TYPE_STRING, /* destination definition */
451 G_TYPE_VARIANT, /* protocol registered port */
452 G_TYPE_VARIANT, /* ettercap listener port */
453 G_TYPE_STRING, /* protocol name lower case */
454 G_TYPE_STRING); /* protocol name upper case */
455 /* walk through list of registered redirects */
456 res = ec_walk_redirects(>kui_sslredir_add_list);
457
458 if (res == -E_NOTFOUND) {
459 DEBUG_MSG("gtk_sslredir_create_lists(): no redirects registered - "
460 "apparently no redirect commands enabled in etter.conf");
461 gtkui_infobar_show(GTK_MESSAGE_WARNING,
462 "Traffic redirect not enabled in etter.conf. ");
463 }
464 }
465
466
467 /* populate registered services */
468 if (proto_list == NULL) {
469 proto_list = gtk_list_store_new(4,
470 G_TYPE_STRING, /* protocol name lower case */
471 G_TYPE_STRING, /* protocol name upper case */
472 G_TYPE_VARIANT, /* protocol registered port */
473 G_TYPE_VARIANT);/* ettercap listener port */
474
475 res = ec_walk_redirect_services(>kui_sslredir_add_service);
476
477 if (res == -E_NOTFOUND) {
478 g_object_unref(proto_list);
479 proto_list = NULL;
480 }
481 }
482
483
484
485 }
486
487 /*
488 * callback function to compose the list of active services
489 */
gtkui_sslredir_add_service(struct serv_entry * se)490 static void gtkui_sslredir_add_service(struct serv_entry *se)
491 {
492 GVariant *gv_from_port, *gv_to_port;
493 GtkTreeIter iter;
494
495 DEBUG_MSG("gtkui_sslredir_add_service(%s)", se->name);
496
497 /* Make GVariant from uint16 */
498 gv_from_port = g_variant_new_uint16(se->from_port);
499 gv_to_port = g_variant_new_uint16(se->to_port);
500
501 /* update protocol list store */
502 gtk_list_store_append(proto_list, &iter);
503 gtk_list_store_set(proto_list, &iter,
504 0, ec_strlc(se->name),
505 1, ec_struc(se->name),
506 2, gv_from_port,
507 3, gv_to_port,
508 -1);
509
510 }
511 /*
512 * callback function to compose the list of active redirects
513 */
gtkui_sslredir_add_list(struct redir_entry * re)514 static void gtkui_sslredir_add_list(struct redir_entry *re)
515 {
516 GVariant *gv_from_port, *gv_to_port;
517 GtkTreeIter iter;
518
519 DEBUG_MSG("gtkui_sslredir_add_list(%s)", re->name);
520
521 /* make GVariant from uint16 */
522 gv_from_port = g_variant_new_uint16(re->from_port);
523 gv_to_port = g_variant_new_uint16(re->to_port);
524
525 /* add rule to rules list */
526 gtk_list_store_append(redirrules, &iter);
527 gtk_list_store_set(redirrules, &iter,
528 0, re->proto,
529 1, (re->proto == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"),
530 2, re->destination,
531 3, gv_from_port,
532 4, gv_to_port,
533 5, ec_strlc(re->name),
534 6, ec_struc(re->name),
535 -1);
536
537 }
538
539
540 /*
541 * callback when IP address family is changed
542 * - update preset string of source / destination entry widgets
543 */
gtkui_sslredir_af_changed(GtkWidget * widget,gpointer data)544 void gtkui_sslredir_af_changed(GtkWidget *widget, gpointer data)
545 {
546 GtkTreeModel *model;
547 GtkTreeIter iter;
548 ec_redir_proto_t proto;
549
550
551 model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
552 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter);
553 gtk_tree_model_get(model, &iter, 1, &proto, -1);
554
555 switch (proto) {
556 case EC_REDIR_PROTO_IPV4:
557 gtk_entry_set_text(GTK_ENTRY(data), "0.0.0.0/0");
558 gtk_widget_grab_focus(data);
559 break;
560 case EC_REDIR_PROTO_IPV6:
561 gtk_entry_set_text(GTK_ENTRY(data), "::/0");
562 gtk_widget_grab_focus(data);
563 break;
564 default:
565 break;
566 }
567
568 }
569
570 /*
571 * callback function when delete key is pressed in redirect rule list
572 */
gtkui_sslredir_key_pressed(GtkWidget * widget,GdkEventKey * event,gpointer data)573 gboolean gtkui_sslredir_key_pressed(GtkWidget *widget, GdkEventKey *event,
574 gpointer data)
575 {
576 DEBUG_MSG("gtkui_sslredir_key_pressed()");
577
578 if (event->keyval == gdk_keyval_from_name("Delete")) {
579 gtkui_sslredir_del(widget, data);
580 return TRUE;
581 }
582
583 if (event->keyval == gdk_keyval_from_name("Insert")) {
584 gtkui_sslredir_add(widget, data);
585 return TRUE;
586 }
587
588 /* fall through to other handlers */
589 return FALSE;
590 }
591
592 /* EOF */
593
594 // vim:ts=3:expandtab
595
596