Skip to content
Closed
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d4dc3ad
add check for FTP command format
somecookie May 12, 2026
5028f33
adjust command comment
somecookie May 12, 2026
03d61d7
fix typo
somecookie May 12, 2026
5afbe4b
remove assure and merge in condition
somecookie May 12, 2026
0f614e2
add back debug
somecookie May 12, 2026
b0eef7d
remove weird char
somecookie May 12, 2026
e5b8579
remove trailing whitespace
somecookie May 12, 2026
1af928d
fix if format
somecookie May 12, 2026
2c46042
fix PR review
somecookie May 12, 2026
61e5948
fix typo
somecookie May 12, 2026
7ee396e
log bad char and it's position
somecookie May 12, 2026
5b6e34d
move logic to Uri.cc
somecookie May 18, 2026
cc8aae5
refactor function
somecookie May 18, 2026
645e8fc
remove whitesapces
somecookie May 18, 2026
699b944
run scripts/source-maintenance.sh
somecookie May 18, 2026
7172526
replace c-string with SBuf
somecookie May 18, 2026
773b02c
Fix linter
somecookie May 19, 2026
9759307
update comment of containsFtpCommandDelimiter
somecookie May 26, 2026
bf23c6d
update debug messages
somecookie May 26, 2026
0335fd3
avoid decoding when checking for CRLF
somecookie May 27, 2026
75000be
fix linter
somecookie May 27, 2026
97711b5
Fix typo
somecookie May 28, 2026
53afbfc
use decode in check and remove unused proxy_host
somecookie Jun 4, 2026
5af247a
small fixes
somecookie Jun 5, 2026
11ab7c6
fix compiler and comment
somecookie Jun 5, 2026
af94fd2
revert removal of proxy_host
somecookie Jun 5, 2026
0881b5d
remove invalid string from logs
somecookie Jun 5, 2026
89cbe35
fixup: Clarified intended/validated bufLen scope
rousskov Jun 15, 2026
02a3453
fixup: Annotated complex assertion condition, dependencies
rousskov Jun 15, 2026
9474c89
fixup: Polished foundHost validation explanation
rousskov Jun 15, 2026
29d0f8c
fixup: Clarified loginInfo scope
rousskov Jun 15, 2026
5b290a8
fixup: Minor optimization: Perform the faster check first
rousskov Jun 15, 2026
d759856
fixup: Do not convert urlpath to SBuf twice.
rousskov Jun 15, 2026
9f48a4f
fixup: Avoid "empty" words in C++ names
rousskov Jun 15, 2026
f056109
fixup: AnyP::Uri::parse() helpers should throw on errors
rousskov Jun 15, 2026
652e948
fixup: Name the set of FTP delimiter characters
rousskov Jun 15, 2026
01608f5
fixup: Documented why FTP is treated specially
rousskov Jun 15, 2026
60f573d
fixup: More common/readable `if` statement formatting
rousskov Jun 15, 2026
4e9a4b7
fixup: Updated a stale branch-added comment
rousskov Jun 15, 2026
516d1f0
fixup: Explicitly name code that forms FTP commands
rousskov Jun 15, 2026
dde3c53
fixup: No Foo:: inside Foo
rousskov Jun 16, 2026
becd5b4
OT: Do not attempt to reforward pinned requests
rousskov Jun 16, 2026
21581bd
Reject FTP commands with parameters containing CR characters
rousskov Jun 17, 2026
56fdddd
Centralize and "guarantee" FTP command checks
rousskov Jun 17, 2026
5c0a27f
Revert "Reject FTP commands with parameters containing CR characters"
rousskov Jun 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/clients/FtpClient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,21 @@ Ftp::Client::dataClosed(const CommCloseCbParams &)
void
Ftp::Client::writeCommand(const char *buf)
{
// The caller must supply a non-empty command followed by CRLF.

@yadij yadij Jun 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the check being added is not validating "non-empty", it is validating length. The string may still be whitespace characters, which make non-zero length empty.

(I am not certain this is more than a theoretical case, thus the non-blocker review)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the check being added is not validating "non-empty", it is validating length. The string may still be whitespace characters, which make non-zero length empty.

// The caller must supply a non-empty command followed by CRLF.
Assure(bufLen > 2);

This source code comment uses the words "non-empty" to mean "has at least one character". IMO, that is a reasonable usage. "Has at least one non-space character" could also be a reasonable definition in this context, but that is not the definition being used here. The actual assertion code (quoted above) clearly distinguishes the two cases, so I do not think there is an ambiguity problem here.

A command consisting entirely of space characters would be invalid and should not be generated, but our new assertions do not validate that invariant (because it is unrelated to this PR scope and correctly detecting excessive spaces in the assembled command may not be trivial and could be controversial). I do not recommend adding such an assertion in this PR.

Removing "non-empty" from this C++ comment would make this code worse because many readers would suspect an off-by one error without the comment -- the assertions further below only require a bufLen >= 2 condition. Using that weaker condition instead is not an improvement either -- Squid should not generate a \r\n command, of course.

If you can suggest a better wording for this comment, please do so.

// TODO: Move CRLF appending code from callers to here.
const auto bufLen = strlen(buf);
Assure(bufLen > 2);
Assure(buf[bufLen-2] == '\r');
Assure(buf[bufLen-1] == '\n');

const auto crlfCharPosition = strcspn(buf, crlf);
if (crlfCharPosition != bufLen-2) {
const auto invalidCharName = buf[crlfCharPosition] == '\r' ? "CR" : "LF";
debugs(9, 2, "ERROR: Caller assembled a malformed FTP command. Found " << invalidCharName << " at position " << crlfCharPosition);
failed(ERR_FTP_FAILURE, 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we should throw here. We tried, but other/out-of-scope problems in current code forced us to table that idea (for now). FWIW, I am uncomfortable with the proposed failed() call in the middle of transaction processing stack, but it matches how we handle similar problems in FTP code, and it passes our tests. In the absence of specific evidence to the contrary, it is the right step forward here despite my concerns, until other improvements allow us to replace such calls with exceptions.

return;
}

char *ebuf;
/* trace FTP protocol communications at level 2 */
debugs(9, 2, "ftp<< " << buf);
Expand Down
Loading