diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c index bb7fc0f1b..c67f2c202 100644 --- a/ncat/ncat_connect.c +++ b/ncat/ncat_connect.c @@ -1078,6 +1078,13 @@ int ncat_connect(void) return rc == NSOCK_LOOP_ERROR ? 1 : 0; } +static void send_udp_null(nsock_pool nsp) +{ + char *NULL_PROBE = "\0"; + int length = 1; + nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, NULL_PROBE, length); +} + static void connect_handler(nsock_pool nsp, nsock_event evt, void *data) { enum nse_status status = nse_status(evt); @@ -1086,10 +1093,12 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data) ncat_assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL); if (status == NSE_STATUS_ERROR) { - loguser("%s.\n", socket_strerror(nse_errorcode(evt))); + if (!o.zerobyte||o.verbose) + loguser("%s.\n", socket_strerror(nse_errorcode(evt))); exit(1); } else if (status == NSE_STATUS_TIMEOUT) { - loguser("%s.\n", socket_strerror(ETIMEDOUT)); + if (!o.zerobyte||o.verbose) + loguser("%s.\n", socket_strerror(ETIMEDOUT)); exit(1); } else { ncat_assert(status == NSE_STATUS_SUCCESS); @@ -1104,7 +1113,10 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data) } #endif - connect_report(cs.sock_nsi); + if (o.proto != IPPROTO_UDP && o.zerobyte) { + connect_report(cs.sock_nsi); + nsock_loop_quit(nsp); + } /* Create IOD for nsp->stdin */ if ((cs.stdin_nsi = nsock_iod_new2(nsp, 0, NULL)) == NULL) @@ -1134,12 +1146,15 @@ static void post_connect(nsock_pool nsp, nsock_iod iod) /* Start the initial reads. */ - if (!o.sendonly) + if (!o.sendonly && !o.zerobyte) nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL); - if (!o.recvonly) + if (!o.recvonly && !o.zerobyte) nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0); + if (o.zerobyte && o.proto==IPPROTO_UDP) + send_udp_null(nsp); + /* The --idle-timeout option says to exit after a certain period of inactivity. We start a timer here and reset it on every read event; see refresh_idle_timer. */ @@ -1158,6 +1173,7 @@ static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data) ncat_assert(type == NSE_TYPE_READ); + if (status == NSE_STATUS_EOF) { shutdown(nsock_iod_get_sd(cs.sock_nsi), SHUT_WR); /* In --send-only mode or non-TCP mode, exit after EOF on stdin. */ @@ -1212,7 +1228,8 @@ static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data) nsock_loop_quit(nsp); return; } else if (status == NSE_STATUS_ERROR) { - loguser("%s.\n", socket_strerror(nse_errorcode(evt))); + if (!o.zerobyte||o.verbose) + loguser("%s.\n", socket_strerror(nse_errorcode(evt))); exit(1); } else if (status == NSE_STATUS_TIMEOUT) { loguser("%s.\n", socket_strerror(ETIMEDOUT)); @@ -1259,6 +1276,11 @@ static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data) ncat_assert(status == NSE_STATUS_SUCCESS); } + if (o.zerobyte){ + ncat_assert(o.proto == IPPROTO_UDP); + nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL); + return; + } /* The write to the socket was successful. Allow reading more from stdin now. */ nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0); @@ -1276,6 +1298,13 @@ static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data) ncat_assert(status == NSE_STATUS_SUCCESS); + if (o.zerobyte&&o.proto==IPPROTO_UDP){ + if (o.verbose) + loguser("UDP packet sent successfully\n"); + nsock_loop_quit(nsp); + return; + } + loguser("Idle timeout expired (%d ms).\n", o.idletimeout); exit(1); diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c index c9a21b1d2..87f29b751 100644 --- a/ncat/ncat_core.c +++ b/ncat/ncat_core.c @@ -200,6 +200,7 @@ void options_init(void) o.execmode = EXEC_PLAIN; o.proxy_auth = NULL; o.proxytype = NULL; + o.zerobyte = 0; #ifdef HAVE_OPENSSL o.ssl = 0; diff --git a/ncat/ncat_core.h b/ncat/ncat_core.h index 7a4344424..a8a588187 100644 --- a/ncat/ncat_core.h +++ b/ncat/ncat_core.h @@ -205,6 +205,7 @@ struct options { int sslverify; char *ssltrustfile; char *sslciphers; + int zerobyte; }; extern struct options o; diff --git a/ncat/ncat_main.c b/ncat/ncat_main.c index 864a24814..8498d329e 100644 --- a/ncat/ncat_main.c +++ b/ncat/ncat_main.c @@ -334,7 +334,7 @@ int main(int argc, char *argv[]) while (1) { /* handle command line arguments */ int option_index; - int c = getopt_long(argc, argv, "46UCc:e:g:G:i:km:hp:d:lo:x:ts:uvw:n", + int c = getopt_long(argc, argv, "46UCc:e:g:G:i:km:hp:d:lo:x:ts:uvw:n:z", long_options, &option_index); /* That's the end of the options. */ @@ -458,6 +458,9 @@ int main(int argc, char *argv[]) case 't': o.telnet = 1; break; + case 'z': + o.zerobyte = 1; + break; case 0: if (strcmp(long_options[option_index].name, "version") == 0) { print_banner(); @@ -606,6 +609,7 @@ int main(int argc, char *argv[]) " --sctp Use SCTP instead of default TCP\n" " -v, --verbose Set verbosity level (can be used several times)\n" " -w, --wait