Add explicit TLS support for FTP

This is defined in RFC 4217; TLS initialized by the client sending an
`AUTH TLS` command.

Fixes GH-4463
This commit is contained in:
Johanna Amann 2025-05-27 13:45:23 +01:00
parent cef63e871e
commit 718307214e
9 changed files with 74 additions and 1 deletions

View file

@ -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) {

View file

@ -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
};
/**

View file

@ -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%);

View file

@ -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]

View file

@ -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

View file

@ -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 <unknown> - <init> - - - 220 (vsFTPd 3.0.5) - - - - -
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40284 127.0.0.1 21 <unknown> - AUTH TLS - - 234 Proceed with negotiation. - - - - -
#close XXXX-XX-XX-XX-XX-XX

View file

@ -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

Binary file not shown.

View file

@ -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 += { "<init>", "AUTH" };
event ftp_starttls(c: connection) {
print "starttls", c$id;
}