Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

ncat: nsock_loop error 10038 #978

Closed
nnposter opened this Issue Aug 23, 2017 · 8 comments

Comments

Projects
None yet
5 participants

Synopsis:
Ncat 7.60 on Windows is unable to perform a simple client TCP connect. The same problem is not observed on Linux. A nine-months old version of ncat also works fine.

The key error message is

libnsock select_loop(): nsock_loop error 10038: An operation was attempted on something that is not a socket.

There was no recent change in routine select_loop() in nsock/src/engine_select.c to provide an obvious explanation.

Details:
The following is observed on Windows 8 with stock ncat 7.60 (and also on Windows 7 with close-enough ncat r36949):

C:\temp>ncat -vv 10.128.24.212 21
Ncat: Version 7.60 ( https://nmap.org/ncat )
NCAT DEBUG: Using trusted CA certificates from C:\temp\ca-bundle.crt.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to 10.128.24.212:21 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [10.128.24.212:21]
Ncat: Connected to 10.128.24.212:21.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [10.128.24.212:21] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
libnsock select_loop(): nsock_loop error 10038: An operation was attempted on something that is not a socket.
Ncat: 0 bytes sent, 0 bytes received in 0.06 seconds.

The same version of ncat (r36949) on Ubuntu does not have the problem:

$ ncat -vv 10.128.24.212 21
Ncat: Version 7.60SVN ( https://nmap.org/ncat )
NCAT DEBUG: Using system default trusted CA certificates and those in /usr/share/ncat/ca-bundle.crt.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to 10.128.24.212:21 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [10.128.24.212:21]
Ncat: Connected to 10.128.24.212:21.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [10.128.24.212:21] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
libnsock nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 18 [10.128.24.212:21] (20 bytes): 220 (vsFTPd 3.0.2)..
220 (vsFTPd 3.0.2)
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #1 [10.128.24.212:21] EID 34

An older version of ncat (r36483) on the same Windows 8 and Windows 7 also works fine:

C:\oldncat\ncat -vv 10.128.24.212 21
Ncat: Version 7.31SVN ( https://nmap.org/ncat )
NCAT DEBUG: Using trusted CA certificates from C:\oldncat\ca-bundle.crt.
NCAT DEBUG: Unable to load trusted CA certificates from C:\oldncat\ca-bundle.crt: error:02001002:system library:fopen:No such file or directory
libnsock nsock_iod_new2(): nsock_iod_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to 10.128.24.212:21 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [10.128.24.212:21]
Ncat: Connected to 10.128.24.212:21.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [10.128.24.212:21] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
libnsock nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 18 [10.128.24.212:21] (20 bytes): 220 (vsFTPd 3.0.2)..
220 (vsFTPd 3.0.2)
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #1 [10.128.24.212:21] EID 34

maddisoj commented Aug 29, 2017 edited

Regression seems to have appeared with version 7.60; 7.50 works fine for me on Windows 7.

C:\Users\james>ncat -v
Ncat: Version 7.60 ( https://nmap.org/ncat )
Ncat: You must specify a host to connect to. QUITTING.

C:\Users\james>ncat -vv localhost 4321
Ncat: Version 7.60 ( https://nmap.org/ncat )
NCAT DEBUG: Using trusted CA certificates from C:\Program Files (x86)\Nmap\ca-bundle.crt.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to ::1:4321 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [::1:4321]
Ncat: Connected to ::1:4321.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [::1:4321] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
libnsock select_loop(): nsock_loop error 10038: An operation was attempted on something that is not a socket.
Ncat: 0 bytes sent, 0 bytes received in 0.14 seconds.
libnsock nsock_trace_handler_callback(): Callback: READ KILL for EID 18 [::1:4321]
libnsock nsock_trace_handler_callback(): Callback: READ KILL for EID 26 [peer unspecified]
libnsock nsock_iod_delete(): nsock_iod_delete (IOD #1)
libnsock nsock_iod_delete(): nsock_iod_delete (IOD #2)
C:\Users\james>ncat -v
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: You must specify a host to connect to. QUITTING.

C:\Users\james>ncat -vv localhost 4321
Ncat: Version 7.50 ( https://nmap.org/ncat )
NCAT DEBUG: Using trusted CA certificates from C:\Program Files (x86)\Nmap\ca-bundle.crt.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to ::1:4321 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [::1:4321]
Ncat: Connected to ::1:4321.
libnsock nsock_iod_new2(): nsock_iod_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [::1:4321] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
libnsock nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 18 [::1:4321] (13 bytes): Hello World!.
Hello World!

gvanem commented Aug 29, 2017

Confirmed. The reason is that fselect() could call select() with socket 0 in the except_fd_set. Try with this to just remove it:

--- a/nbase/nbase_misc.c 2017-06-20 17:16:33
+++ b/nbase/nbase_misc.c 2017-08-29 15:53:50
@@ -502,6 +502,8 @@
         if (emaster)
             eset = *emaster;

+        FD_CLR(STDIN_FILENO, &eset);
+
         fds_ready = 0;
         /* selecting on anything other than stdin? */
         if (s > 1)

hdoreau commented Aug 30, 2017

Can someone try git-bisect on this? I unfortunately do not have access to a windows machine but may be able to advise if this is a nsock issue. Knowing the faulty commit would help a lot.

I was able to narrow it down to r36816 (2065d75)

gvanem commented Aug 30, 2017

You could also try the secret option -nsock-engine E.g.:

ncat --nsock-engine poll ...
ncat --nsock-engine iocp ...

hdoreau commented Aug 31, 2017 edited

I think that @gvanem is right. Windows does not allow selecting on non-sockets. You can try the suggested patch (please move the new FD_CLR statement right below the existing one on line 479 though). Can you check that it does not introduce regression WRT the bug that r36816 was attempting to fix (see http://seclists.org/nmap-dev/2017/q1/220)? Can you also check with a regular file as stdin: 'ncat host < file.input'?

Using alternative engines with ncat "works" but is discouraged on windows because of this kind of issues. We have no fpoll() wrapper and I am unsure how iocp behaves on stdin. I would be happy to know it though! :)

nnposter commented Sep 3, 2017

This helps with making the connection but the same error pops up again at the end of the session.

I have put together a band-aid patch below, which gets rid of the error (including at the session end) but :

  • I am not familiar with this part of the code base so I have low confidence in the patch.
  • Nothing has been done about faking exceptional conditions on STDIN_FILENO.
  • In previous versions of ncat a simple stdin-based client session always ended up with close: No such file or directory. Now the event is close: Result too large.
--- a/nbase/nbase_misc.c
+++ b/nbase/nbase_misc.c
@@ -428,6 +428,8 @@
     int iter = -1, i;
     struct timeval stv;
     fd_set rset, wset, eset;
+    int r_stdin = rmaster != NULL && FD_ISSET(STDIN_FILENO, rmaster);
+    int e_stdin = emaster != NULL && FD_ISSET(STDIN_FILENO, emaster);
 
     /* Figure out whether there are any FDs in the sets, as @$@!$# Windows
        returns WSAINVAL (10022) if you call a select() with no FDs, even though
@@ -441,8 +443,8 @@
         s--;
     }
 
-    /* Handle the case where stdin is not being read from. */
-    if (rmaster == NULL || !FD_ISSET(STDIN_FILENO, rmaster)) {
+    /* Handle the case where stdin is not in scope. */
+    if (!(r_stdin || e_stdin)) {
         if (s > 0) {
             /* Do a normal select. */
             return select(s, rmaster, wmaster, emaster, tv);
@@ -476,7 +478,10 @@
         stdin_thread_started = 1;
     }
 
-    FD_CLR(STDIN_FILENO, rmaster);
+    if (r_stdin)
+        FD_CLR(STDIN_FILENO, rmaster);
+    if (e_stdin)
+        FD_CLR(STDIN_FILENO, emaster);
 
     if (tv) {
         int usecs = (tv->tv_sec * 1000000) + tv->tv_usec;
@@ -509,7 +514,7 @@
         else
             usleep(stv.tv_sec * 1000000UL + stv.tv_usec);
 
-        if (fds_ready > -1 && win_stdin_ready()) {
+        if (fds_ready > -1 && r_stdin && win_stdin_ready()) {
             FD_SET(STDIN_FILENO, &rset);
             fds_ready++;
         }

@nnposter That patch looks good to me. I looked over the MSDN docs and there shouldn't be any sort of "exceptional condition" for STDIN; that's for URG/OOB traffic, generally. I applied it and will be doing some more testing to be sure. I should have been running ncat-test.pl on Windows before release!

@nmap-bot nmap-bot closed this in dace53a Sep 30, 2017

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