diff --git a/scripts/base/frameworks/notice/weird.zeek b/scripts/base/frameworks/notice/weird.zeek
index ee8b850dd2..ec617da556 100644
--- a/scripts/base/frameworks/notice/weird.zeek
+++ b/scripts/base/frameworks/notice/weird.zeek
@@ -138,6 +138,10 @@ export {
["FIN_storm"] = ACTION_NOTICE_PER_ORIG,
["FTP_max_command_length_exceeded"] = ACTION_LOG_PER_CONN,
["FTP_too_many_pending_commands"] = ACTION_LOG_PER_CONN,
+ ["FTP_user_too_long"] = ACTION_LOG_PER_CONN,
+ ["FTP_reply_msg_too_long"] = ACTION_LOG_PER_CONN,
+ ["FTP_arg_too_long"] = ACTION_LOG_PER_CONN,
+ ["FTP_password_too_long"] = ACTION_LOG_PER_CONN,
["HTTP_bad_chunk_size"] = ACTION_LOG,
["HTTP_chunked_transfer_for_multipart_message"] = ACTION_LOG,
["HTTP_overlapping_messages"] = ACTION_LOG,
diff --git a/scripts/base/protocols/ftp/main.zeek b/scripts/base/protocols/ftp/main.zeek
index 0fd075c3ac..d56c276886 100644
--- a/scripts/base/protocols/ftp/main.zeek
+++ b/scripts/base/protocols/ftp/main.zeek
@@ -57,6 +57,24 @@ export {
## sends a reply. If this value is exceeded a weird named
## FTP_too_many_pending_commands is logged for the connection.
option max_pending_commands = 20;
+
+ ## Truncate the user field in the log to that many bytes to avoid
+ ## excessive logging volume as this values is replicated in each
+ ## of the entries related to an FTP session.
+ option max_user_length = 128;
+
+ ## Truncate the password field in the log to that many bytes to avoid
+ ## excessive logging volume as this values is replicated in each
+ ## of the entries related to an FTP session.
+ option max_password_length = 128;
+
+ ## Truncate the arg field in the log to that many bytes to avoid
+ ## excessive logging volume.
+ option max_arg_length = 4096;
+
+ ## Truncate the reply_msg field in the log to that many bytes to avoid
+ ## excessive logging volume.
+ option max_reply_msg_length = 4096;
}
# Add the state tracking information variable to the connection record
@@ -151,8 +169,10 @@ function set_ftp_session(c: connection)
}
}
-function ftp_message(s: Info)
+function ftp_message(c: connection)
{
+ if ( ! c?$ftp ) return;
+ local s: Info = c$ftp;
s$ts=s$cmdarg$ts;
s$command=s$cmdarg$cmd;
@@ -160,6 +180,20 @@ function ftp_message(s: Info)
if ( s$cmdarg$cmd in file_cmds )
s$arg = build_url_ftp(s);
+ # Avoid logging arg or reply_msg that are too big.
+ if ( |s$arg| > max_arg_length )
+ {
+ Reporter::conn_weird("FTP_arg_too_long", c, cat(|s$arg|), "FTP");
+ s$arg = s$arg[:max_arg_length];
+ }
+
+ if ( s?$reply_msg && |s$reply_msg| > max_reply_msg_length )
+ {
+ Reporter::conn_weird("FTP_reply_msg_too_long", c, cat(|s$reply_msg|), "FTP");
+ s$reply_msg = s$reply_msg[:max_reply_msg_length];
+ }
+
+
if ( s$arg == "" )
delete s$arg;
@@ -228,7 +262,7 @@ event ftp_request(c: connection, command: string, arg: string) &priority=5
if ( c?$ftp && c$ftp?$cmdarg && c$ftp?$reply_code )
{
remove_pending_cmd(c$ftp$pending_commands, c$ftp$cmdarg);
- ftp_message(c$ftp);
+ ftp_message(c);
}
local id = c$id;
@@ -242,11 +276,25 @@ event ftp_request(c: connection, command: string, arg: string) &priority=5
cat(|c$ftp$pending_commands|), "FTP");
if ( command == "USER" )
+ {
+ if ( |arg| > max_user_length )
+ {
+ Reporter::conn_weird("FTP_user_too_long", c, cat(|arg|), "FTP");
+ arg = arg[:max_user_length];
+ }
+
c$ftp$user = arg;
-
+ }
else if ( command == "PASS" )
- c$ftp$password = arg;
+ {
+ if ( |arg| > max_password_length )
+ {
+ Reporter::conn_weird("FTP_password_too_long", c, cat(|arg|), "FTP");
+ arg = arg[:max_password_length];
+ }
+ c$ftp$password = arg;
+ }
else if ( command == "PORT" || command == "EPRT" )
{
local data = (command == "PORT") ?
@@ -331,7 +379,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior
if ( |c$ftp$pending_commands| > 1 )
{
remove_pending_cmd(c$ftp$pending_commands, c$ftp$cmdarg);
- ftp_message(c$ftp);
+ ftp_message(c);
}
}
@@ -382,6 +430,6 @@ hook finalize_ftp(c: connection)
for ( _, cmdarg in c$ftp$pending_commands )
{
c$ftp$cmdarg = cmdarg;
- ftp_message(c$ftp);
+ ftp_message(c);
}
}
diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output
index 9ec9d98fe8..5fe1183b58 100644
--- a/testing/btest/Baseline/plugins.hooks/output
+++ b/testing/btest/Baseline/plugins.hooks/output
@@ -543,7 +543,11 @@
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::default_capture_password, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::guest_ids, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::logged_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
+0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::max_arg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
+0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::max_password_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::max_pending_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
+0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::max_reply_msg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
+0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FTP::max_user_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (FileExtract::default_limit, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (Files::enable_reassembler, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
0.000000 MetaHookPost CallFunction(Option::set_change_handler, , (GridFTP::max_time, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)) ->
@@ -2112,7 +2116,11 @@
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::default_capture_password, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::guest_ids, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::logged_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
+0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::max_arg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
+0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::max_password_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::max_pending_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
+0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::max_reply_msg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
+0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FTP::max_user_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (FileExtract::default_limit, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (Files::enable_reassembler, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
0.000000 MetaHookPre CallFunction(Option::set_change_handler, , (GridFTP::max_time, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100))
@@ -3680,7 +3688,11 @@
0.000000 | HookCallFunction Option::set_change_handler(FTP::default_capture_password, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(FTP::guest_ids, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(FTP::logged_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
+0.000000 | HookCallFunction Option::set_change_handler(FTP::max_arg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
+0.000000 | HookCallFunction Option::set_change_handler(FTP::max_password_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(FTP::max_pending_commands, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
+0.000000 | HookCallFunction Option::set_change_handler(FTP::max_reply_msg_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
+0.000000 | HookCallFunction Option::set_change_handler(FTP::max_user_length, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(FileExtract::default_limit, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(Files::enable_reassembler, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
0.000000 | HookCallFunction Option::set_change_handler(GridFTP::max_time, Config::config_option_changed{ Config::log = Config::Info($ts=network_time(), $id=Config::ID, $old_value=Config::format_value(lookup_ID(Config::ID)), $new_value=Config::format_value(Config::new_value))if ( != Config::location) Config::log$location = Config::locationLog::write(Config::LOG, to_any_coerceConfig::log)return (Config::new_value)}, -100)
diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/ftp.log
new file mode 100644
index 0000000000..fbeaa36ddf
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/ftp.log
@@ -0,0 +1,17 @@
+### 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 141.142.220.235 50003 199.233.217.249 21 anonymous - USER anonymous - - 331 Guest login ok, t - - - - -
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive T 141.142.220.235 199.233.217.249 56666 -
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive T 141.142.220.235 199.233.217.249 56667 FEDbaA44a90dKFRzf3
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233 text/plain 77 226 Transfer complete - - - - F6wZ8iqUoaPxGYCAj
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,2 - - 200 PORT command succ F 199.233.217.249 141.142.220.235 33582 F6wZ8iqUoaPxGYCAj
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,2 - - 200 PORT command succ F 199.233.217.249 141.142.220.235 37835 F7BoKm1QaCQXKASXLl
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233 text/plain 77 226 Transfer complete - - - - FIXQK42rXgY0sM33Ue
+#close XXXX-XX-XX-XX-XX-XX
diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/weird.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/weird.log
new file mode 100644
index 0000000000..2595763de6
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-arg-length/weird.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 weird
+#open XXXX-XX-XX-XX-XX-XX
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
+#types time string addr port addr port string string bool string string
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 FTP_reply_msg_too_long 55 F zeek FTP
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 FTP_arg_too_long 34 F zeek FTP
+#close XXXX-XX-XX-XX-XX-XX
diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/ftp.log
new file mode 100644
index 0000000000..5d0a3165e5
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/ftp.log
@@ -0,0 +1,16 @@
+### 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 141.142.220.235 50003 199.233.217.249 21 anon te PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) T 141.142.220.235 199.233.217.249 56666 -
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anon te PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) T 141.142.220.235 199.233.217.249 56667 FEDbaA44a90dKFRzf3
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anon te RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - F6wZ8iqUoaPxGYCAj
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anon te PORT 141,142,220,235,131,46 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 33582 F6wZ8iqUoaPxGYCAj
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anon te PORT 141,142,220,235,147,203 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 37835 F7BoKm1QaCQXKASXLl
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 anon te RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - FIXQK42rXgY0sM33Ue
+#close XXXX-XX-XX-XX-XX-XX
diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/weird.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/weird.log
new file mode 100644
index 0000000000..b8faa58a76
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-max-user-length/weird.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 weird
+#open XXXX-XX-XX-XX-XX-XX
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
+#types time string addr port addr port string string bool string string
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 FTP_user_too_long 9 F zeek FTP
+XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 141.142.220.235 50003 199.233.217.249 21 FTP_password_too_long 4 F zeek FTP
+#close XXXX-XX-XX-XX-XX-XX
diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-max-arg-length.zeek b/testing/btest/scripts/base/protocols/ftp/ftp-max-arg-length.zeek
new file mode 100644
index 0000000000..db858f6421
--- /dev/null
+++ b/testing/btest/scripts/base/protocols/ftp/ftp-max-arg-length.zeek
@@ -0,0 +1,12 @@
+# Test truncation of the arg field in the ftp.log.
+#
+# @TEST-EXEC: zeek -b -r $TRACES/ftp/ipv4.trace %INPUT
+# @TEST-EXEC: btest-diff ftp.log
+# @TEST-EXEC: btest-diff weird.log
+
+@load base/protocols/conn
+@load base/protocols/ftp
+
+redef FTP::logged_commands += { "CWD", "USER" };
+redef FTP::max_arg_length = 13;
+redef FTP::max_reply_msg_length = 17;
diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-max-user-length.zeek b/testing/btest/scripts/base/protocols/ftp/ftp-max-user-length.zeek
new file mode 100644
index 0000000000..48f27e1026
--- /dev/null
+++ b/testing/btest/scripts/base/protocols/ftp/ftp-max-user-length.zeek
@@ -0,0 +1,13 @@
+# Test truncation of the user and password fields in the log.
+# The password is "test", the user is "anonymous".
+#
+# @TEST-EXEC: zeek -b -r $TRACES/ftp/ipv4.trace %INPUT
+# @TEST-EXEC: btest-diff ftp.log
+# @TEST-EXEC: btest-diff weird.log
+
+@load base/protocols/conn
+@load base/protocols/ftp
+
+redef FTP::max_user_length = 4;
+redef FTP::max_password_length = 2;
+redef FTP::default_capture_password = T;
diff --git a/testing/external/commit-hash.zeek-testing-private b/testing/external/commit-hash.zeek-testing-private
index 193ea5a63d..a60dfa3909 100644
--- a/testing/external/commit-hash.zeek-testing-private
+++ b/testing/external/commit-hash.zeek-testing-private
@@ -1 +1 @@
-0bd2853c1666e89da1c262107d8be7a445078f8a
+ecadd8772e54199ed47c0a97398a39e3abd5b5c7