Nmap Development mailing list archives

Re: Ideas for Windows Ncat: non-blocking read from stdin


From: David Fifield <david () bamsoftware com>
Date: Wed, 4 Mar 2009 21:42:27 -0700

On Sun, Mar 01, 2009 at 07:35:22PM -0700, David Fifield wrote:
I saw this in the TODO and I want to share some ideas about it.

o Ncat Windows issue where you make a connection and then take several
  seconds to type in a line to the server, Ncat wrongly times out when
  trying to write your line to the remote server. [David]

I checked this out over the weekend. This is what I wrote to Fyodor:

I found the source of the problem. It is related to the fselect call.
When reading from a TTY, fselect says that stdin is readable when a key
is hit:
        if (stdtty) {
            if (_kbhit()) {
                FD_SET(STDIN_FILENO, &rset);
                fds_ready++;
            }
        }
So Nsock a read on stdin, expecting it to return immediately. But the
input is still being buffered by the console until you hit enter,
turning the read into a blocking read. When you finish typing, the read
finishes, and Ncat schedules a write. No time is supposed to have gone
by during the read, so nsock_tod (time of day) is not updated, and the
write timeout is set to two seconds after you *started* typing. If it
takes you more than two seconds to type, the write is timed out as soon
as it is created.

This is my current idea: create a thread (with CreateThread) that does
nothing but read stdin and write to an anonymous pipe (created with
CreatePipe). Duplicate the pipe's handle in the main program so that
when Ncat thinks it's reading from stdin, it's reading from the pipe.
The thread takes care of line buffering and echoing, and ensures that
the main process won't block when it reads from the pipe.

I did all this in r12437. It took a long day of reading MSDN docs but
the technique is easy to understand. There's a long comment at the top
of nbase/nbase_winunix.c with technical details for anyone interested.

I retained Kris's looping fselect implementation. I didn't find a way to
wait on a pipe until input is available; the best I found was checking
and returning instantly with the PeekNamedPipe function.

If you wondered why the simple example at
http://nmap.org/ncat/guide/ncat-usage.html#ncat-connect didn't work on
Windows, it was because of this issue. Those examples should work now.

David Fifield

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: