- Package:
- netcat-openbsd
- Source:
- netcat-openbsd
- Description:
- TCP/IP swiss army knife
- Submitter:
- Cristian Ionescu-Idbohrn
- Date:
- 2017-11-23 15:15:10 UTC
- Severity:
- important
This is netcat-openbsd 1.105-7
------------------------------
Command line is:
$ echo 'ehlo itsme' | nc.openbsd host.example.com 25
The output is:
220 host.example.com ESMTP Postfix
250-host.example.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
The simple trace is:
1 0.000000000 1.1.1.11 ? 1.1.1.1 TCP 74 47242?smtp(25) [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1188714834 TSecr=0 WS=128
2 0.000130857 1.1.1.1 ? 1.1.1.11 TCP 74 smtp(25)?47242 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=1189398612 TSecr=1188714834 WS=128
3 0.000171694 1.1.1.11 ? 1.1.1.1 TCP 66 47242?smtp(25) [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=1188714834 TSecr=1189398612
4 0.000539830 1.1.1.11 ? 1.1.1.1 SMTP 77 C: ehlo itsme
5 0.000555726 1.1.1.11 ? 1.1.1.1 TCP 66 47242?smtp(25) [FIN, ACK] Seq=12 Ack=1 Win=29312 Len=0 TSval=1188714834 TSecr=1189398612
6 0.000682959 1.1.1.1 ? 1.1.1.11 TCP 66 smtp(25)?47242 [ACK] Seq=1 Ack=12 Win=29056 Len=0 TSval=1189398612 TSecr=1188714834
7 0.009776682 1.1.1.1 ? 1.1.1.11 SMTP 106 S: 220 host.example.com ESMTP Postfix
8 0.009800662 1.1.1.11 ? 1.1.1.1 TCP 66 47242?smtp(25) [ACK] Seq=13 Ack=41 Win=29312 Len=0 TSval=1188714836 TSecr=1189398615
9 0.009807945 1.1.1.1 ? 1.1.1.11 SMTP 195 S: 250 host.example.com | 250 PIPELINING | 250 SIZE 10240000 | 250 VRFY | 250 ETRN | 250 ENHANCEDSTATUSCODES | 250 8BITMIME | 250 DSN
10 0.009822556 1.1.1.11 ? 1.1.1.1 TCP 66 47242?smtp(25) [ACK] Seq=13 Ack=171 Win=30336 Len=0 TSval=1188714836 TSecr=1189398615
This is netcat-openbsd 1.130-1
------------------------------
Same command line:
$ echo 'ehlo itsme' | nc.openbsd host.example.com 25
There is _no_ output.
It seems nc.openbsd is closing the socket before reading/showing
whatever host.example.com returns. Note the two resets '[RST]'
bellow.
11 25.973506450 1.1.1.11 ? 1.1.1.1 TCP 74 47246?smtp(25) [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1188721327 TSecr=0 WS=128
12 25.973662894 1.1.1.1 ? 1.1.1.11 TCP 74 smtp(25)?47246 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=1189405106 TSecr=1188721327 WS=128
13 25.973690712 1.1.1.11 ? 1.1.1.1 TCP 66 47246?smtp(25) [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=1188721327 TSecr=1189405106
14 25.973728427 1.1.1.11 ? 1.1.1.1 SMTP 77 C: ehlo itsme
15 25.973747259 1.1.1.11 ? 1.1.1.1 TCP 66 47246?smtp(25) [FIN, ACK] Seq=12 Ack=1 Win=29312 Len=0 TSval=1188721327 TSecr=1189405106
16 25.973845701 1.1.1.1 ? 1.1.1.11 TCP 66 smtp(25)?47246 [ACK] Seq=1 Ack=12 Win=29056 Len=0 TSval=1189405106 TSecr=1188721327
17 25.974788937 1.1.1.1 ? 1.1.1.11 SMTP 106 S: 220 host.example.com ESMTP Postfix
18 25.974817575 1.1.1.11 ? 1.1.1.1 TCP 54 47246?smtp(25) [RST] Seq=13 Win=0 Len=0
^^^
19 25.974872212 1.1.1.1 ? 1.1.1.11 SMTP 195 S: 250 host.example.com | 250 PIPELINING | 250 SIZE 10240000 | 250 VRFY | 250 ETRN | 250 ENHANCEDSTATUSCODES | 250 8BITMIME | 250 DSN
20 25.974896332 1.1.1.11 ? 1.1.1.1 TCP 54 47246?smtp(25) [RST] Seq=13 Win=0 Len=0
^^^
If I add the '-q1' option (wait one second after EOF on stdin) to the
command line:
$ echo 'ehlo itsme' | nc.openbsd -q1 host.example.com 25
then I get the expected output:
220 host.example.com ESMTP Postfix
250-host.example.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
Note, no '[RST]' in the packet trace.
1 0.000000000 1.1.1.11 ? 1.1.1.1 TCP 74 47742?smtp(25) [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1189159653 TSecr=0 WS=128
2 0.000144981 1.1.1.1 ? 1.1.1.11 TCP 74 smtp(25)?47742 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=1189843431 TSecr=1189159653 WS=128
3 0.000173801 1.1.1.11 ? 1.1.1.1 TCP 66 47742?smtp(25) [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=1189159653 TSecr=1189843431
4 0.000208860 1.1.1.11 ? 1.1.1.1 SMTP 77 C: ehlo itsme
5 0.000338115 1.1.1.1 ? 1.1.1.11 TCP 66 smtp(25)?47742 [ACK] Seq=1 Ack=12 Win=29056 Len=0 TSval=1189843432 TSecr=1189159653
6 0.001715233 1.1.1.1 ? 1.1.1.11 SMTP 106 S: 220 host.example.com ESMTP Postfix
7 0.001733564 1.1.1.11 ? 1.1.1.1 TCP 66 47742?smtp(25) [ACK] Seq=12 Ack=41 Win=29312 Len=0 TSval=1189159653 TSecr=1189843432
8 0.001875842 1.1.1.1 ? 1.1.1.11 SMTP 195 S: 250 host.example.com | 250 PIPELINING | 250 SIZE 10240000 | 250 VRFY | 250 ETRN | 250 ENHANCEDSTATUSCODES | 250 8BITMIME | 250 DSN
9 0.001895568 1.1.1.11 ? 1.1.1.1 TCP 66 47742?smtp(25) [ACK] Seq=12 Ack=170 Win=30336 Len=0 TSval=1189159653 TSecr=1189843432
10 1.002139332 1.1.1.11 ? 1.1.1.1 TCP 66 47742?smtp(25) [FIN, ACK] Seq=12 Ack=170 Win=30336 Len=0 TSval=1189159903 TSecr=1189843432
11 1.002387350 1.1.1.1 ? 1.1.1.11 TCP 66 smtp(25)?47742 [FIN, ACK] Seq=170 Ack=13 Win=29056 Len=0 TSval=1189843682 TSecr=1189159903
12 1.002412151 1.1.1.11 ? 1.1.1.1 TCP 66 47742?smtp(25) [ACK] Seq=13 Ack=171 Win=30336 Len=0 TSval=1189159903 TSecr=1189843682
This particular problem (along with the same no-output when using "nc -d -l")
seems to be caused by a Debian change which introduces the -q option[1]. This
causes the readwrite loop to exit before handling possible return data or the
received data in the listen case.
One draw back with the proposed fix: while this now allows to receive the data
sent back, it will hang there until stopped. That problem comes from upstream
changes. They added a -N flag to send shutdown messages to the remote socket
when the input stream was closed (which was the default in the old version of
nc). So:
echo 'ehlo itsme' | nc.openbsd -N host.example.com 25
would then behave as expected. Not sure how to handle this. IMO it would have
been better if upstream kept the old behaviour as default and added an option to
*not* do the shutdown. But now that its done that way it might be confusing to
change it.
--- one possible fix ---
Description: Fix handling of delayed exit option
The option for delayed exit (-q#) existed before but since upstream
rewrote the readwrite call the patch adding it had to be adapted.
However the current implementation causes the loop to exit too early.
Move the exit handling to those places which do exit the loop in the
original code. While on it also add some code to close the net_fd on
delayed exit.
Author: Stefan Bader <stefan.bader@canonical.com>
Index: netcat-openbsd-1.130/netcat.c
===================================================================
--- netcat-openbsd-1.130.orig/netcat.c
+++ netcat-openbsd-1.130/netcat.c
@@ -178,6 +178,8 @@ char *proto_name(int uflag, int dccpf
static int connect_with_timeout(int fd, const struct sockaddr *sa,
socklen_t salen, int ctimeout);
+
+int quit_fd = -1;
static void quit();
int
@@ -1028,19 +1030,31 @@ readwrite(int net_fd)
/* both inputs are gone, buffers are empty, we are done */
if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
&& stdinbufpos == 0 && netinbufpos == 0) {
- close(net_fd);
- return;
+ if (qflag == 0) {
+ close(net_fd);
+ return;
+ }
+ goto delay_exit;
}
/* both outputs are gone, we can't continue */
if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
- close(net_fd);
- return;
+ if (qflag == 0) {
+ close(net_fd);
+ return;
+ }
+ goto delay_exit;
}
/* listen and net in gone, queues empty, done */
if (lflag && pfd[POLL_NETIN].fd == -1
&& stdinbufpos == 0 && netinbufpos == 0) {
- close(net_fd);
- return;
+ if (qflag == 0) {
+ close(net_fd);
+ return;
+ }
+delay_exit:
+ quit_fd = net_fd;
+ signal(SIGALRM, quit);
+ alarm(qflag);
}
/* poll */
@@ -1159,20 +1173,10 @@ readwrite(int net_fd)
if (pfd[POLL_NETOUT].fd != -1 && Nflag)
shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
pfd[POLL_NETOUT].fd = -1;
- goto exit_on_eof;
}
/* net in gone and queue empty? */
if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
pfd[POLL_STDOUT].fd = -1;
- exit_on_eof:
- /* if the user asked to exit on EOF, do it */
- if (qflag == 0)
- return;
- /* if user asked to die after a while, arrange for it */
- else if (qflag > 0) {
- signal(SIGALRM, quit);
- alarm(qflag);
- }
}
}
}
@@ -1615,6 +1619,8 @@ usage(int ret)
*/
static void quit()
{
- /* XXX: should explicitly close fds here */
+ if (quit_fd >= 0)
+ close(quit_fd);
+
exit(0);
}
We believe that the bug you reported is fixed in the latest version of
netcat-openbsd, which is due to be installed in the Debian FTP archive.
A summary of the changes between this version and the previous one is
attached.
Thank you for reporting the bug, which will now be closed. If you
have further comments please address them to 849192@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.
Debian distribution maintenance software
pp.
Aron Xu <aron@debian.org> (supplier of updated netcat-openbsd package)
(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Thu, 26 Jan 2017 16:51:13 +0800
Source: netcat-openbsd
Binary: netcat-openbsd
Architecture: source amd64
Version: 1.130-2
Distribution: unstable
Urgency: medium
Maintainer: Aron Xu <aron@debian.org>
Changed-By: Aron Xu <aron@debian.org>
Description:
netcat-openbsd - TCP/IP swiss army knife
Closes: 849192
Changes:
netcat-openbsd (1.130-2) unstable; urgency=medium
.
* Fix handling of delayed exit option (Closes: #849192, LP: #1656785)
Thanks to Stefan Bader!
Checksums-Sha1:
9689c1b4dc540b4b9968d2cdbbeb6a4fa212edc4 1610 netcat-openbsd_1.130-2.dsc
189dab80d6ec76f7d72be1c44f3288d4e79bb02d 28532 netcat-openbsd_1.130-2.debian.tar.xz
5a6ed60d496d8856978312c9621896bc4c1bf57e 27260 netcat-openbsd-dbgsym_1.130-2_amd64.deb
5216ca87d255b2869c0ec5ff55f83e6cb485f6fa 4788 netcat-openbsd_1.130-2_amd64.buildinfo
7c5958fc1f08b8e01454beb74f9e33c59f450c4b 38024 netcat-openbsd_1.130-2_amd64.deb
Checksums-Sha256:
4a66048d12a7c08d2ff9d84a44ef0215551d8710f01f4cf8617627797aecd151 1610 netcat-openbsd_1.130-2.dsc
54322c9385d3ef787cd6fb3b5bf4c50b5b591e51b82e9610e6615254f8a19113 28532 netcat-openbsd_1.130-2.debian.tar.xz
3204ba643976689742962bba67077775c58ca2208f9ac30205bb6e71913e583c 27260 netcat-openbsd-dbgsym_1.130-2_amd64.deb
292c567bbd0c3eeb0d46a7717519fe28d789cf7d058f1bc4b03a70312da58276 4788 netcat-openbsd_1.130-2_amd64.buildinfo
cb3bcba1b2a54550bcccbd4ea37ee82999435367e25f94c3638d2ee0cc94c2d3 38024 netcat-openbsd_1.130-2_amd64.deb
Files:
66e27be50b46d15d94db7940b75da43e 1610 net important netcat-openbsd_1.130-2.dsc
9528387da2ee6e4c6b2d1ca33948e196 28532 net important netcat-openbsd_1.130-2.debian.tar.xz
978f66b24df28682d6ae60f2297a3fbb 27260 debug extra netcat-openbsd-dbgsym_1.130-2_amd64.deb
054d8296660189dbbb7c125dfed0df18 4788 net important netcat-openbsd_1.130-2_amd64.buildinfo
806e6f2cfad41d8f7c6fc448da6c7fbe 38024 net important netcat-openbsd_1.130-2_amd64.deb
-----BEGIN PGP SIGNATURE-----
iQFDBAEBCAAtFiEET3MbhxKET+7/a6zdW0gHVdEZ6o4FAliJxY8PHHN5cUBkZWJp
YW4ub3JnAAoJEFtIB1XRGeqOHEIH/1ijNhqLb0rWIUqLhWtoO49Wuo5wvQFu5jk3
SFx7UKR24evo886QXgdI/fnZKb46bNytb/xPUjHldQybki+7tguU5AcmoRXFvjlz
E7V+nI8fo6I4ITepRpCuHjU/9jfoINKZ3lDD6EoMjB+l2NlSC/ek/vQBS9Y/Ieqs
W04Wl7r3a0qM+sGioaRGhcIJPfMUmCkTynIVYMrqsuwxTHSmY2z6HikAaZ7lLoBk
09wqv/TnsbiGRnQPx7cWP2yj0YxbqCLXPR6pKasgxus0buteH4rxRN/Hm/RbENdI
3fYDET111UhvNyHHEqMplBnbmkOH7SUB0SGm41FCaZUfnYENAPE=
=dGtm
-----END PGP SIGNATURE-----
Thanks. Good but not prefect :( Try: $ echo ehlo itsme | nc.openbsd localhost 25 It will just hang in a 'poll' until it later exits with: Error: timeout exceeded And "later" is 5 minutes. postfix mail server here.
On Thu, 26 Jan 2017 17:03:27 +0100 (CET) Cristian Ionescu-Idbohrn This is what I was trying to say about -N. It is a change that comes from openbsd. From a practical point of view, using -N is what was done by default before. If the option is not used nc will not send a shutdown request and that causes it to hang around.
Control: tag -1 wontfix
Hi Cristian,
As Stefan hinted at, this is a deliberate upstream decision. Since
netcat-openbsd 1.110 one needs to pass ‘-N’ in order to shutdown(2) the
socket once EOF has been reach.
In upstream's own words [0]:
Don't shutdown nc(1)'s network socket when stdin closes. Matches
*Hobbit*'s original netcat and GNU netcat; revert to old behaviour
with the new -N flag if needed. After much discussion with otto
deraadt tedu and Martin Pelikan.
(Passing ‘-q’ with a non-negative value should imply ‘-N’ though, cf.
#854292.)
Cheers,