summaryrefslogtreecommitdiff
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
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
-rw-r--r--channels.c374
-rw-r--r--channels.h6
-rw-r--r--readconf.c42
-rw-r--r--ssh.121
-rw-r--r--ssh.c5
-rw-r--r--ssh_config.516
6 files changed, 346 insertions, 118 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/*
diff --git a/channels.h b/channels.h
index d1cf5dc6a..126b04345 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.129 2017/09/12 06:35:32 djm Exp $ */ 1/* $OpenBSD: channels.h,v 1.130 2017/09/21 19:16:53 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -57,7 +57,9 @@
57#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ 57#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
58#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ 58#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
59#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */ 59#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
60#define SSH_CHANNEL_MAX_TYPE 21 60#define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */
61#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */
62#define SSH_CHANNEL_MAX_TYPE 23
61 63
62#define CHANNEL_CANCEL_PORT_STATIC -1 64#define CHANNEL_CANCEL_PORT_STATIC -1
63 65
diff --git a/readconf.c b/readconf.c
index 4f38b27cf..f63894f9c 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.c,v 1.278 2017/09/03 23:33:13 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.279 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
@@ -836,6 +836,7 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
836 char **cpptr, fwdarg[256]; 836 char **cpptr, fwdarg[256];
837 u_int i, *uintptr, max_entries = 0; 837 u_int i, *uintptr, max_entries = 0;
838 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; 838 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
839 int remotefwd, dynamicfwd;
839 LogLevel *log_level_ptr; 840 LogLevel *log_level_ptr;
840 SyslogFacility *log_facility_ptr; 841 SyslogFacility *log_facility_ptr;
841 long long val64; 842 long long val64;
@@ -1255,31 +1256,36 @@ parse_keytypes:
1255 fatal("%.200s line %d: Missing port argument.", 1256 fatal("%.200s line %d: Missing port argument.",
1256 filename, linenum); 1257 filename, linenum);
1257 1258
1258 if (opcode == oLocalForward || 1259 remotefwd = (opcode == oRemoteForward);
1259 opcode == oRemoteForward) { 1260 dynamicfwd = (opcode == oDynamicForward);
1260 arg2 = strdelim(&s);
1261 if (arg2 == NULL || *arg2 == '\0')
1262 fatal("%.200s line %d: Missing target argument.",
1263 filename, linenum);
1264 1261
1265 /* construct a string for parse_forward */ 1262 if (!dynamicfwd) {
1266 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 1263 arg2 = strdelim(&s);
1267 } else if (opcode == oDynamicForward) { 1264 if (arg2 == NULL || *arg2 == '\0') {
1268 strlcpy(fwdarg, arg, sizeof(fwdarg)); 1265 if (remotefwd)
1266 dynamicfwd = 1;
1267 else
1268 fatal("%.200s line %d: Missing target "
1269 "argument.", filename, linenum);
1270 } else {
1271 /* construct a string for parse_forward */
1272 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1273 arg2);
1274 }
1269 } 1275 }
1276 if (dynamicfwd)
1277 strlcpy(fwdarg, arg, sizeof(fwdarg));
1270 1278
1271 if (parse_forward(&fwd, fwdarg, 1279 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
1272 opcode == oDynamicForward ? 1 : 0,
1273 opcode == oRemoteForward ? 1 : 0) == 0)
1274 fatal("%.200s line %d: Bad forwarding specification.", 1280 fatal("%.200s line %d: Bad forwarding specification.",
1275 filename, linenum); 1281 filename, linenum);
1276 1282
1277 if (*activep) { 1283 if (*activep) {
1278 if (opcode == oLocalForward || 1284 if (remotefwd) {
1279 opcode == oDynamicForward)
1280 add_local_forward(options, &fwd);
1281 else if (opcode == oRemoteForward)
1282 add_remote_forward(options, &fwd); 1285 add_remote_forward(options, &fwd);
1286 } else {
1287 add_local_forward(options, &fwd);
1288 }
1283 } 1289 }
1284 break; 1290 break;
1285 1291
diff --git a/ssh.1 b/ssh.1
index 3aacec415..2ab1697f9 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh.1,v 1.383 2017/06/09 06:43:01 djm Exp $ 36.\" $OpenBSD: ssh.1,v 1.384 2017/09/21 19:16:53 markus Exp $
37.Dd $Mdocdate: June 9 2017 $ 37.Dd $Mdocdate: September 21 2017 $
38.Dt SSH 1 38.Dt SSH 1
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -592,21 +592,30 @@ Causes most warning and diagnostic messages to be suppressed.
592.Ar remote_socket : local_socket 592.Ar remote_socket : local_socket
593.Sm on 593.Sm on
594.Xc 594.Xc
595.It Fl R Xo
596.Sm off
597.Oo Ar bind_address : Oc
598.Ar port
599.Sm on
600.Xc
595Specifies that connections to the given TCP port or Unix socket on the remote 601Specifies that connections to the given TCP port or Unix socket on the remote
596(server) host are to be forwarded to the given host and port, or Unix socket, 602(server) host are to be forwarded to the local side.
597on the local side. 603.Pp
598This works by allocating a socket to listen to either a TCP 604This works by allocating a socket to listen to either a TCP
599.Ar port 605.Ar port
600or to a Unix socket on the remote side. 606or to a Unix socket on the remote side.
601Whenever a connection is made to this port or Unix socket, the 607Whenever a connection is made to this port or Unix socket, the
602connection is forwarded over the secure channel, and a connection 608connection is forwarded over the secure channel, and a connection
603is made to either 609is made from the local machine to either an explicit destination specified by
604.Ar host 610.Ar host
605port 611port
606.Ar hostport , 612.Ar hostport ,
607or 613or
608.Ar local_socket , 614.Ar local_socket ,
609from the local machine. 615or, if no explicit destination was specified,
616.Nm
617will act as a SOCKS 4/5 proxy and forward connections to the destinations
618requested by the remote SOCKS client.
610.Pp 619.Pp
611Port forwardings can also be specified in the configuration file. 620Port forwardings can also be specified in the configuration file.
612Privileged ports can be forwarded only when 621Privileged ports can be forwarded only when
diff --git a/ssh.c b/ssh.c
index ecc50f37e..ae37432bd 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.463 2017/09/12 06:32:07 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.464 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
@@ -868,7 +868,8 @@ main(int ac, char **av)
868 break; 868 break;
869 869
870 case 'R': 870 case 'R':
871 if (parse_forward(&fwd, optarg, 0, 1)) { 871 if (parse_forward(&fwd, optarg, 0, 1) ||
872 parse_forward(&fwd, optarg, 1, 1)) {
872 add_remote_forward(&options, &fwd); 873 add_remote_forward(&options, &fwd);
873 } else { 874 } else {
874 fprintf(stderr, 875 fprintf(stderr,
diff --git a/ssh_config.5 b/ssh_config.5
index ca5a41103..eab8dd01c 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.255 2017/09/04 06:34:43 jmc Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.256 2017/09/21 19:16:53 markus Exp $
37.Dd $Mdocdate: September 4 2017 $ 37.Dd $Mdocdate: September 21 2017 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -1298,13 +1298,19 @@ accept the tokens described in the
1298section. 1298section.
1299.It Cm RemoteForward 1299.It Cm RemoteForward
1300Specifies that a TCP port on the remote machine be forwarded over 1300Specifies that a TCP port on the remote machine be forwarded over
1301the secure channel to the specified host and port from the local machine. 1301the secure channel.
1302The remote port may either be fowarded to a specified host and port
1303from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote
1304client to connect to arbitrary destinations from the local machine.
1302The first argument must be 1305The first argument must be
1303.Sm off 1306.Sm off
1304.Oo Ar bind_address : Oc Ar port 1307.Oo Ar bind_address : Oc Ar port
1305.Sm on 1308.Sm on
1306and the second argument must be 1309If forwarding to a specific destination then the second argument must be
1307.Ar host : Ns Ar hostport . 1310.Ar host : Ns Ar hostport ,
1311otherwise if no destination argument is specified then the remote forwarding
1312will be established as a SOCKS proxy.
1313.Pp
1308IPv6 addresses can be specified by enclosing addresses in square brackets. 1314IPv6 addresses can be specified by enclosing addresses in square brackets.
1309Multiple forwardings may be specified, and additional 1315Multiple forwardings may be specified, and additional
1310forwardings can be given on the command line. 1316forwardings can be given on the command line.