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;