diff options
author | beck <> | 2019-11-13 04:10:38 +0000 |
---|---|---|
committer | beck <> | 2019-11-13 04:10:38 +0000 |
commit | bb392e46353010e9b8df230389fa7a849f4ec42e (patch) | |
tree | b9dc89ebc1f5efebbaf280c80b0cc30be3db858a /src/usr.bin/nc/netcat.c | |
parent | 6c950d6ea19b4cc2844f226bb33a9847cab36f21 (diff) | |
download | openbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.tar.gz openbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.tar.bz2 openbsd-bb392e46353010e9b8df230389fa7a849f4ec42e.zip |
refactor the nc pool loop to not shut down the socket early, and
to handle tls_shutdown correctly if using TLS, doing tls_shutdown
correctly if we are using the -N flag
ok sthen@
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r-- | src/usr.bin/nc/netcat.c | 100 |
1 files changed, 64 insertions, 36 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index a53fe1c4cd..1dc95e9f36 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: netcat.c,v 1.210 2019/11/04 17:33:28 millert Exp $ */ | 1 | /* $OpenBSD: netcat.c,v 1.211 2019/11/13 04:10:38 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> | 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> |
4 | * Copyright (c) 2015 Bob Beck. All rights reserved. | 4 | * Copyright (c) 2015 Bob Beck. All rights reserved. |
@@ -1103,13 +1103,14 @@ void | |||
1103 | readwrite(int net_fd, struct tls *tls_ctx) | 1103 | readwrite(int net_fd, struct tls *tls_ctx) |
1104 | { | 1104 | { |
1105 | struct pollfd pfd[4]; | 1105 | struct pollfd pfd[4]; |
1106 | int gone[4] = { 0 }; | ||
1106 | int stdin_fd = STDIN_FILENO; | 1107 | int stdin_fd = STDIN_FILENO; |
1107 | int stdout_fd = STDOUT_FILENO; | 1108 | int stdout_fd = STDOUT_FILENO; |
1108 | unsigned char netinbuf[BUFSIZE]; | 1109 | unsigned char netinbuf[BUFSIZE]; |
1109 | size_t netinbufpos = 0; | 1110 | size_t netinbufpos = 0; |
1110 | unsigned char stdinbuf[BUFSIZE]; | 1111 | unsigned char stdinbuf[BUFSIZE]; |
1111 | size_t stdinbufpos = 0; | 1112 | size_t stdinbufpos = 0; |
1112 | int n, num_fds; | 1113 | int n, num_fds, shutdown_netin, shutdown_netout; |
1113 | ssize_t ret; | 1114 | ssize_t ret; |
1114 | 1115 | ||
1115 | /* don't read from stdin if requested */ | 1116 | /* don't read from stdin if requested */ |
@@ -1132,17 +1133,20 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1132 | pfd[POLL_STDOUT].fd = stdout_fd; | 1133 | pfd[POLL_STDOUT].fd = stdout_fd; |
1133 | pfd[POLL_STDOUT].events = 0; | 1134 | pfd[POLL_STDOUT].events = 0; |
1134 | 1135 | ||
1136 | /* used to indicate we wish to shut down the network socket */ | ||
1137 | shutdown_netin = shutdown_netout = 0; | ||
1138 | |||
1135 | while (1) { | 1139 | while (1) { |
1136 | /* both inputs are gone, buffers are empty, we are done */ | 1140 | /* both inputs are gone, buffers are empty, we are done */ |
1137 | if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 && | 1141 | if (gone[POLL_STDIN] && gone[POLL_NETIN] && |
1138 | stdinbufpos == 0 && netinbufpos == 0) | 1142 | stdinbufpos == 0 && netinbufpos == 0) |
1139 | return; | 1143 | return; |
1140 | /* both outputs are gone, we can't continue */ | 1144 | /* both outputs are gone, we can't continue */ |
1141 | if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) | 1145 | if (gone[POLL_NETOUT] && gone[POLL_STDOUT]) |
1142 | return; | 1146 | return; |
1143 | /* listen and net in gone, queues empty, done */ | 1147 | /* listen and net in gone, queues empty, done */ |
1144 | if (lflag && pfd[POLL_NETIN].fd == -1 && | 1148 | if (lflag && gone[POLL_NETIN] && stdinbufpos == 0 |
1145 | stdinbufpos == 0 && netinbufpos == 0) | 1149 | && netinbufpos == 0) |
1146 | return; | 1150 | return; |
1147 | 1151 | ||
1148 | /* help says -i is for "wait between lines sent". We read and | 1152 | /* help says -i is for "wait between lines sent". We read and |
@@ -1151,6 +1155,12 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1151 | if (iflag) | 1155 | if (iflag) |
1152 | sleep(iflag); | 1156 | sleep(iflag); |
1153 | 1157 | ||
1158 | /* If it's gone, take it away from poll */ | ||
1159 | for (n = 0; n < 4; n++) { | ||
1160 | if (gone[n]) | ||
1161 | pfd[n].events = pfd[n].revents = 0; | ||
1162 | } | ||
1163 | |||
1154 | /* poll */ | 1164 | /* poll */ |
1155 | num_fds = poll(pfd, 4, timeout); | 1165 | num_fds = poll(pfd, 4, timeout); |
1156 | 1166 | ||
@@ -1165,36 +1175,36 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1165 | /* treat socket error conditions */ | 1175 | /* treat socket error conditions */ |
1166 | for (n = 0; n < 4; n++) { | 1176 | for (n = 0; n < 4; n++) { |
1167 | if (pfd[n].revents & (POLLERR|POLLNVAL)) { | 1177 | if (pfd[n].revents & (POLLERR|POLLNVAL)) { |
1168 | pfd[n].fd = -1; | 1178 | gone[n] = 1; |
1169 | } | 1179 | } |
1170 | } | 1180 | } |
1171 | /* reading is possible after HUP */ | 1181 | /* reading is possible after HUP */ |
1172 | if (pfd[POLL_STDIN].events & POLLIN && | 1182 | if (pfd[POLL_STDIN].events & POLLIN && |
1173 | pfd[POLL_STDIN].revents & POLLHUP && | 1183 | pfd[POLL_STDIN].revents & POLLHUP && |
1174 | !(pfd[POLL_STDIN].revents & POLLIN)) | 1184 | !(pfd[POLL_STDIN].revents & POLLIN)) |
1175 | pfd[POLL_STDIN].fd = -1; | 1185 | gone[POLL_STDIN] = 1; |
1176 | 1186 | ||
1177 | if (pfd[POLL_NETIN].events & POLLIN && | 1187 | if (pfd[POLL_NETIN].events & POLLIN && |
1178 | pfd[POLL_NETIN].revents & POLLHUP && | 1188 | pfd[POLL_NETIN].revents & POLLHUP && |
1179 | !(pfd[POLL_NETIN].revents & POLLIN)) | 1189 | !(pfd[POLL_NETIN].revents & POLLIN)) |
1180 | pfd[POLL_NETIN].fd = -1; | 1190 | gone[POLL_NETIN] = 1; |
1181 | 1191 | ||
1182 | if (pfd[POLL_NETOUT].revents & POLLHUP) { | 1192 | if (pfd[POLL_NETOUT].revents & POLLHUP) { |
1183 | if (Nflag) | 1193 | if (Nflag) |
1184 | shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); | 1194 | shutdown_netout = 1; |
1185 | pfd[POLL_NETOUT].fd = -1; | 1195 | gone[POLL_NETOUT] = 1; |
1186 | } | 1196 | } |
1187 | /* if HUP, stop watching stdout */ | ||
1188 | if (pfd[POLL_STDOUT].revents & POLLHUP) | ||
1189 | pfd[POLL_STDOUT].fd = -1; | ||
1190 | /* if no net out, stop watching stdin */ | 1197 | /* if no net out, stop watching stdin */ |
1191 | if (pfd[POLL_NETOUT].fd == -1) | 1198 | if (gone[POLL_NETOUT]) |
1192 | pfd[POLL_STDIN].fd = -1; | 1199 | gone[POLL_STDIN] = 1; |
1200 | |||
1201 | /* if stdout HUP's, stop watching stdout */ | ||
1202 | if (pfd[POLL_STDOUT].revents & POLLHUP) | ||
1203 | gone[POLL_STDOUT] = 1; | ||
1193 | /* if no stdout, stop watching net in */ | 1204 | /* if no stdout, stop watching net in */ |
1194 | if (pfd[POLL_STDOUT].fd == -1) { | 1205 | if (gone[POLL_STDOUT]) { |
1195 | if (pfd[POLL_NETIN].fd != -1) | 1206 | shutdown_netin = 1; |
1196 | shutdown(pfd[POLL_NETIN].fd, SHUT_RD); | 1207 | gone[POLL_NETIN] = 1; |
1197 | pfd[POLL_NETIN].fd = -1; | ||
1198 | } | 1208 | } |
1199 | 1209 | ||
1200 | /* try to read from stdin */ | 1210 | /* try to read from stdin */ |
@@ -1206,7 +1216,7 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1206 | else if (ret == TLS_WANT_POLLOUT) | 1216 | else if (ret == TLS_WANT_POLLOUT) |
1207 | pfd[POLL_STDIN].events = POLLOUT; | 1217 | pfd[POLL_STDIN].events = POLLOUT; |
1208 | else if (ret == 0 || ret == -1) | 1218 | else if (ret == 0 || ret == -1) |
1209 | pfd[POLL_STDIN].fd = -1; | 1219 | gone[POLL_STDIN] = 1; |
1210 | /* read something - poll net out */ | 1220 | /* read something - poll net out */ |
1211 | if (stdinbufpos > 0) | 1221 | if (stdinbufpos > 0) |
1212 | pfd[POLL_NETOUT].events = POLLOUT; | 1222 | pfd[POLL_NETOUT].events = POLLOUT; |
@@ -1223,7 +1233,7 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1223 | else if (ret == TLS_WANT_POLLOUT) | 1233 | else if (ret == TLS_WANT_POLLOUT) |
1224 | pfd[POLL_NETOUT].events = POLLOUT; | 1234 | pfd[POLL_NETOUT].events = POLLOUT; |
1225 | else if (ret == -1) | 1235 | else if (ret == -1) |
1226 | pfd[POLL_NETOUT].fd = -1; | 1236 | gone[POLL_NETOUT] = 1; |
1227 | /* buffer empty - remove self from polling */ | 1237 | /* buffer empty - remove self from polling */ |
1228 | if (stdinbufpos == 0) | 1238 | if (stdinbufpos == 0) |
1229 | pfd[POLL_NETOUT].events = 0; | 1239 | pfd[POLL_NETOUT].events = 0; |
@@ -1240,17 +1250,15 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1240 | else if (ret == TLS_WANT_POLLOUT) | 1250 | else if (ret == TLS_WANT_POLLOUT) |
1241 | pfd[POLL_NETIN].events = POLLOUT; | 1251 | pfd[POLL_NETIN].events = POLLOUT; |
1242 | else if (ret == -1) | 1252 | else if (ret == -1) |
1243 | pfd[POLL_NETIN].fd = -1; | 1253 | gone[POLL_NETIN] = 1; |
1244 | /* eof on net in - remove from pfd */ | 1254 | /* eof on net in - remove from pfd */ |
1245 | if (ret == 0) { | 1255 | if (ret == 0) { |
1246 | shutdown(pfd[POLL_NETIN].fd, SHUT_RD); | 1256 | gone[POLL_NETIN] = 1; |
1247 | pfd[POLL_NETIN].fd = -1; | ||
1248 | } | 1257 | } |
1249 | if (recvlimit > 0 && ++recvcount >= recvlimit) { | 1258 | if (recvlimit > 0 && ++recvcount >= recvlimit) { |
1250 | if (pfd[POLL_NETIN].fd != -1) | 1259 | shutdown_netin = 1; |
1251 | shutdown(pfd[POLL_NETIN].fd, SHUT_RD); | 1260 | gone[POLL_NETIN] = 1; |
1252 | pfd[POLL_NETIN].fd = -1; | 1261 | gone[POLL_STDIN] = 1; |
1253 | pfd[POLL_STDIN].fd = -1; | ||
1254 | } | 1262 | } |
1255 | /* read something - poll stdout */ | 1263 | /* read something - poll stdout */ |
1256 | if (netinbufpos > 0) | 1264 | if (netinbufpos > 0) |
@@ -1272,7 +1280,7 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1272 | else if (ret == TLS_WANT_POLLOUT) | 1280 | else if (ret == TLS_WANT_POLLOUT) |
1273 | pfd[POLL_STDOUT].events = POLLOUT; | 1281 | pfd[POLL_STDOUT].events = POLLOUT; |
1274 | else if (ret == -1) | 1282 | else if (ret == -1) |
1275 | pfd[POLL_STDOUT].fd = -1; | 1283 | gone[POLL_STDOUT] = 1; |
1276 | /* buffer empty - remove self from polling */ | 1284 | /* buffer empty - remove self from polling */ |
1277 | if (netinbufpos == 0) | 1285 | if (netinbufpos == 0) |
1278 | pfd[POLL_STDOUT].events = 0; | 1286 | pfd[POLL_STDOUT].events = 0; |
@@ -1282,14 +1290,34 @@ readwrite(int net_fd, struct tls *tls_ctx) | |||
1282 | } | 1290 | } |
1283 | 1291 | ||
1284 | /* stdin gone and queue empty? */ | 1292 | /* stdin gone and queue empty? */ |
1285 | if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) { | 1293 | if (gone[POLL_STDIN] && stdinbufpos == 0) { |
1286 | if (pfd[POLL_NETOUT].fd != -1 && Nflag) | 1294 | if (Nflag) { |
1287 | shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); | 1295 | shutdown_netin = 1; |
1288 | pfd[POLL_NETOUT].fd = -1; | 1296 | shutdown_netout = 1; |
1297 | } | ||
1298 | gone[POLL_NETOUT] = 1; | ||
1289 | } | 1299 | } |
1290 | /* net in gone and queue empty? */ | 1300 | /* net in gone and queue empty? */ |
1291 | if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) { | 1301 | if (gone[POLL_NETIN] && netinbufpos == 0) { |
1292 | pfd[POLL_STDOUT].fd = -1; | 1302 | if (Nflag) { |
1303 | shutdown_netin = 1; | ||
1304 | shutdown_netout = 1; | ||
1305 | } | ||
1306 | gone[POLL_STDOUT] = 1; | ||
1307 | } | ||
1308 | |||
1309 | /* call tls_close if any part of the network socket is closing */ | ||
1310 | if ((shutdown_netin || shutdown_netout) && usetls) { | ||
1311 | timeout_tls(pfd[POLL_NETIN].fd, tls_ctx, tls_close); | ||
1312 | shutdown_netout = shutdown_netin = 1; | ||
1313 | } | ||
1314 | if (shutdown_netin) { | ||
1315 | shutdown(pfd[POLL_NETIN].fd, SHUT_RD); | ||
1316 | gone[POLL_NETIN] = 1; | ||
1317 | } | ||
1318 | if (shutdown_netout) { | ||
1319 | shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); | ||
1320 | gone[POLL_NETOUT] = 1; | ||
1293 | } | 1321 | } |
1294 | } | 1322 | } |
1295 | } | 1323 | } |