Re: Ncat/Nsock notification of connection reset

Henri Doreau <[email protected]>
Newsgroups gmane.comp.security.nmap.devel
Message-ID <CAPXEBz4u1y7+14-X+3MadDp62mjK8Vw2dZTMuQkWQP76sYO4dw@mail.gmail.com>
2017-03-18 23:15 GMT+01:00 Henri Doreau <[email protected]>:
> Commenting that check out and a dirty-fix of
> nsock internals seems to resolve the issue. Ncat client exits as soon
> as the RST from the dying server is received.
>

Please find the aforementioned patch attached. Requires adjustments &
cleanup but should be a good starting point.

Regards

-- 
Henri

_______________________________________________
Sent through the dev mailing list
https://nmap.org/mailman/listinfo/dev
Archived at http://seclists.org/nmap-dev/
nsock_ev_except_basefix.patch (text/x-patch, 8 KB)
diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c
index b7773bd..5a38442 100644
--- a/ncat/ncat_connect.c
+++ b/ncat/ncat_connect.c
@@ -1265,7 +1265,7 @@ static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
     if (status == NSE_STATUS_EOF) {
         Close(STDOUT_FILENO);
         /* In --recv-only mode or non-TCP mode, exit after EOF on the socket. */
-        if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.recvonly))
+        //if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.recvonly))
             nsock_loop_quit(nsp);
         return;
     } else if (status == NSE_STATUS_ERROR) {
diff --git a/nsock/src/engine_epoll.c b/nsock/src/engine_epoll.c
index 00c28cb..af232d9 100644
--- a/nsock/src/engine_epoll.c
+++ b/nsock/src/engine_epoll.c
@@ -74,12 +74,12 @@
 
 #define EPOLL_R_FLAGS (EPOLLIN | EPOLLPRI)
 #define EPOLL_W_FLAGS EPOLLOUT
-#ifdef EPOLLRDHUP
-  #define EPOLL_X_FLAGS (EPOLLERR | EPOLLRDHUP| EPOLLHUP)
-#else
-  /* EPOLLRDHUP was introduced later and might be unavailable on older systems. */
-  #define EPOLL_X_FLAGS (EPOLLERR | EPOLLHUP)
-#endif /* EPOLLRDHUP */
+
+/* EPOLLRDHUP was introduced later and might be unavailable on older systems. */
+#ifndef EPOLLRDHUP
+  #define EPOLLRDHUP 0
+#endif
+#define EPOLL_X_FLAGS (EPOLLERR | EPOLLRDHUP| EPOLLHUP)
 
 
 /* --- ENGINE INTERFACE PROTOTYPES --- */
@@ -178,8 +178,6 @@ int epoll_iod_register(struct npool *nsp, struct niod *iod, struct nevent *nse,
     epev.events |= EPOLL_R_FLAGS;
   if (ev & EV_WRITE)
     epev.events |= EPOLL_W_FLAGS;
-  if (ev & EV_EXCEPT)
-    epev.events |= EPOLL_X_FLAGS;
 
   sd = nsock_iod_get_sd(iod);
   if (epoll_ctl(einfo->epfd, EPOLL_CTL_ADD, sd, &epev) < 0)
@@ -233,8 +231,6 @@ int epoll_iod_modify(struct npool *nsp, struct niod *iod, struct nevent *nse, in
     epev.events |= EPOLL_R_FLAGS;
   if (iod->watched_events & EV_WRITE)
     epev.events |= EPOLL_W_FLAGS;
-  if (iod->watched_events & EV_EXCEPT)
-    epev.events |= EPOLL_X_FLAGS;
 
   sd = nsock_iod_get_sd(iod);
 
@@ -328,7 +324,7 @@ static inline int get_evmask(struct epoll_engine_info *einfo, int n) {
   if (einfo->events[n].events & EPOLL_W_FLAGS)
     evmask |= EV_WRITE;
   if (einfo->events[n].events & EPOLL_X_FLAGS)
-    evmask |= (EV_READ | EV_WRITE | EV_EXCEPT);
+    evmask |= EV_EXCEPT;
 
   return evmask;
 }
diff --git a/nsock/src/engine_poll.c b/nsock/src/engine_poll.c
index 39d166e..62a8e9f 100644
--- a/nsock/src/engine_poll.c
+++ b/nsock/src/engine_poll.c
@@ -294,10 +294,6 @@ int poll_iod_modify(struct npool *nsp, struct niod *iod, struct nevent *nse, int
     pinfo->events[sd].events |= POLL_R_FLAGS;
   if (iod->watched_events & EV_WRITE)
     pinfo->events[sd].events |= POLL_W_FLAGS;
-#ifndef WIN32
-  if (iod->watched_events & EV_EXCEPT)
-    pinfo->events[sd].events |= POLL_X_FLAGS;
-#endif
 
   return 1;
 }
@@ -403,7 +399,7 @@ static inline int get_evmask(struct npool *nsp, struct niod *nsi) {
       if (pev->revents & POLL_W_FLAGS)
         evmask |= EV_WRITE;
       if (pev->events && (pev->revents & POLL_X_FLAGS))
-        evmask |= (EV_READ | EV_WRITE | EV_EXCEPT);
+        evmask |= EV_EXCEPT;
   }
   return evmask;
 }
diff --git a/nsock/src/engine_select.c b/nsock/src/engine_select.c
index 8b61482..fceb981 100644
--- a/nsock/src/engine_select.c
+++ b/nsock/src/engine_select.c
@@ -208,6 +208,9 @@ int select_iod_modify(struct npool *nsp, struct niod *iod, struct nevent *nse, i
   iod->watched_events |= ev_set;
   iod->watched_events &= ~ev_clr;
 
+  ev_set |= EV_EXCEPT;
+  ev_clr &= ~EV_EXCEPT;
+
   sd = nsock_iod_get_sd(iod);
 
   /* -- set events -- */
@@ -233,7 +236,7 @@ int select_iod_modify(struct npool *nsp, struct niod *iod, struct nevent *nse, i
 
   /* -- update max_sd -- */
   if (ev_set != EV_NONE)
-    sinfo->max_sd = MAX(sinfo->max_sd,sd);
+    sinfo->max_sd = MAX(sinfo->max_sd, sd);
   else if (ev_clr != EV_NONE && iod->events_pending == 1 && (sinfo->max_sd == sd))
     sinfo->max_sd--;
 
diff --git a/nsock/src/nsock_core.c b/nsock/src/nsock_core.c
index b8aa352..6914bd9 100644
--- a/nsock/src/nsock_core.c
+++ b/nsock/src/nsock_core.c
@@ -168,6 +168,18 @@ static int socket_count_dec_ssl_desire(struct nevent *nse) {
 }
 #endif
 
+static int should_stop_watch_read(const struct niod *iod, int ev_set) {
+  return (ev_set & EV_READ) &&
+#if HAVE_PCAP
+         !iod->readpcapsd_count &&
+#endif
+         !iod->readsd_count;
+}
+
+static int should_stop_watch_write(const struct niod *iod, int ev_set) {
+  return (ev_set & EV_WRITE) && !iod->writesd_count;
+}
+
 /* Update the events that the IO engine should watch for a given IOD.
  *
  * ev_inc is a set of events for which the event counters should be increased.
@@ -188,18 +200,18 @@ static void update_events(struct niod * iod, struct npool *ms, struct nevent *ns
   setmask = ev_inc;
   clrmask = EV_NONE;
 
-  if ((ev_dec & EV_READ) &&
-#if HAVE_PCAP
-      !iod->readpcapsd_count &&
-#endif
-      !iod->readsd_count)
+  if (should_clear_ev_read(iod, ev_dec))
     clrmask |= EV_READ;
 
-  if ((ev_dec & EV_WRITE) && !iod->writesd_count)
+  if (should_clear_ev_write(iod, ev_dec))
     clrmask |= EV_WRITE;
 
+  /* EV_EXCEPT is systematically set and cannot be removed */
+  if (ev_inc & EV_EXCEPT)
+    nsock_log_info("Invalid event set, no need to specify EV_EXCEPT");
+
   if (ev_dec & EV_EXCEPT)
-    clrmask |= EV_EXCEPT;
+    nsock_log_info("Invalid event set, refusing to clear EV_EXCEPT");
 
   if (!IOD_PROPGET(iod, IOD_REGISTERED)) {
     assert(clrmask == EV_NONE);
@@ -426,7 +438,6 @@ void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status
 
     ev |= socket_count_read_dec(iod);
     ev |= socket_count_write_dec(iod);
-    ev |= EV_EXCEPT;
     update_events(iod, ms, nse, EV_NONE, ev);
   }
 
@@ -951,7 +962,9 @@ enum nsock_loopstatus nsock_loop(nsock_pool nsp, int msec_timeout) {
 }
 
 void process_event(struct npool *nsp, gh_list_t *evlist, struct nevent *nse, int ev) {
-  int match_r = 0, match_w = 0;
+  int match_r = ev & EV_READ;
+  int match_w = ev & EV_WRITE;
+  int match_x = ev & EV_EXCEPT;
 #if HAVE_OPENSSL
   int desire_r = 0, desire_w = 0;
 #endif
@@ -972,8 +985,6 @@ void process_event(struct npool *nsp, gh_list_t *evlist, struct nevent *nse, int
         break;
 
       case NSE_TYPE_READ:
-        match_r = ev & EV_READ;
-        match_w = ev & EV_WRITE;
 #if HAVE_OPENSSL
         desire_r = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ;
         desire_w = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE;
@@ -981,16 +992,15 @@ void process_event(struct npool *nsp, gh_list_t *evlist, struct nevent *nse, int
           handle_read_result(nsp, nse, NSE_STATUS_SUCCESS);
         else
 #endif
-        if (!nse->iod->ssl && match_r)
+        if ((!nse->iod->ssl && match_r) || match_x)
           handle_read_result(nsp, nse, NSE_STATUS_SUCCESS);
 
         if (event_timedout(nse))
           handle_read_result(nsp, nse, NSE_STATUS_TIMEOUT);
+
         break;
 
       case NSE_TYPE_WRITE:
-        match_r = ev & EV_READ;
-        match_w = ev & EV_WRITE;
 #if HAVE_OPENSSL
         desire_r = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ;
         desire_w = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE;
@@ -998,8 +1008,8 @@ void process_event(struct npool *nsp, gh_list_t *evlist, struct nevent *nse, int
           handle_write_result(nsp, nse, NSE_STATUS_SUCCESS);
         else
 #endif
-          if (!nse->iod->ssl && match_w)
-            handle_write_result(nsp, nse, NSE_STATUS_SUCCESS);
+        if ((!nse->iod->ssl && match_w) || match_x)
+          handle_write_result(nsp, nse, NSE_STATUS_SUCCESS);
 
         if (event_timedout(nse))
           handle_write_result(nsp, nse, NSE_STATUS_TIMEOUT);
@@ -1263,7 +1273,7 @@ void nsock_pool_add_event(struct npool *nsp, struct nevent *nse) {
         assert(nse->iod->sd >= 0);
         socket_count_read_inc(nse->iod);
         socket_count_write_inc(nse->iod);
-        update_events(nse->iod, nsp, nse, EV_READ|EV_WRITE|EV_EXCEPT, EV_NONE);
+        update_events(nse->iod, nsp, nse, EV_READ|EV_WRITE, EV_NONE);
       }
       iod_add_event(nse->iod, nse);
       break;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.