diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 159 |
1 files changed, 119 insertions, 40 deletions
diff --git a/channels.c b/channels.c index 028c09e6a..0886a91ef 100644 --- a/channels.c +++ b/channels.c | |||
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $"); | 43 | RCSID("$OpenBSD: channels.c,v 1.73 2000/11/06 23:04:55 markus Exp $"); |
44 | 44 | ||
45 | #include "ssh.h" | 45 | #include "ssh.h" |
46 | #include "packet.h" | 46 | #include "packet.h" |
@@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
588 | struct sockaddr addr; | 588 | struct sockaddr addr; |
589 | int newsock, newch; | 589 | int newsock, newch; |
590 | socklen_t addrlen; | 590 | socklen_t addrlen; |
591 | char buf[1024], *remote_hostname; | 591 | char buf[1024], *remote_hostname, *rtype; |
592 | int remote_port; | 592 | int remote_port; |
593 | 593 | ||
594 | rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ? | ||
595 | "forwarded-tcpip" : "direct-tcpip"; | ||
596 | |||
594 | if (FD_ISSET(c->sock, readset)) { | 597 | if (FD_ISSET(c->sock, readset)) { |
595 | debug("Connection to port %d forwarding " | 598 | debug("Connection to port %d forwarding " |
596 | "to %.100s port %d requested.", | 599 | "to %.100s port %d requested.", |
@@ -608,19 +611,26 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
608 | "connect from %.200s port %d", | 611 | "connect from %.200s port %d", |
609 | c->listening_port, c->path, c->host_port, | 612 | c->listening_port, c->path, c->host_port, |
610 | remote_hostname, remote_port); | 613 | remote_hostname, remote_port); |
611 | newch = channel_new("direct-tcpip", | 614 | |
615 | newch = channel_new(rtype, | ||
612 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | 616 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
613 | c->local_window_max, c->local_maxpacket, | 617 | c->local_window_max, c->local_maxpacket, |
614 | 0, xstrdup(buf), 1); | 618 | 0, xstrdup(buf), 1); |
615 | if (compat20) { | 619 | if (compat20) { |
616 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 620 | packet_start(SSH2_MSG_CHANNEL_OPEN); |
617 | packet_put_cstring("direct-tcpip"); | 621 | packet_put_cstring(rtype); |
618 | packet_put_int(newch); | 622 | packet_put_int(newch); |
619 | packet_put_int(c->local_window_max); | 623 | packet_put_int(c->local_window_max); |
620 | packet_put_int(c->local_maxpacket); | 624 | packet_put_int(c->local_maxpacket); |
621 | /* target host and port */ | 625 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { |
622 | packet_put_string(c->path, strlen(c->path)); | 626 | /* listen address, port */ |
623 | packet_put_int(c->host_port); | 627 | packet_put_string(c->path, strlen(c->path)); |
628 | packet_put_int(c->listening_port); | ||
629 | } else { | ||
630 | /* target host, port */ | ||
631 | packet_put_string(c->path, strlen(c->path)); | ||
632 | packet_put_int(c->host_port); | ||
633 | } | ||
624 | /* originator host and port */ | 634 | /* originator host and port */ |
625 | packet_put_cstring(remote_hostname); | 635 | packet_put_cstring(remote_hostname); |
626 | packet_put_int(remote_port); | 636 | packet_put_int(remote_port); |
@@ -657,10 +667,20 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
657 | error("accept from auth socket: %.100s", strerror(errno)); | 667 | error("accept from auth socket: %.100s", strerror(errno)); |
658 | return; | 668 | return; |
659 | } | 669 | } |
660 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | 670 | newch = channel_new("accepted auth socket", |
661 | xstrdup("accepted auth socket")); | 671 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
662 | packet_start(SSH_SMSG_AGENT_OPEN); | 672 | c->local_window_max, c->local_maxpacket, |
663 | packet_put_int(newch); | 673 | 0, xstrdup("accepted auth socket"), 1); |
674 | if (compat20) { | ||
675 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
676 | packet_put_cstring("auth-agent@openssh.com"); | ||
677 | packet_put_int(newch); | ||
678 | packet_put_int(c->local_window_max); | ||
679 | packet_put_int(c->local_maxpacket); | ||
680 | } else { | ||
681 | packet_start(SSH_SMSG_AGENT_OPEN); | ||
682 | packet_put_int(newch); | ||
683 | } | ||
664 | packet_send(); | 684 | packet_send(); |
665 | } | 685 | } |
666 | } | 686 | } |
@@ -820,11 +840,15 @@ channel_handler_init_20(void) | |||
820 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; | 840 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; |
821 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | 841 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; |
822 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | 842 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
843 | channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; | ||
823 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | 844 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; |
845 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | ||
824 | 846 | ||
825 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; | 847 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; |
826 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | 848 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; |
849 | channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; | ||
827 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | 850 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; |
851 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
828 | } | 852 | } |
829 | 853 | ||
830 | void | 854 | void |
@@ -1326,6 +1350,7 @@ channel_stop_listening() | |||
1326 | channel_free(i); | 1350 | channel_free(i); |
1327 | break; | 1351 | break; |
1328 | case SSH_CHANNEL_PORT_LISTENER: | 1352 | case SSH_CHANNEL_PORT_LISTENER: |
1353 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1329 | case SSH_CHANNEL_X11_LISTENER: | 1354 | case SSH_CHANNEL_X11_LISTENER: |
1330 | close(channels[i].sock); | 1355 | close(channels[i].sock); |
1331 | channel_free(i); | 1356 | channel_free(i); |
@@ -1369,6 +1394,7 @@ channel_still_open() | |||
1369 | case SSH_CHANNEL_FREE: | 1394 | case SSH_CHANNEL_FREE: |
1370 | case SSH_CHANNEL_X11_LISTENER: | 1395 | case SSH_CHANNEL_X11_LISTENER: |
1371 | case SSH_CHANNEL_PORT_LISTENER: | 1396 | case SSH_CHANNEL_PORT_LISTENER: |
1397 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1372 | case SSH_CHANNEL_CLOSED: | 1398 | case SSH_CHANNEL_CLOSED: |
1373 | case SSH_CHANNEL_AUTH_SOCKET: | 1399 | case SSH_CHANNEL_AUTH_SOCKET: |
1374 | continue; | 1400 | continue; |
@@ -1414,6 +1440,7 @@ channel_open_message() | |||
1414 | case SSH_CHANNEL_FREE: | 1440 | case SSH_CHANNEL_FREE: |
1415 | case SSH_CHANNEL_X11_LISTENER: | 1441 | case SSH_CHANNEL_X11_LISTENER: |
1416 | case SSH_CHANNEL_PORT_LISTENER: | 1442 | case SSH_CHANNEL_PORT_LISTENER: |
1443 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1417 | case SSH_CHANNEL_CLOSED: | 1444 | case SSH_CHANNEL_CLOSED: |
1418 | case SSH_CHANNEL_AUTH_SOCKET: | 1445 | case SSH_CHANNEL_AUTH_SOCKET: |
1419 | continue; | 1446 | continue; |
@@ -1446,19 +1473,44 @@ channel_open_message() | |||
1446 | * Initiate forwarding of connections to local port "port" through the secure | 1473 | * Initiate forwarding of connections to local port "port" through the secure |
1447 | * channel to host:port from remote side. | 1474 | * channel to host:port from remote side. |
1448 | */ | 1475 | */ |
1476 | void | ||
1477 | channel_request_local_forwarding(u_short listen_port, const char *host_to_connect, | ||
1478 | u_short port_to_connect, int gateway_ports) | ||
1479 | { | ||
1480 | channel_request_forwarding( | ||
1481 | NULL, listen_port, | ||
1482 | host_to_connect, port_to_connect, | ||
1483 | gateway_ports, /*remote_fwd*/ 0); | ||
1484 | } | ||
1449 | 1485 | ||
1486 | /* | ||
1487 | * If 'remote_fwd' is true we have a '-R style' listener for protocol 2 | ||
1488 | * (SSH_CHANNEL_RPORT_LISTENER). | ||
1489 | */ | ||
1450 | void | 1490 | void |
1451 | channel_request_local_forwarding(u_short port, const char *host, | 1491 | channel_request_forwarding( |
1452 | u_short host_port, int gateway_ports) | 1492 | const char *listen_address, u_short listen_port, |
1493 | const char *host_to_connect, u_short port_to_connect, | ||
1494 | int gateway_ports, int remote_fwd) | ||
1453 | { | 1495 | { |
1454 | int success, ch, sock, on = 1; | 1496 | int success, ch, sock, on = 1, ctype; |
1455 | struct addrinfo hints, *ai, *aitop; | 1497 | struct addrinfo hints, *ai, *aitop; |
1456 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 1498 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
1499 | const char *host; | ||
1457 | struct linger linger; | 1500 | struct linger linger; |
1458 | 1501 | ||
1502 | if (remote_fwd) { | ||
1503 | host = listen_address; | ||
1504 | ctype = SSH_CHANNEL_RPORT_LISTENER; | ||
1505 | } else { | ||
1506 | host = host_to_connect; | ||
1507 | ctype =SSH_CHANNEL_PORT_LISTENER; | ||
1508 | } | ||
1509 | |||
1459 | if (strlen(host) > sizeof(channels[0].path) - 1) | 1510 | if (strlen(host) > sizeof(channels[0].path) - 1) |
1460 | packet_disconnect("Forward host name too long."); | 1511 | packet_disconnect("Forward host name too long."); |
1461 | 1512 | ||
1513 | /* XXX listen_address is currently ignored */ | ||
1462 | /* | 1514 | /* |
1463 | * getaddrinfo returns a loopback address if the hostname is | 1515 | * getaddrinfo returns a loopback address if the hostname is |
1464 | * set to NULL and hints.ai_flags is not AI_PASSIVE | 1516 | * set to NULL and hints.ai_flags is not AI_PASSIVE |
@@ -1467,7 +1519,7 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1467 | hints.ai_family = IPv4or6; | 1519 | hints.ai_family = IPv4or6; |
1468 | hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; | 1520 | hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; |
1469 | hints.ai_socktype = SOCK_STREAM; | 1521 | hints.ai_socktype = SOCK_STREAM; |
1470 | snprintf(strport, sizeof strport, "%d", port); | 1522 | snprintf(strport, sizeof strport, "%d", listen_port); |
1471 | if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) | 1523 | if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) |
1472 | packet_disconnect("getaddrinfo: fatal error"); | 1524 | packet_disconnect("getaddrinfo: fatal error"); |
1473 | 1525 | ||
@@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1477 | continue; | 1529 | continue; |
1478 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 1530 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
1479 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 1531 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
1480 | error("channel_request_local_forwarding: getnameinfo failed"); | 1532 | error("channel_request_forwarding: getnameinfo failed"); |
1481 | continue; | 1533 | continue; |
1482 | } | 1534 | } |
1483 | /* Create a port to listen for the host. */ | 1535 | /* Create a port to listen for the host. */ |
@@ -1515,18 +1567,16 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1515 | continue; | 1567 | continue; |
1516 | } | 1568 | } |
1517 | /* Allocate a channel number for the socket. */ | 1569 | /* Allocate a channel number for the socket. */ |
1518 | ch = channel_new( | 1570 | ch = channel_new("port listener", ctype, sock, sock, -1, |
1519 | "port listener", SSH_CHANNEL_PORT_LISTENER, | ||
1520 | sock, sock, -1, | ||
1521 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 1571 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
1522 | 0, xstrdup("port listener"), 1); | 1572 | 0, xstrdup("port listener"), 1); |
1523 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); | 1573 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); |
1524 | channels[ch].host_port = host_port; | 1574 | channels[ch].host_port = port_to_connect; |
1525 | channels[ch].listening_port = port; | 1575 | channels[ch].listening_port = listen_port; |
1526 | success = 1; | 1576 | success = 1; |
1527 | } | 1577 | } |
1528 | if (success == 0) | 1578 | if (success == 0) |
1529 | packet_disconnect("cannot listen port: %d", port); | 1579 | packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */ |
1530 | freeaddrinfo(aitop); | 1580 | freeaddrinfo(aitop); |
1531 | } | 1581 | } |
1532 | 1582 | ||
@@ -1536,19 +1586,15 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1536 | */ | 1586 | */ |
1537 | 1587 | ||
1538 | void | 1588 | void |
1539 | channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, | 1589 | channel_request_remote_forwarding(u_short listen_port, |
1540 | u_short port_to_connect) | 1590 | const char *host_to_connect, u_short port_to_connect) |
1541 | { | 1591 | { |
1542 | int payload_len; | 1592 | int payload_len, type, success = 0; |
1593 | |||
1543 | /* Record locally that connection to this host/port is permitted. */ | 1594 | /* Record locally that connection to this host/port is permitted. */ |
1544 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) | 1595 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) |
1545 | fatal("channel_request_remote_forwarding: too many forwards"); | 1596 | fatal("channel_request_remote_forwarding: too many forwards"); |
1546 | 1597 | ||
1547 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); | ||
1548 | permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; | ||
1549 | permitted_opens[num_permitted_opens].listen_port = listen_port; | ||
1550 | num_permitted_opens++; | ||
1551 | |||
1552 | /* Send the forward request to the remote side. */ | 1598 | /* Send the forward request to the remote side. */ |
1553 | if (compat20) { | 1599 | if (compat20) { |
1554 | const char *address_to_bind = "0.0.0.0"; | 1600 | const char *address_to_bind = "0.0.0.0"; |
@@ -1557,6 +1603,10 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne | |||
1557 | packet_put_char(0); /* boolean: want reply */ | 1603 | packet_put_char(0); /* boolean: want reply */ |
1558 | packet_put_cstring(address_to_bind); | 1604 | packet_put_cstring(address_to_bind); |
1559 | packet_put_int(listen_port); | 1605 | packet_put_int(listen_port); |
1606 | packet_send(); | ||
1607 | packet_write_wait(); | ||
1608 | /* Assume that server accepts the request */ | ||
1609 | success = 1; | ||
1560 | } else { | 1610 | } else { |
1561 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); | 1611 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); |
1562 | packet_put_int(listen_port); | 1612 | packet_put_int(listen_port); |
@@ -1564,11 +1614,27 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne | |||
1564 | packet_put_int(port_to_connect); | 1614 | packet_put_int(port_to_connect); |
1565 | packet_send(); | 1615 | packet_send(); |
1566 | packet_write_wait(); | 1616 | packet_write_wait(); |
1567 | /* | 1617 | |
1568 | * Wait for response from the remote side. It will send a disconnect | 1618 | /* Wait for response from the remote side. */ |
1569 | * message on failure, and we will never see it here. | 1619 | type = packet_read(&payload_len); |
1570 | */ | 1620 | switch (type) { |
1571 | packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); | 1621 | case SSH_SMSG_SUCCESS: |
1622 | success = 1; | ||
1623 | break; | ||
1624 | case SSH_SMSG_FAILURE: | ||
1625 | log("Warning: Server denied remote port forwarding."); | ||
1626 | break; | ||
1627 | default: | ||
1628 | /* Unknown packet */ | ||
1629 | packet_disconnect("Protocol error for port forward request:" | ||
1630 | "received packet type %d.", type); | ||
1631 | } | ||
1632 | } | ||
1633 | if (success) { | ||
1634 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); | ||
1635 | permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; | ||
1636 | permitted_opens[num_permitted_opens].listen_port = listen_port; | ||
1637 | num_permitted_opens++; | ||
1572 | } | 1638 | } |
1573 | } | 1639 | } |
1574 | 1640 | ||
@@ -1598,9 +1664,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports) | |||
1598 | packet_disconnect("Requested forwarding of port %d but user is not root.", | 1664 | packet_disconnect("Requested forwarding of port %d but user is not root.", |
1599 | port); | 1665 | port); |
1600 | #endif | 1666 | #endif |
1601 | /* | 1667 | /* Initiate forwarding */ |
1602 | * Initiate forwarding, | ||
1603 | */ | ||
1604 | channel_request_local_forwarding(port, hostname, host_port, gateway_ports); | 1668 | channel_request_local_forwarding(port, hostname, host_port, gateway_ports); |
1605 | 1669 | ||
1606 | /* Free the argument string. */ | 1670 | /* Free the argument string. */ |
@@ -1656,6 +1720,18 @@ channel_connect_to(const char *host, u_short host_port) | |||
1656 | /* success */ | 1720 | /* success */ |
1657 | return sock; | 1721 | return sock; |
1658 | } | 1722 | } |
1723 | int | ||
1724 | channel_connect_by_listen_adress(u_short listen_port) | ||
1725 | { | ||
1726 | int i; | ||
1727 | for (i = 0; i < num_permitted_opens; i++) | ||
1728 | if (permitted_opens[i].listen_port == listen_port) | ||
1729 | return channel_connect_to( | ||
1730 | permitted_opens[i].host_to_connect, | ||
1731 | permitted_opens[i].port_to_connect); | ||
1732 | debug("channel_connect_by_listen_adress: unknown listen_port %d", listen_port); | ||
1733 | return -1; | ||
1734 | } | ||
1659 | 1735 | ||
1660 | /* | 1736 | /* |
1661 | * This is called after receiving PORT_OPEN message. This attempts to | 1737 | * This is called after receiving PORT_OPEN message. This attempts to |
@@ -2233,8 +2309,11 @@ auth_input_request_forwarding(struct passwd * pw) | |||
2233 | packet_disconnect("listen: %.100s", strerror(errno)); | 2309 | packet_disconnect("listen: %.100s", strerror(errno)); |
2234 | 2310 | ||
2235 | /* Allocate a channel for the authentication agent socket. */ | 2311 | /* Allocate a channel for the authentication agent socket. */ |
2236 | newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock, | 2312 | newch = channel_new("auth socket", |
2237 | xstrdup("auth socket")); | 2313 | SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, |
2314 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | ||
2315 | 0, xstrdup("auth socket"), 1); | ||
2316 | |||
2238 | strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, | 2317 | strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, |
2239 | sizeof(channels[newch].path)); | 2318 | sizeof(channels[newch].path)); |
2240 | return 1; | 2319 | return 1; |