diff --git a/src/analyzer/protocol/ftp/FTP.cc b/src/analyzer/protocol/ftp/FTP.cc index eda45c2148..368162005b 100644 --- a/src/analyzer/protocol/ftp/FTP.cc +++ b/src/analyzer/protocol/ftp/FTP.cc @@ -65,6 +65,11 @@ static bool is_ftp_cmd(int len, const char* s) { void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) { analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, orig); + if ( tls_active ) { + ForwardStream(length, data, orig); + return; + } + if ( (orig && ! ftp_request) || (! orig && ! ftp_reply) ) return; @@ -172,6 +177,17 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) { } } + if ( reply_code == 234 && auth_requested.size() > 0 && auth_requested == "TLS" ) { + EnqueueConnEvent(ftp_starttls, ConnVal()); + Analyzer* ssl = analyzer_mgr->InstantiateAnalyzer("SSL", Conn()); + if ( ssl ) { + AddChildAnalyzer(ssl); + RemoveSupportAnalyzer(nvt_orig); + RemoveSupportAnalyzer(nvt_resp); + tls_active = true; + } + } + if ( reply_code == 334 && auth_requested.size() > 0 && auth_requested == "GSSAPI" ) { // Server wants to proceed with an ADAT exchange and we // know how to analyze the GSI mechanism, so attach analyzer @@ -192,7 +208,8 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) { EnqueueConnEvent(f, std::move(vl)); - ForwardStream(length, data, orig); + if ( ! tls_active ) + ForwardStream(length, data, orig); } void FTP_ADAT_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { diff --git a/src/analyzer/protocol/ftp/FTP.h b/src/analyzer/protocol/ftp/FTP.h index f8bae5788b..c0bae38dde 100644 --- a/src/analyzer/protocol/ftp/FTP.h +++ b/src/analyzer/protocol/ftp/FTP.h @@ -24,6 +24,7 @@ protected: analyzer::login::NVT_Analyzer* nvt_resp; uint32_t pending_reply; // code associated with multi-line reply, or 0 std::string auth_requested; // AUTH method requested + bool tls_active = false; // starttls active }; /** diff --git a/src/analyzer/protocol/ftp/events.bif b/src/analyzer/protocol/ftp/events.bif index 6cc2317936..cf102dc582 100644 --- a/src/analyzer/protocol/ftp/events.bif +++ b/src/analyzer/protocol/ftp/events.bif @@ -33,3 +33,9 @@ event ftp_request%(c: connection, command: string, arg: string%); ## parse_ftp_epsv parse_ftp_pasv parse_ftp_port event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%); +## Generated if an FTP connection switched to TLS using AUTH TLS. After this +## event no more FTP events will be raised for the connection. See the SSL +## analyzer for related SSL events, which will now be generated. +## +## c: The connection. +event ftp_starttls%(c: connection%); diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/.stdout b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/.stdout new file mode 100644 index 0000000000..ea35dc336b --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/.stdout @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +starttls, [orig_h=127.0.0.1, orig_p=40284/tcp, resp_h=127.0.0.1, resp_p=21/tcp, proto=6] diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/conn.log new file mode 100644 index 0000000000..e3d1c23666 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/conn.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents ip_proto +#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] count +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 tcp ftp,ssl 23.881319 1133 3314 RSTR T T 0 ShAdDafr 40 3221 44 5598 - 6 +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ftp.log new file mode 100644 index 0000000000..c3ff41ddf8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ftp.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ftp +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid +#types time string addr port addr port string string string string string count count string bool addr addr port string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 - - - - 220 (vsFTPd 3.0.5) - - - - - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 - AUTH TLS - - 234 Proceed with negotiation. - - - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ssl.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ssl.log new file mode 100644 index 0000000000..fef021bdc1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-auth-tls/ssl.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssl +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established ssl_history cert_chain_fps client_cert_chain_fps sni_matches_cert +#types time string addr port addr port string string string string bool string string bool string vector[string] vector[string] bool +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 TLSv13 TLS_AES_256_GCM_SHA384 secp256r1 127.0.0.1 F - - T CsiI - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/ftp/ftp-auth-tls.pcap b/testing/btest/Traces/ftp/ftp-auth-tls.pcap new file mode 100644 index 0000000000..cc93e042b2 Binary files /dev/null and b/testing/btest/Traces/ftp/ftp-auth-tls.pcap differ diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-auth-tls.zeek b/testing/btest/scripts/base/protocols/ftp/ftp-auth-tls.zeek new file mode 100644 index 0000000000..524d357497 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ftp/ftp-auth-tls.zeek @@ -0,0 +1,13 @@ +# This tests explicit TLS. +# +# @TEST-EXEC: zeek -r $TRACES/ftp/ftp-auth-tls.pcap %INPUT +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff ftp.log +# @TEST-EXEC: btest-diff ssl.log +# @TEST-EXEC: btest-diff .stdout + +redef FTP::logged_commands += { "", "AUTH" }; + +event ftp_starttls(c: connection) { + print "starttls", c$id; +}