Skip to content

SSL packets are not written to stdout if stdout is pipe #2788

Closed

Description

@u19809

Describe the bug

We use ncat as a process between a data sync and a data source where sync and source are using linux pipes to write and read data from ncat. our main application uses 'pipe'-s to fork ncat and writes/reads data to and from the relevant pipes.

What we see happening when running the system with strace, that ncat receives a packet from the host it connected to of - say - 15K and that it writes 8K to the stdout (which is the pipe to the sync). Then it does a select on stdin and the socket it opened to the host but does never come back to write the rest of the 15K packet to the stdout.

The 8K corresponds to the DEFAULT_TCP_BUF_LEN constant defined in ncat.h and which determines the buffering IO size

This only happens when using SSL to connect to the host and NOT if you use regular sockets.

We think that this is due to the fact that ssl internally buffers the read bytes (all 15K is read in one recvfrom) and that ssl has some bytes in the internal buffer, whereas the regular socket uses read/recv directly and hence can use the select to know if more data is available. Regular sockets read the 15K in 2 separate packets, one 8K and one 6-ishK

To Reproduce
we use the following command line options "--ssl localhost someport --no-shutdown"

Expected behavior
We would expect the rest of the SSL data to be written to stdout/pipe

Version info (please complete the following information):

  • OS: redhat 8
  • Output of ncat --version: 7.92

Activity

  1. dmiller-nmap commented on Nov 21, 2024

    @dmiller-nmap

    I think this should be resolved by 3a0db5d. The issue is, as you said, that OpenSSL may have buffered data from the socket ready to be read, but Nsock does not issue a call to SSL_read() until the socket is "ready" according to select(). In server/listen mode, Ncat does the right thing by calling SSL_pending() after a SSL_read() call to check whether it should try again without waiting for select(), but in client/connect mode, it uses Nsock.

    The fix is to issue a non-blocking SSL_read() call as soon as the read event is requested. If there's pending data, it will be returned immediately. If not, we get a correct SSL_WANT_READ or SSL_WANT_WRITE so we know what condition to look for on the socket before trying again.

    I didn't see this issue until after I made the commit, so I'll commit a changelog entry that references this issue to close it out. If anyone can independently verify the fix, I'd greatly appreciate that, too.

  2. added a commit that references this issue on Nov 21, 2024
    a47850b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions