summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2017-09-21 19:16:53 +0000
committerDamien Miller <djm@mindrot.org>2017-09-22 09:14:53 +1000
commit609d7a66ce578abf259da2d5f6f68795c2bda731 (patch)
treefa0c5a5d6f04f69a6cd15bd4d3954412c4a1480c /channels.c
parent36945fa103176c00b39731e1fc1919a0d0808b81 (diff)
upstream commit
Add 'reverse' dynamic forwarding which combines dynamic forwarding (-D) with remote forwarding (-R) where the remote-forwarded port expects SOCKS-requests. The SSH server code is unchanged and the parsing happens at the SSH clients side. Thus the full SOCKS-request is sent over the forwarded channel and the client parses c->output. Parsing happens in channel_before_prepare_select(), _before_ the select bitmask is computed in the pre[] handlers, but after network input processing in the post[] handlers. help and ok djm@ Upstream-ID: aa25a6a3851064f34fe719e0bf15656ad5a64b89
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c374
1 files changed, 289 insertions, 85 deletions
diff --git a/channels.c b/channels.c
index 89b7d3486..8ef37c453 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.371 2017/09/19 12:10:30 millert Exp $ */ 1/* $OpenBSD: channels.c,v 1.372 2017/09/21 19:16:53 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -209,6 +209,8 @@ static const char *channel_rfwd_bind_host(const char *listen_host);
209/* non-blocking connect helpers */ 209/* non-blocking connect helpers */
210static int connect_next(struct channel_connect *); 210static int connect_next(struct channel_connect *);
211static void channel_connect_ctx_free(struct channel_connect *); 211static void channel_connect_ctx_free(struct channel_connect *);
212static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *);
213static int rdynamic_connect_finish(struct ssh *, Channel *);
212 214
213/* Setup helper */ 215/* Setup helper */
214static void channel_handler_init(struct ssh_channels *sc); 216static void channel_handler_init(struct ssh_channels *sc);
@@ -282,6 +284,8 @@ channel_lookup(struct ssh *ssh, int id)
282 case SSH_CHANNEL_LARVAL: 284 case SSH_CHANNEL_LARVAL:
283 case SSH_CHANNEL_CONNECTING: 285 case SSH_CHANNEL_CONNECTING:
284 case SSH_CHANNEL_DYNAMIC: 286 case SSH_CHANNEL_DYNAMIC:
287 case SSH_CHANNEL_RDYNAMIC_OPEN:
288 case SSH_CHANNEL_RDYNAMIC_FINISH:
285 case SSH_CHANNEL_OPENING: 289 case SSH_CHANNEL_OPENING:
286 case SSH_CHANNEL_OPEN: 290 case SSH_CHANNEL_OPEN:
287 case SSH_CHANNEL_ABANDONED: 291 case SSH_CHANNEL_ABANDONED:
@@ -671,6 +675,7 @@ channel_still_open(struct ssh *ssh)
671 case SSH_CHANNEL_CLOSED: 675 case SSH_CHANNEL_CLOSED:
672 case SSH_CHANNEL_AUTH_SOCKET: 676 case SSH_CHANNEL_AUTH_SOCKET:
673 case SSH_CHANNEL_DYNAMIC: 677 case SSH_CHANNEL_DYNAMIC:
678 case SSH_CHANNEL_RDYNAMIC_OPEN:
674 case SSH_CHANNEL_CONNECTING: 679 case SSH_CHANNEL_CONNECTING:
675 case SSH_CHANNEL_ZOMBIE: 680 case SSH_CHANNEL_ZOMBIE:
676 case SSH_CHANNEL_ABANDONED: 681 case SSH_CHANNEL_ABANDONED:
@@ -681,6 +686,7 @@ channel_still_open(struct ssh *ssh)
681 continue; 686 continue;
682 case SSH_CHANNEL_OPENING: 687 case SSH_CHANNEL_OPENING:
683 case SSH_CHANNEL_OPEN: 688 case SSH_CHANNEL_OPEN:
689 case SSH_CHANNEL_RDYNAMIC_FINISH:
684 case SSH_CHANNEL_X11_OPEN: 690 case SSH_CHANNEL_X11_OPEN:
685 case SSH_CHANNEL_MUX_CLIENT: 691 case SSH_CHANNEL_MUX_CLIENT:
686 case SSH_CHANNEL_MUX_PROXY: 692 case SSH_CHANNEL_MUX_PROXY:
@@ -707,6 +713,8 @@ channel_find_open(struct ssh *ssh)
707 switch (c->type) { 713 switch (c->type) {
708 case SSH_CHANNEL_CLOSED: 714 case SSH_CHANNEL_CLOSED:
709 case SSH_CHANNEL_DYNAMIC: 715 case SSH_CHANNEL_DYNAMIC:
716 case SSH_CHANNEL_RDYNAMIC_OPEN:
717 case SSH_CHANNEL_RDYNAMIC_FINISH:
710 case SSH_CHANNEL_X11_LISTENER: 718 case SSH_CHANNEL_X11_LISTENER:
711 case SSH_CHANNEL_PORT_LISTENER: 719 case SSH_CHANNEL_PORT_LISTENER:
712 case SSH_CHANNEL_RPORT_LISTENER: 720 case SSH_CHANNEL_RPORT_LISTENER:
@@ -772,6 +780,8 @@ channel_open_message(struct ssh *ssh)
772 case SSH_CHANNEL_OPENING: 780 case SSH_CHANNEL_OPENING:
773 case SSH_CHANNEL_CONNECTING: 781 case SSH_CHANNEL_CONNECTING:
774 case SSH_CHANNEL_DYNAMIC: 782 case SSH_CHANNEL_DYNAMIC:
783 case SSH_CHANNEL_RDYNAMIC_OPEN:
784 case SSH_CHANNEL_RDYNAMIC_FINISH:
775 case SSH_CHANNEL_OPEN: 785 case SSH_CHANNEL_OPEN:
776 case SSH_CHANNEL_X11_OPEN: 786 case SSH_CHANNEL_X11_OPEN:
777 case SSH_CHANNEL_MUX_PROXY: 787 case SSH_CHANNEL_MUX_PROXY:
@@ -1124,8 +1134,7 @@ channel_pre_mux_client(struct ssh *ssh,
1124 1134
1125/* try to decode a socks4 header */ 1135/* try to decode a socks4 header */
1126static int 1136static int
1127channel_decode_socks4(struct ssh *ssh, Channel *c, 1137channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
1128 fd_set *readset, fd_set *writeset)
1129{ 1138{
1130 const u_char *p; 1139 const u_char *p;
1131 char *host; 1140 char *host;
@@ -1141,11 +1150,11 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1141 1150
1142 debug2("channel %d: decode socks4", c->self); 1151 debug2("channel %d: decode socks4", c->self);
1143 1152
1144 have = sshbuf_len(c->input); 1153 have = sshbuf_len(input);
1145 len = sizeof(s4_req); 1154 len = sizeof(s4_req);
1146 if (have < len) 1155 if (have < len)
1147 return 0; 1156 return 0;
1148 p = sshbuf_ptr(c->input); 1157 p = sshbuf_ptr(input);
1149 1158
1150 need = 1; 1159 need = 1;
1151 /* SOCKS4A uses an invalid IP address 0.0.0.x */ 1160 /* SOCKS4A uses an invalid IP address 0.0.0.x */
@@ -1170,15 +1179,15 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1170 } 1179 }
1171 if (found < need) 1180 if (found < need)
1172 return 0; 1181 return 0;
1173 if ((r = sshbuf_get(c->input, &s4_req.version, 1)) != 0 || 1182 if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 ||
1174 (r = sshbuf_get(c->input, &s4_req.command, 1)) != 0 || 1183 (r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||
1175 (r = sshbuf_get(c->input, &s4_req.dest_port, 2)) != 0 || 1184 (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||
1176 (r = sshbuf_get(c->input, &s4_req.dest_addr, 4)) != 0) { 1185 (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {
1177 debug("channels %d: decode socks4: %s", c->self, ssh_err(r)); 1186 debug("channels %d: decode socks4: %s", c->self, ssh_err(r));
1178 return -1; 1187 return -1;
1179 } 1188 }
1180 have = sshbuf_len(c->input); 1189 have = sshbuf_len(input);
1181 p = sshbuf_ptr(c->input); 1190 p = sshbuf_ptr(input);
1182 if (memchr(p, '\0', have) == NULL) { 1191 if (memchr(p, '\0', have) == NULL) {
1183 error("channel %d: decode socks4: user not nul terminated", 1192 error("channel %d: decode socks4: user not nul terminated",
1184 c->self); 1193 c->self);
@@ -1188,7 +1197,7 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1188 debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); 1197 debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
1189 len++; /* trailing '\0' */ 1198 len++; /* trailing '\0' */
1190 strlcpy(username, p, sizeof(username)); 1199 strlcpy(username, p, sizeof(username));
1191 if ((r = sshbuf_consume(c->input, len)) != 0) { 1200 if ((r = sshbuf_consume(input, len)) != 0) {
1192 fatal("%s: channel %d: consume: %s", __func__, 1201 fatal("%s: channel %d: consume: %s", __func__,
1193 c->self, ssh_err(r)); 1202 c->self, ssh_err(r));
1194 } 1203 }
@@ -1198,8 +1207,8 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1198 host = inet_ntoa(s4_req.dest_addr); 1207 host = inet_ntoa(s4_req.dest_addr);
1199 c->path = xstrdup(host); 1208 c->path = xstrdup(host);
1200 } else { /* SOCKS4A: two strings */ 1209 } else { /* SOCKS4A: two strings */
1201 have = sshbuf_len(c->input); 1210 have = sshbuf_len(input);
1202 p = sshbuf_ptr(c->input); 1211 p = sshbuf_ptr(input);
1203 if (memchr(p, '\0', have) == NULL) { 1212 if (memchr(p, '\0', have) == NULL) {
1204 error("channel %d: decode socks4a: host not nul " 1213 error("channel %d: decode socks4a: host not nul "
1205 "terminated", c->self); 1214 "terminated", c->self);
@@ -1215,7 +1224,7 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1215 return -1; 1224 return -1;
1216 } 1225 }
1217 c->path = xstrdup(p); 1226 c->path = xstrdup(p);
1218 if ((r = sshbuf_consume(c->input, len)) != 0) { 1227 if ((r = sshbuf_consume(input, len)) != 0) {
1219 fatal("%s: channel %d: consume: %s", __func__, 1228 fatal("%s: channel %d: consume: %s", __func__,
1220 c->self, ssh_err(r)); 1229 c->self, ssh_err(r));
1221 } 1230 }
@@ -1234,7 +1243,7 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1234 s4_rsp.command = 90; /* cd: req granted */ 1243 s4_rsp.command = 90; /* cd: req granted */
1235 s4_rsp.dest_port = 0; /* ignored */ 1244 s4_rsp.dest_port = 0; /* ignored */
1236 s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ 1245 s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
1237 if ((r = sshbuf_put(c->output, &s4_rsp, sizeof(s4_rsp))) != 0) { 1246 if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) {
1238 fatal("%s: channel %d: append reply: %s", __func__, 1247 fatal("%s: channel %d: append reply: %s", __func__,
1239 c->self, ssh_err(r)); 1248 c->self, ssh_err(r));
1240 } 1249 }
@@ -1251,8 +1260,7 @@ channel_decode_socks4(struct ssh *ssh, Channel *c,
1251#define SSH_SOCKS5_SUCCESS 0x00 1260#define SSH_SOCKS5_SUCCESS 0x00
1252 1261
1253static int 1262static int
1254channel_decode_socks5(struct ssh *ssh, Channel *c, 1263channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
1255 fd_set *readset, fd_set *writeset)
1256{ 1264{
1257 /* XXX use get/put_u8 instead of trusting struct padding */ 1265 /* XXX use get/put_u8 instead of trusting struct padding */
1258 struct { 1266 struct {
@@ -1268,10 +1276,10 @@ channel_decode_socks5(struct ssh *ssh, Channel *c,
1268 int r; 1276 int r;
1269 1277
1270 debug2("channel %d: decode socks5", c->self); 1278 debug2("channel %d: decode socks5", c->self);
1271 p = sshbuf_ptr(c->input); 1279 p = sshbuf_ptr(input);
1272 if (p[0] != 0x05) 1280 if (p[0] != 0x05)
1273 return -1; 1281 return -1;
1274 have = sshbuf_len(c->input); 1282 have = sshbuf_len(input);
1275 if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { 1283 if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
1276 /* format: ver | nmethods | methods */ 1284 /* format: ver | nmethods | methods */
1277 if (have < 2) 1285 if (have < 2)
@@ -1291,17 +1299,16 @@ channel_decode_socks5(struct ssh *ssh, Channel *c,
1291 c->self); 1299 c->self);
1292 return -1; 1300 return -1;
1293 } 1301 }
1294 if ((r = sshbuf_consume(c->input, nmethods + 2)) != 0) { 1302 if ((r = sshbuf_consume(input, nmethods + 2)) != 0) {
1295 fatal("%s: channel %d: consume: %s", __func__, 1303 fatal("%s: channel %d: consume: %s", __func__,
1296 c->self, ssh_err(r)); 1304 c->self, ssh_err(r));
1297 } 1305 }
1298 /* version, method */ 1306 /* version, method */
1299 if ((r = sshbuf_put_u8(c->output, 0x05)) != 0 || 1307 if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||
1300 (r = sshbuf_put_u8(c->output, SSH_SOCKS5_NOAUTH)) != 0) { 1308 (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) {
1301 fatal("%s: channel %d: append reply: %s", __func__, 1309 fatal("%s: channel %d: append reply: %s", __func__,
1302 c->self, ssh_err(r)); 1310 c->self, ssh_err(r));
1303 } 1311 }
1304 FD_SET(c->sock, writeset);
1305 c->flags |= SSH_SOCKS5_AUTHDONE; 1312 c->flags |= SSH_SOCKS5_AUTHDONE;
1306 debug2("channel %d: socks5 auth done", c->self); 1313 debug2("channel %d: socks5 auth done", c->self);
1307 return 0; /* need more */ 1314 return 0; /* need more */
@@ -1338,19 +1345,19 @@ channel_decode_socks5(struct ssh *ssh, Channel *c,
1338 need++; 1345 need++;
1339 if (have < need) 1346 if (have < need)
1340 return 0; 1347 return 0;
1341 if ((r = sshbuf_consume(c->input, sizeof(s5_req))) != 0) { 1348 if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) {
1342 fatal("%s: channel %d: consume: %s", __func__, 1349 fatal("%s: channel %d: consume: %s", __func__,
1343 c->self, ssh_err(r)); 1350 c->self, ssh_err(r));
1344 } 1351 }
1345 if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { 1352 if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
1346 /* host string length */ 1353 /* host string length */
1347 if ((r = sshbuf_consume(c->input, 1)) != 0) { 1354 if ((r = sshbuf_consume(input, 1)) != 0) {
1348 fatal("%s: channel %d: consume: %s", __func__, 1355 fatal("%s: channel %d: consume: %s", __func__,
1349 c->self, ssh_err(r)); 1356 c->self, ssh_err(r));
1350 } 1357 }
1351 } 1358 }
1352 if ((r = sshbuf_get(c->input, &dest_addr, addrlen)) != 0 || 1359 if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||
1353 (r = sshbuf_get(c->input, &dest_port, 2)) != 0) { 1360 (r = sshbuf_get(input, &dest_port, 2)) != 0) {
1354 debug("channel %d: parse addr/port: %s", c->self, ssh_err(r)); 1361 debug("channel %d: parse addr/port: %s", c->self, ssh_err(r));
1355 return -1; 1362 return -1;
1356 } 1363 }
@@ -1380,9 +1387,9 @@ channel_decode_socks5(struct ssh *ssh, Channel *c,
1380 s5_rsp.atyp = SSH_SOCKS5_IPV4; 1387 s5_rsp.atyp = SSH_SOCKS5_IPV4;
1381 dest_port = 0; /* ignored */ 1388 dest_port = 0; /* ignored */
1382 1389
1383 if ((r = sshbuf_put(c->output, &s5_rsp, sizeof(s5_rsp))) != 0 || 1390 if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||
1384 (r = sshbuf_put_u32(c->output, ntohl(INADDR_ANY))) != 0 || 1391 (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 ||
1385 (r = sshbuf_put(c->output, &dest_port, sizeof(dest_port))) != 0) 1392 (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)
1386 fatal("%s: channel %d: append reply: %s", __func__, 1393 fatal("%s: channel %d: append reply: %s", __func__,
1387 c->self, ssh_err(r)); 1394 c->self, ssh_err(r));
1388 return 1; 1395 return 1;
@@ -1434,10 +1441,10 @@ channel_pre_dynamic(struct ssh *ssh, Channel *c,
1434 /* XXX sshbuf_peek_u8? */ 1441 /* XXX sshbuf_peek_u8? */
1435 switch (p[0]) { 1442 switch (p[0]) {
1436 case 0x04: 1443 case 0x04:
1437 ret = channel_decode_socks4(ssh, c, readset, writeset); 1444 ret = channel_decode_socks4(c, c->input, c->output);
1438 break; 1445 break;
1439 case 0x05: 1446 case 0x05:
1440 ret = channel_decode_socks5(ssh, c, readset, writeset); 1447 ret = channel_decode_socks5(c, c->input, c->output);
1441 break; 1448 break;
1442 default: 1449 default:
1443 ret = -1; 1450 ret = -1;
@@ -1449,6 +1456,8 @@ channel_pre_dynamic(struct ssh *ssh, Channel *c,
1449 debug2("channel %d: pre_dynamic: need more", c->self); 1456 debug2("channel %d: pre_dynamic: need more", c->self);
1450 /* need more */ 1457 /* need more */
1451 FD_SET(c->sock, readset); 1458 FD_SET(c->sock, readset);
1459 if (sshbuf_len(c->output))
1460 FD_SET(c->sock, writeset);
1452 } else { 1461 } else {
1453 /* switch to the next state */ 1462 /* switch to the next state */
1454 c->type = SSH_CHANNEL_OPENING; 1463 c->type = SSH_CHANNEL_OPENING;
@@ -1456,6 +1465,81 @@ channel_pre_dynamic(struct ssh *ssh, Channel *c,
1456 } 1465 }
1457} 1466}
1458 1467
1468/* simulate read-error */
1469static void
1470rdynamic_close(struct ssh *ssh, Channel *c)
1471{
1472 c->type = SSH_CHANNEL_OPEN;
1473 chan_read_failed(ssh, c);
1474 sshbuf_reset(c->input);
1475 chan_ibuf_empty(ssh, c);
1476 sshbuf_reset(c->output);
1477 chan_write_failed(ssh, c);
1478}
1479
1480/* reverse dynamic port forwarding */
1481static void
1482channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c)
1483{
1484 const u_char *p;
1485 u_int have, len;
1486 int r, ret;
1487
1488 have = sshbuf_len(c->output);
1489 debug2("channel %d: pre_rdynamic: have %d", c->self, have);
1490 /* sshbuf_dump(c->output, stderr); */
1491 /* EOF received */
1492 if (c->flags & CHAN_EOF_RCVD) {
1493 if ((r = sshbuf_consume(c->output, have)) != 0) {
1494 fatal("%s: channel %d: consume: %s",
1495 __func__, c->self, ssh_err(r));
1496 }
1497 rdynamic_close(ssh, c);
1498 return;
1499 }
1500 /* check if the fixed size part of the packet is in buffer. */
1501 if (have < 3)
1502 return;
1503 /* try to guess the protocol */
1504 p = sshbuf_ptr(c->output);
1505 switch (p[0]) {
1506 case 0x04:
1507 /* switch input/output for reverse forwarding */
1508 ret = channel_decode_socks4(c, c->output, c->input);
1509 break;
1510 case 0x05:
1511 ret = channel_decode_socks5(c, c->output, c->input);
1512 break;
1513 default:
1514 ret = -1;
1515 break;
1516 }
1517 if (ret < 0) {
1518 rdynamic_close(ssh, c);
1519 } else if (ret == 0) {
1520 debug2("channel %d: pre_rdynamic: need more", c->self);
1521 /* send socks request to peer */
1522 len = sshbuf_len(c->input);
1523 if (len > 0 && len < c->remote_window) {
1524 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
1525 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1526 (r = sshpkt_put_stringb(ssh, c->input)) != 0 ||
1527 (r = sshpkt_send(ssh)) != 0) {
1528 fatal("%s: channel %i: rdynamic: %s", __func__,
1529 c->self, ssh_err(r));
1530 }
1531 if ((r = sshbuf_consume(c->input, len)) != 0) {
1532 fatal("%s: channel %d: consume: %s",
1533 __func__, c->self, ssh_err(r));
1534 }
1535 c->remote_window -= len;
1536 }
1537 } else if (rdynamic_connect_finish(ssh, c) < 0) {
1538 /* the connect failed */
1539 rdynamic_close(ssh, c);
1540 }
1541}
1542
1459/* This is our fake X11 server socket. */ 1543/* This is our fake X11 server socket. */
1460static void 1544static void
1461channel_post_x11_listener(struct ssh *ssh, Channel *c, 1545channel_post_x11_listener(struct ssh *ssh, Channel *c,
@@ -1699,14 +1783,15 @@ static void
1699channel_post_connecting(struct ssh *ssh, Channel *c, 1783channel_post_connecting(struct ssh *ssh, Channel *c,
1700 fd_set *readset, fd_set *writeset) 1784 fd_set *readset, fd_set *writeset)
1701{ 1785{
1702 int err = 0, sock, r; 1786 int err = 0, sock, isopen, r;
1703 socklen_t sz = sizeof(err); 1787 socklen_t sz = sizeof(err);
1704 1788
1705 if (!FD_ISSET(c->sock, writeset)) 1789 if (!FD_ISSET(c->sock, writeset))
1706 return; 1790 return;
1707 if (!c->have_remote_id) 1791 if (!c->have_remote_id)
1708 fatal(":%s: channel %d: no remote id", __func__, c->self); 1792 fatal(":%s: channel %d: no remote id", __func__, c->self);
1709 1793 /* for rdynamic the OPEN_CONFIRMATION has been sent already */
1794 isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH);
1710 if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { 1795 if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
1711 err = errno; 1796 err = errno;
1712 error("getsockopt SO_ERROR failed"); 1797 error("getsockopt SO_ERROR failed");
@@ -1716,14 +1801,21 @@ channel_post_connecting(struct ssh *ssh, Channel *c,
1716 c->self, c->connect_ctx.host, c->connect_ctx.port); 1801 c->self, c->connect_ctx.host, c->connect_ctx.port);
1717 channel_connect_ctx_free(&c->connect_ctx); 1802 channel_connect_ctx_free(&c->connect_ctx);
1718 c->type = SSH_CHANNEL_OPEN; 1803 c->type = SSH_CHANNEL_OPEN;
1719 if ((r = sshpkt_start(ssh, 1804 if (isopen) {
1720 SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || 1805 /* no message necessary */
1721 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || 1806 } else {
1722 (r = sshpkt_put_u32(ssh, c->self)) != 0 || 1807 if ((r = sshpkt_start(ssh,
1723 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || 1808 SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
1724 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { 1809 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1725 fatal("%s: channel %i: confirm: %s", __func__, 1810 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
1726 c->self, ssh_err(r)); 1811 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
1812 (r = sshpkt_put_u32(ssh, c->local_maxpacket))
1813 != 0)
1814 fatal("%s: channel %i: confirm: %s", __func__,
1815 c->self, ssh_err(r));
1816 if ((r = sshpkt_send(ssh)) != 0)
1817 fatal("%s: channel %i: %s", __func__, c->self,
1818 ssh_err(r));
1727 } 1819 }
1728 } else { 1820 } else {
1729 debug("channel %d: connection failed: %s", 1821 debug("channel %d: connection failed: %s",
@@ -1739,22 +1831,27 @@ channel_post_connecting(struct ssh *ssh, Channel *c,
1739 error("connect_to %.100s port %d: failed.", 1831 error("connect_to %.100s port %d: failed.",
1740 c->connect_ctx.host, c->connect_ctx.port); 1832 c->connect_ctx.host, c->connect_ctx.port);
1741 channel_connect_ctx_free(&c->connect_ctx); 1833 channel_connect_ctx_free(&c->connect_ctx);
1742 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || 1834 if (isopen) {
1743 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || 1835 rdynamic_close(ssh, c);
1744 (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED)) != 0) { 1836 } else {
1745 fatal("%s: channel %i: failure: %s", __func__, 1837 if ((r = sshpkt_start(ssh,
1746 c->self, ssh_err(r)); 1838 SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
1747 } 1839 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1748 if ((datafellows & SSH_BUG_OPENFAILURE) == 0 && 1840 (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED))
1749 ((r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || 1841 != 0)
1750 (r = sshpkt_put_cstring(ssh, "")) != 0)) { 1842 fatal("%s: channel %i: failure: %s", __func__,
1751 fatal("%s: channel %i: failure: %s", __func__, 1843 c->self, ssh_err(r));
1752 c->self, ssh_err(r)); 1844 if ((datafellows & SSH_BUG_OPENFAILURE) == 0 &&
1845 ((r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||
1846 (r = sshpkt_put_cstring(ssh, "")) != 0))
1847 fatal("%s: channel %i: failure: %s", __func__,
1848 c->self, ssh_err(r));
1849 if ((r = sshpkt_send(ssh)) != 0)
1850 fatal("%s: channel %i: %s", __func__, c->self,
1851 ssh_err(r));
1852 chan_mark_dead(ssh, c);
1753 } 1853 }
1754 chan_mark_dead(ssh, c);
1755 } 1854 }
1756 if ((r = sshpkt_send(ssh)) != 0)
1757 fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
1758} 1855}
1759 1856
1760static int 1857static int
@@ -2187,6 +2284,7 @@ channel_handler_init(struct ssh_channels *sc)
2187 pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 2284 pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
2188 pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 2285 pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
2189 pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; 2286 pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
2287 pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting;
2190 pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; 2288 pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
2191 pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; 2289 pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
2192 2290
@@ -2199,6 +2297,7 @@ channel_handler_init(struct ssh_channels *sc)
2199 post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 2297 post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2200 post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 2298 post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
2201 post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; 2299 post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
2300 post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting;
2202 post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; 2301 post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
2203 post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; 2302 post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
2204 2303
@@ -2280,6 +2379,27 @@ channel_handler(struct ssh *ssh, int table,
2280} 2379}
2281 2380
2282/* 2381/*
2382 * Create sockets before allocating the select bitmasks.
2383 * This is necessary for things that need to happen after reading
2384 * the network-input but before channel_prepare_select().
2385 */
2386static void
2387channel_before_prepare_select(struct ssh *ssh)
2388{
2389 struct ssh_channels *sc = ssh->chanctxt;
2390 Channel *c;
2391 u_int i, oalloc;
2392
2393 for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
2394 c = sc->channels[i];
2395 if (c == NULL)
2396 continue;
2397 if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN)
2398 channel_before_prepare_select_rdynamic(ssh, c);
2399 }
2400}
2401
2402/*
2283 * Allocate/update select bitmasks and add any bits relevant to channels in 2403 * Allocate/update select bitmasks and add any bits relevant to channels in
2284 * select bitmasks. 2404 * select bitmasks.
2285 */ 2405 */
@@ -2289,6 +2409,8 @@ channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp,
2289{ 2409{
2290 u_int n, sz, nfdset; 2410 u_int n, sz, nfdset;
2291 2411
2412 channel_before_prepare_select(ssh); /* might update channel_max_fd */
2413
2292 n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd); 2414 n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd);
2293 2415
2294 nfdset = howmany(n+1, NFDBITS); 2416 nfdset = howmany(n+1, NFDBITS);
@@ -2794,6 +2916,8 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
2794 2916
2795 /* Ignore any data for non-open channels (might happen on close) */ 2917 /* Ignore any data for non-open channels (might happen on close) */
2796 if (c->type != SSH_CHANNEL_OPEN && 2918 if (c->type != SSH_CHANNEL_OPEN &&
2919 c->type != SSH_CHANNEL_RDYNAMIC_OPEN &&
2920 c->type != SSH_CHANNEL_RDYNAMIC_FINISH &&
2797 c->type != SSH_CHANNEL_X11_OPEN) 2921 c->type != SSH_CHANNEL_X11_OPEN)
2798 return 0; 2922 return 0;
2799 2923
@@ -3032,7 +3156,7 @@ channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
3032 if ((c = channel_lookup(ssh, id)) == NULL) { 3156 if ((c = channel_lookup(ssh, id)) == NULL) {
3033 logit("Received window adjust for non-open channel %d.", id); 3157 logit("Received window adjust for non-open channel %d.", id);
3034 return 0; 3158 return 0;
3035 } 3159 }
3036 3160
3037 if (channel_proxy_upstream(c, type, seq, ssh)) 3161 if (channel_proxy_upstream(c, type, seq, ssh))
3038 return 0; 3162 return 0;
@@ -3939,21 +4063,18 @@ channel_connect_ctx_free(struct channel_connect *cctx)
3939} 4063}
3940 4064
3941/* 4065/*
3942 * Return CONNECTING channel to remote host:port or local socket path, 4066 * Return connecting socket to remote host:port or local socket path,
3943 * passing back the failure reason if appropriate. 4067 * passing back the failure reason if appropriate.
3944 */ 4068 */
3945static Channel * 4069static int
3946connect_to_reason(struct ssh *ssh, const char *name, int port, 4070connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype,
3947 char *ctype, char *rname, int *reason, const char **errmsg) 4071 char *ctype, char *rname, struct channel_connect *cctx,
4072 int *reason, const char **errmsg)
3948{ 4073{
3949 struct addrinfo hints; 4074 struct addrinfo hints;
3950 int gaierr; 4075 int gaierr;
3951 int sock = -1; 4076 int sock = -1;
3952 char strport[NI_MAXSERV]; 4077 char strport[NI_MAXSERV];
3953 struct channel_connect cctx;
3954 Channel *c;
3955
3956 memset(&cctx, 0, sizeof(cctx));
3957 4078
3958 if (port == PORT_STREAMLOCAL) { 4079 if (port == PORT_STREAMLOCAL) {
3959 struct sockaddr_un *sunaddr; 4080 struct sockaddr_un *sunaddr;
@@ -3961,7 +4082,7 @@ connect_to_reason(struct ssh *ssh, const char *name, int port,
3961 4082
3962 if (strlen(name) > sizeof(sunaddr->sun_path)) { 4083 if (strlen(name) > sizeof(sunaddr->sun_path)) {
3963 error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); 4084 error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
3964 return (NULL); 4085 return -1;
3965 } 4086 }
3966 4087
3967 /* 4088 /*
@@ -3974,18 +4095,18 @@ connect_to_reason(struct ssh *ssh, const char *name, int port,
3974 ai->ai_addr = (struct sockaddr *)(ai + 1); 4095 ai->ai_addr = (struct sockaddr *)(ai + 1);
3975 ai->ai_addrlen = sizeof(*sunaddr); 4096 ai->ai_addrlen = sizeof(*sunaddr);
3976 ai->ai_family = AF_UNIX; 4097 ai->ai_family = AF_UNIX;
3977 ai->ai_socktype = SOCK_STREAM; 4098 ai->ai_socktype = socktype;
3978 ai->ai_protocol = PF_UNSPEC; 4099 ai->ai_protocol = PF_UNSPEC;
3979 sunaddr = (struct sockaddr_un *)ai->ai_addr; 4100 sunaddr = (struct sockaddr_un *)ai->ai_addr;
3980 sunaddr->sun_family = AF_UNIX; 4101 sunaddr->sun_family = AF_UNIX;
3981 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); 4102 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
3982 cctx.aitop = ai; 4103 cctx->aitop = ai;
3983 } else { 4104 } else {
3984 memset(&hints, 0, sizeof(hints)); 4105 memset(&hints, 0, sizeof(hints));
3985 hints.ai_family = ssh->chanctxt->IPv4or6; 4106 hints.ai_family = ssh->chanctxt->IPv4or6;
3986 hints.ai_socktype = SOCK_STREAM; 4107 hints.ai_socktype = socktype;
3987 snprintf(strport, sizeof strport, "%d", port); 4108 snprintf(strport, sizeof strport, "%d", port);
3988 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) 4109 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop))
3989 != 0) { 4110 != 0) {
3990 if (errmsg != NULL) 4111 if (errmsg != NULL)
3991 *errmsg = ssh_gai_strerror(gaierr); 4112 *errmsg = ssh_gai_strerror(gaierr);
@@ -3993,32 +4114,46 @@ connect_to_reason(struct ssh *ssh, const char *name, int port,
3993 *reason = SSH2_OPEN_CONNECT_FAILED; 4114 *reason = SSH2_OPEN_CONNECT_FAILED;
3994 error("connect_to %.100s: unknown host (%s)", name, 4115 error("connect_to %.100s: unknown host (%s)", name,
3995 ssh_gai_strerror(gaierr)); 4116 ssh_gai_strerror(gaierr));
3996 return NULL; 4117 return -1;
3997 } 4118 }
3998 } 4119 }
3999 4120
4000 cctx.host = xstrdup(name); 4121 cctx->host = xstrdup(name);
4001 cctx.port = port; 4122 cctx->port = port;
4002 cctx.ai = cctx.aitop; 4123 cctx->ai = cctx->aitop;
4003 4124
4004 if ((sock = connect_next(&cctx)) == -1) { 4125 if ((sock = connect_next(cctx)) == -1) {
4005 error("connect to %.100s port %d failed: %s", 4126 error("connect to %.100s port %d failed: %s",
4006 name, port, strerror(errno)); 4127 name, port, strerror(errno));
4007 channel_connect_ctx_free(&cctx); 4128 return -1;
4008 return NULL;
4009 } 4129 }
4010 c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, 4130
4011 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); 4131 return sock;
4012 c->connect_ctx = cctx;
4013 return c;
4014} 4132}
4015 4133
4016/* Return CONNECTING channel to remote host:port or local socket path */ 4134/* Return CONNECTING channel to remote host:port or local socket path */
4017static Channel * 4135static Channel *
4018connect_to(struct ssh *ssh, const char *name, int port, 4136connect_to(struct ssh *ssh, const char *host, int port,
4019 char *ctype, char *rname) 4137 char *ctype, char *rname)
4020{ 4138{
4021 return connect_to_reason(ssh, name, port, ctype, rname, NULL, NULL); 4139 struct channel_connect cctx;
4140 Channel *c;
4141 int sock;
4142
4143 memset(&cctx, 0, sizeof(cctx));
4144 sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
4145 &cctx, NULL, NULL);
4146 if (sock == -1) {
4147 channel_connect_ctx_free(&cctx);
4148 return NULL;
4149 }
4150 c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
4151 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
4152 c->host_port = port;
4153 c->path = xstrdup(host);
4154 c->connect_ctx = cctx;
4155
4156 return c;
4022} 4157}
4023 4158
4024/* 4159/*
@@ -4038,6 +4173,9 @@ channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
4038 if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) { 4173 if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) {
4039 if (fp->downstream) 4174 if (fp->downstream)
4040 return fp->downstream; 4175 return fp->downstream;
4176 if (fp->port_to_connect == 0)
4177 return rdynamic_connect_prepare(ssh,
4178 ctype, rname);
4041 return connect_to(ssh, 4179 return connect_to(ssh,
4042 fp->host_to_connect, fp->port_to_connect, 4180 fp->host_to_connect, fp->port_to_connect,
4043 ctype, rname); 4181 ctype, rname);
@@ -4075,7 +4213,10 @@ channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
4075 char *ctype, char *rname, int *reason, const char **errmsg) 4213 char *ctype, char *rname, int *reason, const char **errmsg)
4076{ 4214{
4077 struct ssh_channels *sc = ssh->chanctxt; 4215 struct ssh_channels *sc = ssh->chanctxt;
4216 struct channel_connect cctx;
4217 Channel *c;
4078 u_int i, permit, permit_adm = 1; 4218 u_int i, permit, permit_adm = 1;
4219 int sock;
4079 ForwardPermission *fp; 4220 ForwardPermission *fp;
4080 4221
4081 permit = sc->all_opens_permitted; 4222 permit = sc->all_opens_permitted;
@@ -4107,7 +4248,22 @@ channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
4107 *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; 4248 *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
4108 return NULL; 4249 return NULL;
4109 } 4250 }
4110 return connect_to_reason(ssh, host, port, ctype, rname, reason, errmsg); 4251
4252 memset(&cctx, 0, sizeof(cctx));
4253 sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
4254 &cctx, reason, errmsg);
4255 if (sock == -1) {
4256 channel_connect_ctx_free(&cctx);
4257 return NULL;
4258 }
4259
4260 c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
4261 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
4262 c->host_port = port;
4263 c->path = xstrdup(host);
4264 c->connect_ctx = cctx;
4265
4266 return c;
4111} 4267}
4112 4268
4113/* Check if connecting to that path is permitted and connect. */ 4269/* Check if connecting to that path is permitted and connect. */
@@ -4174,6 +4330,54 @@ channel_send_window_changes(struct ssh *ssh)
4174 } 4330 }
4175} 4331}
4176 4332
4333/* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */
4334static Channel *
4335rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
4336{
4337 Channel *c;
4338 int r;
4339
4340 c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1,
4341 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
4342 c->host_port = 0;
4343 c->path = NULL;
4344
4345 /*
4346 * We need to open the channel before we have a FD,
4347 * so that we can get SOCKS header from peer.
4348 */
4349 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
4350 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
4351 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
4352 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
4353 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
4354 fatal("%s: channel %i: confirm: %s", __func__,
4355 c->self, ssh_err(r));
4356 }
4357 return c;
4358}
4359
4360/* Return CONNECTING socket to remote host:port or local socket path */
4361static int
4362rdynamic_connect_finish(struct ssh *ssh, Channel *c)
4363{
4364 struct channel_connect cctx;
4365 int sock;
4366
4367 memset(&cctx, 0, sizeof(cctx));
4368 sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
4369 NULL, &cctx, NULL, NULL);
4370 if (sock == -1)
4371 channel_connect_ctx_free(&cctx);
4372 else {
4373 /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */
4374 c->type = SSH_CHANNEL_RDYNAMIC_FINISH;
4375 c->connect_ctx = cctx;
4376 channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0);
4377 }
4378 return sock;
4379}
4380
4177/* -- X11 forwarding */ 4381/* -- X11 forwarding */
4178 4382
4179/* 4383/*