Skip to content

ENT-14104: Added GETPATCH protocol command for serving leech2 patches#6163

Open
larsewi wants to merge 1 commit into
cfengine:masterfrom
larsewi:leech2-patch-stream
Open

ENT-14104: Added GETPATCH protocol command for serving leech2 patches#6163
larsewi wants to merge 1 commit into
cfengine:masterfrom
larsewi:leech2-patch-stream

Conversation

@larsewi

@larsewi larsewi commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

The hub sends 'GETPATCH ' over the established TLS connection, and the server replies with a leech2 patch using a new patch stream API, which reuses the wire format from the file stream protocol. The patch is created by an enterprise hook; CFEngine Community refuses the request. This introduces protocol version 5 - "leech2".

Ticket: ENT-14104

Together with:

Comment thread cf-serverd/cf-serverd-enterprise-stubs.c Fixed
Comment thread cf-serverd/server_tls.c Dismissed
@larsewi larsewi force-pushed the leech2-patch-stream branch 2 times, most recently from 6ae1b0d to 7023be6 Compare June 5, 2026 14:48
@larsewi

larsewi commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@cf-bottom Jenkins please :)

@larsewi larsewi marked this pull request as ready for review June 5, 2026 15:13
@larsewi larsewi force-pushed the leech2-patch-stream branch from 7023be6 to 55294e4 Compare June 5, 2026 16:01
@cfengine cfengine deleted a comment from cf-bottom Jun 5, 2026
@cf-bottom

Copy link
Copy Markdown

Comment thread cf-testd/cf-testd.c Fixed
The hub sends 'GETPATCH <hash>' over the established TLS connection, and
the server replies with a leech2 patch using a new patch stream API,
which reuses the wire format from the file stream protocol. The patch is
created by an enterprise hook; CFEngine Community refuses the request.
This introduces protocol version 5 - "leech2".

Ticket: ENT-14104
Changelog: Title
Signed-off-by: Lars Erik Wik <lars.erik.wik@northern.tech>
@larsewi larsewi force-pushed the leech2-patch-stream branch from 55294e4 to 4054ba7 Compare June 5, 2026 17:03

@olehermanse olehermanse left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good overall. Some comments / suggestions below.

Comment thread cf-serverd/server_tls.c
Comment on lines +1128 to +1132
int ret = sscanf(recvbuffer, "GETPATCH %63s", last_hash);
if (ret != 1)
{
goto protocol_error;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could check that last_hash only contains the allowed characters here. I.e. since hex hashes can only be a-f + 0-9, we could reject it if it contains other characters like /.;'\ etc.

Comment thread libcfnet/patch_stream.c
Comment on lines +51 to +52
while (!eof)
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should probably set some limit here and handle the case where client is trying to send patches "forever"?

Comment thread cf-serverd/server_tls.c
/* Refuse using the stream protocol, as opposed to
* RefuseAccess(), because the client expects stream protocol
* messages after sending the GETPATCH request. */
PatchStreamRefuse(ConnectionInfoSSL(conn->conn_info));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here I think you should handle the return value of PatchStremRefuse, or comment on why it is not necessary.

Comment thread cf-serverd/server_tls.c
Comment on lines +1152 to +1154
/* A failed patch stream is not fatal to the connection. The
* enterprise hook does all relevant Log()ing. */
ServeLeech2Patch(conn, last_hash);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AI review:

The comment says a failed stream "is not fatal to the connection," which is fine for the application-level failure, but if the refusal message itself fails to send the TLS connection may be in a broken state and the busy-loop will keep trying to serve it. Existing handlers (e.g., COOKIE → ReturnCookies) at least break to the protocol-error path on failure.

Comment thread libcfnet/patch_stream.c
return false;
}

if (msg_len > 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When do we receive a 0 length message?

Comment thread libcfnet/patch_stream.h
Comment on lines +86 to +87
* @param data Is set to the received patch buffer (caller takes ownership
* and must free it with free())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Highlight the fact that it may be set to NULL and must be checked for NULL before access?

Comment thread cf-serverd/server_tls.c
Comment on lines +1134 to +1135
Log(LOG_LEVEL_VERBOSE, "%14s %7s %.7s...",
"Received:", "GETPATCH", last_hash);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This won't be formatted correctly / as expected. %7s is meant to pad anything below 7 characters up to 7, so all of them are aligned - however GETPATCH is 8 characters, so all those log messages will be misaligned. We should probably change this and all the other log message format strings to %8s.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants