diff --git a/README b/README deleted file mode 100644 index 4c8ed85..0000000 --- a/README +++ /dev/null @@ -1,313 +0,0 @@ -[![Build Status](https://travis-ci.org/tomac/yersinia.svg?branch=master)](https://travis-ci.org/tomac/yersinia) - -Spanning Tree -------------- - -#1: DOS attack sending conf BPDUs - - Let's send some conf BPDUs claiming be root!!! By sending continously conf BPDU with root pathcost 0, randomly - generated bridge id (and therefore the same root id), and some default values for other fields, we try to - annoy the switches close to us, causing a DoS when trying to parse and recalculate their STP engines. - - Source MAC: randomly generated. - Destination MAC: 01:80:c2:00:00:00 - Bridge ID: 8000:source_mac - Root ID: 8000:source_mac - Hello time: 2 - Forward delay: 15 - Max age: 20 - Root pathcost: 0 - - - 01:20:26: STP: VLAN0001 heard root 32768-d1bf.6d60.097b on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-9ac6.0f72.7118 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-85a3.3662.43dc on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-3d84.bc1c.918e on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-b2e2.1a12.dbb4 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-4ba6.2d45.5844 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-deb0.4f14.7288 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-4879.8036.0e24 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-2776.e340.9222 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-299e.de76.c07d on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-d38b.bc5b.e90d on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-78ee.0205.afdb on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-b32b.e969.81b1 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-b16b.c428.88a3 on Fa0/8 - 01:20:26: STP: VLAN0001 heard root 32768-dd01.1436.9044 on Fa0/8 - - - -#2: DOS attack sending tcn BPDUs - - This attack sends continously tcn BPDUs causing the root switch to send conf BPDUs acknowledging the change. - Besides, the root switch will send topology change notifications to the members of the tree, and they will - have to recalculate their STP engine to learn the new change. - - Source MAC: randomly generated. - Destination MAC: 01:80:c2:00:00:00 - - - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - 01:35:39: STP: VLAN0001 Topology Change rcvd on Fa0/8 - - - -#3: NONDOS attack Claiming Root Role - - Now our aim is to get the root role of the tree. How can we accomplish this issue? Just listening to the network - to find out which one is the root role, and start sending conf BPDU with lower priority to become root. - - Source MAC: same one as the sniffed BPDU. - Destination MAC: same one as the sniffed BPDU. - Bridge ID: the sniffed one slightly modified to have a lower priority - Root ID: 8000: same as bridge id. - Hello time: same one as the sniffed BPDU. - Forward delay: same one as the sniffed BPDU. - Max age: same one as the sniffed BPDU. - Root pathcost: same one as the sniffed BPDU. - - - 01:58:48: STP: VLAN0001 heard root 32769-000e.84d4.2280 on Fa0/8 - 01:58:48: supersedes 32769-000e.84d5.2280 - 01:58:48: STP: VLAN0001 new root is 32769, 000e.84d4.2280 on port Fa0/8, cost 19 - - - -#4 NONDOS attack Claiming a non-root role - - We pretend to be another weird switch playing with STP and praising our root id :) - - -#5 DOS attack causing eternal root elections - - By sending config BPDUs autodecrementing their priority, we can cause infinite root elections in the STP tree. - It would be something similar to recount the election's votes to determine the winner (do you remember Florida?) - - - 00:20:21: STP: VLAN0001 heard root 32769-000e.84d4.2280 on Fa0/9 - 00:20:21: supersedes 32769-000e.84d5.2280 - 00:20:21: STP: VLAN0001 new root is 32769, 000e.84d4.2280 on port Fa0/9, cost 19 - 00:20:23: STP: VLAN0001 heard root 32769-000e.84d3.2280 on Fa0/9 - 00:20:23: supersedes 32769-000e.84d4.2280 - 00:20:23: STP: VLAN0001 new root is 32769, 000e.84d3.2280 on port Fa0/9, cost 19 - 00:20:25: STP: VLAN0001 heard root 32769-000e.84d2.2280 on Fa0/9 - 00:20:25: supersedes 32769-000e.84d3.2280 - 00:20:25: STP: VLAN0001 new root is 32769, 000e.84d2.2280 on port Fa0/9, cost 19 - 00:20:27: STP: VLAN0001 heard root 32769-000e.84d1.2280 on Fa0/9 - 00:20:27: supersedes 32769-000e.84d2.2280 - 00:20:27: STP: VLAN0001 new root is 32769, 000e.84d1.2280 on port Fa0/9, cost 19 - 00:20:29: STP: VLAN0001 heard root 32769-000e.84d0.2280 on Fa0/9 - 00:20:29: supersedes 32769-000e.84d1.2280 - 00:20:29: STP: VLAN0001 new root is 32769, 000e.84d0.2280 on port Fa0/9, cost 19 - 00:20:31: STP: VLAN0001 heard root 32769-000e.84cf.2280 on Fa0/9 - 00:20:31: supersedes 32769-000e.84d0.2280 - 00:20:31: STP: VLAN0001 new root is 32769, 000e.84cf.2280 on port Fa0/9, cost 19 - 00:20:33: STP: VLAN0001 heard root 32769-000e.84ce.2280 on Fa0/9 - 00:20:33: supersedes 32769-000e.84cf.2280 - 00:20:33: STP: VLAN0001 new root is 32769, 000e.84ce.2280 on port Fa0/9, cost 19 - 00:20:35: STP: VLAN0001 heard root 32769-000e.84cd.2280 on Fa0/9 - 00:20:35: supersedes 32769-000e.84ce.2280 - 00:20:35: STP: VLAN0001 new root is 32769, 000e.84cd.2280 on port Fa0/9, cost 19 - 00:20:37: STP: VLAN0001 heard root 32769-000e.84cc.2280 on Fa0/9 - 00:20:37: supersedes 32769-000e.84cd.2280 - 00:20:37: STP: VLAN0001 new root is 32769, 000e.84cc.2280 on port Fa0/9, cost 19 - 00:20:39: STP: VLAN0001 heard root 32769-000e.84cb.2280 on Fa0/9 - 00:20:39: supersedes 32769-000e.84cc.2280 - 00:20:39: STP: VLAN0001 new root is 32769, 000e.84cb.2280 on port Fa0/9, cost 19 - - - -#6 DOS Attack causing root dissapearance - - This time we try to exhaust the root election proccess. We manage to become root in the STP tree, - but we stop sending config BPDUs until it reaches max_age seconds (usually 20), forcing a new - election proccess. - - - 02:02:43: STP: VLAN0001 heard root 32769-000e.84d4.2280 on Fa0/9 - 02:02:43: supersedes 32769-000e.84d5.2280 - 02:02:43: STP: VLAN0001 new root is 32769, 000e.84d4.2280 on port Fa0/9, cost 19 - 02:03:03: STP: VLAN0001 we are the spanning tree root - 02:03:04: STP: VLAN0001 heard root 32769-000e.84d4.2280 on Fa0/9 - 02:03:04: supersedes 32769-000e.84d5.2280 - 02:03:04: STP: VLAN0001 new root is 32769, 000e.84d4.2280 on port Fa0/9, cost 19 - 02:03:04: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:06: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:08: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:10: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:12: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:14: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:16: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:18: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:20: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:22: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:24: STP: VLAN0001 we are the spanning tree root - 02:03:24: STP: VLAN0001 heard root 32769-000e.84d4.2280 on Fa0/9 - 02:03:24: supersedes 32769-000e.84d5.2280 - 02:03:24: STP: VLAN0001 new root is 32769, 000e.84d4.2280 on port Fa0/9, cost 19 - 02:03:24: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:26: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:28: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:30: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:32: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:34: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:36: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:38: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:40: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:42: STP: VLAN0001 sent Topology Change Notice on Fa0/9 - 02:03:44: STP: VLAN0001 we are the spanning tree root - - - -Mitigations (Cisco only) ------------------------- - -- Use port security and disable STP in those ports that don't require STP. -For information about port security, please check the following url: -http://www.cisco.com/en/US/products/hw/switches/ps628/products_configuration_guide_chapter09186a0080150bcd.html - -- If you are using the portfast feature in your STP configuration, enable also the BPDU guard for avoiding these -attacks when the port automatically enters the forwarding state: -http://www.cisco.com/warp/public/473/65.html - -- Use the root guard feature for avoiding rogue devices to become root: -http://www.cisco.com/en/US/tech/tk389/tk621/technologies_tech_note09186a00800ae96b.shtml - - -Further reading ---------------- - -- Guillermo Marro's nice Master Thesis: -http://seclab.cs.ucdavis.edu/papers/Marro_masters_thesis.pdf - -- Oleg K. Artemjev, Vladislav V. Myasnyankin. Fun with the Spanning Tree Protocol -http://phrack.org/issues/61/12.html - - - -CDP ---- - -Cisco devices have always spoken a different language to communicate among them, -to tell everybody that they are alive and which nifty features they have. CDP -stands for Cisco Discovery Protocol. By means of this particular language, Cisco -devices set up a virtual world where everyone is happy and ther is no crime at -all. Or at least it seems to be this way, since many network administrators -aren't worried for CDP yet. Although some of information that can be sent in a -CDP packet is still undocumented (CDP is a propietary protocol and it seems that -Cisco does not want to give details about it), at least one old attack (that it -is still valid) is known, and there is a public implementation (FX did it!). - -This attack is a DoS trying to exhaust the device memory so that it can't -allocate more memory for any device process. How can we do it? Simply sending -CDP packets with bogus data simulating real Cisco devices. The target device -will begin to allocate memory in its CDP table to save the new neighbor -information, but without knowing that it is going to have thousands or millions -of new friends. - -Other attack implemented in the current code is the ability to set up a new -virtual Cisco device that it is designated only for make a little mess, trying -to confuse network administrators. - -Screenshot of the attack running: - -Output of a Cisco 2503 router: - -athens#sh mem - Head Total(b) Used(b) Free(b) Lowest(b) Largest(b) -Processor 4873C 3893444 3893444 0 0 0 -I/O 400000 2097152 2097088 64 64 64 - - -%SCHED-3-THRASHING: Process thrashing on watched queue 'CDP packets' (count 57). --Process= "CDP Protocol", ipl= 6, pid= 9 --Traceback= 3159232 31594DE 3201660 -%LANCE-5-COLL: Unit 0, excessive collisions. TDR=7 -%SCHED-3-THRASHING: Process thrashing on watched queue 'CDP packets' (count 57). --Process= "CDP Protocol", ipl= 6, pid= 9 --Traceback= 3159232 31594DE 3201660 -%SYS-2-MALLOCFAIL: Memory allocation of 100 bytes failed from 0x3201B3E, pool Processor, alignment 0 --Process= "CDP Protocol", ipl= 0, pid= 9 --Traceback= 314E8A4 314FA06 3201B46 32016C8 -%SCHED-3-THRASHING: Process thrashing on watched queue 'CDP packets' (count 57). --Process= "CDP Protocol", ipl= 6, pid= 9 --Traceback= 3159232 31594DE 3201660 -%SYS-2-MALLOCFAIL: Memory allocation of 100 bytes failed from 0x3201B3E, pool Processor, alignment 0 --Process= "CDP Protocol", ipl= 0, pid= 9 --Traceback= 314E8A4 314FA06 3201B46 32016C8 -%SYS-2-MALLOCFAIL: Memory allocation of 100 bytes failed from 0x3201B3E, pool Processor, alignment 0 --Process= "CDP Protocol", ipl= 0, pid= 9 --Traceback= 314E8A4 314FA06 3201B46 32016C8 - - -And a couple of minutes later after killing the attack, the router surprisingly gets halted for several seconds, -and then kicks you out of the terminal :) - - -%SYS-3-CPUHOG: Task ran for 16884 msec (69/69), Process = Exec, PC = 3158D42 --Traceback= 3158CEE 3158D4A 30F7330 30F742A 30FF3A4 30FEF76 30FEF1C 3116860 - - - -Output of a Cisco 2950 switch: - -00:06:08: %SYS-2-MALLOCFAIL: Memory allocation of 224 bytes failed from 0x800118D0, alignment 0 -Pool: Processor Free: 0 Cause: Not enough free memory -Alternate Pool: I/O Free: 32 Cause: Not enough free memory - --Process= "CDP Protocol", ipl= 0, pid= 26 --Traceback= 801DFC30 801E1DD8 800118D8 80011218 801D932C 801D9318 -00:06:08: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:09: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:10: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:11: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:12: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:13: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:14: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:15: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:16: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:17: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:18: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:19: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:20: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:21: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:22: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:23: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:38: %SYS-2-MALLOCFAIL: Memory allocation of 140 bytes failed from 0x801E28BC, alignment 0 -Pool: Processor Free: 0 Cause: Not enough free memory -Alternate Pool: I/O Free: 32 Cause: Not enough free memory - --Process= "Calhoun Statistics Process", ipl= 0, pid= 21 --Traceback= 801DFC30 801E1DD8 801E28C4 801F13BC 801F1470 802F7C90 802F9190 802F9788 801D932C 801D9318 -00:06:38: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:39: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:40: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:41: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:42: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:44: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:45: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:46: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:47: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:48: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:49: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:50: ../src-calhoun/strata_stats.c at line 137: can't not push event list -00:06:59: %SYS-3-CPUHOG: Task ran for 2076 msec (11/10), process = Net Background, PC = 801ABD40. --Traceback= 801ABD48 801D932C 801D9318 - -And then, the CDP process is totally down, even when we stop the attack. No more CDP babies... diff --git a/README.md b/README.md index cb840a3..b6e7f18 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,26 @@ [![Build Status](https://travis-ci.org/tomac/yersinia.svg?branch=master)](https://travis-ci.org/tomac/yersinia) +How to Install +------------- + +Clone this repo inside `/opt/yersinia`. +Install the dependencies: +``` +sudo apt install autoconf libgtk-3-dev libnet1-dev libgtk2.0-dev libpcap-dev -y +``` +Then go inside `/opt/yersinia` and execute: +``` +./autogen.sh +./configure --with-gtk # flag required to compile with GUI support +make +make install +``` + +And that's it, you can now start it with: +``` +yersinia -G +``` + Spanning Tree ------------- diff --git a/src/admin.c b/src/admin.c index d007b22..135f796 100644 --- a/src/admin.c +++ b/src/admin.c @@ -5,6 +5,8 @@ * By David Barroso and Alfredo Andres * Copyright 2005-2017 Alfredo Andres and David Barroso * + * << Code amended by Nicolae Mercore - 11.2024 >> + * * 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 @@ -232,7 +234,7 @@ admin_th_listen(void *arg) else { write_log(0,"\n Connection accepted for %s\n", inet_ntoa(*ip_addr)); - if ( pthread_create( &tid, NULL, &admin_th_network_peer, (void *)sock2 ) < 0) + if ( pthread_create( &tid, NULL, &admin_th_network_peer, (void *)(intptr_t)sock2 ) < 0) { n=errno; thread_error("pthread_create admin_th_listen",n); @@ -330,13 +332,13 @@ admin_th_network_peer(void *sock) if (pthread_mutex_lock(&terms->mutex) != 0) thread_error("th_network_peer pthread_mutex_lock",errno); - fail = term_add_node(&term_node, TERM_VTY, sock, pthread_self()); + fail = term_add_node(&term_node, TERM_VTY, (int)sock, pthread_self()); if (fail == -1) { if (pthread_mutex_unlock(&terms->mutex) != 0) thread_error("th_network_peer pthread_mutex_unlock",errno); - admin_th_network_peer_exit(term_node, sock); + admin_th_network_peer_exit(term_node, (int)(intptr_t)sock); } if (term_node == NULL) @@ -346,7 +348,7 @@ admin_th_network_peer(void *sock) if (pthread_mutex_unlock(&terms->mutex) != 0) thread_error("th_network_peer pthread_mutex_unlock",errno); - admin_th_network_peer_exit(term_node, sock); + admin_th_network_peer_exit(term_node, (int)(intptr_t)sock); } pthread_mutex_lock(&term_node->thread.finished); @@ -377,14 +379,14 @@ admin_th_network_peer(void *sock) thread_error("getpeername",errno); if (pthread_mutex_unlock(&terms->mutex) != 0) thread_error("th_vty_peer pthread_mutex_unlock",errno); - admin_th_network_peer_exit(term_node, sock); + admin_th_network_peer_exit(term_node, (int)(intptr_t)sock); } if (init_attribs(term_node) < 0) { if (pthread_mutex_unlock(&terms->mutex) != 0) thread_error("th_vty_peer pthread_mutex_unlock",errno); - admin_th_network_peer_exit(term_node, sock); + admin_th_network_peer_exit(term_node, (int)(intptr_t)sock); } term_node->from_port = ntohs(name.sin_port); diff --git a/src/admin.h b/src/admin.h index 338c049..a1114e8 100644 --- a/src/admin.h +++ b/src/admin.h @@ -5,6 +5,8 @@ * By David Barroso and Alfredo Andres * Copyright 2005-2017 Alfredo Andres and David Barroso * + * << Code amended by Nicolae Mercore - 11.2024 >> + * * 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 @@ -48,7 +50,7 @@ extern int8_t bin_data[]; /* Extern functions...*/ extern void write_log( u_int16_t mode, char *msg, ... ); extern int8_t attack_kill_th(struct term_node *, pthread_t); -extern int8_t term_add_node(struct term_node **, int8_t, int32_t, pthread_t); +extern int8_t term_add_node(struct term_node **, int8_t, int, pthread_t); extern int8_t term_write(struct term_node *, char *, u_int16_t); extern void term_delete_all(void); extern void term_delete_node(struct term_node *, int8_t); diff --git a/src/gtk-callbacks.c b/src/gtk-callbacks.c index d6ddab9..7aeb015 100644 --- a/src/gtk-callbacks.c +++ b/src/gtk-callbacks.c @@ -33,6 +33,7 @@ #include #include "gtk-callbacks.h" +#include "gtk-interface.h" #define GLADE_HOOKUP_OBJECT(component,widget,name) \ g_object_set_data_full (G_OBJECT (component), name, \ @@ -765,13 +766,18 @@ gtk_c_clock_update(GtkWidget *clock) void -gtk_c_tree_update( GtkWidget *tree_model ) +gtk_c_tree_update( GtkListStore *tree_model ) { u_int8_t i, j; GtkTreeIter iter; GtkTreePath *path; char tmp[3]; + if (!GTK_IS_LIST_STORE(tree_model)) { + write_log(0, "Error: tree_model is not a valid GtkListStore\n"); + return; + } + j = 0; for( i=0; i < MAX_PROTOCOLS; i++ ) { @@ -782,8 +788,9 @@ gtk_c_tree_update( GtkWidget *tree_model ) path = gtk_tree_path_new_from_string( tmp ); if ( path ) { - gtk_tree_model_get_iter( GTK_TREE_MODEL( tree_model ), &iter, path ); - gtk_list_store_set( GTK_LIST_STORE( tree_model ), &iter, 1, protocols[i].packets, -1 ); + if (gtk_tree_model_get_iter( GTK_TREE_MODEL( tree_model ), &iter, path )) { + gtk_list_store_set( tree_model, &iter, 1, protocols[i].packets, -1 ); + } gtk_tree_path_free( path ); } j++; @@ -794,8 +801,9 @@ gtk_c_tree_update( GtkWidget *tree_model ) path = gtk_tree_path_new_from_string( tmp ); if ( path ) { - gtk_tree_model_get_iter( GTK_TREE_MODEL( tree_model ), &iter, path ); - gtk_list_store_set( GTK_LIST_STORE( tree_model ), &iter, 1, packet_stats.global_counter.total_packets, -1 ); + if (gtk_tree_model_get_iter( GTK_TREE_MODEL( tree_model ), &iter, path )) { + gtk_list_store_set( tree_model, &iter, 1, packet_stats.global_counter.total_packets, -1 ); + } gtk_tree_path_free( path ); } } @@ -840,14 +848,28 @@ gtk_c_refresh_mwindow(gpointer userdata) values = NULL; /* Check if it is Yersinia log */ - if ( ! helper->mode || ( helper->mode >= MAX_PROTOCOLS ) ) + if ( ! helper->mode || ( helper->mode >= MAX_PROTOCOLS ) ) { + return TRUE; + } + + /* Get the protocol tree using access function */ + GtkWidget *protocol_tree = gtk_i_get_protocol_tree(helper->mode); + if (!protocol_tree || !GTK_IS_TREE_VIEW(protocol_tree)) { return TRUE; + } params = protocols[helper->mode].parameters; extra_params = protocols[helper->mode].extra_parameters; - if ((tree_model = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(protocols_tree[helper->mode])))) == NULL) + if ((tree_model = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(protocol_tree)))) == NULL) { write_log(0, "Error in gtk_tree_view_get_model\n"); + return TRUE; + } + + if (!GTK_IS_LIST_STORE(tree_model)) { + write_log(0, "Error: tree_model is not a valid GtkListStore\n"); + return TRUE; + } valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(tree_model), &iter); @@ -971,6 +993,21 @@ gtk_c_refresh_mwindow(gpointer userdata) } } + /* Auto-select first row with data to trigger detail display */ + if (helper->mode < MAX_PROTOCOLS && protocols[helper->mode].stats[0].header->ts.tv_sec > 0) { + GtkWidget *protocol_tree = gtk_i_get_protocol_tree(helper->mode); + if (protocol_tree) { + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(protocol_tree)); + if (selection) { + GtkTreePath *path = gtk_tree_path_new_from_string("0"); + if (path) { + gtk_tree_selection_select_path(selection, path); + gtk_tree_path_free(path); + } + } + } + } + return TRUE; } @@ -979,99 +1016,56 @@ void gtk_c_tree_selection_changed_cb( GtkTreeSelection *selection, gpointer user { GtkTreeIter iter; GtkTreeModel *model; - GtkWidget *tree; - GtkListStore *tree_model; - u_int8_t row = 0; - u_int8_t j, k, mode; - char **values = NULL, *ptrtlv; - struct commands_param *params; + char *protocol_name = NULL; + int protocol_index = -1; struct gtk_s_helper *helper = (struct gtk_s_helper *) userdata; - if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) - gtk_tree_model_get(model, &iter, 0, &row, -1); - - mode = gtk_notebook_get_current_page(GTK_NOTEBOOK(helper->notebook)); - params = (struct commands_param *)protocols[mode].parameters; - - if ( protocols[mode].stats[row].header->ts.tv_sec <= 0) - { - /* write_log(0, "Ohhh no hay paquetes del modo %d, fila %d :(\n", mode, row); */ + /* Basic validation */ + if (!helper) { return; } - tree = lookup_widget(GTK_WIDGET(helper->notebook), "main_vhvvs_tree"); - - if ((tree_model = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))) == NULL) - { - write_log(0, "Error in gtk_tree_view_get_model\n"); + if (!selection) { return; } - gtk_list_store_clear(tree_model); - - if (protocols[mode].get_printable_packet) - { - values = (*protocols[mode].get_printable_packet)(&protocols[mode].stats[row]); - - if ( ! values ) - { - write_log(0, "Error in get_printable_packet (mode %d)\n", mode); - return ; - } - } - else - { - write_log(0, "Warning: there is no get_printable_packet for protocol %d\n", mode); - return ; + if (!gtk_tree_selection_get_selected(selection, &model, &iter)) { + return; } - j = 0; - k = 0; - - /* Normal parameters (-2 for the interface and defaults) */ - while (j < protocols[mode].nparams) - { - if ((params[j].type != FIELD_IFACE) && (params[j].type != FIELD_DEFAULT) && (params[j].type != FIELD_EXTRA)) - { - gtk_list_store_append(GTK_LIST_STORE(tree_model), &iter); - gtk_list_store_set(GTK_LIST_STORE(tree_model), &iter, 0, params[j].ldesc, -1); - gtk_list_store_set(GTK_LIST_STORE(tree_model), &iter, 1, values[k], -1); - if (params[j].meaning) - gtk_list_store_set( GTK_LIST_STORE( tree_model ), &iter, 2, parser_get_meaning( values[k], params[j].meaning ), -1 ); - k++; - } - j++; + /* Get the protocol name from the first column */ + gtk_tree_model_get(model, &iter, 0, &protocol_name, -1); + + if (!protocol_name) { + return; } - ptrtlv = values[k]; - if (protocols[mode].extra_nparams > 0) - { - while( ptrtlv && strlen( ptrtlv ) ) - { - gtk_list_store_append(GTK_LIST_STORE(tree_model), &iter); - gtk_list_store_set(GTK_LIST_STORE(tree_model), &iter, 0, ptrtlv, -1); - ptrtlv += strlen( ptrtlv ) + 1; - if (ptrtlv) - { - gtk_list_store_set(GTK_LIST_STORE(tree_model), &iter, 1, ptrtlv, -1); - ptrtlv += strlen( ptrtlv ) + 1; - } + /* Find the protocol index */ + for (int i = 0; i < MAX_PROTOCOLS; i++) { + if (protocols[i].visible && protocols[i].namep && + strcmp(protocols[i].namep, protocol_name) == 0) { + protocol_index = i; + break; } } - gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter); - gtk_list_store_set (GTK_LIST_STORE(tree_model), &iter, 0, "Interface", -1); - gtk_list_store_set (GTK_LIST_STORE(tree_model), &iter, 1, protocols[mode].stats[row].iface, -1); - - k = 0; + if (protocol_index == -1) { + g_free(protocol_name); + return; + } - while( values[k] ) - { - free((void *)values[k]); - k++; + /* Switch to the corresponding notebook tab */ + if (helper->notebook) { + gtk_notebook_set_current_page(GTK_NOTEBOOK(helper->notebook), protocol_index); + + /* Update helper->mode to match the new tab */ + helper->mode = protocol_index; + + /* Refresh the TreeView for this protocol to show packet data */ + gtk_c_refresh_mwindow(helper); } - free(values); + g_free(protocol_name); } diff --git a/src/gtk-callbacks.h b/src/gtk-callbacks.h index 345f52a..f068e2c 100644 --- a/src/gtk-callbacks.h +++ b/src/gtk-callbacks.h @@ -68,7 +68,7 @@ void gtk_c_attackparams_ok_click( GtkWidget *, gpointer ); gboolean gtk_c_attackparams_delete_event( GtkWidget *, GdkEvent *, gpointer ); void gtk_c_update_hexview(GtkTreeSelection *, gpointer); void gtk_c_clock_update(GtkWidget *); -void gtk_c_tree_update(GtkWidget *); +void gtk_c_tree_update( GtkListStore * ); void gtk_c_refresh_mwindow_notebook(GtkNotebook *, GtkNotebookPage *, guint, gpointer); gboolean gtk_c_refresh_mwindow(gpointer); void gtk_c_tree_selection_changed_cb (GtkTreeSelection *, gpointer); diff --git a/src/gtk-interface.c b/src/gtk-interface.c index eee367e..c2913c0 100644 --- a/src/gtk-interface.c +++ b/src/gtk-interface.c @@ -402,7 +402,32 @@ gtk_i_create_Main (struct gtk_s_helper *helper) gtk_widget_show (toolbar_clear_img); toolbar_clear = (GtkWidget*) gtk_menu_tool_button_new (toolbar_clear_img, _("Clear stats")); gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbar_clear), tooltips, ("Clear ALL packet statistics"), NULL); - gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_clear), menu_actions_clear_menu); + /* Create a separate menu for the toolbar to avoid the warning */ + GtkWidget *toolbar_clear_menu = gtk_menu_new(); + + /* Copy the menu items to the toolbar menu */ + for (i = 0; i < MAX_PROTOCOLS; i++) + { + GtkWidget *toolbar_clear_proto = gtk_menu_item_new_with_mnemonic (_(protocols[i].namep)); + gtk_widget_set_name(toolbar_clear_proto, protocols[i].namep); + if (protocols[i].visible) + gtk_widget_show (toolbar_clear_proto); + gtk_container_add (GTK_CONTAINER (toolbar_clear_menu), toolbar_clear_proto); + g_signal_connect ((gpointer) toolbar_clear_proto, "activate", + G_CALLBACK (gtk_c_on_actions_clear_activate), + helper); + } + + /* Add "All protocols" option */ + GtkWidget *toolbar_clear_all = gtk_menu_item_new_with_mnemonic (_("All protocols")); + gtk_widget_set_name(toolbar_clear_all, "ALL"); + gtk_widget_show (toolbar_clear_all); + gtk_container_add (GTK_CONTAINER (toolbar_clear_menu), toolbar_clear_all); + g_signal_connect ((gpointer) toolbar_clear_all, "activate", + G_CALLBACK (gtk_c_on_actions_clear_activate), + helper); + + gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_clear), toolbar_clear_menu); gtk_widget_show (toolbar_clear); gtk_container_add (GTK_CONTAINER (toolbar), toolbar_clear); @@ -411,7 +436,32 @@ gtk_i_create_Main (struct gtk_s_helper *helper) gtk_widget_show (toolbar_capture_img); toolbar_capture = (GtkWidget*) gtk_menu_tool_button_new (toolbar_capture_img, _("Capture")); gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(toolbar_capture), tooltips, ("Capture traffic in PCAP format"), NULL); - gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_capture), menu_capture_menu); + /* Create a separate menu for the toolbar to avoid the warning */ + GtkWidget *toolbar_capture_menu = gtk_menu_new(); + + /* Copy the capture menu items to the toolbar menu */ + for (i = 0; i < MAX_PROTOCOLS; i++) + { + GtkWidget *toolbar_capture_proto = gtk_menu_item_new_with_mnemonic (_(protocols[i].namep)); + gtk_widget_set_name(toolbar_capture_proto, protocols[i].namep); + if (protocols[i].visible) + gtk_widget_show (toolbar_capture_proto); + gtk_container_add (GTK_CONTAINER (toolbar_capture_menu), toolbar_capture_proto); + g_signal_connect ((gpointer) toolbar_capture_proto, "activate", + G_CALLBACK (gtk_c_on_capture_activate), + helper); + } + + /* Add "All protocols" option */ + GtkWidget *toolbar_capture_all = gtk_menu_item_new_with_mnemonic (_("All protocols")); + gtk_widget_set_name(toolbar_capture_all, "ALL"); + gtk_widget_show (toolbar_capture_all); + gtk_container_add (GTK_CONTAINER (toolbar_capture_menu), toolbar_capture_all); + g_signal_connect ((gpointer) toolbar_capture_all, "activate", + G_CALLBACK (gtk_c_on_capture_activate), + helper); + + gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_capture), toolbar_capture_menu); gtk_widget_show (toolbar_capture); gtk_container_add (GTK_CONTAINER (toolbar), toolbar_capture); @@ -480,6 +530,11 @@ gtk_i_create_Main (struct gtk_s_helper *helper) column = gtk_tree_view_column_new_with_attributes ("Packets", cell2, "text", 1, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (main_vhvs_tree), GTK_TREE_VIEW_COLUMN (column)); + /* Connect selection signal for left tree to update central tree */ + GtkTreeSelection *left_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(main_vhvs_tree)); + g_signal_connect(G_OBJECT(left_selection), "changed", + G_CALLBACK(gtk_c_tree_selection_changed_cb), helper); + main_vhv_vbox = gtk_vbox_new (FALSE, 5); gtk_widget_show (main_vhv_vbox); gtk_paned_pack2 (GTK_PANED (main_vh_vpaned), main_vhv_vbox, TRUE, TRUE); @@ -494,19 +549,32 @@ gtk_i_create_Main (struct gtk_s_helper *helper) gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(main_vhvvs_tree), TRUE); main_vhvvs_tree_model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (main_vhvv_scroll), main_vhvvs_tree); + gtk_container_add (GTK_CONTAINER (main_vhvv_scroll), main_vhvvs_tree); gtk_tree_view_set_model (GTK_TREE_VIEW (main_vhvvs_tree), GTK_TREE_MODEL (main_vhvvs_tree_model)); gtk_widget_show (main_vhvvs_tree); + /* Create separate cell renderers for each column */ cell = gtk_cell_renderer_text_new (); - + g_object_set(cell, "background", "#EEEEEE", "background-set", TRUE, NULL); + g_object_set(cell, "foreground", "#000000", "foreground-set", TRUE, NULL); column = gtk_tree_view_column_new_with_attributes ("Field", cell, "text", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (main_vhvvs_tree), GTK_TREE_VIEW_COLUMN (column)); + + cell = gtk_cell_renderer_text_new (); + g_object_set(cell, "background", "#FFFFFF", "background-set", TRUE, NULL); + g_object_set(cell, "foreground", "#000000", "foreground-set", TRUE, NULL); column = gtk_tree_view_column_new_with_attributes ("Value", cell, "text", 1, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (main_vhvvs_tree), GTK_TREE_VIEW_COLUMN (column)); + + cell = gtk_cell_renderer_text_new (); + g_object_set(cell, "background", "#ADD8E6", "background-set", TRUE, NULL); + g_object_set(cell, "foreground", "#000000", "foreground-set", TRUE, NULL); column = gtk_tree_view_column_new_with_attributes ("Description", cell, "text", 2, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (main_vhvvs_tree), GTK_TREE_VIEW_COLUMN (column)); + /* Force column headers to be visible */ + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(main_vhvvs_tree), TRUE); + main_vhvv_eventbox = gtk_event_box_new(); gtk_widget_set_size_request (main_vhvv_eventbox, 20, 20); //color.red = 0; @@ -1561,6 +1629,21 @@ GtkWidget *gtk_i_create_attackparamsdialog( GTK_ATTACK_PARAMS_CONTEXT *params_ct return main_dialog; } +/* Protocol TreeView access functions */ +GtkWidget* gtk_i_get_protocol_tree(int protocol_index) { + if (protocol_index < 0 || protocol_index >= MAX_PROTOCOLS) { + return NULL; + } + return protocols_tree[protocol_index]; +} + +GtkListStore* gtk_i_get_protocol_tree_model(int protocol_index) { + if (protocol_index < 0 || protocol_index >= MAX_PROTOCOLS) { + return NULL; + } + return protocols_tree_model[protocol_index]; +} + GtkWidget* create_protocol_mwindow(GtkWidget *Main, struct gtk_s_helper *helper, u_int8_t proto) @@ -1619,7 +1702,6 @@ create_protocol_mwindow(GtkWidget *Main, struct gtk_s_helper *helper, u_int8_t p gtk_widget_set_size_request (scroll, 250, 250); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), protocols_tree[proto]); gtk_tree_view_set_model (GTK_TREE_VIEW(protocols_tree[proto]), GTK_TREE_MODEL(protocols_tree_model[proto])); - g_object_unref(protocols_tree_model[proto]); gtk_widget_show (protocols_tree[proto]); cell = gtk_cell_renderer_text_new (); diff --git a/src/gtk-interface.h b/src/gtk-interface.h index 78bcf84..286c248 100644 --- a/src/gtk-interface.h +++ b/src/gtk-interface.h @@ -29,6 +29,10 @@ static GtkWidget *protocols_tree[MAX_PROTOCOLS + 1]; static GtkListStore *protocols_tree_model[MAX_PROTOCOLS + 1]; +/* Protocol TreeView access functions */ +GtkWidget* gtk_i_get_protocol_tree(int protocol_index); +GtkListStore* gtk_i_get_protocol_tree_model(int protocol_index); + GtkWidget* gtk_i_create_Main (struct gtk_s_helper *); GtkWidget* gtk_i_create_opendialog (struct gtk_s_helper *); GtkWidget* gtk_i_create_savedialog (struct gtk_s_helper *); diff --git a/src/parser.c b/src/parser.c index f3912c3..ca35edc 100644 --- a/src/parser.c +++ b/src/parser.c @@ -103,7 +103,7 @@ parser_initial(struct term_tty *tty, struct cl_args *cl_args, int argc, char **a if (!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help")) { parser_help(); - break; + return -1; } else if (!strcmp(argv[i],"-V") || !strcmp(argv[i],"--Version"))