diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Makefile.in | 3 | ||||
-rw-r--r-- | src/lib/ndpi_content_match.c.inc | 300 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 201 | ||||
-rw-r--r-- | src/lib/protocols/btlib.c | 5 | ||||
-rw-r--r-- | src/lib/protocols/coap.c | 2 | ||||
-rw-r--r-- | src/lib/protocols/csgo.c | 5 | ||||
-rw-r--r-- | src/lib/protocols/directconnect.c | 1 | ||||
-rw-r--r-- | src/lib/protocols/dns.c | 4 | ||||
-rw-r--r-- | src/lib/protocols/dropbox.c | 10 | ||||
-rw-r--r-- | src/lib/protocols/edonkey.c | 3 | ||||
-rw-r--r-- | src/lib/protocols/ftp_data.c | 4 | ||||
-rw-r--r-- | src/lib/protocols/gnutella.c | 1 | ||||
-rw-r--r-- | src/lib/protocols/http.c | 2 | ||||
-rw-r--r-- | src/lib/protocols/icecast.c | 2 | ||||
-rw-r--r-- | src/lib/protocols/mail_smtp.c | 7 | ||||
-rw-r--r-- | src/lib/protocols/memcached.c | 3 | ||||
-rw-r--r-- | src/lib/protocols/mysql.c | 52 | ||||
-rw-r--r-- | src/lib/protocols/sip.c | 22 | ||||
-rw-r--r-- | src/lib/protocols/ssl.c | 682 |
19 files changed, 1068 insertions, 241 deletions
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in index cadd65ddd..65934502d 100644 --- a/src/lib/Makefile.in +++ b/src/lib/Makefile.in @@ -58,6 +58,9 @@ clean: distclean: clean /bin/rm -f Makefile +cppcheck: + cppcheck --template='{file}:{line}:{severity}:{message}' --quiet --enable=all --force -I ../include *.c protocols/*.c + install: $(NDPI_LIBS) mkdir -p $(DESTDIR)$(libdir) cp $(NDPI_LIBS) $(DESTDIR)$(libdir)/ diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc index a060182d8..537b41b5e 100644 --- a/src/lib/ndpi_content_match.c.inc +++ b/src/lib/ndpi_content_match.c.inc @@ -79,34 +79,295 @@ static ndpi_network host_protocol_list[] = { /* WhatsApp Inc. + List of the WhatsApp server IP addresses and ranges (https://developers.facebook.com/docs/whatsapp/network-debugging/ Dec 21, 2018) */ - { 0x1F0D4B00 /* 31.13.75.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, - { 0x1F0D5600 /* 31.13.86.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, - { 0x3216C6CC /* 50.22.198.204/30 */, 30, NDPI_PROTOCOL_WHATSAPP }, - { 0x4B7E2720 /* 75.126.39.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8AE00 /* 108.168.174.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8B0C0 /* 108.168.176.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8B100 /* 108.168.177.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0x6CA8B460 /* 108.168.180.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0x9E553A00 /* 158.85.58.0/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, - { 0x9E55FE40 /* 158.85.254.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xA92C5360 /* 169.44.82.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8FE41 /* 108.168.254.65/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8FFE0 /* 108.168.255.224/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x6CA8FFE3 /* 108.168.255.227/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00135 /* 157.240.1.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00136 /* 157.240.1.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00A35 /* 157.240.10.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00A36 /* 157.240.10.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00B35 /* 157.240.11.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00B36 /* 157.240.11.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00C35 /* 157.240.12.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00C36 /* 157.240.12.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00D36 /* 157.240.13.54/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00E34 /* 157.240.14.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00F35 /* 157.240.15.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00F36 /* 157.240.15.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01034 /* 157.240.16.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01234 /* 157.240.18.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01335 /* 157.240.19.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01336 /* 157.240.19.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00235 /* 157.240.2.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00236 /* 157.240.2.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01434 /* 157.240.20.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01534 /* 157.240.21.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01635 /* 157.240.22.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01636 /* 157.240.22.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01735 /* 157.240.23.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01736 /* 157.240.23.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01D35 /* 157.240.29.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01D36 /* 157.240.29.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00635 /* 157.240.6.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00636 /* 157.240.6.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00735 /* 157.240.7.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00736 /* 157.240.7.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00835 /* 157.240.8.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00836 /* 157.240.8.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00935 /* 157.240.9.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00936 /* 157.240.9.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E550060 /* 158.85.0.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E55E0A0 /* 158.85.224.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E55E920 /* 158.85.233.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E55F980 /* 158.85.249.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E55FE40 /* 158.85.254.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E552E80 /* 158.85.46.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E5530E0 /* 158.85.48.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E5505C0 /* 158.85.5.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E553A00 /* 158.85.58.0/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0x9E553DC0 /* 158.85.61.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92CA700 /* 169.44.167.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C2400 /* 169.44.36.0/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C3940 /* 169.44.57.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C3A40 /* 169.44.58.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5000 /* 169.44.80.0/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5280 /* 169.44.82.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C52C0 /* 169.44.82.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5260 /* 169.44.82.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5300 /* 169.44.83.0/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5380 /* 169.44.83.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C53C0 /* 169.44.83.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5360 /* 169.44.83.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5400 /* 169.44.84.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C5540 /* 169.44.85.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92C57A0 /* 169.44.87.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DA9C0 /* 169.45.169.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DB660 /* 169.45.182.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DD240 /* 169.45.210.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0xA92DD6E0 /* 169.45.214.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0xA92DDBE0 /* 169.45.219.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xA92DF860 /* 169.45.248.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xA92F05C0 /* 169.47.5.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, - { 0xA92F2320 /* 169.47.35.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xA9373CAA /* 169.55.60.170/32 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xA93C4F00 /* 169.60.79.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, - { 0xA93F4C11 /* 169.63.76.0/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, - { 0xA93F4940 /* 169.63.73.64/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DEDC0 /* 169.45.237.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DEE20 /* 169.45.238.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DF2C0 /* 169.45.242.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DF8A0 /* 169.45.248.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92DF860 /* 169.45.248.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92D4720 /* 169.45.71.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92D4760 /* 169.45.71.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92D5780 /* 169.45.87.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92E6F90 /* 169.46.111.144/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92E34E0 /* 169.46.52.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F8260 /* 169.47.130.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F9100 /* 169.47.145.0/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F9980 /* 169.47.153.128/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92FC0C0 /* 169.47.192.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92FC280 /* 169.47.194.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92FC680 /* 169.47.198.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92FD4A0 /* 169.47.212.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2180 /* 169.47.33.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2320 /* 169.47.35.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2580 /* 169.47.37.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2880 /* 169.47.40.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2AA0 /* 169.47.42.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2AC0 /* 169.47.42.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2A60 /* 169.47.42.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F2FA0 /* 169.47.47.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F05C0 /* 169.47.5.192/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA92F0640 /* 169.47.6.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9307220 /* 169.48.114.32/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93079C0 /* 169.48.121.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9307A40 /* 169.48.122.64/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA930D2B0 /* 169.48.210.176/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA930D2E0 /* 169.48.210.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA930D340 /* 169.48.211.64/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA930D480 /* 169.48.212.128/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA935FA80 /* 169.53.250.128/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA935FC40 /* 169.53.252.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA935FF40 /* 169.53.255.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9351D80 /* 169.53.29.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9353020 /* 169.53.48.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93547E0 /* 169.53.71.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9355140 /* 169.53.81.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA936C1A0 /* 169.54.193.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93602A0 /* 169.54.2.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA936D200 /* 169.54.210.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA936DE80 /* 169.54.222.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9362CE0 /* 169.54.44.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9363320 /* 169.54.51.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93637C0 /* 169.54.55.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0xA93764A0 /* 169.55.100.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9377E40 /* 169.55.126.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA937D260 /* 169.55.210.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0xA937EBA0 /* 169.55.235.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9373C94 /* 169.55.60.148/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9373CAA /* 169.55.60.170/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93743E0 /* 169.55.67.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9374580 /* 169.55.69.128/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9374A20 /* 169.55.74.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA9374B60 /* 169.55.75.96/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C8180 /* 169.60.129.128/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C9300 /* 169.60.147.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93CC540 /* 169.60.197.64/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C4A70 /* 169.60.74.112/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C4A80 /* 169.60.74.128/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C4A20 /* 169.60.74.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C4B80 /* 169.60.75.128/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93C4F00 /* 169.60.79.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93D6500 /* 169.61.101.0/24 */, 24, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93D5190 /* 169.61.81.144/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93D51E0 /* 169.61.81.224/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93D5240 /* 169.61.82.64/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93D5480 /* 169.61.84.128/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93F4080 /* 169.63.64.128/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93F4920 /* 169.63.73.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93F4940 /* 169.63.73.64/26 */, 26, NDPI_PROTOCOL_WHATSAPP }, + { 0xA93F4C00 /* 169.63.76.0/25 */, 25, NDPI_PROTOCOL_WHATSAPP }, { 0xADC0A220 /* 173.192.162.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xADC0DB80 /* 173.192.219.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xADC0DEA0 /* 173.192.222.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xADC1E680 /* 173.193.230.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xADC1E6C0 /* 173.193.230.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xADC1EF00 /* 173.193.239.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xAE24D080 /* 174.36.208.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xAE24D220 /* 174.36.210.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xAE24FBC0 /* 174.36.251.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xAE25F340 /* 174.37.243.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xAE25FB00 /* 174.37.251.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC030 /* 179.60.192.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC031 /* 179.60.192.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC033 /* 179.60.192.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC134 /* 179.60.193.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC235 /* 179.60.194.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC236 /* 179.60.194.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC331 /* 179.60.195.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC333 /* 179.60.195.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, { 0xB8AD8840 /* 184.173.136.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xB93CDA35 /* 185.60.218.53/32 */, 27, NDPI_PROTOCOL_WHATSAPP }, - { 0xC60BFB20 /* 198.11.251.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xB8AD9320 /* 184.173.147.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xB8ADA140 /* 184.173.161.64/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB8ADAD74 /* 184.173.173.116/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB8ADB320 /* 184.173.179.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CD835 /* 185.60.216.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CD836 /* 185.60.216.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CD935 /* 185.60.217.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CD936 /* 185.60.217.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CDA35 /* 185.60.218.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CDA36 /* 185.60.218.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CDB35 /* 185.60.219.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB93CDB36 /* 185.60.219.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xC09BD4C0 /* 192.155.212.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xC60BC1B6 /* 198.11.193.182/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0xC60BFB20 /* 198.11.251.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xC6175000 /* 198.23.80.0/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, { 0xD02B73C0 /* 208.43.115.192/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0xD02B754F /* 208.43.117.79/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, { 0xD02B7A80 /* 208.43.122.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4033 /* 31.13.64.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4035 /* 31.13.64.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4131 /* 31.13.65.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4132 /* 31.13.65.50/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4334 /* 31.13.67.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4430 /* 31.13.68.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4434 /* 31.13.68.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D45F0 /* 31.13.69.240/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4631 /* 31.13.70.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4632 /* 31.13.70.50/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4731 /* 31.13.71.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4732 /* 31.13.71.50/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4830 /* 31.13.72.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4834 /* 31.13.72.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4934 /* 31.13.73.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4A34 /* 31.13.74.52/31 */, 31, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4B30 /* 31.13.75.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4B34 /* 31.13.75.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4C51 /* 31.13.76.81/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4C52 /* 31.13.76.82/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4E35 /* 31.13.78.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4E37 /* 31.13.78.55/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5030 /* 31.13.80.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5035 /* 31.13.80.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5130 /* 31.13.81.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5135 /* 31.13.81.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5233 /* 31.13.82.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5237 /* 31.13.82.55/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5331 /* 31.13.83.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5333 /* 31.13.83.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5431 /* 31.13.84.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5433 /* 31.13.84.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5531 /* 31.13.85.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5533 /* 31.13.85.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5631 /* 31.13.86.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5633 /* 31.13.86.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5730 /* 31.13.87.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5733 /* 31.13.87.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5831 /* 31.13.88.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5834 /* 31.13.88.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5935 /* 31.13.89.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5936 /* 31.13.89.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5A31 /* 31.13.90.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5A33 /* 31.13.90.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5B31 /* 31.13.91.49/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5B33 /* 31.13.91.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5C30 /* 31.13.92.48/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5C34 /* 31.13.92.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5D35 /* 31.13.93.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5D36 /* 31.13.93.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5E34 /* 31.13.94.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5E36 /* 31.13.94.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5F32 /* 31.13.95.50/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D5F3F /* 31.13.95.63/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216C6CC /* 50.22.198.204/30 */, 30, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216D280 /* 50.22.210.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216D220 /* 50.22.210.32/30 */, 30, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216E140 /* 50.22.225.64/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216EBF8 /* 50.22.235.248/30 */, 30, NDPI_PROTOCOL_WHATSAPP }, + { 0x3216F0A0 /* 50.22.240.160/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x32175A80 /* 50.23.90.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x32613980 /* 50.97.57.128/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E0C70 /* 75.126.12.112/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E7B40 /* 75.126.123.64/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E8AA0 /* 75.126.138.160/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E8D50 /* 75.126.141.80/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E1430 /* 75.126.20.48/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E2720 /* 75.126.39.32/27 */, 27, NDPI_PROTOCOL_WHATSAPP }, + { 0x4B7E51C0 /* 75.126.81.192/28 */, 28, NDPI_PROTOCOL_WHATSAPP }, + { 0x66846036 /* 102.132.96.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x66846136 /* 102.132.97.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00D36 /* 157.240.13.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00E34 /* 157.240.14.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01034 /* 157.240.16.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01234 /* 157.240.18.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF0C034 /* 157.240.192.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF0C132 /* 157.240.193.50/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF0C236 /* 157.240.194.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01434 /* 157.240.20.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01533 /* 157.240.21.51/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01534 /* 157.240.21.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01836 /* 157.240.24.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01936 /* 157.240.25.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01A36 /* 157.240.26.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01B36 /* 157.240.27.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF00336 /* 157.240.3.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x9DF01E36 /* 157.240.30.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0xB33CC134 /* 179.60.193.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4238 /* 31.13.66.56/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4334 /* 31.13.67.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4934 /* 31.13.73.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4A34 /* 31.13.74.52/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, + { 0x1F0D4F35 /* 31.13.79.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP }, /* Files */ - { 0xB93CD835 /* 185.60.216.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CD835 /* 185.60.216.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CD836 /* 185.60.216.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CD935 /* 185.60.217.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CD936 /* 185.60.217.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CDA35 /* 185.60.218.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CDA36 /* 185.60.218.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CDB35 /* 185.60.219.53/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, + { 0xB93CDB36 /* 185.60.219.54/32 */, 32, NDPI_PROTOCOL_WHATSAPP_FILES }, /* WeChat @@ -661,7 +922,12 @@ static ndpi_network host_protocol_list[] = { { 0x022E8A340 /* 34.232.163.64/28 */, 28, NDPI_PROTOCOL_VIBER }, { 0x022F67200 /* 34.246.114.0/23 */, 23, NDPI_PROTOCOL_VIBER }, { 0x3400FC00 /* 52.0.252.0/22 */, 22, NDPI_PROTOCOL_VIBER }, + { 0x3403A746 /* 52.3.167.70/32 */, 32, NDPI_PROTOCOL_VIBER }, + { 0x34162CEB /* 52.22.44.235/32 */, 32, NDPI_PROTOCOL_VIBER }, + { 0x34165F0F /* 52.22.95.15/32 */, 32, NDPI_PROTOCOL_VIBER }, { 0x3640BFF0 /* 54.64.191.240/28 */, 28, NDPI_PROTOCOL_VIBER }, + { 0x3655545D /* 54.85.84.93/32 */, 32, NDPI_PROTOCOL_VIBER }, + { 0x3655565D /* 54.85.86.93/32 */, 32, NDPI_PROTOCOL_VIBER }, { 0x36A5FFD0 /* 54.165.255.208/28 */, 28, NDPI_PROTOCOL_VIBER }, { 0x36A5FFE0 /* 54.165.255.224/27 */, 27, NDPI_PROTOCOL_VIBER }, { 0x36DBBFA0 /* 54.219.191.160/28 */, 28, NDPI_PROTOCOL_VIBER }, diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index e18c220a5..7a954a710 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -423,7 +423,8 @@ static const char* categories[] = { "Malware", "Advertisement", "Banned_Site", - "Site_Unavailable" + "Site_Unavailable", + "Allowed_Site", }; /* ****************************************** */ @@ -545,7 +546,7 @@ ndpi_port_range * ndpi_build_default_ports_range(ndpi_port_range *ports, ports[i].port_low = portB_low, ports[i].port_high = portB_high; i++; ports[i].port_low = portC_low, ports[i].port_high = portC_high; i++; ports[i].port_low = portD_low, ports[i].port_high = portD_high; i++; - ports[i].port_low = portE_low, ports[i].port_high = portE_high; i++; + ports[i].port_low = portE_low, ports[i].port_high = portE_high; return(ports); } @@ -564,7 +565,7 @@ ndpi_port_range * ndpi_build_default_ports(ndpi_port_range *ports, ports[i].port_low = portB, ports[i].port_high = portB; i++; ports[i].port_low = portC, ports[i].port_high = portC; i++; ports[i].port_low = portD, ports[i].port_high = portD; i++; - ports[i].port_low = portE, ports[i].port_high = portE; i++; + ports[i].port_low = portE, ports[i].port_high = portE; return(ports); } @@ -718,8 +719,7 @@ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_mod, ndpi_proto_defaults_t *def, u_int8_t customUserProto, ndpi_default_ports_tree_node_t **root, - const char *_func, int _line) -{ + const char *_func, int _line) { ndpi_default_ports_tree_node_t *ret; u_int16_t port; @@ -999,6 +999,7 @@ static void free_hyperscan_memory(struct hs *h) { if(h) { hs_free_scratch(h->scratch); hs_free_database(h->database); + free(h); } } @@ -2174,16 +2175,6 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str /* ******************************************* */ -/* u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host /\* network byte order *\/) { */ -/* struct in_addr pin; */ - -/* pin.s_addr = host; */ - -/* return(ndpi_network_ptree_match(ndpi_struct, &pin)); */ -/* } */ - -/* ******************************************* */ - #if 0 static u_int8_t tor_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin) { return((ndpi_network_ptree_match(ndpi_struct, pin) == NDPI_PROTOCOL_TOR) ? 1 : 0); @@ -2380,7 +2371,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(void) { for(i=0; i<NUM_CUSTOM_CATEGORIES; i++) snprintf(ndpi_str->custom_category_labels[i], - CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u", i+1); + CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u", (unsigned int)(i+1)); return ndpi_str; } @@ -2698,8 +2689,8 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struc struct ndpi_flow_struct *flow, u_int8_t proto, u_int16_t sport, u_int16_t dport, u_int8_t *user_defined_proto) { - *user_defined_proto = 0; /* Default */ + if(sport && dport) { ndpi_default_ports_tree_node_t *found = ndpi_get_guessed_protocol_id(ndpi_struct, proto, sport, dport); @@ -2895,12 +2886,18 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_mod, Format: <tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto> + Subprotocols Format: + host:"<value>",host:"<value>",.....@<subproto> + + IP based Subprotocols Format (<value> is IP or CIDR): + ip:<value>,ip:<value>,.....@<subproto> + Example: tcp:80,tcp:3128@HTTP udp:139@NETBIOS */ -int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char* path) { +int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, const char* path) { FILE *fd; char *buffer, *old_buffer; int chunk_len = 512, buffer_len = chunk_len, old_buffer_len; @@ -2909,14 +2906,14 @@ int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char fd = fopen(path, "r"); if(fd == NULL) { - NDPI_LOG_ERR(ndpi_mod, "Unable to open file %s [%s]", path, strerror(errno)); + NDPI_LOG_ERR(ndpi_mod, "Unable to open file %s [%s]\n", path, strerror(errno)); goto error; } buffer = ndpi_malloc(buffer_len); if(buffer == NULL) { - NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure"); + NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure\n"); goto close_fd; } @@ -2933,7 +2930,7 @@ int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char buffer = ndpi_realloc(old_buffer, old_buffer_len, buffer_len); if(buffer == NULL) { - NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure"); + NDPI_LOG_ERR(ndpi_mod, "Memory allocation failure\n"); free(old_buffer); goto close_fd; } @@ -3023,8 +3020,7 @@ void ndpi_set_bitmask_protocol_detection(char * label, /* ******************************************************************** */ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct, - const NDPI_PROTOCOL_BITMASK * dbm) -{ + const NDPI_PROTOCOL_BITMASK * dbm) { NDPI_PROTOCOL_BITMASK detection_bitmask_local; NDPI_PROTOCOL_BITMASK *detection_bitmask = &detection_bitmask_local; u_int32_t a = 0; @@ -3861,8 +3857,6 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, const struct ndpi_tcphdr *tcph = packet->tcp; const struct ndpi_udphdr *udph = flow->packet.udp; - u_int8_t proxy_enabled = 0; - packet->tcp_retransmission = 0, packet->packet_direction = 0; if(ndpi_struct->direction_detect_disable) { @@ -3907,7 +3901,7 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, flow->l4.tcp.seen_ack = 1; } if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) - || (proxy_enabled && (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0))) { + || (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) { /* initialize tcp sequence counters */ /* the ack flag needs to be set to get valid sequence numbers from the other * direction. Usually it will catch the second packet syn+ack but it works @@ -3919,9 +3913,8 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, if(tcph->ack != 0) { flow->next_tcp_seq_nr[flow->packet.packet_direction] = ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len); - if(!proxy_enabled) { - flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq); - } + + flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq); } } else if(packet->payload_packet_len > 0) { /* check tcp sequence counters */ @@ -4185,7 +4178,7 @@ static ndpi_protocol ndpi_process_partial_detection(struct ndpi_detection_module ret.app_protocol = ret.master_protocol; ndpi_fill_protocol_category(ndpi_struct, flow, &ret); - + ndpi_int_change_protocol(ndpi_struct, flow, ret.app_protocol, ret.master_protocol); return(ret); @@ -4279,6 +4272,20 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st && (flow->protos.stun_ssl.stun.num_processed_pkts > 0)) guessed_protocol_id = NDPI_PROTOCOL_STUN; + + if(flow->host_server_name[0] != '\0') { + ndpi_protocol_match_result ret_match; + + ndpi_match_host_subprotocol(ndpi_struct, flow, + (char *)flow->host_server_name, + strlen((const char*)flow->host_server_name), + &ret_match, + NDPI_PROTOCOL_DNS); + + if(ret_match.protocol_id != NDPI_PROTOCOL_UNKNOWN) + guessed_host_protocol_id = ret_match.protocol_id; + } + ndpi_int_change_protocol(ndpi_struct, flow, guessed_host_protocol_id, guessed_protocol_id); @@ -4433,18 +4440,8 @@ int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_struct struct hs_list *h = (struct hs_list*)malloc(sizeof(struct hs_list)); if(h) { - char tmp[256]; int i, j; - for(i=0, j=0; (j<sizeof(tmp)) && (name[i] != '\0'); i++) { - if(name[i] == '.') - tmp[j++] = '\\'; - - tmp[j++] = name[i]; - } - - tmp[j] = '\0'; - h->expression = ndpi_strdup(name), h->id = (unsigned int)category; if(h->expression == NULL) { free(h); @@ -4507,7 +4504,8 @@ int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str) ndpi_str->custom_categories.hostnames = (struct hs*)malloc(sizeof(struct hs)); if(ndpi_str->custom_categories.hostnames == NULL) { - free(expressions), free(ids); + free(expressions); + free(ids); return(-1); /* Failed */ } @@ -4599,9 +4597,9 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc ndpi_protocol *ret) { if(ndpi_struct->custom_categories.categories_loaded) { if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) { - flow->category = flow->guessed_header_category; + flow->category = ret->category = flow->guessed_header_category; return; - } + } if(flow->host_server_name[0] != '\0') { unsigned long id; @@ -4652,14 +4650,29 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct flow->num_processed_pkts++; if(flow->server_id == NULL) flow->server_id = dst; /* Default */ - if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) - goto ret_protocols; + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) { + /* + With SSL we might want to dissect further packets to decode + the certificate type for instance + */ + if(flow->check_extra_packets + /* + && ((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) + || (flow->detected_protocol_stack[1] == NDPI_PROTOCOL_SSL)) + */ + ) { + ndpi_process_extra_packet(ndpi_struct, flow, packet, packetlen, current_tick_l, src, dst); + ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; + return(ret); + } else + goto ret_protocols; + } /* need at least 20 bytes for ip header */ if(packetlen < 20) { /* reset protocol which is normally done in init_packet_header */ ndpi_int_reset_packet_protocol(&flow->packet); - return(ret); + goto invalidate_ptr; } flow->packet.tick_timestamp_l = current_tick_l; @@ -4670,7 +4683,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct /* we are interested in ipv4 packet */ if(ndpi_init_packet_header(ndpi_struct, flow, packetlen) != 0) - return(ret); + goto invalidate_ptr; /* detect traffic for tcp or udp only */ flow->src = src, flow->dst = dst; @@ -4731,19 +4744,19 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_struct, flow); if(ndpi_struct->custom_categories.categories_loaded && flow->packet.iph) { - ndpi_protocol ret; - + ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED }; + ndpi_fill_ip_protocol_category(ndpi_struct, flow->packet.iph->saddr, flow->packet.iph->daddr, &ret); flow->guessed_header_category = ret.category; } else flow->guessed_header_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED; - + if(flow->guessed_protocol_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS-1)) { /* This is a custom protocol and it has priority over everything else */ ret.master_protocol = NDPI_PROTOCOL_UNKNOWN, ret.app_protocol = flow->guessed_protocol_id ? flow->guessed_protocol_id : flow->guessed_host_protocol_id; ndpi_fill_protocol_category(ndpi_struct, flow, &ret); - return(ret); + goto invalidate_ptr; } if(user_defined_proto && flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) { @@ -4754,7 +4767,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct } ndpi_fill_protocol_category(ndpi_struct, flow, &ret); - return(ret); + goto invalidate_ptr; } } else { /* guess host protocol */ @@ -4784,8 +4797,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct ndpi_check_flow_func(ndpi_struct, flow, &ndpi_selection_packet); ndpi_fill_protocol_category(ndpi_struct, flow, &ret); - - return(ret); + goto invalidate_ptr; } ndpi_check_flow_func(ndpi_struct, flow, &ndpi_selection_packet); @@ -4797,10 +4809,14 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct if(a != NDPI_PROTOCOL_UNKNOWN) { int i; - for(i=0; (i<sizeof(flow->host_server_name)) && (flow->host_server_name[i] != '\0'); i++) - flow->host_server_name[i] = tolower(flow->host_server_name[i]); - - flow->host_server_name[i] ='\0'; + for(i=0; i<sizeof(flow->host_server_name); i++) { + if(flow->host_server_name[i] != '\0') + flow->host_server_name[i] = tolower(flow->host_server_name[i]); + else { + flow->host_server_name[i] ='\0'; + break; + } + } } ret_protocols: @@ -4831,6 +4847,13 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct ret = ndpi_detection_giveup(ndpi_struct, flow, 0); } + invalidate_ptr: + /* + Invalidate packet memory to avoid accessing the pointers below + when the packet is no longer accessible + */ + flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL; + return(ret); } @@ -5030,7 +5053,8 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struc packet->line[packet->parsed_lines].ptr = packet->payload; packet->line[packet->parsed_lines].len = 0; - for(a = 0; a < packet->payload_packet_len; a++) { + for(a = 0; (a < packet->payload_packet_len) + && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET); a++) { if((a + 1) == packet->payload_packet_len) return; /* Return if only one byte remains (prevent invalid reads past end-of-buffer) */ @@ -5691,8 +5715,8 @@ char *ndpi_get_packet_dst_ip_string(struct ndpi_detection_module_struct *ndpi_st /* ****************************************************** */ u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t * str, - u_int16_t max_chars_to_read, u_int16_t * bytes_read) -{ + u_int16_t max_chars_to_read, + u_int16_t * bytes_read) { u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read); return ntohs(val); } @@ -6107,7 +6131,7 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str u_int16_t master_protocol_id, ndpi_protocol_match_result *ret_match, u_int8_t is_host_match) { - int matching_protocol_id = NDPI_PROTOCOL_UNKNOWN; + int matching_protocol_id; struct ndpi_packet_struct *packet = &flow->packet; #ifndef HAVE_HYPERSCAN @@ -6117,6 +6141,8 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str #else struct hs *hs = (struct hs*)ndpi_struct->hyperscan; hs_error_t status; + + matching_protocol_id = NDPI_PROTOCOL_UNKNOWN; /* TODO HYPERSCAN In case of match fill up ret_match and set flow protocol + category @@ -6378,3 +6404,54 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc return(0); /* OK */ } + +/* **************************************** */ + +/* **************************************** */ + +struct cipher_weakness { + u_int16_t cipher_id; + ndpi_cipher_weakness weakness_type; +}; + +static struct cipher_weakness safe_ssl_ciphers[] = { + /* https://community.qualys.com/thread/18212-how-does-qualys-determine-the-server-cipher-suites */ + /* INSECURE */ + { 0xc011, NDPI_CIPHER_INSECURE }, /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ + { 0x0005, NDPI_CIPHER_INSECURE }, /* TLS_RSA_WITH_RC4_128_SHA */ + { 0x0004, NDPI_CIPHER_INSECURE }, /* TLS_RSA_WITH_RC4_128_MD5 */ + /* WEAK */ + { 0x009d, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_GCM_SHA384 */ + { 0x003d, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ + { 0x0035, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_256_CBC_SHA */ + { 0x0084, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */ + { 0x009c, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_GCM_SHA256 */ + { 0x003c, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_CBC_SHA256 */ + { 0x002f, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_AES_128_CBC_SHA */ + { 0x0041, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */ + { 0xc012, NDPI_CIPHER_WEAK }, /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */ + { 0x0016, NDPI_CIPHER_WEAK }, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ + { 0x000a, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */ + { 0x0096, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_SEED_CBC_SHA */ + { 0x0007, NDPI_CIPHER_WEAK }, /* TLS_RSA_WITH_IDEA_CBC_SHA */ + + { 0x0, NDPI_CIPHER_SAFE } /* END */ +}; + +u_int8_t ndpi_is_safe_ssl_cipher(u_int16_t cipher) { + u_int i; + + for(i=0; safe_ssl_ciphers[i].cipher_id != 0; i++) { + if(safe_ssl_ciphers[i].cipher_id == cipher) { +#ifdef CERTIFICATE_DEBUG + printf("%s %s(%04X / %u)\n", + (safe_ssl_ciphers[i].weakness_type == NDPI_CIPHER_WEAK) ? "WEAK" : "INSECURE", + __FUNCTION__, cipher, cipher); +#endif + + return(safe_ssl_ciphers[i].weakness_type); + } + } + + return(NDPI_CIPHER_SAFE); /* We're safe */ +} diff --git a/src/lib/protocols/btlib.c b/src/lib/protocols/btlib.c index 5992c1b28..ea06a6348 100644 --- a/src/lib/protocols/btlib.c +++ b/src/lib/protocols/btlib.c @@ -204,8 +204,7 @@ void cb_data(bt_parse_data_cb_t *cbd,int *ret) { if(cbd->t == 0) return; if(cbd->t == 1) { - - DEBUG_TRACE(printf("%s %lld\n",cbd->buf,cbd->v.i)); + DEBUG_TRACE(printf("%s %lld\n",cbd->buf, (long long)cbd->v.i)); if(STREQ(cbd->buf,"a.port")) { p->a.port = (u_int16_t)(cbd->v.i & 0xffff); @@ -234,7 +233,7 @@ void cb_data(bt_parse_data_cb_t *cbd,int *ret) { p->h_mint = 1; return; } - DEBUG_TRACE(printf("UNKNOWN %s %lld\n",cbd->buf,cbd->v.i)); + DEBUG_TRACE(printf("UNKNOWN %s %lld\n",cbd->buf, (long long)cbd->v.i)); return; } if(cbd->t != 2) { diff --git a/src/lib/protocols/coap.c b/src/lib/protocols/coap.c index cf5061bbe..c99ab5fc1 100644 --- a/src/lib/protocols/coap.c +++ b/src/lib/protocols/coap.c @@ -130,7 +130,7 @@ void ndpi_search_coap (struct ndpi_detection_module_struct *ndpi_struct, if(h->version == 1) { if(h->type == CON || h->type == NO_CON || h->type == ACK || h->type == RST ) { if(h->tkl < 8) { - if((h->code >= 0 && h->code <= 5) || (h->code >= 65 && h->code <= 69) || + if((/* h->code >= 0 && */ h->code <= 5) || (h->code >= 65 && h->code <= 69) || (h->code >= 128 && h->code <= 134) || (h->code >= 140 && h->code <= 143) || (h->code >= 160 && h->code <= 165)) { diff --git a/src/lib/protocols/csgo.c b/src/lib/protocols/csgo.c index 7f4479419..f316f96b7 100644 --- a/src/lib/protocols/csgo.c +++ b/src/lib/protocols/csgo.c @@ -30,6 +30,11 @@ void ndpi_search_csgo(struct ndpi_detection_module_struct* ndpi_struct, struct n struct ndpi_packet_struct* packet = &flow->packet; if (packet->udp != NULL) { + if (packet->payload_packet_len < sizeof(uint32_t)) { + NDPI_LOG_DBG2(ndpi_struct, "Short csgo packet\n"); + return; + } + uint32_t w = htonl(get_u_int32_t(packet->payload, 0)); NDPI_LOG_DBG2(ndpi_struct, "CSGO: word %08x\n", w); diff --git a/src/lib/protocols/directconnect.c b/src/lib/protocols/directconnect.c index 5088685e4..19582724d 100644 --- a/src/lib/protocols/directconnect.c +++ b/src/lib/protocols/directconnect.c @@ -318,7 +318,6 @@ static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct struct ndpi_id_struct *dst = flow->dst; int pos, count = 0; - if (dst != NULL && dst->detected_directconnect_udp_port == packet->udp->dest) { if ((u_int32_t) (packet->tick_timestamp - diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 1c2593feb..dc97f3fe7 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -190,11 +190,11 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd flow->protos.dns.rsp_type = rsp_type; /* here x points to the response "class" field */ - if((x+12) < flow->packet.payload_packet_len) { + if((x+12) <= flow->packet.payload_packet_len) { x += 6; data_len = get16(&x, flow->packet.payload); - if(((x + data_len) < flow->packet.payload_packet_len) + if(((x + data_len) <= flow->packet.payload_packet_len) && (((rsp_type == 0x1) && (data_len == 4)) /* A */ #ifdef NDPI_DETECTION_SUPPORT_IPV6 || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */ diff --git a/src/lib/protocols/dropbox.c b/src/lib/protocols/dropbox.c index 39bb96ff2..895bb0164 100644 --- a/src/lib/protocols/dropbox.c +++ b/src/lib/protocols/dropbox.c @@ -30,11 +30,9 @@ #define DB_LSP_PORT 17500 - static void ndpi_int_dropbox_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int8_t due_to_correlation) -{ + u_int8_t due_to_correlation) { ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_DROPBOX, NDPI_PROTOCOL_UNKNOWN); } @@ -51,8 +49,7 @@ static void ndpi_check_dropbox(struct ndpi_detection_module_struct *ndpi_struct, if(packet->udp->dest == dropbox_port) { if(packet->udp->source == dropbox_port) { if(payload_len > 10) { - if(ndpi_strnstr((const char *)packet->payload, "\"host_int\"", payload_len) != NULL) { - + if(ndpi_strnstr((const char *)packet->payload, "\"host_int\"", payload_len) != NULL) { NDPI_LOG_INFO(ndpi_struct, "found dropbox\n"); ndpi_int_dropbox_add_connection(ndpi_struct, flow, 0); return; @@ -60,8 +57,7 @@ static void ndpi_check_dropbox(struct ndpi_detection_module_struct *ndpi_struct, } } else { if(payload_len > 10) { - if(ndpi_strnstr((const char *)packet->payload, "Bus17Cmd", payload_len) != NULL) { - + if(ndpi_strnstr((const char *)packet->payload, "Bus17Cmd", payload_len) != NULL) { NDPI_LOG_INFO(ndpi_struct, "found dropbox\n"); ndpi_int_dropbox_add_connection(ndpi_struct, flow, 0); return; diff --git a/src/lib/protocols/edonkey.c b/src/lib/protocols/edonkey.c index 547bafc5f..ca5abebad 100644 --- a/src/lib/protocols/edonkey.c +++ b/src/lib/protocols/edonkey.c @@ -177,7 +177,6 @@ static void ndpi_check_edonkey(struct ndpi_detection_module_struct *ndpi_struct, /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */ flow->edonkey_stage = packet->packet_direction + 1; } - } else { NDPI_LOG_DBG2(ndpi_struct, "EDONKEY stage %u: \n", flow->edonkey_stage); @@ -187,7 +186,7 @@ static void ndpi_check_edonkey(struct ndpi_detection_module_struct *ndpi_struct, } /* This is a packet in another direction. Check if we find the proper response. */ - if((payload_len == 0) || (ndpi_edonkey_payload_check(packet->payload, payload_len))) { + if(ndpi_edonkey_payload_check(packet->payload, payload_len)) { NDPI_LOG_INFO(ndpi_struct, "found EDONKEY\n"); ndpi_int_edonkey_add_connection(ndpi_struct, flow); } else { diff --git a/src/lib/protocols/ftp_data.c b/src/lib/protocols/ftp_data.c index 7c646c363..3aaf6f97e 100644 --- a/src/lib/protocols/ftp_data.c +++ b/src/lib/protocols/ftp_data.c @@ -62,9 +62,11 @@ static int ndpi_match_ftp_data_directory(struct ndpi_detection_module_struct *nd ; } else return 0; + + return 1; } - return 1; + return 0; } static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { diff --git a/src/lib/protocols/gnutella.c b/src/lib/protocols/gnutella.c index 5bc2980cc..75a8e534b 100644 --- a/src/lib/protocols/gnutella.c +++ b/src/lib/protocols/gnutella.c @@ -68,7 +68,6 @@ void ndpi_search_gnutella(struct ndpi_detection_module_struct *ndpi_struct, stru struct ndpi_id_struct *src = flow->src; struct ndpi_id_struct *dst = flow->dst; - u_int16_t c; NDPI_LOG_DBG(ndpi_struct, "search GNUTELLA\n"); diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c index 33ef9e2ed..e715dd499 100644 --- a/src/lib/protocols/http.c +++ b/src/lib/protocols/http.c @@ -184,6 +184,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_ case 'P': switch(flow->packet.http_method.ptr[1]) { + case 'A': flow->http.method = NDPI_HTTP_METHOD_PATCH; break; case 'O': flow->http.method = NDPI_HTTP_METHOD_POST; break; case 'U': flow->http.method = NDPI_HTTP_METHOD_PUT; break; } @@ -414,6 +415,7 @@ static struct l_string { STATIC_STRING_L("OPTIONS "), STATIC_STRING_L("HEAD "), STATIC_STRING_L("PUT "), + STATIC_STRING_L("PATCH "), STATIC_STRING_L("DELETE "), STATIC_STRING_L("CONNECT "), STATIC_STRING_L("PROPFIND "), diff --git a/src/lib/protocols/icecast.c b/src/lib/protocols/icecast.c index 515d5b572..0bb87b88a 100644 --- a/src/lib/protocols/icecast.c +++ b/src/lib/protocols/icecast.c @@ -64,6 +64,8 @@ void ndpi_search_icecast_tcp(struct ndpi_detection_module_struct *ndpi_struct, s goto icecast_exclude; } + if(flow == NULL) return; + if((packet->packet_direction == flow->setup_packet_direction) && (flow->packet_counter < 10)) { return; diff --git a/src/lib/protocols/mail_smtp.c b/src/lib/protocols/mail_smtp.c index f7fbd337c..fdc47d15c 100644 --- a/src/lib/protocols/mail_smtp.c +++ b/src/lib/protocols/mail_smtp.c @@ -58,13 +58,16 @@ void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct NDPI_LOG_DBG(ndpi_struct, "search mail_smtp\n"); - if (packet->payload_packet_len > 2 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) { + if((packet->payload_packet_len > 2) + && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET) + && (ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) + ) { u_int8_t a; u_int8_t bit_count = 0; NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow,packet); - for (a = 0; a < packet->parsed_lines; a++) { + for (a = 0; a < packet->parsed_lines; a++) { // expected server responses if (packet->line[a].len >= 3) { if (memcmp(packet->line[a].ptr, "220", 3) == 0) { diff --git a/src/lib/protocols/memcached.c b/src/lib/protocols/memcached.c index e9deb5cc9..44a8b0858 100644 --- a/src/lib/protocols/memcached.c +++ b/src/lib/protocols/memcached.c @@ -89,7 +89,7 @@ #define MEMCACHED_MIN_MATCH 2 /* Minimum number of command/responses required */ -#define MEMCACHED_MATCH(cr) memcmp(offset, cr, cr ## _LEN) +#define MEMCACHED_MATCH(cr) (cr ## _LEN > length || memcmp(offset, cr, cr ## _LEN)) static void ndpi_int_memcached_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) @@ -105,6 +105,7 @@ void ndpi_search_memcached( { struct ndpi_packet_struct *packet = &flow->packet; const u_int8_t *offset = packet->payload; + const u_int16_t length = packet->payload_packet_len; u_int8_t *matches; NDPI_LOG_DBG(ndpi_struct, "search memcached\n"); diff --git a/src/lib/protocols/mysql.c b/src/lib/protocols/mysql.c index d1602a2fe..1306c381d 100644 --- a/src/lib/protocols/mysql.c +++ b/src/lib/protocols/mysql.c @@ -29,42 +29,46 @@ #include "ndpi_api.h" - -static void ndpi_int_mysql_add_connection(struct ndpi_detection_module_struct - *ndpi_struct, struct ndpi_flow_struct *flow) -{ - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MYSQL, NDPI_PROTOCOL_UNKNOWN); -} - -void ndpi_search_mysql_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ +void ndpi_search_mysql_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; NDPI_LOG_DBG(ndpi_struct, "search MySQL\n"); if(packet->tcp) { - if (packet->payload_packet_len > 38 //min length - && get_u_int16_t(packet->payload, 0) == packet->payload_packet_len - 4 //first 3 bytes are length - && get_u_int8_t(packet->payload, 2) == 0x00 //3rd byte of packet length - && get_u_int8_t(packet->payload, 3) == 0x00 //packet sequence number is 0 for startup packet - && get_u_int8_t(packet->payload, 5) > 0x30 //server version > 0 - && get_u_int8_t(packet->payload, 5) < 0x37 //server version < 7 - && get_u_int8_t(packet->payload, 6) == 0x2e //dot - ) { + if(packet->payload_packet_len > 38 //min length + && get_u_int16_t(packet->payload, 0) == packet->payload_packet_len - 4 //first 3 bytes are length + && get_u_int8_t(packet->payload, 2) == 0x00 //3rd byte of packet length + && get_u_int8_t(packet->payload, 3) == 0x00 //packet sequence number is 0 for startup packet + && get_u_int8_t(packet->payload, 5) > 0x30 //server version > 0 + && get_u_int8_t(packet->payload, 5) < 0x37 //server version < 7 + && get_u_int8_t(packet->payload, 6) == 0x2e //dot + ) { +#if 0 + /* Old code */ u_int32_t a; - for (a = 7; a + 31 < packet->payload_packet_len; a++) { - if (packet->payload[a] == 0x00) { - if (get_u_int8_t(packet->payload, a + 13) == 0x00 //filler byte - && get_u_int64_t(packet->payload, a + 19) == 0x0ULL //13 more - && get_u_int32_t(packet->payload, a + 27) == 0x0 //filler bytes - && get_u_int8_t(packet->payload, a + 31) == 0x0) { + + for(a = 7; a + 31 < packet->payload_packet_len; a++) { + if(packet->payload[a] == 0x00) { + if(get_u_int8_t(packet->payload, a + 13) == 0x00 // filler byte + && get_u_int64_t(packet->payload, a + 19) == 0x0ULL // 13 more + && get_u_int32_t(packet->payload, a + 27) == 0x0 // filler bytes + && get_u_int8_t(packet->payload, a + 31) == 0x0) { NDPI_LOG_INFO(ndpi_struct, "found MySQL\n"); - ndpi_int_mysql_add_connection(ndpi_struct, flow); + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MYSQL, NDPI_PROTOCOL_UNKNOWN); return; } + break; } } +#else + if(strncmp((const char*)&packet->payload[packet->payload_packet_len-22], + "mysql_", 6) == 0) { + NDPI_LOG_INFO(ndpi_struct, "found MySQL\n"); + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MYSQL, NDPI_PROTOCOL_UNKNOWN); + return; + } +#endif } } diff --git a/src/lib/protocols/sip.c b/src/lib/protocols/sip.c index 1436b2cec..2583dbfdf 100644 --- a/src/lib/protocols/sip.c +++ b/src/lib/protocols/sip.c @@ -123,6 +123,28 @@ void ndpi_search_sip_handshake(struct ndpi_detection_module_struct return; } + if ((memcmp(packet_payload, "PUBLISH ", 8) == 0 || memcmp(packet_payload, "publish ", 8) == 0) + && (memcmp(&packet_payload[8], "SIP:", 4) == 0 || memcmp(&packet_payload[8], "sip:", 4) == 0)) { + NDPI_LOG_INFO(ndpi_struct, "found sip PUBLISH\n"); + ndpi_int_sip_add_connection(ndpi_struct, flow, 0); + return; + } + + if ((memcmp(packet_payload, "SUBSCRIBE ", 10) == 0 || memcmp(packet_payload, "subscribe ", 10) == 0) + && (memcmp(&packet_payload[10], "SIP:", 4) == 0 || memcmp(&packet_payload[10], "sip:", 4) == 0)) { + NDPI_LOG_INFO(ndpi_struct, "found sip SUBSCRIBE\n"); + ndpi_int_sip_add_connection(ndpi_struct, flow, 0); + return; + } + + /* SIP message extension RFC 3248 */ + if ((memcmp(packet_payload, "MESSAGE ", 8) == 0 || memcmp(packet_payload, "message ", 8) == 0) + && (memcmp(&packet_payload[8], "SIP:", 4) == 0 || memcmp(&packet_payload[8], "sip:", 4) == 0)) { + NDPI_LOG_INFO(ndpi_struct, "found sip MESSAGE\n"); + ndpi_int_sip_add_connection(ndpi_struct, flow, 0); + return; + } + /* Courtesy of Miguel Quesada <mquesadab@gmail.com> */ if ((memcmp(packet_payload, "OPTIONS ", 8) == 0 || memcmp(packet_payload, "options ", 8) == 0) diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c index 05988a8d4..eee31e94b 100644 --- a/src/lib/protocols/ssl.c +++ b/src/lib/protocols/ssl.c @@ -27,7 +27,7 @@ #include "ndpi_api.h" -// #define CERTIFICATE_DEBUG 1 +/* #define CERTIFICATE_DEBUG 1 */ #define NDPI_MAX_SSL_REQUEST_SIZE 10000 @@ -35,6 +35,204 @@ extern u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); +/* **************************************** */ + +typedef struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +} MD5_CTX; + +/* **************************************** */ + +static int is_big_endian(void) { + static const int n = 1; + return ((char *) &n)[0] == 0; +} + +static void byteReverse(unsigned char *buf, unsigned longs) { + uint32_t t; + + // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN + if (is_big_endian()) { + do { + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + * (uint32_t *) buf = t; + buf += 4; + } while (--longs); + } +} + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +// initialization constants. +static void MD5Init(MD5_CTX *ctx) { + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { + uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { + uint32_t t; + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) + ctx->bits[1]++; + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += t; + len -= t; + } + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += 64; + len -= 64; + } + + memcpy(ctx->in, buf, len); +} + +static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) { + unsigned count; + unsigned char *p; + uint32_t *c = (uint32_t*)ctx->in; + + count = (ctx->bits[0] >> 3) & 0x3F; + + p = ctx->in + count; + *p++ = 0x80; + count = 64 - 1 - count; + if (count < 8) { + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + memset(ctx->in, 0, 56); + } else { + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + c[14] = ctx->bits[0]; + c[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(*ctx)); +} + +/* **************************************** */ + static u_int32_t ndpi_ssl_refine_master_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int32_t protocol) { @@ -143,18 +341,42 @@ static void stripCertificateTrailer(char *buffer, int buffer_len) { } } -/* Code fixes courtesy of Alexsandro Brahm <alex@digistar.com.br> */ +/* https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 */ + +#define JA3_STR_LEN 1024 +#define MAX_NUM_JA3 128 + +struct ja3_info { + u_int16_t ssl_version; + u_int16_t num_cipher, cipher[MAX_NUM_JA3]; + u_int16_t num_ssl_extension, ssl_extension[MAX_NUM_JA3]; + u_int16_t num_elliptic_curve, elliptic_curve[MAX_NUM_JA3]; + u_int8_t num_elliptic_curve_point_format, elliptic_curve_point_format[MAX_NUM_JA3]; +}; + +/* **************************************** */ + +/* code fixes courtesy of Alexsandro Brahm <alex@digistar.com.br> */ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, char *buffer, int buffer_len) { struct ndpi_packet_struct *packet = &flow->packet; + struct ja3_info ja3; + u_int8_t invalid_ja3 = 0; + u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2], ja3_str_len; + char ja3_str[JA3_STR_LEN]; + MD5_CTX ctx; + u_char md5_hash[16]; + + flow->protos.stun_ssl.ssl.ssl_version = ssl_version; + + memset(&ja3, 0, sizeof(ja3)); #ifdef CERTIFICATE_DEBUG { - u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2]; - u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4]; - - printf("SSL Record [version: 0x%02X][len: %u]\n", ssl_version, ssl_len); + u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4]; + + printf("SSL Record [version: %u][len: %u]\n", ssl_version, ssl_len); } #endif @@ -183,10 +405,84 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, if((handshake_protocol == 0x02) || (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) { u_int num_found = 0; + u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9])); + + ja3.ssl_version = ssl_version; + + if(handshake_protocol == 0x02) { + u_int16_t offset = 43, extension_len, j; + u_int8_t session_id_len = packet->payload[43]; + + offset += session_id_len+1; + + ja3.num_cipher = 1, ja3.cipher[0] = ntohs(*((u_int16_t*)&packet->payload[offset])); + flow->protos.stun_ssl.ssl.server_unsafe_cipher = ndpi_is_safe_ssl_cipher(ja3.cipher[0]); + flow->protos.stun_ssl.ssl.server_cipher = ja3.cipher[0]; + +#ifdef CERTIFICATE_DEBUG + printf("SSL [server][session_id_len: %u][cipher: %04X]\n", session_id_len, ja3.cipher[0]); +#endif + + offset += 2 + 1; + extension_len = ntohs(*((u_int16_t*)&packet->payload[offset])); + +#ifdef CERTIFICATE_DEBUG + printf("SSL [server][extension_len: %u]\n", extension_len); +#endif + offset += 2; + + for(i=0; i<extension_len; ) { + u_int16_t id, len; + + if(offset >= (packet->payload_packet_len+4)) break; + + id = ntohs(*((u_int16_t*)&packet->payload[offset])); + len = ntohs(*((u_int16_t*)&packet->payload[offset+2])); + + if(ja3.num_ssl_extension < MAX_NUM_JA3) + ja3.ssl_extension[ja3.num_ssl_extension++] = id; + +#ifdef CERTIFICATE_DEBUG + printf("SSL [server][extension_id: %u]\n", id); +#endif + + i += 4 + len, offset += 4 + len; + } + + ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version); + + for(i=0; i<ja3.num_cipher; i++) + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.cipher[i]); + + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); + + /* ********** */ - if(handshake_protocol == 0x02) + for(i=0; i<ja3.num_ssl_extension; i++) + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", (i > 0) ? "-" : "", ja3.ssl_extension[i]); + +#ifdef CERTIFICATE_DEBUG + printf("SSL [server] %s\n", ja3_str); +#endif + +#ifdef CERTIFICATE_DEBUG + printf("[JA3] Server: %s \n", ja3_str); +#endif + + MD5Init(&ctx); + MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str)); + MD5Final(md5_hash, &ctx); + + for(i=0, j=0; i<16; i++) + j += snprintf(&flow->protos.stun_ssl.ssl.ja3_server[j], + sizeof(flow->protos.stun_ssl.ssl.ja3_server)-j, "%02x", md5_hash[i]); + +#ifdef CERTIFICATE_DEBUG + printf("[JA3] Server: %s \n", flow->protos.stun_ssl.ssl.ja3_server); +#endif + flow->l4.tcp.ssl_seen_server_cert = 1; - else + } else flow->l4.tcp.ssl_seen_certificate = 1; /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */ @@ -235,6 +531,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, snprintf(flow->protos.stun_ssl.ssl.server_certificate, sizeof(flow->protos.stun_ssl.ssl.server_certificate), "%s", buffer); } + return(1 /* Server Certificate */); } } @@ -242,101 +539,251 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, } } else if(handshake_protocol == 0x01 /* Client Hello */) { u_int offset, base_offset = 43; + if(base_offset + 2 <= packet->payload_packet_len) { - u_int16_t session_id_len = packet->payload[base_offset]; + u_int16_t session_id_len = packet->payload[base_offset]; + u_int16_t ssl_version = ntohs(*((u_int16_t*)&packet->payload[9])); - if((session_id_len+base_offset+2) <= total_len) { - u_int16_t cypher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8); - offset = base_offset + session_id_len + cypher_len + 2; + ja3.ssl_version = ssl_version; - flow->l4.tcp.ssl_seen_client_cert = 1; + if((session_id_len+base_offset+2) <= total_len) { + u_int16_t cipher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8); + u_int16_t i, cipher_offset = base_offset + session_id_len + 3; - if(offset < total_len) { - u_int16_t compression_len; - u_int16_t extensions_len; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [client cipher_len: %u]\n", cipher_len); +#endif + + if((cipher_offset+cipher_len) <= total_len) { + for(i=0; i<cipher_len;) { + u_int16_t *id = (u_int16_t*)&packet->payload[cipher_offset+i]; + +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [cipher suite: %u] [%u/%u]\n", ntohs(*id), i, cipher_len); +#endif + if((*id == 0) || (packet->payload[cipher_offset+i] != packet->payload[cipher_offset+i+1])) { + /* + Skip GREASE [https://tools.ietf.org/id/draft-ietf-tls-grease-01.html] + https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 + */ + + if(ja3.num_cipher < MAX_NUM_JA3) + ja3.cipher[ja3.num_cipher++] = ntohs(*id); + else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid cipher %u\n", ja3.num_cipher); +#endif + } + } + + i += 2; + } + } else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid len %u vs %u\n", (cipher_offset+cipher_len), total_len); +#endif + } + + offset = base_offset + session_id_len + cipher_len + 2; + + flow->l4.tcp.ssl_seen_client_cert = 1; + + if(offset < total_len) { + u_int16_t compression_len; + u_int16_t extensions_len; - offset++; - compression_len = packet->payload[offset]; - offset++; + offset++; + compression_len = packet->payload[offset]; + offset++; #ifdef CERTIFICATE_DEBUG - printf("SSL [compression_len: %u]\n", compression_len); + printf("Client SSL [compression_len: %u]\n", compression_len); #endif - // offset += compression_len + 3; - offset += compression_len; + // offset += compression_len + 3; + offset += compression_len; - if(offset < total_len) { - extensions_len = ntohs(*((u_int16_t*)&packet->payload[offset])); - offset += 2; + if(offset < total_len) { + extensions_len = ntohs(*((u_int16_t*)&packet->payload[offset])); + offset += 2; #ifdef CERTIFICATE_DEBUG - printf("SSL [extensions_len: %u]\n", extensions_len); + printf("Client SSL [extensions_len: %u]\n", extensions_len); #endif - if((extensions_len+offset) <= total_len) { - /* Move to the first extension - Type is u_int to avoid possible overflow on extension_len addition */ - u_int extension_offset = 0; + if((extensions_len+offset) <= total_len) { + /* Move to the first extension + Type is u_int to avoid possible overflow on extension_len addition */ + u_int extension_offset = 0; + u_int32_t md5h[4], j; - while(extension_offset < extensions_len) { - u_int16_t extension_id, extension_len; + while(extension_offset < extensions_len) { + u_int16_t extension_id, extension_len, extn_off = offset+extension_offset; - extension_id = ntohs(*((u_int16_t*)&packet->payload[offset+extension_offset])); - extension_offset += 2; + extension_id = ntohs(*((u_int16_t*)&packet->payload[offset+extension_offset])); + extension_offset += 2; - extension_len = ntohs(*((u_int16_t*)&packet->payload[offset+extension_offset])); - extension_offset += 2; + extension_len = ntohs(*((u_int16_t*)&packet->payload[offset+extension_offset])); + extension_offset += 2; #ifdef CERTIFICATE_DEBUG - printf("SSL [extension_id: %u][extension_len: %u]\n", extension_id, extension_len); + printf("Client SSL [extension_id: %u][extension_len: %u]\n", extension_id, extension_len); #endif - if(extension_id == 0) { -#if 1 - u_int16_t len; - - len = (packet->payload[offset+extension_offset+3] << 8) + packet->payload[offset+extension_offset+4]; - len = (u_int)ndpi_min(len, buffer_len-1); - strncpy(buffer, (char*)&packet->payload[offset+extension_offset+5], len); - buffer[len] = '\0'; -#else - /* old code */ - u_int begin = 0; - char *server_name = (char*)&packet->payload[offset+extension_offset]; - - while(begin < extension_len) { - if((!ndpi_isprint(server_name[begin])) - || ndpi_ispunct(server_name[begin]) - || ndpi_isspace(server_name[begin])) - begin++; - else - break; - } + if((extension_id == 0) || (packet->payload[extn_off] != packet->payload[extn_off+1])) { + /* Skip GREASE */ - len = (u_int)ndpi_min(extension_len-begin, buffer_len-1); - strncpy(buffer, &server_name[begin], len); - buffer[len] = '\0'; + if(ja3.num_ssl_extension < MAX_NUM_JA3) + ja3.ssl_extension[ja3.num_ssl_extension++] = extension_id; + else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid extensions %u\n", ja3.num_ssl_extension); #endif + } + } + + if(extension_id == 0 /* server name */) { + u_int16_t len; + + len = (packet->payload[offset+extension_offset+3] << 8) + packet->payload[offset+extension_offset+4]; + len = (u_int)ndpi_min(len, buffer_len-1); + strncpy(buffer, (char*)&packet->payload[offset+extension_offset+5], len); + buffer[len] = '\0'; + + stripCertificateTrailer(buffer, buffer_len); + + if(!ndpi_struct->disable_metadata_export) { + snprintf(flow->protos.stun_ssl.ssl.client_certificate, + sizeof(flow->protos.stun_ssl.ssl.client_certificate), "%s", buffer); + } + } else if(extension_id == 10 /* supported groups */) { + u_int16_t i, s_offset = offset+extension_offset + 2; + +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [EllipticCurveGroups: len=%u]\n", extension_len); +#endif + + if((s_offset+extension_len-2) <= total_len) { + for(i=0; i<extension_len-2;) { + u_int16_t s_group = ntohs(*((u_int16_t*)&packet->payload[s_offset+i])); - stripCertificateTrailer(buffer, buffer_len); +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [EllipticCurve: %u]\n", s_group); +#endif + if((s_group == 0) || (packet->payload[s_offset+i] != packet->payload[s_offset+i+1])) { + /* Skip GREASE */ + if(ja3.num_elliptic_curve < MAX_NUM_JA3) + ja3.elliptic_curve[ja3.num_elliptic_curve++] = s_group; + else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve); +#endif + } + } - if(!ndpi_struct->disable_metadata_export) { - snprintf(flow->protos.stun_ssl.ssl.client_certificate, - sizeof(flow->protos.stun_ssl.ssl.client_certificate), "%s", buffer); + i += 2; } + } else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid len %u vs %u\n", (s_offset+extension_len-1), total_len); +#endif + } + } else if(extension_id == 11 /* ec_point_formats groups */) { + u_int16_t i, s_offset = offset+extension_offset + 1; - /* We're happy now */ - return(2 /* Client Certificate */); +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [EllipticCurveFormat: len=%u]\n", extension_len); +#endif + if((s_offset+extension_len) < total_len) { + for(i=0; i<extension_len-1;i++) { + u_int8_t s_group = packet->payload[s_offset+i]; + +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [EllipticCurveFormat: %u]\n", s_group); +#endif + + if(ja3.num_elliptic_curve_point_format < MAX_NUM_JA3) + ja3.elliptic_curve_point_format[ja3.num_elliptic_curve_point_format++] = s_group; + else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid num elliptic %u\n", ja3.num_elliptic_curve_point_format); +#endif + } + } + } else { + invalid_ja3 = 1; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL Invalid len %u vs %u\n", s_offset+extension_len, total_len); +#endif } + } + + extension_offset += extension_len; - extension_offset += extension_len; +#ifdef CERTIFICATE_DEBUG + printf("Client SSL [extension_offset/len: %u/%u]\n", extension_offset, extension_len); +#endif + } /* while */ + + if(!invalid_ja3) { + ja3_str_len = snprintf(ja3_str, sizeof(ja3_str), "%u,", ja3.ssl_version); + + for(i=0; i<ja3.num_cipher; i++) { + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", + (i > 0) ? "-" : "", ja3.cipher[i]); } + + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); + + /* ********** */ + + for(i=0; i<ja3.num_ssl_extension; i++) + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", + (i > 0) ? "-" : "", ja3.ssl_extension[i]); + + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); + + /* ********** */ + + for(i=0; i<ja3.num_elliptic_curve; i++) + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", + (i > 0) ? "-" : "", ja3.elliptic_curve[i]); + + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, ","); + + for(i=0; i<ja3.num_elliptic_curve_point_format; i++) + ja3_str_len += snprintf(&ja3_str[ja3_str_len], sizeof(ja3_str)-ja3_str_len, "%s%u", + (i > 0) ? "-" : "", ja3.elliptic_curve_point_format[i]); + +#ifdef CERTIFICATE_DEBUG + printf("[JA3] Client: %s \n", ja3_str); +#endif + + MD5Init(&ctx); + MD5Update(&ctx, (const unsigned char *)ja3_str, strlen(ja3_str)); + MD5Final(md5_hash, &ctx); + + for(i=0, j=0; i<16; i++) + j += snprintf(&flow->protos.stun_ssl.ssl.ja3_client[j], + sizeof(flow->protos.stun_ssl.ssl.ja3_client)-j, "%02x", md5_hash[i]); + +#ifdef CERTIFICATE_DEBUG + printf("[JA3] Client: %s \n", flow->protos.stun_ssl.ssl.ja3_client); +#endif } + + return(2 /* Client Certificate */); } } } } + } } } } @@ -345,69 +792,70 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct, } void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow, - char *buffer, int buffer_len) { - struct ndpi_packet_struct *packet = &flow->packet; + struct ndpi_flow_struct *flow, + char *buffer, int buffer_len) { + struct ndpi_packet_struct *packet = &flow->packet; - if(packet->payload[0] != 0x16 /* Handshake */) - return; + if(packet->payload[0] != 0x16 /* Handshake */) + return; - u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */; - u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */ + u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */; + u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */ - if(handshake_protocol != 0x02 && handshake_protocol != 0xb /* Server Hello and Certificate message types are interesting for us */) - return; + if(handshake_protocol != 0x02 && handshake_protocol != 0xb /* Server Hello and Certificate message types are interesting for us */) + return; - /* Truncate total len, search at least in incomplete packet */ - if(total_len > packet->payload_packet_len) - total_len = packet->payload_packet_len; + /* Truncate total len, search at least in incomplete packet */ + if(total_len > packet->payload_packet_len) + total_len = packet->payload_packet_len; - memset(buffer, 0, buffer_len); + memset(buffer, 0, buffer_len); - /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */ - u_int num_found = 0; - u_int i, j; - for(i = 9; i < packet->payload_packet_len-4; i++) { - /* Organization OID: 2.5.4.10 */ - if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) { - u_int8_t type_tag = packet->payload[i+3]; // 0x0c: utf8string / 0x13: printable_string - u_int8_t server_len = packet->payload[i+4]; - - num_found++; - /* what we want is subject certificate, so we bypass the issuer certificate */ - if(num_found != 2) continue; - - // packet is truncated... further inspection is not needed - if(i+4+server_len >= packet->payload_packet_len) { - break; - } + /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */ + u_int num_found = 0; + u_int i, j; + for(i = 9; i < packet->payload_packet_len-4; i++) { + /* Organization OID: 2.5.4.10 */ + if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) { + u_int8_t type_tag = packet->payload[i+3]; // 0x0c: utf8string / 0x13: printable_string + u_int8_t server_len = packet->payload[i+4]; - char *server_org = (char*)&packet->payload[i+5]; + num_found++; + /* what we want is subject certificate, so we bypass the issuer certificate */ + if(num_found != 2) continue; - u_int len = (u_int)ndpi_min(server_len, buffer_len-1); - strncpy(buffer, server_org, len); - buffer[len] = '\0'; + // packet is truncated... further inspection is not needed + if(i+4+server_len >= packet->payload_packet_len) { + break; + } - // check if organization string are all printable - u_int8_t is_printable = 1; - for (j = 0; j < len; j++) { - if(!ndpi_isprint(buffer[j])) { - is_printable = 0; - break; - } - } + char *server_org = (char*)&packet->payload[i+5]; + + u_int len = (u_int)ndpi_min(server_len, buffer_len-1); + strncpy(buffer, server_org, len); + buffer[len] = '\0'; - if(is_printable == 1) { - snprintf(flow->protos.stun_ssl.ssl.server_organization, - sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer); + // check if organization string are all printable + u_int8_t is_printable = 1; + for (j = 0; j < len; j++) { + if(!ndpi_isprint(buffer[j])) { + is_printable = 0; + break; + } + } + + if(is_printable == 1) { + snprintf(flow->protos.stun_ssl.ssl.server_organization, + sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer); #ifdef CERTIFICATE_DEBUG - printf("Certificate origanization: %s\n", flow->protos.stun_ssl.ssl.server_organization); + printf("Certificate organization: %s\n", flow->protos.stun_ssl.ssl.server_organization); #endif - } - } + } } + } } + int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; @@ -745,7 +1193,7 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc /* No whatsapp, let's try SSL */ if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0) return; - } + } if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) { NDPI_LOG_DBG2(ndpi_struct, "first ssl packet\n"); |