diff options
-rw-r--r-- | channels.c | 523 | ||||
-rw-r--r-- | channels.h | 6 | ||||
-rw-r--r-- | clientloop.c | 542 | ||||
-rw-r--r-- | compat.c | 18 | ||||
-rw-r--r-- | compat.h | 6 | ||||
-rw-r--r-- | dispatch.c | 4 | ||||
-rw-r--r-- | nchan.c | 266 | ||||
-rw-r--r-- | packet.c | 395 | ||||
-rw-r--r-- | packet.h | 3 | ||||
-rw-r--r-- | ssh-keyscan.c | 3 | ||||
-rw-r--r-- | ssh.c | 174 | ||||
-rw-r--r-- | ssh_api.c | 3 | ||||
-rw-r--r-- | sshconnect.c | 32 | ||||
-rw-r--r-- | sshd.c | 8 | ||||
-rw-r--r-- | ttymodes.c | 106 |
15 files changed, 407 insertions, 1682 deletions
diff --git a/channels.c b/channels.c index d030fcdd9..5a7e56ed0 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.358 2017/04/30 23:13:25 djm 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 |
@@ -571,14 +571,6 @@ channel_not_very_much_buffered_data(void) | |||
571 | for (i = 0; i < channels_alloc; i++) { | 571 | for (i = 0; i < channels_alloc; i++) { |
572 | c = channels[i]; | 572 | c = channels[i]; |
573 | if (c != NULL && c->type == SSH_CHANNEL_OPEN) { | 573 | if (c != NULL && c->type == SSH_CHANNEL_OPEN) { |
574 | #if 0 | ||
575 | if (!compat20 && | ||
576 | buffer_len(&c->input) > packet_get_maxsize()) { | ||
577 | debug2("channel %d: big input buffer %d", | ||
578 | c->self, buffer_len(&c->input)); | ||
579 | return 0; | ||
580 | } | ||
581 | #endif | ||
582 | if (buffer_len(&c->output) > packet_get_maxsize()) { | 574 | if (buffer_len(&c->output) > packet_get_maxsize()) { |
583 | debug2("channel %d: big output buffer %u > %u", | 575 | debug2("channel %d: big output buffer %u > %u", |
584 | c->self, buffer_len(&c->output), | 576 | c->self, buffer_len(&c->output), |
@@ -616,8 +608,6 @@ channel_still_open(void) | |||
616 | case SSH_CHANNEL_RUNIX_LISTENER: | 608 | case SSH_CHANNEL_RUNIX_LISTENER: |
617 | continue; | 609 | continue; |
618 | case SSH_CHANNEL_LARVAL: | 610 | case SSH_CHANNEL_LARVAL: |
619 | if (!compat20) | ||
620 | fatal("cannot happen: SSH_CHANNEL_LARVAL"); | ||
621 | continue; | 611 | continue; |
622 | case SSH_CHANNEL_OPENING: | 612 | case SSH_CHANNEL_OPENING: |
623 | case SSH_CHANNEL_OPEN: | 613 | case SSH_CHANNEL_OPEN: |
@@ -627,11 +617,9 @@ channel_still_open(void) | |||
627 | return 1; | 617 | return 1; |
628 | case SSH_CHANNEL_INPUT_DRAINING: | 618 | case SSH_CHANNEL_INPUT_DRAINING: |
629 | case SSH_CHANNEL_OUTPUT_DRAINING: | 619 | case SSH_CHANNEL_OUTPUT_DRAINING: |
630 | if (!compat13) | 620 | fatal("cannot happen: OUT_DRAIN"); |
631 | fatal("cannot happen: OUT_DRAIN"); | ||
632 | return 1; | ||
633 | default: | 621 | default: |
634 | fatal("channel_still_open: bad channel type %d", c->type); | 622 | fatal("%s: bad channel type %d", __func__, c->type); |
635 | /* NOTREACHED */ | 623 | /* NOTREACHED */ |
636 | } | 624 | } |
637 | } | 625 | } |
@@ -672,11 +660,9 @@ channel_find_open(void) | |||
672 | return i; | 660 | return i; |
673 | case SSH_CHANNEL_INPUT_DRAINING: | 661 | case SSH_CHANNEL_INPUT_DRAINING: |
674 | case SSH_CHANNEL_OUTPUT_DRAINING: | 662 | case SSH_CHANNEL_OUTPUT_DRAINING: |
675 | if (!compat13) | 663 | fatal("cannot happen: OUT_DRAIN"); |
676 | fatal("cannot happen: OUT_DRAIN"); | ||
677 | return i; | ||
678 | default: | 664 | default: |
679 | fatal("channel_find_open: bad channel type %d", c->type); | 665 | fatal("%s: bad channel type %d", __func__, c->type); |
680 | /* NOTREACHED */ | 666 | /* NOTREACHED */ |
681 | } | 667 | } |
682 | } | 668 | } |
@@ -896,22 +882,11 @@ channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset) | |||
896 | } | 882 | } |
897 | 883 | ||
898 | static void | 884 | static void |
899 | channel_pre_open_13(Channel *c, fd_set *readset, fd_set *writeset) | ||
900 | { | ||
901 | if (buffer_len(&c->input) < packet_get_maxsize()) | ||
902 | FD_SET(c->sock, readset); | ||
903 | if (buffer_len(&c->output) > 0) | ||
904 | FD_SET(c->sock, writeset); | ||
905 | } | ||
906 | |||
907 | static void | ||
908 | channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) | 885 | channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) |
909 | { | 886 | { |
910 | u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); | ||
911 | |||
912 | if (c->istate == CHAN_INPUT_OPEN && | 887 | if (c->istate == CHAN_INPUT_OPEN && |
913 | limit > 0 && | 888 | c->remote_window > 0 && |
914 | buffer_len(&c->input) < limit && | 889 | buffer_len(&c->input) < c->remote_window && |
915 | buffer_check_alloc(&c->input, CHAN_RBUF)) | 890 | buffer_check_alloc(&c->input, CHAN_RBUF)) |
916 | FD_SET(c->rfd, readset); | 891 | FD_SET(c->rfd, readset); |
917 | if (c->ostate == CHAN_OUTPUT_OPEN || | 892 | if (c->ostate == CHAN_OUTPUT_OPEN || |
@@ -927,8 +902,8 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
927 | } | 902 | } |
928 | } | 903 | } |
929 | /** XXX check close conditions, too */ | 904 | /** XXX check close conditions, too */ |
930 | if (compat20 && c->efd != -1 && | 905 | if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && |
931 | !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) { | 906 | c->ostate == CHAN_OUTPUT_CLOSED)) { |
932 | if (c->extended_usage == CHAN_EXTENDED_WRITE && | 907 | if (c->extended_usage == CHAN_EXTENDED_WRITE && |
933 | buffer_len(&c->extended) > 0) | 908 | buffer_len(&c->extended) > 0) |
934 | FD_SET(c->efd, writeset); | 909 | FD_SET(c->efd, writeset); |
@@ -941,29 +916,6 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
941 | /* XXX: What about efd? races? */ | 916 | /* XXX: What about efd? races? */ |
942 | } | 917 | } |
943 | 918 | ||
944 | /* ARGSUSED */ | ||
945 | static void | ||
946 | channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset) | ||
947 | { | ||
948 | if (buffer_len(&c->input) == 0) { | ||
949 | packet_start(SSH_MSG_CHANNEL_CLOSE); | ||
950 | packet_put_int(c->remote_id); | ||
951 | packet_send(); | ||
952 | c->type = SSH_CHANNEL_CLOSED; | ||
953 | debug2("channel %d: closing after input drain.", c->self); | ||
954 | } | ||
955 | } | ||
956 | |||
957 | /* ARGSUSED */ | ||
958 | static void | ||
959 | channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset) | ||
960 | { | ||
961 | if (buffer_len(&c->output) == 0) | ||
962 | chan_mark_dead(c); | ||
963 | else | ||
964 | FD_SET(c->sock, writeset); | ||
965 | } | ||
966 | |||
967 | /* | 919 | /* |
968 | * This is a special state for X11 authentication spoofing. An opened X11 | 920 | * This is a special state for X11 authentication spoofing. An opened X11 |
969 | * connection (when authentication spoofing is being done) remains in this | 921 | * connection (when authentication spoofing is being done) remains in this |
@@ -1039,32 +991,6 @@ x11_open_helper(Buffer *b) | |||
1039 | } | 991 | } |
1040 | 992 | ||
1041 | static void | 993 | static void |
1042 | channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset) | ||
1043 | { | ||
1044 | int ret = x11_open_helper(&c->output); | ||
1045 | |||
1046 | if (ret == 1) { | ||
1047 | /* Start normal processing for the channel. */ | ||
1048 | c->type = SSH_CHANNEL_OPEN; | ||
1049 | channel_pre_open_13(c, readset, writeset); | ||
1050 | } else if (ret == -1) { | ||
1051 | /* | ||
1052 | * We have received an X11 connection that has bad | ||
1053 | * authentication information. | ||
1054 | */ | ||
1055 | logit("X11 connection rejected because of wrong authentication."); | ||
1056 | buffer_clear(&c->input); | ||
1057 | buffer_clear(&c->output); | ||
1058 | channel_close_fd(&c->sock); | ||
1059 | c->sock = -1; | ||
1060 | c->type = SSH_CHANNEL_CLOSED; | ||
1061 | packet_start(SSH_MSG_CHANNEL_CLOSE); | ||
1062 | packet_put_int(c->remote_id); | ||
1063 | packet_send(); | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | static void | ||
1068 | channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) | 994 | channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) |
1069 | { | 995 | { |
1070 | int ret = x11_open_helper(&c->output); | 996 | int ret = x11_open_helper(&c->output); |
@@ -1081,11 +1007,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
1081 | buffer_clear(&c->input); | 1007 | buffer_clear(&c->input); |
1082 | chan_ibuf_empty(c); | 1008 | chan_ibuf_empty(c); |
1083 | buffer_clear(&c->output); | 1009 | buffer_clear(&c->output); |
1084 | /* for proto v1, the peer will send an IEOF */ | 1010 | chan_write_failed(c); |
1085 | if (compat20) | ||
1086 | chan_write_failed(c); | ||
1087 | else | ||
1088 | c->type = SSH_CHANNEL_OPEN; | ||
1089 | debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); | 1011 | debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); |
1090 | } | 1012 | } |
1091 | } | 1013 | } |
@@ -1449,28 +1371,19 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1449 | nc = channel_new("accepted x11 socket", | 1371 | nc = channel_new("accepted x11 socket", |
1450 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | 1372 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
1451 | c->local_window_max, c->local_maxpacket, 0, buf, 1); | 1373 | c->local_window_max, c->local_maxpacket, 0, buf, 1); |
1452 | if (compat20) { | 1374 | packet_start(SSH2_MSG_CHANNEL_OPEN); |
1453 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 1375 | packet_put_cstring("x11"); |
1454 | packet_put_cstring("x11"); | 1376 | packet_put_int(nc->self); |
1455 | packet_put_int(nc->self); | 1377 | packet_put_int(nc->local_window_max); |
1456 | packet_put_int(nc->local_window_max); | 1378 | packet_put_int(nc->local_maxpacket); |
1457 | packet_put_int(nc->local_maxpacket); | 1379 | /* originator ipaddr and port */ |
1458 | /* originator ipaddr and port */ | 1380 | packet_put_cstring(remote_ipaddr); |
1459 | packet_put_cstring(remote_ipaddr); | 1381 | if (datafellows & SSH_BUG_X11FWD) { |
1460 | if (datafellows & SSH_BUG_X11FWD) { | 1382 | debug2("ssh2 x11 bug compat mode"); |
1461 | debug2("ssh2 x11 bug compat mode"); | ||
1462 | } else { | ||
1463 | packet_put_int(remote_port); | ||
1464 | } | ||
1465 | packet_send(); | ||
1466 | } else { | 1383 | } else { |
1467 | packet_start(SSH_SMSG_X11_OPEN); | 1384 | packet_put_int(remote_port); |
1468 | packet_put_int(nc->self); | ||
1469 | if (packet_get_protocol_flags() & | ||
1470 | SSH_PROTOFLAG_HOST_IN_FWD_OPEN) | ||
1471 | packet_put_cstring(buf); | ||
1472 | packet_send(); | ||
1473 | } | 1385 | } |
1386 | packet_send(); | ||
1474 | free(remote_ipaddr); | 1387 | free(remote_ipaddr); |
1475 | } | 1388 | } |
1476 | } | 1389 | } |
@@ -1500,46 +1413,35 @@ port_open_helper(Channel *c, char *rtype) | |||
1500 | free(c->remote_name); | 1413 | free(c->remote_name); |
1501 | c->remote_name = xstrdup(buf); | 1414 | c->remote_name = xstrdup(buf); |
1502 | 1415 | ||
1503 | if (compat20) { | 1416 | packet_start(SSH2_MSG_CHANNEL_OPEN); |
1504 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 1417 | packet_put_cstring(rtype); |
1505 | packet_put_cstring(rtype); | 1418 | packet_put_int(c->self); |
1506 | packet_put_int(c->self); | 1419 | packet_put_int(c->local_window_max); |
1507 | packet_put_int(c->local_window_max); | 1420 | packet_put_int(c->local_maxpacket); |
1508 | packet_put_int(c->local_maxpacket); | 1421 | if (strcmp(rtype, "direct-tcpip") == 0) { |
1509 | if (strcmp(rtype, "direct-tcpip") == 0) { | 1422 | /* target host, port */ |
1510 | /* target host, port */ | ||
1511 | packet_put_cstring(c->path); | ||
1512 | packet_put_int(c->host_port); | ||
1513 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { | ||
1514 | /* target path */ | ||
1515 | packet_put_cstring(c->path); | ||
1516 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | ||
1517 | /* listen path */ | ||
1518 | packet_put_cstring(c->path); | ||
1519 | } else { | ||
1520 | /* listen address, port */ | ||
1521 | packet_put_cstring(c->path); | ||
1522 | packet_put_int(local_port); | ||
1523 | } | ||
1524 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | ||
1525 | /* reserved for future owner/mode info */ | ||
1526 | packet_put_cstring(""); | ||
1527 | } else { | ||
1528 | /* originator host and port */ | ||
1529 | packet_put_cstring(remote_ipaddr); | ||
1530 | packet_put_int((u_int)remote_port); | ||
1531 | } | ||
1532 | packet_send(); | ||
1533 | } else { | ||
1534 | packet_start(SSH_MSG_PORT_OPEN); | ||
1535 | packet_put_int(c->self); | ||
1536 | packet_put_cstring(c->path); | 1423 | packet_put_cstring(c->path); |
1537 | packet_put_int(c->host_port); | 1424 | packet_put_int(c->host_port); |
1538 | if (packet_get_protocol_flags() & | 1425 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { |
1539 | SSH_PROTOFLAG_HOST_IN_FWD_OPEN) | 1426 | /* target path */ |
1540 | packet_put_cstring(c->remote_name); | 1427 | packet_put_cstring(c->path); |
1541 | packet_send(); | 1428 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { |
1429 | /* listen path */ | ||
1430 | packet_put_cstring(c->path); | ||
1431 | } else { | ||
1432 | /* listen address, port */ | ||
1433 | packet_put_cstring(c->path); | ||
1434 | packet_put_int(local_port); | ||
1435 | } | ||
1436 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | ||
1437 | /* reserved for future owner/mode info */ | ||
1438 | packet_put_cstring(""); | ||
1439 | } else { | ||
1440 | /* originator host and port */ | ||
1441 | packet_put_cstring(remote_ipaddr); | ||
1442 | packet_put_int((u_int)remote_port); | ||
1542 | } | 1443 | } |
1444 | packet_send(); | ||
1543 | free(remote_ipaddr); | 1445 | free(remote_ipaddr); |
1544 | free(local_ipaddr); | 1446 | free(local_ipaddr); |
1545 | } | 1447 | } |
@@ -1649,16 +1551,11 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1649 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | 1551 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
1650 | c->local_window_max, c->local_maxpacket, | 1552 | c->local_window_max, c->local_maxpacket, |
1651 | 0, "accepted auth socket", 1); | 1553 | 0, "accepted auth socket", 1); |
1652 | if (compat20) { | 1554 | packet_start(SSH2_MSG_CHANNEL_OPEN); |
1653 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 1555 | packet_put_cstring("auth-agent@openssh.com"); |
1654 | packet_put_cstring("auth-agent@openssh.com"); | 1556 | packet_put_int(nc->self); |
1655 | packet_put_int(nc->self); | 1557 | packet_put_int(c->local_window_max); |
1656 | packet_put_int(c->local_window_max); | 1558 | packet_put_int(c->local_maxpacket); |
1657 | packet_put_int(c->local_maxpacket); | ||
1658 | } else { | ||
1659 | packet_start(SSH_SMSG_AGENT_OPEN); | ||
1660 | packet_put_int(nc->self); | ||
1661 | } | ||
1662 | packet_send(); | 1559 | packet_send(); |
1663 | } | 1560 | } |
1664 | } | 1561 | } |
@@ -1680,17 +1577,11 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) | |||
1680 | c->self, c->connect_ctx.host, c->connect_ctx.port); | 1577 | c->self, c->connect_ctx.host, c->connect_ctx.port); |
1681 | channel_connect_ctx_free(&c->connect_ctx); | 1578 | channel_connect_ctx_free(&c->connect_ctx); |
1682 | c->type = SSH_CHANNEL_OPEN; | 1579 | c->type = SSH_CHANNEL_OPEN; |
1683 | if (compat20) { | 1580 | packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); |
1684 | packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); | 1581 | packet_put_int(c->remote_id); |
1685 | packet_put_int(c->remote_id); | 1582 | packet_put_int(c->self); |
1686 | packet_put_int(c->self); | 1583 | packet_put_int(c->local_window); |
1687 | packet_put_int(c->local_window); | 1584 | packet_put_int(c->local_maxpacket); |
1688 | packet_put_int(c->local_maxpacket); | ||
1689 | } else { | ||
1690 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | ||
1691 | packet_put_int(c->remote_id); | ||
1692 | packet_put_int(c->self); | ||
1693 | } | ||
1694 | } else { | 1585 | } else { |
1695 | debug("channel %d: connection failed: %s", | 1586 | debug("channel %d: connection failed: %s", |
1696 | c->self, strerror(err)); | 1587 | c->self, strerror(err)); |
@@ -1705,17 +1596,12 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) | |||
1705 | error("connect_to %.100s port %d: failed.", | 1596 | error("connect_to %.100s port %d: failed.", |
1706 | c->connect_ctx.host, c->connect_ctx.port); | 1597 | c->connect_ctx.host, c->connect_ctx.port); |
1707 | channel_connect_ctx_free(&c->connect_ctx); | 1598 | channel_connect_ctx_free(&c->connect_ctx); |
1708 | if (compat20) { | 1599 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); |
1709 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 1600 | packet_put_int(c->remote_id); |
1710 | packet_put_int(c->remote_id); | 1601 | packet_put_int(SSH2_OPEN_CONNECT_FAILED); |
1711 | packet_put_int(SSH2_OPEN_CONNECT_FAILED); | 1602 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { |
1712 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { | 1603 | packet_put_cstring(strerror(err)); |
1713 | packet_put_cstring(strerror(err)); | 1604 | packet_put_cstring(""); |
1714 | packet_put_cstring(""); | ||
1715 | } | ||
1716 | } else { | ||
1717 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | ||
1718 | packet_put_int(c->remote_id); | ||
1719 | } | 1605 | } |
1720 | chan_mark_dead(c); | 1606 | chan_mark_dead(c); |
1721 | } | 1607 | } |
@@ -1749,10 +1635,6 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1749 | debug2("channel %d: not open", c->self); | 1635 | debug2("channel %d: not open", c->self); |
1750 | chan_mark_dead(c); | 1636 | chan_mark_dead(c); |
1751 | return -1; | 1637 | return -1; |
1752 | } else if (compat13) { | ||
1753 | buffer_clear(&c->output); | ||
1754 | c->type = SSH_CHANNEL_INPUT_DRAINING; | ||
1755 | debug2("channel %d: input draining.", c->self); | ||
1756 | } else { | 1638 | } else { |
1757 | chan_read_failed(c); | 1639 | chan_read_failed(c); |
1758 | } | 1640 | } |
@@ -1820,7 +1702,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1820 | } | 1702 | } |
1821 | #ifdef _AIX | 1703 | #ifdef _AIX |
1822 | /* XXX: Later AIX versions can't push as much data to tty */ | 1704 | /* XXX: Later AIX versions can't push as much data to tty */ |
1823 | if (compat20 && c->wfd_isatty) | 1705 | if (c->wfd_isatty) |
1824 | dlen = MIN(dlen, 8*1024); | 1706 | dlen = MIN(dlen, 8*1024); |
1825 | #endif | 1707 | #endif |
1826 | 1708 | ||
@@ -1833,17 +1715,13 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1833 | debug2("channel %d: not open", c->self); | 1715 | debug2("channel %d: not open", c->self); |
1834 | chan_mark_dead(c); | 1716 | chan_mark_dead(c); |
1835 | return -1; | 1717 | return -1; |
1836 | } else if (compat13) { | ||
1837 | buffer_clear(&c->output); | ||
1838 | debug2("channel %d: input draining.", c->self); | ||
1839 | c->type = SSH_CHANNEL_INPUT_DRAINING; | ||
1840 | } else { | 1718 | } else { |
1841 | chan_write_failed(c); | 1719 | chan_write_failed(c); |
1842 | } | 1720 | } |
1843 | return -1; | 1721 | return -1; |
1844 | } | 1722 | } |
1845 | #ifndef BROKEN_TCGETATTR_ICANON | 1723 | #ifndef BROKEN_TCGETATTR_ICANON |
1846 | if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') { | 1724 | if (c->isatty && dlen >= 1 && buf[0] != '\r') { |
1847 | if (tcgetattr(c->wfd, &tio) == 0 && | 1725 | if (tcgetattr(c->wfd, &tio) == 0 && |
1848 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { | 1726 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
1849 | /* | 1727 | /* |
@@ -1860,7 +1738,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1860 | buffer_consume(&c->output, len); | 1738 | buffer_consume(&c->output, len); |
1861 | } | 1739 | } |
1862 | out: | 1740 | out: |
1863 | if (compat20 && olen > 0) | 1741 | if (olen > 0) |
1864 | c->local_consumed += olen - buffer_len(&c->output); | 1742 | c->local_consumed += olen - buffer_len(&c->output); |
1865 | return 1; | 1743 | return 1; |
1866 | } | 1744 | } |
@@ -1944,8 +1822,6 @@ channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
1944 | { | 1822 | { |
1945 | channel_handle_rfd(c, readset, writeset); | 1823 | channel_handle_rfd(c, readset, writeset); |
1946 | channel_handle_wfd(c, readset, writeset); | 1824 | channel_handle_wfd(c, readset, writeset); |
1947 | if (!compat20) | ||
1948 | return; | ||
1949 | channel_handle_efd(c, readset, writeset); | 1825 | channel_handle_efd(c, readset, writeset); |
1950 | channel_check_window(c); | 1826 | channel_check_window(c); |
1951 | } | 1827 | } |
@@ -1979,9 +1855,6 @@ channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset) | |||
1979 | u_int need; | 1855 | u_int need; |
1980 | ssize_t len; | 1856 | ssize_t len; |
1981 | 1857 | ||
1982 | if (!compat20) | ||
1983 | fatal("%s: entered with !compat20", __func__); | ||
1984 | |||
1985 | if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && | 1858 | if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && |
1986 | (c->istate == CHAN_INPUT_OPEN || | 1859 | (c->istate == CHAN_INPUT_OPEN || |
1987 | c->istate == CHAN_INPUT_WAIT_DRAIN)) { | 1860 | c->istate == CHAN_INPUT_WAIT_DRAIN)) { |
@@ -2074,26 +1947,15 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
2074 | nc->flags |= CHAN_LOCAL; | 1947 | nc->flags |= CHAN_LOCAL; |
2075 | } | 1948 | } |
2076 | 1949 | ||
2077 | /* ARGSUSED */ | ||
2078 | static void | 1950 | static void |
2079 | channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset) | 1951 | channel_handler_init(void) |
2080 | { | 1952 | { |
2081 | int len; | 1953 | int i; |
2082 | 1954 | ||
2083 | /* Send buffered output data to the socket. */ | 1955 | for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { |
2084 | if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) { | 1956 | channel_pre[i] = NULL; |
2085 | len = write(c->sock, buffer_ptr(&c->output), | 1957 | channel_post[i] = NULL; |
2086 | buffer_len(&c->output)); | ||
2087 | if (len <= 0) | ||
2088 | buffer_clear(&c->output); | ||
2089 | else | ||
2090 | buffer_consume(&c->output, len); | ||
2091 | } | 1958 | } |
2092 | } | ||
2093 | |||
2094 | static void | ||
2095 | channel_handler_init_20(void) | ||
2096 | { | ||
2097 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; | 1959 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; |
2098 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | 1960 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; |
2099 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | 1961 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
@@ -2120,64 +1982,6 @@ channel_handler_init_20(void) | |||
2120 | channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; | 1982 | channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; |
2121 | } | 1983 | } |
2122 | 1984 | ||
2123 | static void | ||
2124 | channel_handler_init_13(void) | ||
2125 | { | ||
2126 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13; | ||
2127 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13; | ||
2128 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | ||
2129 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | ||
2130 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | ||
2131 | channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; | ||
2132 | channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; | ||
2133 | channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; | ||
2134 | channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; | ||
2135 | |||
2136 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; | ||
2137 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | ||
2138 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | ||
2139 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
2140 | channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; | ||
2141 | channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; | ||
2142 | channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; | ||
2143 | } | ||
2144 | |||
2145 | static void | ||
2146 | channel_handler_init_15(void) | ||
2147 | { | ||
2148 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; | ||
2149 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | ||
2150 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | ||
2151 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | ||
2152 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | ||
2153 | channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; | ||
2154 | channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; | ||
2155 | |||
2156 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | ||
2157 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | ||
2158 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
2159 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; | ||
2160 | channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; | ||
2161 | channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; | ||
2162 | } | ||
2163 | |||
2164 | static void | ||
2165 | channel_handler_init(void) | ||
2166 | { | ||
2167 | int i; | ||
2168 | |||
2169 | for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { | ||
2170 | channel_pre[i] = NULL; | ||
2171 | channel_post[i] = NULL; | ||
2172 | } | ||
2173 | if (compat20) | ||
2174 | channel_handler_init_20(); | ||
2175 | else if (compat13) | ||
2176 | channel_handler_init_13(); | ||
2177 | else | ||
2178 | channel_handler_init_15(); | ||
2179 | } | ||
2180 | |||
2181 | /* gc dead channels */ | 1985 | /* gc dead channels */ |
2182 | static void | 1986 | static void |
2183 | channel_garbage_collect(Channel *c) | 1987 | channel_garbage_collect(Channel *c) |
@@ -2312,16 +2116,9 @@ channel_output_poll(void) | |||
2312 | * We are only interested in channels that can have buffered | 2116 | * We are only interested in channels that can have buffered |
2313 | * incoming data. | 2117 | * incoming data. |
2314 | */ | 2118 | */ |
2315 | if (compat13) { | 2119 | if (c->type != SSH_CHANNEL_OPEN) |
2316 | if (c->type != SSH_CHANNEL_OPEN && | 2120 | continue; |
2317 | c->type != SSH_CHANNEL_INPUT_DRAINING) | 2121 | if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { |
2318 | continue; | ||
2319 | } else { | ||
2320 | if (c->type != SSH_CHANNEL_OPEN) | ||
2321 | continue; | ||
2322 | } | ||
2323 | if (compat20 && | ||
2324 | (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { | ||
2325 | /* XXX is this true? */ | 2122 | /* XXX is this true? */ |
2326 | debug3("channel %d: will not send data after close", c->self); | 2123 | debug3("channel %d: will not send data after close", c->self); |
2327 | continue; | 2124 | continue; |
@@ -2359,24 +2156,12 @@ channel_output_poll(void) | |||
2359 | * Send some data for the other side over the secure | 2156 | * Send some data for the other side over the secure |
2360 | * connection. | 2157 | * connection. |
2361 | */ | 2158 | */ |
2362 | if (compat20) { | 2159 | if (len > c->remote_window) |
2363 | if (len > c->remote_window) | 2160 | len = c->remote_window; |
2364 | len = c->remote_window; | 2161 | if (len > c->remote_maxpacket) |
2365 | if (len > c->remote_maxpacket) | 2162 | len = c->remote_maxpacket; |
2366 | len = c->remote_maxpacket; | ||
2367 | } else { | ||
2368 | if (packet_is_interactive()) { | ||
2369 | if (len > 1024) | ||
2370 | len = 512; | ||
2371 | } else { | ||
2372 | /* Keep the packets at reasonable size. */ | ||
2373 | if (len > packet_get_maxsize()/2) | ||
2374 | len = packet_get_maxsize()/2; | ||
2375 | } | ||
2376 | } | ||
2377 | if (len > 0) { | 2163 | if (len > 0) { |
2378 | packet_start(compat20 ? | 2164 | packet_start(SSH2_MSG_CHANNEL_DATA); |
2379 | SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); | ||
2380 | packet_put_int(c->remote_id); | 2165 | packet_put_int(c->remote_id); |
2381 | packet_put_string(buffer_ptr(&c->input), len); | 2166 | packet_put_string(buffer_ptr(&c->input), len); |
2382 | packet_send(); | 2167 | packet_send(); |
@@ -2384,8 +2169,6 @@ channel_output_poll(void) | |||
2384 | c->remote_window -= len; | 2169 | c->remote_window -= len; |
2385 | } | 2170 | } |
2386 | } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | 2171 | } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { |
2387 | if (compat13) | ||
2388 | fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); | ||
2389 | /* | 2172 | /* |
2390 | * input-buffer is empty and read-socket shutdown: | 2173 | * input-buffer is empty and read-socket shutdown: |
2391 | * tell peer, that we will not send more data: send IEOF. | 2174 | * tell peer, that we will not send more data: send IEOF. |
@@ -2398,8 +2181,7 @@ channel_output_poll(void) | |||
2398 | chan_ibuf_empty(c); | 2181 | chan_ibuf_empty(c); |
2399 | } | 2182 | } |
2400 | /* Send extended data, i.e. stderr */ | 2183 | /* Send extended data, i.e. stderr */ |
2401 | if (compat20 && | 2184 | if (!(c->flags & CHAN_EOF_SENT) && |
2402 | !(c->flags & CHAN_EOF_SENT) && | ||
2403 | c->remote_window > 0 && | 2185 | c->remote_window > 0 && |
2404 | (len = buffer_len(&c->extended)) > 0 && | 2186 | (len = buffer_len(&c->extended)) > 0 && |
2405 | c->extended_usage == CHAN_EXTENDED_READ) { | 2187 | c->extended_usage == CHAN_EXTENDED_READ) { |
@@ -2738,26 +2520,23 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) | |||
2738 | * that window updates are sent back. Otherwise the connection might | 2520 | * that window updates are sent back. Otherwise the connection might |
2739 | * deadlock. | 2521 | * deadlock. |
2740 | */ | 2522 | */ |
2741 | if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) { | 2523 | if (c->ostate != CHAN_OUTPUT_OPEN) { |
2742 | if (compat20) { | 2524 | c->local_window -= win_len; |
2743 | c->local_window -= win_len; | 2525 | c->local_consumed += win_len; |
2744 | c->local_consumed += win_len; | ||
2745 | } | ||
2746 | return 0; | 2526 | return 0; |
2747 | } | 2527 | } |
2748 | 2528 | ||
2749 | if (compat20) { | 2529 | if (win_len > c->local_maxpacket) { |
2750 | if (win_len > c->local_maxpacket) { | 2530 | logit("channel %d: rcvd big packet %d, maxpack %d", |
2751 | logit("channel %d: rcvd big packet %d, maxpack %d", | 2531 | c->self, win_len, c->local_maxpacket); |
2752 | c->self, win_len, c->local_maxpacket); | 2532 | } |
2753 | } | 2533 | if (win_len > c->local_window) { |
2754 | if (win_len > c->local_window) { | 2534 | logit("channel %d: rcvd too much data %d, win %d", |
2755 | logit("channel %d: rcvd too much data %d, win %d", | 2535 | c->self, win_len, c->local_window); |
2756 | c->self, win_len, c->local_window); | 2536 | return 0; |
2757 | return 0; | ||
2758 | } | ||
2759 | c->local_window -= win_len; | ||
2760 | } | 2537 | } |
2538 | c->local_window -= win_len; | ||
2539 | |||
2761 | if (c->datagram) | 2540 | if (c->datagram) |
2762 | buffer_put_string(&c->output, data, data_len); | 2541 | buffer_put_string(&c->output, data, data_len); |
2763 | else | 2542 | else |
@@ -2942,17 +2721,15 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) | |||
2942 | c->remote_id = remote_id; | 2721 | c->remote_id = remote_id; |
2943 | c->type = SSH_CHANNEL_OPEN; | 2722 | c->type = SSH_CHANNEL_OPEN; |
2944 | 2723 | ||
2945 | if (compat20) { | 2724 | c->remote_window = packet_get_int(); |
2946 | c->remote_window = packet_get_int(); | 2725 | c->remote_maxpacket = packet_get_int(); |
2947 | c->remote_maxpacket = packet_get_int(); | 2726 | if (c->open_confirm) { |
2948 | if (c->open_confirm) { | 2727 | debug2("callback start"); |
2949 | debug2("callback start"); | 2728 | c->open_confirm(c->self, 1, c->open_confirm_ctx); |
2950 | c->open_confirm(c->self, 1, c->open_confirm_ctx); | 2729 | debug2("callback done"); |
2951 | debug2("callback done"); | ||
2952 | } | ||
2953 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | ||
2954 | c->remote_window, c->remote_maxpacket); | ||
2955 | } | 2730 | } |
2731 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | ||
2732 | c->remote_window, c->remote_maxpacket); | ||
2956 | packet_check_eom(); | 2733 | packet_check_eom(); |
2957 | return 0; | 2734 | return 0; |
2958 | } | 2735 | } |
@@ -2992,21 +2769,19 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) | |||
2992 | if (c->type != SSH_CHANNEL_OPENING) | 2769 | if (c->type != SSH_CHANNEL_OPENING) |
2993 | packet_disconnect("Received open failure for " | 2770 | packet_disconnect("Received open failure for " |
2994 | "non-opening channel %d.", id); | 2771 | "non-opening channel %d.", id); |
2995 | if (compat20) { | 2772 | reason = packet_get_int(); |
2996 | reason = packet_get_int(); | 2773 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { |
2997 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { | 2774 | msg = packet_get_string(NULL); |
2998 | msg = packet_get_string(NULL); | 2775 | lang = packet_get_string(NULL); |
2999 | lang = packet_get_string(NULL); | 2776 | } |
3000 | } | 2777 | logit("channel %d: open failed: %s%s%s", id, |
3001 | logit("channel %d: open failed: %s%s%s", id, | 2778 | reason2txt(reason), msg ? ": ": "", msg ? msg : ""); |
3002 | reason2txt(reason), msg ? ": ": "", msg ? msg : ""); | 2779 | free(msg); |
3003 | free(msg); | 2780 | free(lang); |
3004 | free(lang); | 2781 | if (c->open_confirm) { |
3005 | if (c->open_confirm) { | 2782 | debug2("callback start"); |
3006 | debug2("callback start"); | 2783 | c->open_confirm(c->self, 0, c->open_confirm_ctx); |
3007 | c->open_confirm(c->self, 0, c->open_confirm_ctx); | 2784 | debug2("callback done"); |
3008 | debug2("callback done"); | ||
3009 | } | ||
3010 | } | 2785 | } |
3011 | packet_check_eom(); | 2786 | packet_check_eom(); |
3012 | /* Schedule the channel for cleanup/deletion. */ | 2787 | /* Schedule the channel for cleanup/deletion. */ |
@@ -3022,9 +2797,6 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) | |||
3022 | int id; | 2797 | int id; |
3023 | u_int adjust, tmp; | 2798 | u_int adjust, tmp; |
3024 | 2799 | ||
3025 | if (!compat20) | ||
3026 | return 0; | ||
3027 | |||
3028 | /* Get the channel number and verify it. */ | 2800 | /* Get the channel number and verify it. */ |
3029 | id = packet_get_int(); | 2801 | id = packet_get_int(); |
3030 | c = channel_lookup(id); | 2802 | c = channel_lookup(id); |
@@ -3581,49 +3353,24 @@ channel_rfwd_bind_host(const char *listen_host) | |||
3581 | int | 3353 | int |
3582 | channel_request_remote_forwarding(struct Forward *fwd) | 3354 | channel_request_remote_forwarding(struct Forward *fwd) |
3583 | { | 3355 | { |
3584 | int type, success = 0, idx = -1; | 3356 | int success = 0, idx = -1; |
3585 | 3357 | ||
3586 | /* Send the forward request to the remote side. */ | 3358 | /* Send the forward request to the remote side. */ |
3587 | if (compat20) { | 3359 | packet_start(SSH2_MSG_GLOBAL_REQUEST); |
3588 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 3360 | if (fwd->listen_path != NULL) { |
3589 | if (fwd->listen_path != NULL) { | 3361 | packet_put_cstring("streamlocal-forward@openssh.com"); |
3590 | packet_put_cstring("streamlocal-forward@openssh.com"); | 3362 | packet_put_char(1); /* boolean: want reply */ |
3591 | packet_put_char(1); /* boolean: want reply */ | 3363 | packet_put_cstring(fwd->listen_path); |
3592 | packet_put_cstring(fwd->listen_path); | ||
3593 | } else { | ||
3594 | packet_put_cstring("tcpip-forward"); | ||
3595 | packet_put_char(1); /* boolean: want reply */ | ||
3596 | packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); | ||
3597 | packet_put_int(fwd->listen_port); | ||
3598 | } | ||
3599 | packet_send(); | ||
3600 | packet_write_wait(); | ||
3601 | /* Assume that server accepts the request */ | ||
3602 | success = 1; | ||
3603 | } else if (fwd->listen_path == NULL) { | ||
3604 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); | ||
3605 | packet_put_int(fwd->listen_port); | ||
3606 | packet_put_cstring(fwd->connect_host); | ||
3607 | packet_put_int(fwd->connect_port); | ||
3608 | packet_send(); | ||
3609 | packet_write_wait(); | ||
3610 | |||
3611 | /* Wait for response from the remote side. */ | ||
3612 | type = packet_read(); | ||
3613 | switch (type) { | ||
3614 | case SSH_SMSG_SUCCESS: | ||
3615 | success = 1; | ||
3616 | break; | ||
3617 | case SSH_SMSG_FAILURE: | ||
3618 | break; | ||
3619 | default: | ||
3620 | /* Unknown packet */ | ||
3621 | packet_disconnect("Protocol error for port forward request:" | ||
3622 | "received packet type %d.", type); | ||
3623 | } | ||
3624 | } else { | 3364 | } else { |
3625 | logit("Warning: Server does not support remote stream local forwarding."); | 3365 | packet_put_cstring("tcpip-forward"); |
3366 | packet_put_char(1); /* boolean: want reply */ | ||
3367 | packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); | ||
3368 | packet_put_int(fwd->listen_port); | ||
3626 | } | 3369 | } |
3370 | packet_send(); | ||
3371 | packet_write_wait(); | ||
3372 | /* Assume that server accepts the request */ | ||
3373 | success = 1; | ||
3627 | if (success) { | 3374 | if (success) { |
3628 | /* Record that connection to this host/port is permitted. */ | 3375 | /* Record that connection to this host/port is permitted. */ |
3629 | permitted_opens = xreallocarray(permitted_opens, | 3376 | permitted_opens = xreallocarray(permitted_opens, |
@@ -3722,9 +3469,6 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port) | |||
3722 | { | 3469 | { |
3723 | int i; | 3470 | int i; |
3724 | 3471 | ||
3725 | if (!compat20) | ||
3726 | return -1; | ||
3727 | |||
3728 | for (i = 0; i < num_permitted_opens; i++) { | 3472 | for (i = 0; i < num_permitted_opens; i++) { |
3729 | if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) | 3473 | if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) |
3730 | break; | 3474 | break; |
@@ -3761,9 +3505,6 @@ channel_request_rforward_cancel_streamlocal(const char *path) | |||
3761 | { | 3505 | { |
3762 | int i; | 3506 | int i; |
3763 | 3507 | ||
3764 | if (!compat20) | ||
3765 | return -1; | ||
3766 | |||
3767 | for (i = 0; i < num_permitted_opens; i++) { | 3508 | for (i = 0; i < num_permitted_opens; i++) { |
3768 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) | 3509 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) |
3769 | break; | 3510 | break; |
@@ -4644,12 +4385,8 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, | |||
4644 | new_data = tohex(x11_fake_data, data_len); | 4385 | new_data = tohex(x11_fake_data, data_len); |
4645 | 4386 | ||
4646 | /* Send the request packet. */ | 4387 | /* Send the request packet. */ |
4647 | if (compat20) { | 4388 | channel_request_start(client_session_id, "x11-req", want_reply); |
4648 | channel_request_start(client_session_id, "x11-req", want_reply); | 4389 | packet_put_char(0); /* XXX bool single connection */ |
4649 | packet_put_char(0); /* XXX bool single connection */ | ||
4650 | } else { | ||
4651 | packet_start(SSH_CMSG_X11_REQUEST_FORWARDING); | ||
4652 | } | ||
4653 | packet_put_cstring(proto); | 4390 | packet_put_cstring(proto); |
4654 | packet_put_cstring(new_data); | 4391 | packet_put_cstring(new_data); |
4655 | packet_put_int(screen_number); | 4392 | packet_put_int(screen_number); |
diff --git a/channels.h b/channels.h index ce43236d5..77ec4f966 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.122 2017/04/30 23:13:25 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -200,11 +200,11 @@ struct Channel { | |||
200 | 200 | ||
201 | /* check whether 'efd' is still in use */ | 201 | /* check whether 'efd' is still in use */ |
202 | #define CHANNEL_EFD_INPUT_ACTIVE(c) \ | 202 | #define CHANNEL_EFD_INPUT_ACTIVE(c) \ |
203 | (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \ | 203 | (c->extended_usage == CHAN_EXTENDED_READ && \ |
204 | (c->efd != -1 || \ | 204 | (c->efd != -1 || \ |
205 | buffer_len(&c->extended) > 0)) | 205 | buffer_len(&c->extended) > 0)) |
206 | #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ | 206 | #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ |
207 | (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \ | 207 | (c->extended_usage == CHAN_EXTENDED_WRITE && \ |
208 | c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ | 208 | c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ |
209 | buffer_len(&c->extended) > 0)) | 209 | buffer_len(&c->extended) > 0)) |
210 | 210 | ||
diff --git a/clientloop.c b/clientloop.c index 064816234..469a2f00a 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.291 2017/03/10 05:01:13 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.292 2017/04/30 23:13:25 djm 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 |
@@ -207,15 +207,6 @@ leave_non_blocking(void) | |||
207 | } | 207 | } |
208 | } | 208 | } |
209 | 209 | ||
210 | /* Puts stdin terminal in non-blocking mode. */ | ||
211 | |||
212 | static void | ||
213 | enter_non_blocking(void) | ||
214 | { | ||
215 | in_non_blocking_mode = 1; | ||
216 | set_nonblock(fileno(stdin)); | ||
217 | } | ||
218 | |||
219 | /* | 210 | /* |
220 | * Signal handler for the window change signal (SIGWINCH). This just sets a | 211 | * Signal handler for the window change signal (SIGWINCH). This just sets a |
221 | * flag indicating that the window has changed. | 212 | * flag indicating that the window has changed. |
@@ -455,91 +446,6 @@ client_x11_get_proto(const char *display, const char *xauth_path, | |||
455 | } | 446 | } |
456 | 447 | ||
457 | /* | 448 | /* |
458 | * This is called when the interactive is entered. This checks if there is | ||
459 | * an EOF coming on stdin. We must check this explicitly, as select() does | ||
460 | * not appear to wake up when redirecting from /dev/null. | ||
461 | */ | ||
462 | |||
463 | static void | ||
464 | client_check_initial_eof_on_stdin(void) | ||
465 | { | ||
466 | int len; | ||
467 | char buf[1]; | ||
468 | |||
469 | /* | ||
470 | * If standard input is to be "redirected from /dev/null", we simply | ||
471 | * mark that we have seen an EOF and send an EOF message to the | ||
472 | * server. Otherwise, we try to read a single character; it appears | ||
473 | * that for some files, such /dev/null, select() never wakes up for | ||
474 | * read for this descriptor, which means that we never get EOF. This | ||
475 | * way we will get the EOF if stdin comes from /dev/null or similar. | ||
476 | */ | ||
477 | if (stdin_null_flag) { | ||
478 | /* Fake EOF on stdin. */ | ||
479 | debug("Sending eof."); | ||
480 | stdin_eof = 1; | ||
481 | packet_start(SSH_CMSG_EOF); | ||
482 | packet_send(); | ||
483 | } else { | ||
484 | enter_non_blocking(); | ||
485 | |||
486 | /* Check for immediate EOF on stdin. */ | ||
487 | len = read(fileno(stdin), buf, 1); | ||
488 | if (len == 0) { | ||
489 | /* | ||
490 | * EOF. Record that we have seen it and send | ||
491 | * EOF to server. | ||
492 | */ | ||
493 | debug("Sending eof."); | ||
494 | stdin_eof = 1; | ||
495 | packet_start(SSH_CMSG_EOF); | ||
496 | packet_send(); | ||
497 | } else if (len > 0) { | ||
498 | /* | ||
499 | * Got data. We must store the data in the buffer, | ||
500 | * and also process it as an escape character if | ||
501 | * appropriate. | ||
502 | */ | ||
503 | if ((u_char) buf[0] == escape_char1) | ||
504 | escape_pending1 = 1; | ||
505 | else | ||
506 | buffer_append(&stdin_buffer, buf, 1); | ||
507 | } | ||
508 | leave_non_blocking(); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | |||
513 | /* | ||
514 | * Make packets from buffered stdin data, and buffer them for sending to the | ||
515 | * connection. | ||
516 | */ | ||
517 | |||
518 | static void | ||
519 | client_make_packets_from_stdin_data(void) | ||
520 | { | ||
521 | u_int len; | ||
522 | |||
523 | /* Send buffered stdin data to the server. */ | ||
524 | while (buffer_len(&stdin_buffer) > 0 && | ||
525 | packet_not_very_much_data_to_write()) { | ||
526 | len = buffer_len(&stdin_buffer); | ||
527 | /* Keep the packets at reasonable size. */ | ||
528 | if (len > packet_get_maxsize()) | ||
529 | len = packet_get_maxsize(); | ||
530 | packet_start(SSH_CMSG_STDIN_DATA); | ||
531 | packet_put_string(buffer_ptr(&stdin_buffer), len); | ||
532 | packet_send(); | ||
533 | buffer_consume(&stdin_buffer, len); | ||
534 | /* If we have a pending EOF, send it now. */ | ||
535 | if (stdin_eof && buffer_len(&stdin_buffer) == 0) { | ||
536 | packet_start(SSH_CMSG_EOF); | ||
537 | packet_send(); | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * Checks if the client window has changed, and sends a packet about it to | 449 | * Checks if the client window has changed, and sends a packet about it to |
544 | * the server if so. The actual change is detected elsewhere (by a software | 450 | * the server if so. The actual change is detected elsewhere (by a software |
545 | * interrupt on Unix); this just checks the flag and sends a message if | 451 | * interrupt on Unix); this just checks the flag and sends a message if |
@@ -549,27 +455,14 @@ client_make_packets_from_stdin_data(void) | |||
549 | static void | 455 | static void |
550 | client_check_window_change(void) | 456 | client_check_window_change(void) |
551 | { | 457 | { |
552 | struct winsize ws; | 458 | if (!received_window_change_signal) |
553 | |||
554 | if (! received_window_change_signal) | ||
555 | return; | 459 | return; |
556 | /** XXX race */ | 460 | /** XXX race */ |
557 | received_window_change_signal = 0; | 461 | received_window_change_signal = 0; |
558 | 462 | ||
559 | debug2("client_check_window_change: changed"); | 463 | debug2("%s: changed", __func__); |
560 | 464 | ||
561 | if (compat20) { | 465 | channel_send_window_changes(); |
562 | channel_send_window_changes(); | ||
563 | } else { | ||
564 | if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) | ||
565 | return; | ||
566 | packet_start(SSH_CMSG_WINDOW_SIZE); | ||
567 | packet_put_int((u_int)ws.ws_row); | ||
568 | packet_put_int((u_int)ws.ws_col); | ||
569 | packet_put_int((u_int)ws.ws_xpixel); | ||
570 | packet_put_int((u_int)ws.ws_ypixel); | ||
571 | packet_send(); | ||
572 | } | ||
573 | } | 466 | } |
574 | 467 | ||
575 | static int | 468 | static int |
@@ -623,35 +516,15 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
623 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, | 516 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, |
624 | &minwait_secs, rekeying); | 517 | &minwait_secs, rekeying); |
625 | 518 | ||
626 | if (!compat20) { | 519 | /* channel_prepare_select could have closed the last channel */ |
627 | /* Read from the connection, unless our buffers are full. */ | 520 | if (session_closed && !channel_still_open() && |
628 | if (buffer_len(&stdout_buffer) < buffer_high && | 521 | !packet_have_data_to_write()) { |
629 | buffer_len(&stderr_buffer) < buffer_high && | 522 | /* clear mask since we did not call select() */ |
630 | channel_not_very_much_buffered_data()) | 523 | memset(*readsetp, 0, *nallocp); |
631 | FD_SET(connection_in, *readsetp); | 524 | memset(*writesetp, 0, *nallocp); |
632 | /* | 525 | return; |
633 | * Read from stdin, unless we have seen EOF or have very much | ||
634 | * buffered data to send to the server. | ||
635 | */ | ||
636 | if (!stdin_eof && packet_not_very_much_data_to_write()) | ||
637 | FD_SET(fileno(stdin), *readsetp); | ||
638 | |||
639 | /* Select stdout/stderr if have data in buffer. */ | ||
640 | if (buffer_len(&stdout_buffer) > 0) | ||
641 | FD_SET(fileno(stdout), *writesetp); | ||
642 | if (buffer_len(&stderr_buffer) > 0) | ||
643 | FD_SET(fileno(stderr), *writesetp); | ||
644 | } else { | 526 | } else { |
645 | /* channel_prepare_select could have closed the last channel */ | 527 | FD_SET(connection_in, *readsetp); |
646 | if (session_closed && !channel_still_open() && | ||
647 | !packet_have_data_to_write()) { | ||
648 | /* clear mask since we did not call select() */ | ||
649 | memset(*readsetp, 0, *nallocp); | ||
650 | memset(*writesetp, 0, *nallocp); | ||
651 | return; | ||
652 | } else { | ||
653 | FD_SET(connection_in, *readsetp); | ||
654 | } | ||
655 | } | 528 | } |
656 | 529 | ||
657 | /* Select server connection if have data to write to the server. */ | 530 | /* Select server connection if have data to write to the server. */ |
@@ -665,11 +538,11 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
665 | */ | 538 | */ |
666 | 539 | ||
667 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ | 540 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ |
668 | if (options.server_alive_interval > 0 && compat20) { | 541 | if (options.server_alive_interval > 0) { |
669 | timeout_secs = options.server_alive_interval; | 542 | timeout_secs = options.server_alive_interval; |
670 | server_alive_time = now + options.server_alive_interval; | 543 | server_alive_time = now + options.server_alive_interval; |
671 | } | 544 | } |
672 | if (options.rekey_interval > 0 && compat20 && !rekeying) | 545 | if (options.rekey_interval > 0 && !rekeying) |
673 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); | 546 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); |
674 | set_control_persist_exit_time(); | 547 | set_control_persist_exit_time(); |
675 | if (control_persist_exit_time > 0) { | 548 | if (control_persist_exit_time > 0) { |
@@ -966,11 +839,6 @@ process_cmdline(void) | |||
966 | goto out; | 839 | goto out; |
967 | } | 840 | } |
968 | 841 | ||
969 | if (delete && !compat20) { | ||
970 | logit("Not supported for SSH protocol version 1."); | ||
971 | goto out; | ||
972 | } | ||
973 | |||
974 | while (isspace((u_char)*++s)) | 842 | while (isspace((u_char)*++s)) |
975 | ; | 843 | ; |
976 | 844 | ||
@@ -1027,10 +895,9 @@ out: | |||
1027 | 895 | ||
1028 | /* reasons to suppress output of an escape command in help output */ | 896 | /* reasons to suppress output of an escape command in help output */ |
1029 | #define SUPPRESS_NEVER 0 /* never suppress, always show */ | 897 | #define SUPPRESS_NEVER 0 /* never suppress, always show */ |
1030 | #define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */ | 898 | #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */ |
1031 | #define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */ | 899 | #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */ |
1032 | #define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */ | 900 | #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */ |
1033 | #define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */ | ||
1034 | struct escape_help_text { | 901 | struct escape_help_text { |
1035 | const char *cmd; | 902 | const char *cmd; |
1036 | const char *text; | 903 | const char *text; |
@@ -1040,9 +907,9 @@ static struct escape_help_text esc_txt[] = { | |||
1040 | {".", "terminate session", SUPPRESS_MUXMASTER}, | 907 | {".", "terminate session", SUPPRESS_MUXMASTER}, |
1041 | {".", "terminate connection (and any multiplexed sessions)", | 908 | {".", "terminate connection (and any multiplexed sessions)", |
1042 | SUPPRESS_MUXCLIENT}, | 909 | SUPPRESS_MUXCLIENT}, |
1043 | {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1}, | 910 | {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, |
1044 | {"C", "open a command line", SUPPRESS_MUXCLIENT}, | 911 | {"C", "open a command line", SUPPRESS_MUXCLIENT}, |
1045 | {"R", "request rekey", SUPPRESS_PROTO1}, | 912 | {"R", "request rekey", SUPPRESS_NEVER}, |
1046 | {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, | 913 | {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, |
1047 | {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, | 914 | {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, |
1048 | {"#", "list forwarded connections", SUPPRESS_NEVER}, | 915 | {"#", "list forwarded connections", SUPPRESS_NEVER}, |
@@ -1052,8 +919,7 @@ static struct escape_help_text esc_txt[] = { | |||
1052 | }; | 919 | }; |
1053 | 920 | ||
1054 | static void | 921 | static void |
1055 | print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | 922 | print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) |
1056 | int using_stderr) | ||
1057 | { | 923 | { |
1058 | unsigned int i, suppress_flags; | 924 | unsigned int i, suppress_flags; |
1059 | char string[1024]; | 925 | char string[1024]; |
@@ -1062,7 +928,7 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | |||
1062 | "Supported escape sequences:\r\n", escape_char); | 928 | "Supported escape sequences:\r\n", escape_char); |
1063 | buffer_append(b, string, strlen(string)); | 929 | buffer_append(b, string, strlen(string)); |
1064 | 930 | ||
1065 | suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) | | 931 | suppress_flags = |
1066 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | | 932 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | |
1067 | (mux_client ? 0 : SUPPRESS_MUXMASTER) | | 933 | (mux_client ? 0 : SUPPRESS_MUXMASTER) | |
1068 | (using_stderr ? 0 : SUPPRESS_SYSLOG); | 934 | (using_stderr ? 0 : SUPPRESS_SYSLOG); |
@@ -1171,26 +1037,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1171 | continue; | 1037 | continue; |
1172 | 1038 | ||
1173 | case 'B': | 1039 | case 'B': |
1174 | if (compat20) { | 1040 | snprintf(string, sizeof string, |
1175 | snprintf(string, sizeof string, | 1041 | "%cB\r\n", escape_char); |
1176 | "%cB\r\n", escape_char); | 1042 | buffer_append(berr, string, strlen(string)); |
1177 | buffer_append(berr, string, | 1043 | channel_request_start(c->self, "break", 0); |
1178 | strlen(string)); | 1044 | packet_put_int(1000); |
1179 | channel_request_start(c->self, | 1045 | packet_send(); |
1180 | "break", 0); | ||
1181 | packet_put_int(1000); | ||
1182 | packet_send(); | ||
1183 | } | ||
1184 | continue; | 1046 | continue; |
1185 | 1047 | ||
1186 | case 'R': | 1048 | case 'R': |
1187 | if (compat20) { | 1049 | if (datafellows & SSH_BUG_NOREKEY) |
1188 | if (datafellows & SSH_BUG_NOREKEY) | 1050 | logit("Server does not " |
1189 | logit("Server does not " | 1051 | "support re-keying"); |
1190 | "support re-keying"); | 1052 | else |
1191 | else | 1053 | need_rekeying = 1; |
1192 | need_rekeying = 1; | ||
1193 | } | ||
1194 | continue; | 1054 | continue; |
1195 | 1055 | ||
1196 | case 'V': | 1056 | case 'V': |
@@ -1248,30 +1108,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1248 | exit(0); | 1108 | exit(0); |
1249 | } | 1109 | } |
1250 | /* The child continues serving connections. */ | 1110 | /* The child continues serving connections. */ |
1251 | if (compat20) { | 1111 | buffer_append(bin, "\004", 1); |
1252 | buffer_append(bin, "\004", 1); | 1112 | /* fake EOF on stdin */ |
1253 | /* fake EOF on stdin */ | 1113 | return -1; |
1254 | return -1; | ||
1255 | } else if (!stdin_eof) { | ||
1256 | /* | ||
1257 | * Sending SSH_CMSG_EOF alone does not | ||
1258 | * always appear to be enough. So we | ||
1259 | * try to send an EOF character first. | ||
1260 | */ | ||
1261 | packet_start(SSH_CMSG_STDIN_DATA); | ||
1262 | packet_put_string("\004", 1); | ||
1263 | packet_send(); | ||
1264 | /* Close stdin. */ | ||
1265 | stdin_eof = 1; | ||
1266 | if (buffer_len(bin) == 0) { | ||
1267 | packet_start(SSH_CMSG_EOF); | ||
1268 | packet_send(); | ||
1269 | } | ||
1270 | } | ||
1271 | continue; | ||
1272 | |||
1273 | case '?': | 1114 | case '?': |
1274 | print_escape_help(berr, escape_char, compat20, | 1115 | print_escape_help(berr, escape_char, |
1275 | (c && c->ctl_chan != -1), | 1116 | (c && c->ctl_chan != -1), |
1276 | log_is_on_stderr()); | 1117 | log_is_on_stderr()); |
1277 | continue; | 1118 | continue; |
@@ -1325,115 +1166,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1325 | return bytes; | 1166 | return bytes; |
1326 | } | 1167 | } |
1327 | 1168 | ||
1328 | static void | ||
1329 | client_process_input(fd_set *readset) | ||
1330 | { | ||
1331 | int len; | ||
1332 | char buf[SSH_IOBUFSZ]; | ||
1333 | |||
1334 | /* Read input from stdin. */ | ||
1335 | if (FD_ISSET(fileno(stdin), readset)) { | ||
1336 | /* Read as much as possible. */ | ||
1337 | len = read(fileno(stdin), buf, sizeof(buf)); | ||
1338 | if (len < 0 && | ||
1339 | (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) | ||
1340 | return; /* we'll try again later */ | ||
1341 | if (len <= 0) { | ||
1342 | /* | ||
1343 | * Received EOF or error. They are treated | ||
1344 | * similarly, except that an error message is printed | ||
1345 | * if it was an error condition. | ||
1346 | */ | ||
1347 | if (len < 0) { | ||
1348 | snprintf(buf, sizeof buf, "read: %.100s\r\n", | ||
1349 | strerror(errno)); | ||
1350 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
1351 | } | ||
1352 | /* Mark that we have seen EOF. */ | ||
1353 | stdin_eof = 1; | ||
1354 | /* | ||
1355 | * Send an EOF message to the server unless there is | ||
1356 | * data in the buffer. If there is data in the | ||
1357 | * buffer, no message will be sent now. Code | ||
1358 | * elsewhere will send the EOF when the buffer | ||
1359 | * becomes empty if stdin_eof is set. | ||
1360 | */ | ||
1361 | if (buffer_len(&stdin_buffer) == 0) { | ||
1362 | packet_start(SSH_CMSG_EOF); | ||
1363 | packet_send(); | ||
1364 | } | ||
1365 | } else if (escape_char1 == SSH_ESCAPECHAR_NONE) { | ||
1366 | /* | ||
1367 | * Normal successful read, and no escape character. | ||
1368 | * Just append the data to buffer. | ||
1369 | */ | ||
1370 | buffer_append(&stdin_buffer, buf, len); | ||
1371 | } else { | ||
1372 | /* | ||
1373 | * Normal, successful read. But we have an escape | ||
1374 | * character and have to process the characters one | ||
1375 | * by one. | ||
1376 | */ | ||
1377 | if (process_escapes(NULL, &stdin_buffer, | ||
1378 | &stdout_buffer, &stderr_buffer, buf, len) == -1) | ||
1379 | return; | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | static void | ||
1385 | client_process_output(fd_set *writeset) | ||
1386 | { | ||
1387 | int len; | ||
1388 | char buf[100]; | ||
1389 | |||
1390 | /* Write buffered output to stdout. */ | ||
1391 | if (FD_ISSET(fileno(stdout), writeset)) { | ||
1392 | /* Write as much data as possible. */ | ||
1393 | len = write(fileno(stdout), buffer_ptr(&stdout_buffer), | ||
1394 | buffer_len(&stdout_buffer)); | ||
1395 | if (len <= 0) { | ||
1396 | if (errno == EINTR || errno == EAGAIN || | ||
1397 | errno == EWOULDBLOCK) | ||
1398 | len = 0; | ||
1399 | else { | ||
1400 | /* | ||
1401 | * An error or EOF was encountered. Put an | ||
1402 | * error message to stderr buffer. | ||
1403 | */ | ||
1404 | snprintf(buf, sizeof buf, | ||
1405 | "write stdout: %.50s\r\n", strerror(errno)); | ||
1406 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
1407 | quit_pending = 1; | ||
1408 | return; | ||
1409 | } | ||
1410 | } | ||
1411 | /* Consume printed data from the buffer. */ | ||
1412 | buffer_consume(&stdout_buffer, len); | ||
1413 | } | ||
1414 | /* Write buffered output to stderr. */ | ||
1415 | if (FD_ISSET(fileno(stderr), writeset)) { | ||
1416 | /* Write as much data as possible. */ | ||
1417 | len = write(fileno(stderr), buffer_ptr(&stderr_buffer), | ||
1418 | buffer_len(&stderr_buffer)); | ||
1419 | if (len <= 0) { | ||
1420 | if (errno == EINTR || errno == EAGAIN || | ||
1421 | errno == EWOULDBLOCK) | ||
1422 | len = 0; | ||
1423 | else { | ||
1424 | /* | ||
1425 | * EOF or error, but can't even print | ||
1426 | * error message. | ||
1427 | */ | ||
1428 | quit_pending = 1; | ||
1429 | return; | ||
1430 | } | ||
1431 | } | ||
1432 | /* Consume printed characters from the buffer. */ | ||
1433 | buffer_consume(&stderr_buffer, len); | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | /* | 1169 | /* |
1438 | * Get packets from the connection input buffer, and process them as long as | 1170 | * Get packets from the connection input buffer, and process them as long as |
1439 | * there are packets available. | 1171 | * there are packets available. |
@@ -1553,18 +1285,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1553 | connection_out = packet_get_connection_out(); | 1285 | connection_out = packet_get_connection_out(); |
1554 | max_fd = MAXIMUM(connection_in, connection_out); | 1286 | max_fd = MAXIMUM(connection_in, connection_out); |
1555 | 1287 | ||
1556 | if (!compat20) { | ||
1557 | /* enable nonblocking unless tty */ | ||
1558 | if (!isatty(fileno(stdin))) | ||
1559 | set_nonblock(fileno(stdin)); | ||
1560 | if (!isatty(fileno(stdout))) | ||
1561 | set_nonblock(fileno(stdout)); | ||
1562 | if (!isatty(fileno(stderr))) | ||
1563 | set_nonblock(fileno(stderr)); | ||
1564 | max_fd = MAXIMUM(max_fd, fileno(stdin)); | ||
1565 | max_fd = MAXIMUM(max_fd, fileno(stdout)); | ||
1566 | max_fd = MAXIMUM(max_fd, fileno(stderr)); | ||
1567 | } | ||
1568 | quit_pending = 0; | 1288 | quit_pending = 0; |
1569 | escape_char1 = escape_char_arg; | 1289 | escape_char1 = escape_char_arg; |
1570 | 1290 | ||
@@ -1592,22 +1312,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1592 | if (have_pty) | 1312 | if (have_pty) |
1593 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1313 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1594 | 1314 | ||
1595 | if (compat20) { | 1315 | session_ident = ssh2_chan_id; |
1596 | session_ident = ssh2_chan_id; | 1316 | if (session_ident != -1) { |
1597 | if (session_ident != -1) { | 1317 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
1598 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { | 1318 | channel_register_filter(session_ident, |
1599 | channel_register_filter(session_ident, | 1319 | client_simple_escape_filter, NULL, |
1600 | client_simple_escape_filter, NULL, | 1320 | client_filter_cleanup, |
1601 | client_filter_cleanup, | 1321 | client_new_escape_filter_ctx( |
1602 | client_new_escape_filter_ctx( | 1322 | escape_char_arg)); |
1603 | escape_char_arg)); | ||
1604 | } | ||
1605 | channel_register_cleanup(session_ident, | ||
1606 | client_channel_closed, 0); | ||
1607 | } | 1323 | } |
1608 | } else { | 1324 | channel_register_cleanup(session_ident, |
1609 | /* Check if we should immediately send eof on stdin. */ | 1325 | client_channel_closed, 0); |
1610 | client_check_initial_eof_on_stdin(); | ||
1611 | } | 1326 | } |
1612 | 1327 | ||
1613 | /* Main loop of the client for the interactive session mode. */ | 1328 | /* Main loop of the client for the interactive session mode. */ |
@@ -1616,7 +1331,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1616 | /* Process buffered packets sent by the server. */ | 1331 | /* Process buffered packets sent by the server. */ |
1617 | client_process_buffered_input_packets(); | 1332 | client_process_buffered_input_packets(); |
1618 | 1333 | ||
1619 | if (compat20 && session_closed && !channel_still_open()) | 1334 | if (session_closed && !channel_still_open()) |
1620 | break; | 1335 | break; |
1621 | 1336 | ||
1622 | if (ssh_packet_is_rekeying(active_state)) { | 1337 | if (ssh_packet_is_rekeying(active_state)) { |
@@ -1630,13 +1345,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1630 | need_rekeying = 0; | 1345 | need_rekeying = 0; |
1631 | } else { | 1346 | } else { |
1632 | /* | 1347 | /* |
1633 | * Make packets of buffered stdin data, and buffer | ||
1634 | * them for sending to the server. | ||
1635 | */ | ||
1636 | if (!compat20) | ||
1637 | client_make_packets_from_stdin_data(); | ||
1638 | |||
1639 | /* | ||
1640 | * Make packets from buffered channel data, and | 1348 | * Make packets from buffered channel data, and |
1641 | * enqueue them for sending to the server. | 1349 | * enqueue them for sending to the server. |
1642 | */ | 1350 | */ |
@@ -1673,16 +1381,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1673 | if (quit_pending) | 1381 | if (quit_pending) |
1674 | break; | 1382 | break; |
1675 | 1383 | ||
1676 | if (!compat20) { | ||
1677 | /* Buffer data from stdin */ | ||
1678 | client_process_input(readset); | ||
1679 | /* | ||
1680 | * Process output to stdout and stderr. Output to | ||
1681 | * the connection is processed elsewhere (above). | ||
1682 | */ | ||
1683 | client_process_output(writeset); | ||
1684 | } | ||
1685 | |||
1686 | /* | 1384 | /* |
1687 | * Send as much buffered packet data as possible to the | 1385 | * Send as much buffered packet data as possible to the |
1688 | * sender. | 1386 | * sender. |
@@ -1710,14 +1408,12 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1710 | /* Stop watching for window change. */ | 1408 | /* Stop watching for window change. */ |
1711 | signal(SIGWINCH, SIG_DFL); | 1409 | signal(SIGWINCH, SIG_DFL); |
1712 | 1410 | ||
1713 | if (compat20) { | 1411 | packet_start(SSH2_MSG_DISCONNECT); |
1714 | packet_start(SSH2_MSG_DISCONNECT); | 1412 | packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); |
1715 | packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); | 1413 | packet_put_cstring("disconnected by user"); |
1716 | packet_put_cstring("disconnected by user"); | 1414 | packet_put_cstring(""); /* language tag */ |
1717 | packet_put_cstring(""); /* language tag */ | 1415 | packet_send(); |
1718 | packet_send(); | 1416 | packet_write_wait(); |
1719 | packet_write_wait(); | ||
1720 | } | ||
1721 | 1417 | ||
1722 | channel_free_all(); | 1418 | channel_free_all(); |
1723 | 1419 | ||
@@ -1796,92 +1492,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1796 | 1492 | ||
1797 | /*********/ | 1493 | /*********/ |
1798 | 1494 | ||
1799 | static int | ||
1800 | client_input_stdout_data(int type, u_int32_t seq, void *ctxt) | ||
1801 | { | ||
1802 | u_int data_len; | ||
1803 | char *data = packet_get_string(&data_len); | ||
1804 | packet_check_eom(); | ||
1805 | buffer_append(&stdout_buffer, data, data_len); | ||
1806 | explicit_bzero(data, data_len); | ||
1807 | free(data); | ||
1808 | return 0; | ||
1809 | } | ||
1810 | static int | ||
1811 | client_input_stderr_data(int type, u_int32_t seq, void *ctxt) | ||
1812 | { | ||
1813 | u_int data_len; | ||
1814 | char *data = packet_get_string(&data_len); | ||
1815 | packet_check_eom(); | ||
1816 | buffer_append(&stderr_buffer, data, data_len); | ||
1817 | explicit_bzero(data, data_len); | ||
1818 | free(data); | ||
1819 | return 0; | ||
1820 | } | ||
1821 | static int | ||
1822 | client_input_exit_status(int type, u_int32_t seq, void *ctxt) | ||
1823 | { | ||
1824 | exit_status = packet_get_int(); | ||
1825 | packet_check_eom(); | ||
1826 | /* Acknowledge the exit. */ | ||
1827 | packet_start(SSH_CMSG_EXIT_CONFIRMATION); | ||
1828 | packet_send(); | ||
1829 | /* | ||
1830 | * Must wait for packet to be sent since we are | ||
1831 | * exiting the loop. | ||
1832 | */ | ||
1833 | packet_write_wait(); | ||
1834 | /* Flag that we want to exit. */ | ||
1835 | quit_pending = 1; | ||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | static int | ||
1840 | client_input_agent_open(int type, u_int32_t seq, void *ctxt) | ||
1841 | { | ||
1842 | Channel *c = NULL; | ||
1843 | int r, remote_id, sock; | ||
1844 | |||
1845 | /* Read the remote channel number from the message. */ | ||
1846 | remote_id = packet_get_int(); | ||
1847 | packet_check_eom(); | ||
1848 | |||
1849 | /* | ||
1850 | * Get a connection to the local authentication agent (this may again | ||
1851 | * get forwarded). | ||
1852 | */ | ||
1853 | if ((r = ssh_get_authentication_socket(&sock)) != 0 && | ||
1854 | r != SSH_ERR_AGENT_NOT_PRESENT) | ||
1855 | debug("%s: ssh_get_authentication_socket: %s", | ||
1856 | __func__, ssh_err(r)); | ||
1857 | |||
1858 | |||
1859 | /* | ||
1860 | * If we could not connect the agent, send an error message back to | ||
1861 | * the server. This should never happen unless the agent dies, | ||
1862 | * because authentication forwarding is only enabled if we have an | ||
1863 | * agent. | ||
1864 | */ | ||
1865 | if (sock >= 0) { | ||
1866 | c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, | ||
1867 | -1, 0, 0, 0, "authentication agent connection", 1); | ||
1868 | c->remote_id = remote_id; | ||
1869 | c->force_drain = 1; | ||
1870 | } | ||
1871 | if (c == NULL) { | ||
1872 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | ||
1873 | packet_put_int(remote_id); | ||
1874 | } else { | ||
1875 | /* Send a confirmation to the remote host. */ | ||
1876 | debug("Forwarding authentication connection."); | ||
1877 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | ||
1878 | packet_put_int(remote_id); | ||
1879 | packet_put_int(c->self); | ||
1880 | } | ||
1881 | packet_send(); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | static Channel * | 1495 | static Channel * |
1886 | client_request_forwarded_tcpip(const char *request_type, int rchan, | 1496 | client_request_forwarded_tcpip(const char *request_type, int rchan, |
1887 | u_int rwindow, u_int rmaxpack) | 1497 | u_int rwindow, u_int rmaxpack) |
@@ -2032,11 +1642,6 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | |||
2032 | if (tun_mode == SSH_TUNMODE_NO) | 1642 | if (tun_mode == SSH_TUNMODE_NO) |
2033 | return 0; | 1643 | return 0; |
2034 | 1644 | ||
2035 | if (!compat20) { | ||
2036 | error("Tunnel forwarding is not supported for protocol 1"); | ||
2037 | return -1; | ||
2038 | } | ||
2039 | |||
2040 | debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); | 1645 | debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); |
2041 | 1646 | ||
2042 | /* Open local tunnel device */ | 1647 | /* Open local tunnel device */ |
@@ -2687,7 +2292,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2687 | } | 2292 | } |
2688 | 2293 | ||
2689 | static void | 2294 | static void |
2690 | client_init_dispatch_20(void) | 2295 | client_init_dispatch(void) |
2691 | { | 2296 | { |
2692 | dispatch_init(&dispatch_protocol_error); | 2297 | dispatch_init(&dispatch_protocol_error); |
2693 | 2298 | ||
@@ -2712,45 +2317,6 @@ client_init_dispatch_20(void) | |||
2712 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); | 2317 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); |
2713 | } | 2318 | } |
2714 | 2319 | ||
2715 | static void | ||
2716 | client_init_dispatch_13(void) | ||
2717 | { | ||
2718 | dispatch_init(NULL); | ||
2719 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); | ||
2720 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); | ||
2721 | dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); | ||
2722 | dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); | ||
2723 | dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); | ||
2724 | dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); | ||
2725 | dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status); | ||
2726 | dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data); | ||
2727 | dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data); | ||
2728 | |||
2729 | dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ? | ||
2730 | &client_input_agent_open : &deny_input_open); | ||
2731 | dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? | ||
2732 | &x11_input_open : &deny_input_open); | ||
2733 | } | ||
2734 | |||
2735 | static void | ||
2736 | client_init_dispatch_15(void) | ||
2737 | { | ||
2738 | client_init_dispatch_13(); | ||
2739 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); | ||
2740 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); | ||
2741 | } | ||
2742 | |||
2743 | static void | ||
2744 | client_init_dispatch(void) | ||
2745 | { | ||
2746 | if (compat20) | ||
2747 | client_init_dispatch_20(); | ||
2748 | else if (compat13) | ||
2749 | client_init_dispatch_13(); | ||
2750 | else | ||
2751 | client_init_dispatch_15(); | ||
2752 | } | ||
2753 | |||
2754 | void | 2320 | void |
2755 | client_stop_mux(void) | 2321 | client_stop_mux(void) |
2756 | { | 2322 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: compat.c,v 1.102 2017/04/30 23:11:45 djm Exp $ */ | 1 | /* $OpenBSD: compat.c,v 1.103 2017/04/30 23:13:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -39,24 +39,8 @@ | |||
39 | #include "match.h" | 39 | #include "match.h" |
40 | #include "kex.h" | 40 | #include "kex.h" |
41 | 41 | ||
42 | int compat13 = 0; | ||
43 | int compat20 = 0; | ||
44 | int datafellows = 0; | 42 | int datafellows = 0; |
45 | 43 | ||
46 | void | ||
47 | enable_compat20(void) | ||
48 | { | ||
49 | if (compat20) | ||
50 | return; | ||
51 | debug("Enabling compatibility mode for protocol 2.0"); | ||
52 | compat20 = 1; | ||
53 | } | ||
54 | void | ||
55 | enable_compat13(void) | ||
56 | { | ||
57 | debug("Enabling compatibility mode for protocol 1.3"); | ||
58 | compat13 = 1; | ||
59 | } | ||
60 | /* datafellows bug compatibility */ | 44 | /* datafellows bug compatibility */ |
61 | u_int | 45 | u_int |
62 | compat_datafellows(const char *version) | 46 | compat_datafellows(const char *version) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */ | 1 | /* $OpenBSD: compat.h,v 1.49 2017/04/30 23:13:25 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. |
@@ -63,15 +63,11 @@ | |||
63 | #define SSH_BUG_HOSTKEYS 0x20000000 | 63 | #define SSH_BUG_HOSTKEYS 0x20000000 |
64 | #define SSH_BUG_DHGEX_LARGE 0x40000000 | 64 | #define SSH_BUG_DHGEX_LARGE 0x40000000 |
65 | 65 | ||
66 | void enable_compat13(void); | ||
67 | void enable_compat20(void); | ||
68 | u_int compat_datafellows(const char *); | 66 | u_int compat_datafellows(const char *); |
69 | int proto_spec(const char *); | 67 | int proto_spec(const char *); |
70 | char *compat_cipher_proposal(char *); | 68 | char *compat_cipher_proposal(char *); |
71 | char *compat_pkalg_proposal(char *); | 69 | char *compat_pkalg_proposal(char *); |
72 | char *compat_kex_proposal(char *); | 70 | char *compat_kex_proposal(char *); |
73 | 71 | ||
74 | extern int compat13; | ||
75 | extern int compat20; | ||
76 | extern int datafellows; | 72 | extern int datafellows; |
77 | #endif | 73 | #endif |
diff --git a/dispatch.c b/dispatch.c index aac933e0a..fa4152a44 100644 --- a/dispatch.c +++ b/dispatch.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */ | 1 | /* $OpenBSD: dispatch.c,v 1.28 2017/04/30 23:13:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -45,8 +45,6 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx) | |||
45 | int r; | 45 | int r; |
46 | 46 | ||
47 | logit("dispatch_protocol_error: type %d seq %u", type, seq); | 47 | logit("dispatch_protocol_error: type %d seq %u", type, seq); |
48 | if (!compat20) | ||
49 | fatal("protocol error"); | ||
50 | if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || | 48 | if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || |
51 | (r = sshpkt_put_u32(ssh, seq)) != 0 || | 49 | (r = sshpkt_put_u32(ssh, seq)) != 0 || |
52 | (r = sshpkt_send(ssh)) != 0 || | 50 | (r = sshpkt_send(ssh)) != 0 || |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */ | 1 | /* $OpenBSD: nchan.c,v 1.64 2017/04/30 23:13:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -74,9 +74,6 @@ | |||
74 | /* | 74 | /* |
75 | * ACTIONS: should never update the channel states | 75 | * ACTIONS: should never update the channel states |
76 | */ | 76 | */ |
77 | static void chan_send_ieof1(Channel *); | ||
78 | static void chan_send_oclose1(Channel *); | ||
79 | static void chan_send_close2(Channel *); | ||
80 | static void chan_send_eof2(Channel *); | 77 | static void chan_send_eof2(Channel *); |
81 | static void chan_send_eow2(Channel *); | 78 | static void chan_send_eow2(Channel *); |
82 | 79 | ||
@@ -96,6 +93,7 @@ chan_set_istate(Channel *c, u_int next) | |||
96 | istates[next]); | 93 | istates[next]); |
97 | c->istate = next; | 94 | c->istate = next; |
98 | } | 95 | } |
96 | |||
99 | static void | 97 | static void |
100 | chan_set_ostate(Channel *c, u_int next) | 98 | chan_set_ostate(Channel *c, u_int next) |
101 | { | 99 | { |
@@ -106,34 +104,6 @@ chan_set_ostate(Channel *c, u_int next) | |||
106 | c->ostate = next; | 104 | c->ostate = next; |
107 | } | 105 | } |
108 | 106 | ||
109 | /* | ||
110 | * SSH1 specific implementation of event functions | ||
111 | */ | ||
112 | |||
113 | static void | ||
114 | chan_rcvd_oclose1(Channel *c) | ||
115 | { | ||
116 | debug2("channel %d: rcvd oclose", c->self); | ||
117 | switch (c->istate) { | ||
118 | case CHAN_INPUT_WAIT_OCLOSE: | ||
119 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
120 | break; | ||
121 | case CHAN_INPUT_OPEN: | ||
122 | chan_shutdown_read(c); | ||
123 | chan_send_ieof1(c); | ||
124 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
125 | break; | ||
126 | case CHAN_INPUT_WAIT_DRAIN: | ||
127 | /* both local read_failed and remote write_failed */ | ||
128 | chan_send_ieof1(c); | ||
129 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
130 | break; | ||
131 | default: | ||
132 | error("channel %d: protocol error: rcvd_oclose for istate %d", | ||
133 | c->self, c->istate); | ||
134 | return; | ||
135 | } | ||
136 | } | ||
137 | void | 107 | void |
138 | chan_read_failed(Channel *c) | 108 | chan_read_failed(Channel *c) |
139 | { | 109 | { |
@@ -149,6 +119,7 @@ chan_read_failed(Channel *c) | |||
149 | break; | 119 | break; |
150 | } | 120 | } |
151 | } | 121 | } |
122 | |||
152 | void | 123 | void |
153 | chan_ibuf_empty(Channel *c) | 124 | chan_ibuf_empty(Channel *c) |
154 | { | 125 | { |
@@ -160,14 +131,9 @@ chan_ibuf_empty(Channel *c) | |||
160 | } | 131 | } |
161 | switch (c->istate) { | 132 | switch (c->istate) { |
162 | case CHAN_INPUT_WAIT_DRAIN: | 133 | case CHAN_INPUT_WAIT_DRAIN: |
163 | if (compat20) { | 134 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) |
164 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) | 135 | chan_send_eof2(c); |
165 | chan_send_eof2(c); | 136 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
166 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
167 | } else { | ||
168 | chan_send_ieof1(c); | ||
169 | chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); | ||
170 | } | ||
171 | break; | 137 | break; |
172 | default: | 138 | default: |
173 | error("channel %d: chan_ibuf_empty for istate %d", | 139 | error("channel %d: chan_ibuf_empty for istate %d", |
@@ -175,44 +141,7 @@ chan_ibuf_empty(Channel *c) | |||
175 | break; | 141 | break; |
176 | } | 142 | } |
177 | } | 143 | } |
178 | static void | 144 | |
179 | chan_rcvd_ieof1(Channel *c) | ||
180 | { | ||
181 | debug2("channel %d: rcvd ieof", c->self); | ||
182 | switch (c->ostate) { | ||
183 | case CHAN_OUTPUT_OPEN: | ||
184 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
185 | break; | ||
186 | case CHAN_OUTPUT_WAIT_IEOF: | ||
187 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
188 | break; | ||
189 | default: | ||
190 | error("channel %d: protocol error: rcvd_ieof for ostate %d", | ||
191 | c->self, c->ostate); | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | static void | ||
196 | chan_write_failed1(Channel *c) | ||
197 | { | ||
198 | debug2("channel %d: write failed", c->self); | ||
199 | switch (c->ostate) { | ||
200 | case CHAN_OUTPUT_OPEN: | ||
201 | chan_shutdown_write(c); | ||
202 | chan_send_oclose1(c); | ||
203 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); | ||
204 | break; | ||
205 | case CHAN_OUTPUT_WAIT_DRAIN: | ||
206 | chan_shutdown_write(c); | ||
207 | chan_send_oclose1(c); | ||
208 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
209 | break; | ||
210 | default: | ||
211 | error("channel %d: chan_write_failed for ostate %d", | ||
212 | c->self, c->ostate); | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | void | 145 | void |
217 | chan_obuf_empty(Channel *c) | 146 | chan_obuf_empty(Channel *c) |
218 | { | 147 | { |
@@ -225,8 +154,6 @@ chan_obuf_empty(Channel *c) | |||
225 | switch (c->ostate) { | 154 | switch (c->ostate) { |
226 | case CHAN_OUTPUT_WAIT_DRAIN: | 155 | case CHAN_OUTPUT_WAIT_DRAIN: |
227 | chan_shutdown_write(c); | 156 | chan_shutdown_write(c); |
228 | if (!compat20) | ||
229 | chan_send_oclose1(c); | ||
230 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 157 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
231 | break; | 158 | break; |
232 | default: | 159 | default: |
@@ -235,82 +162,6 @@ chan_obuf_empty(Channel *c) | |||
235 | break; | 162 | break; |
236 | } | 163 | } |
237 | } | 164 | } |
238 | static void | ||
239 | chan_send_ieof1(Channel *c) | ||
240 | { | ||
241 | debug2("channel %d: send ieof", c->self); | ||
242 | switch (c->istate) { | ||
243 | case CHAN_INPUT_OPEN: | ||
244 | case CHAN_INPUT_WAIT_DRAIN: | ||
245 | packet_start(SSH_MSG_CHANNEL_INPUT_EOF); | ||
246 | packet_put_int(c->remote_id); | ||
247 | packet_send(); | ||
248 | break; | ||
249 | default: | ||
250 | error("channel %d: cannot send ieof for istate %d", | ||
251 | c->self, c->istate); | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | static void | ||
256 | chan_send_oclose1(Channel *c) | ||
257 | { | ||
258 | debug2("channel %d: send oclose", c->self); | ||
259 | switch (c->ostate) { | ||
260 | case CHAN_OUTPUT_OPEN: | ||
261 | case CHAN_OUTPUT_WAIT_DRAIN: | ||
262 | buffer_clear(&c->output); | ||
263 | packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); | ||
264 | packet_put_int(c->remote_id); | ||
265 | packet_send(); | ||
266 | break; | ||
267 | default: | ||
268 | error("channel %d: cannot send oclose for ostate %d", | ||
269 | c->self, c->ostate); | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * the same for SSH2 | ||
276 | */ | ||
277 | static void | ||
278 | chan_rcvd_close2(Channel *c) | ||
279 | { | ||
280 | debug2("channel %d: rcvd close", c->self); | ||
281 | if (!(c->flags & CHAN_LOCAL)) { | ||
282 | if (c->flags & CHAN_CLOSE_RCVD) | ||
283 | error("channel %d: protocol error: close rcvd twice", | ||
284 | c->self); | ||
285 | c->flags |= CHAN_CLOSE_RCVD; | ||
286 | } | ||
287 | if (c->type == SSH_CHANNEL_LARVAL) { | ||
288 | /* tear down larval channels immediately */ | ||
289 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
290 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
291 | return; | ||
292 | } | ||
293 | switch (c->ostate) { | ||
294 | case CHAN_OUTPUT_OPEN: | ||
295 | /* | ||
296 | * wait until a data from the channel is consumed if a CLOSE | ||
297 | * is received | ||
298 | */ | ||
299 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
300 | break; | ||
301 | } | ||
302 | switch (c->istate) { | ||
303 | case CHAN_INPUT_OPEN: | ||
304 | chan_shutdown_read(c); | ||
305 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
306 | break; | ||
307 | case CHAN_INPUT_WAIT_DRAIN: | ||
308 | if (!(c->flags & CHAN_LOCAL)) | ||
309 | chan_send_eof2(c); | ||
310 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | 165 | ||
315 | void | 166 | void |
316 | chan_rcvd_eow(Channel *c) | 167 | chan_rcvd_eow(Channel *c) |
@@ -323,32 +174,7 @@ chan_rcvd_eow(Channel *c) | |||
323 | break; | 174 | break; |
324 | } | 175 | } |
325 | } | 176 | } |
326 | static void | 177 | |
327 | chan_rcvd_eof2(Channel *c) | ||
328 | { | ||
329 | debug2("channel %d: rcvd eof", c->self); | ||
330 | c->flags |= CHAN_EOF_RCVD; | ||
331 | if (c->ostate == CHAN_OUTPUT_OPEN) | ||
332 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
333 | } | ||
334 | static void | ||
335 | chan_write_failed2(Channel *c) | ||
336 | { | ||
337 | debug2("channel %d: write failed", c->self); | ||
338 | switch (c->ostate) { | ||
339 | case CHAN_OUTPUT_OPEN: | ||
340 | case CHAN_OUTPUT_WAIT_DRAIN: | ||
341 | chan_shutdown_write(c); | ||
342 | if (strcmp(c->ctype, "session") == 0) | ||
343 | chan_send_eow2(c); | ||
344 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
345 | break; | ||
346 | default: | ||
347 | error("channel %d: chan_write_failed for ostate %d", | ||
348 | c->self, c->ostate); | ||
349 | break; | ||
350 | } | ||
351 | } | ||
352 | static void | 178 | static void |
353 | chan_send_eof2(Channel *c) | 179 | chan_send_eof2(Channel *c) |
354 | { | 180 | { |
@@ -366,6 +192,7 @@ chan_send_eof2(Channel *c) | |||
366 | break; | 192 | break; |
367 | } | 193 | } |
368 | } | 194 | } |
195 | |||
369 | static void | 196 | static void |
370 | chan_send_close2(Channel *c) | 197 | chan_send_close2(Channel *c) |
371 | { | 198 | { |
@@ -383,6 +210,7 @@ chan_send_close2(Channel *c) | |||
383 | c->flags |= CHAN_CLOSE_SENT; | 210 | c->flags |= CHAN_CLOSE_SENT; |
384 | } | 211 | } |
385 | } | 212 | } |
213 | |||
386 | static void | 214 | static void |
387 | chan_send_eow2(Channel *c) | 215 | chan_send_eow2(Channel *c) |
388 | { | 216 | { |
@@ -406,30 +234,71 @@ chan_send_eow2(Channel *c) | |||
406 | void | 234 | void |
407 | chan_rcvd_ieof(Channel *c) | 235 | chan_rcvd_ieof(Channel *c) |
408 | { | 236 | { |
409 | if (compat20) | 237 | debug2("channel %d: rcvd eof", c->self); |
410 | chan_rcvd_eof2(c); | 238 | c->flags |= CHAN_EOF_RCVD; |
411 | else | 239 | if (c->ostate == CHAN_OUTPUT_OPEN) |
412 | chan_rcvd_ieof1(c); | 240 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
413 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | 241 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && |
414 | buffer_len(&c->output) == 0 && | 242 | buffer_len(&c->output) == 0 && |
415 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | 243 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
416 | chan_obuf_empty(c); | 244 | chan_obuf_empty(c); |
417 | } | 245 | } |
246 | |||
418 | void | 247 | void |
419 | chan_rcvd_oclose(Channel *c) | 248 | chan_rcvd_oclose(Channel *c) |
420 | { | 249 | { |
421 | if (compat20) | 250 | debug2("channel %d: rcvd close", c->self); |
422 | chan_rcvd_close2(c); | 251 | if (!(c->flags & CHAN_LOCAL)) { |
423 | else | 252 | if (c->flags & CHAN_CLOSE_RCVD) |
424 | chan_rcvd_oclose1(c); | 253 | error("channel %d: protocol error: close rcvd twice", |
254 | c->self); | ||
255 | c->flags |= CHAN_CLOSE_RCVD; | ||
256 | } | ||
257 | if (c->type == SSH_CHANNEL_LARVAL) { | ||
258 | /* tear down larval channels immediately */ | ||
259 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
260 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
261 | return; | ||
262 | } | ||
263 | switch (c->ostate) { | ||
264 | case CHAN_OUTPUT_OPEN: | ||
265 | /* | ||
266 | * wait until a data from the channel is consumed if a CLOSE | ||
267 | * is received | ||
268 | */ | ||
269 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
270 | break; | ||
271 | } | ||
272 | switch (c->istate) { | ||
273 | case CHAN_INPUT_OPEN: | ||
274 | chan_shutdown_read(c); | ||
275 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
276 | break; | ||
277 | case CHAN_INPUT_WAIT_DRAIN: | ||
278 | if (!(c->flags & CHAN_LOCAL)) | ||
279 | chan_send_eof2(c); | ||
280 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
281 | break; | ||
282 | } | ||
425 | } | 283 | } |
284 | |||
426 | void | 285 | void |
427 | chan_write_failed(Channel *c) | 286 | chan_write_failed(Channel *c) |
428 | { | 287 | { |
429 | if (compat20) | 288 | debug2("channel %d: write failed", c->self); |
430 | chan_write_failed2(c); | 289 | switch (c->ostate) { |
431 | else | 290 | case CHAN_OUTPUT_OPEN: |
432 | chan_write_failed1(c); | 291 | case CHAN_OUTPUT_WAIT_DRAIN: |
292 | chan_shutdown_write(c); | ||
293 | if (strcmp(c->ctype, "session") == 0) | ||
294 | chan_send_eow2(c); | ||
295 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
296 | break; | ||
297 | default: | ||
298 | error("channel %d: chan_write_failed for ostate %d", | ||
299 | c->self, c->ostate); | ||
300 | break; | ||
301 | } | ||
433 | } | 302 | } |
434 | 303 | ||
435 | void | 304 | void |
@@ -447,10 +316,6 @@ chan_is_dead(Channel *c, int do_send) | |||
447 | } | 316 | } |
448 | if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) | 317 | if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) |
449 | return 0; | 318 | return 0; |
450 | if (!compat20) { | ||
451 | debug2("channel %d: is dead", c->self); | ||
452 | return 1; | ||
453 | } | ||
454 | if ((datafellows & SSH_BUG_EXTEOF) && | 319 | if ((datafellows & SSH_BUG_EXTEOF) && |
455 | c->extended_usage == CHAN_EXTENDED_WRITE && | 320 | c->extended_usage == CHAN_EXTENDED_WRITE && |
456 | c->efd != -1 && | 321 | c->efd != -1 && |
@@ -488,7 +353,7 @@ static void | |||
488 | chan_shutdown_write(Channel *c) | 353 | chan_shutdown_write(Channel *c) |
489 | { | 354 | { |
490 | buffer_clear(&c->output); | 355 | buffer_clear(&c->output); |
491 | if (compat20 && c->type == SSH_CHANNEL_LARVAL) | 356 | if (c->type == SSH_CHANNEL_LARVAL) |
492 | return; | 357 | return; |
493 | /* shutdown failure is allowed if write failed already */ | 358 | /* shutdown failure is allowed if write failed already */ |
494 | debug2("channel %d: close_write", c->self); | 359 | debug2("channel %d: close_write", c->self); |
@@ -504,10 +369,11 @@ chan_shutdown_write(Channel *c) | |||
504 | c->self, c->wfd, strerror(errno)); | 369 | c->self, c->wfd, strerror(errno)); |
505 | } | 370 | } |
506 | } | 371 | } |
372 | |||
507 | static void | 373 | static void |
508 | chan_shutdown_read(Channel *c) | 374 | chan_shutdown_read(Channel *c) |
509 | { | 375 | { |
510 | if (compat20 && c->type == SSH_CHANNEL_LARVAL) | 376 | if (c->type == SSH_CHANNEL_LARVAL) |
511 | return; | 377 | return; |
512 | debug2("channel %d: close_read", c->self); | 378 | debug2("channel %d: close_read", c->self); |
513 | if (c->sock != -1) { | 379 | if (c->sock != -1) { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.248 2017/04/30 23:10:43 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.249 2017/04/30 23:13:25 djm 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 |
@@ -278,8 +278,8 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) | |||
278 | int | 278 | int |
279 | ssh_packet_is_rekeying(struct ssh *ssh) | 279 | ssh_packet_is_rekeying(struct ssh *ssh) |
280 | { | 280 | { |
281 | return compat20 && | 281 | return ssh->state->rekeying || |
282 | (ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0)); | 282 | (ssh->kex != NULL && ssh->kex->done == 0); |
283 | } | 283 | } |
284 | 284 | ||
285 | /* | 285 | /* |
@@ -698,7 +698,7 @@ ssh_packet_start_compression(struct ssh *ssh, int level) | |||
698 | { | 698 | { |
699 | int r; | 699 | int r; |
700 | 700 | ||
701 | if (ssh->state->packet_compression && !compat20) | 701 | if (ssh->state->packet_compression) |
702 | return SSH_ERR_INTERNAL_ERROR; | 702 | return SSH_ERR_INTERNAL_ERROR; |
703 | ssh->state->packet_compression = 1; | 703 | ssh->state->packet_compression = 1; |
704 | if ((r = ssh_packet_init_compression(ssh)) != 0 || | 704 | if ((r = ssh_packet_init_compression(ssh)) != 0 || |
@@ -814,99 +814,6 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, | |||
814 | fatal("no SSH protocol 1 support"); | 814 | fatal("no SSH protocol 1 support"); |
815 | } | 815 | } |
816 | 816 | ||
817 | /* | ||
818 | * Finalizes and sends the packet. If the encryption key has been set, | ||
819 | * encrypts the packet before sending. | ||
820 | */ | ||
821 | |||
822 | int | ||
823 | ssh_packet_send1(struct ssh *ssh) | ||
824 | { | ||
825 | struct session_state *state = ssh->state; | ||
826 | u_char buf[8], *cp; | ||
827 | int r, padding, len; | ||
828 | u_int checksum; | ||
829 | |||
830 | /* | ||
831 | * If using packet compression, compress the payload of the outgoing | ||
832 | * packet. | ||
833 | */ | ||
834 | if (state->packet_compression) { | ||
835 | sshbuf_reset(state->compression_buffer); | ||
836 | /* Skip padding. */ | ||
837 | if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0) | ||
838 | goto out; | ||
839 | /* padding */ | ||
840 | if ((r = sshbuf_put(state->compression_buffer, | ||
841 | "\0\0\0\0\0\0\0\0", 8)) != 0) | ||
842 | goto out; | ||
843 | if ((r = compress_buffer(ssh, state->outgoing_packet, | ||
844 | state->compression_buffer)) != 0) | ||
845 | goto out; | ||
846 | sshbuf_reset(state->outgoing_packet); | ||
847 | if ((r = sshbuf_putb(state->outgoing_packet, | ||
848 | state->compression_buffer)) != 0) | ||
849 | goto out; | ||
850 | } | ||
851 | /* Compute packet length without padding (add checksum, remove padding). */ | ||
852 | len = sshbuf_len(state->outgoing_packet) + 4 - 8; | ||
853 | |||
854 | /* Insert padding. Initialized to zero in packet_start1() */ | ||
855 | padding = 8 - len % 8; | ||
856 | if (!cipher_ctx_is_plaintext(state->send_context)) { | ||
857 | cp = sshbuf_mutable_ptr(state->outgoing_packet); | ||
858 | if (cp == NULL) { | ||
859 | r = SSH_ERR_INTERNAL_ERROR; | ||
860 | goto out; | ||
861 | } | ||
862 | arc4random_buf(cp + 8 - padding, padding); | ||
863 | } | ||
864 | if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0) | ||
865 | goto out; | ||
866 | |||
867 | /* Add check bytes. */ | ||
868 | checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet), | ||
869 | sshbuf_len(state->outgoing_packet)); | ||
870 | POKE_U32(buf, checksum); | ||
871 | if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0) | ||
872 | goto out; | ||
873 | |||
874 | #ifdef PACKET_DEBUG | ||
875 | fprintf(stderr, "packet_send plain: "); | ||
876 | sshbuf_dump(state->outgoing_packet, stderr); | ||
877 | #endif | ||
878 | |||
879 | /* Append to output. */ | ||
880 | POKE_U32(buf, len); | ||
881 | if ((r = sshbuf_put(state->output, buf, 4)) != 0) | ||
882 | goto out; | ||
883 | if ((r = sshbuf_reserve(state->output, | ||
884 | sshbuf_len(state->outgoing_packet), &cp)) != 0) | ||
885 | goto out; | ||
886 | if ((r = cipher_crypt(state->send_context, 0, cp, | ||
887 | sshbuf_ptr(state->outgoing_packet), | ||
888 | sshbuf_len(state->outgoing_packet), 0, 0)) != 0) | ||
889 | goto out; | ||
890 | |||
891 | #ifdef PACKET_DEBUG | ||
892 | fprintf(stderr, "encrypted: "); | ||
893 | sshbuf_dump(state->output, stderr); | ||
894 | #endif | ||
895 | state->p_send.packets++; | ||
896 | state->p_send.bytes += len + | ||
897 | sshbuf_len(state->outgoing_packet); | ||
898 | sshbuf_reset(state->outgoing_packet); | ||
899 | |||
900 | /* | ||
901 | * Note that the packet is now only buffered in output. It won't be | ||
902 | * actually sent until ssh_packet_write_wait or ssh_packet_write_poll | ||
903 | * is called. | ||
904 | */ | ||
905 | r = 0; | ||
906 | out: | ||
907 | return r; | ||
908 | } | ||
909 | |||
910 | int | 817 | int |
911 | ssh_set_newkeys(struct ssh *ssh, int mode) | 818 | ssh_set_newkeys(struct ssh *ssh, int mode) |
912 | { | 819 | { |
@@ -1397,13 +1304,6 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1397 | r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); | 1304 | r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); |
1398 | if (r != 0) | 1305 | if (r != 0) |
1399 | break; | 1306 | break; |
1400 | if (!compat20 && ( | ||
1401 | *typep == SSH_SMSG_SUCCESS | ||
1402 | || *typep == SSH_SMSG_FAILURE | ||
1403 | || *typep == SSH_CMSG_EOF | ||
1404 | || *typep == SSH_CMSG_EXIT_CONFIRMATION)) | ||
1405 | if ((r = sshpkt_get_end(ssh)) != 0) | ||
1406 | break; | ||
1407 | /* If we got a packet, return it. */ | 1307 | /* If we got a packet, return it. */ |
1408 | if (*typep != SSH_MSG_NONE) | 1308 | if (*typep != SSH_MSG_NONE) |
1409 | break; | 1309 | break; |
@@ -1924,75 +1824,48 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1924 | 1824 | ||
1925 | for (;;) { | 1825 | for (;;) { |
1926 | msg = NULL; | 1826 | msg = NULL; |
1927 | if (compat20) { | 1827 | r = ssh_packet_read_poll2(ssh, typep, seqnr_p); |
1928 | r = ssh_packet_read_poll2(ssh, typep, seqnr_p); | 1828 | if (r != 0) |
1929 | if (r != 0) | 1829 | return r; |
1930 | return r; | 1830 | if (*typep) { |
1931 | if (*typep) { | 1831 | state->keep_alive_timeouts = 0; |
1932 | state->keep_alive_timeouts = 0; | 1832 | DBG(debug("received packet type %d", *typep)); |
1933 | DBG(debug("received packet type %d", *typep)); | 1833 | } |
1934 | } | 1834 | switch (*typep) { |
1935 | switch (*typep) { | 1835 | case SSH2_MSG_IGNORE: |
1936 | case SSH2_MSG_IGNORE: | 1836 | debug3("Received SSH2_MSG_IGNORE"); |
1937 | debug3("Received SSH2_MSG_IGNORE"); | 1837 | break; |
1938 | break; | 1838 | case SSH2_MSG_DEBUG: |
1939 | case SSH2_MSG_DEBUG: | 1839 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || |
1940 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || | 1840 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || |
1941 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || | 1841 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { |
1942 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { | ||
1943 | free(msg); | ||
1944 | return r; | ||
1945 | } | ||
1946 | debug("Remote: %.900s", msg); | ||
1947 | free(msg); | ||
1948 | break; | ||
1949 | case SSH2_MSG_DISCONNECT: | ||
1950 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || | ||
1951 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1952 | return r; | ||
1953 | /* Ignore normal client exit notifications */ | ||
1954 | do_log2(ssh->state->server_side && | ||
1955 | reason == SSH2_DISCONNECT_BY_APPLICATION ? | ||
1956 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | ||
1957 | "Received disconnect from %s port %d:" | ||
1958 | "%u: %.400s", ssh_remote_ipaddr(ssh), | ||
1959 | ssh_remote_port(ssh), reason, msg); | ||
1960 | free(msg); | ||
1961 | return SSH_ERR_DISCONNECTED; | ||
1962 | case SSH2_MSG_UNIMPLEMENTED: | ||
1963 | if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) | ||
1964 | return r; | ||
1965 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", | ||
1966 | seqnr); | ||
1967 | break; | ||
1968 | default: | ||
1969 | return 0; | ||
1970 | } | ||
1971 | } else { | ||
1972 | r = ssh_packet_read_poll1(ssh, typep); | ||
1973 | switch (*typep) { | ||
1974 | case SSH_MSG_NONE: | ||
1975 | return SSH_MSG_NONE; | ||
1976 | case SSH_MSG_IGNORE: | ||
1977 | break; | ||
1978 | case SSH_MSG_DEBUG: | ||
1979 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1980 | return r; | ||
1981 | debug("Remote: %.900s", msg); | ||
1982 | free(msg); | ||
1983 | break; | ||
1984 | case SSH_MSG_DISCONNECT: | ||
1985 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1986 | return r; | ||
1987 | error("Received disconnect from %s port %d: " | ||
1988 | "%.400s", ssh_remote_ipaddr(ssh), | ||
1989 | ssh_remote_port(ssh), msg); | ||
1990 | free(msg); | 1842 | free(msg); |
1991 | return SSH_ERR_DISCONNECTED; | 1843 | return r; |
1992 | default: | ||
1993 | DBG(debug("received packet type %d", *typep)); | ||
1994 | return 0; | ||
1995 | } | 1844 | } |
1845 | debug("Remote: %.900s", msg); | ||
1846 | free(msg); | ||
1847 | break; | ||
1848 | case SSH2_MSG_DISCONNECT: | ||
1849 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || | ||
1850 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) | ||
1851 | return r; | ||
1852 | /* Ignore normal client exit notifications */ | ||
1853 | do_log2(ssh->state->server_side && | ||
1854 | reason == SSH2_DISCONNECT_BY_APPLICATION ? | ||
1855 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | ||
1856 | "Received disconnect from %s port %d:" | ||
1857 | "%u: %.400s", ssh_remote_ipaddr(ssh), | ||
1858 | ssh_remote_port(ssh), reason, msg); | ||
1859 | free(msg); | ||
1860 | return SSH_ERR_DISCONNECTED; | ||
1861 | case SSH2_MSG_UNIMPLEMENTED: | ||
1862 | if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) | ||
1863 | return r; | ||
1864 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", | ||
1865 | seqnr); | ||
1866 | break; | ||
1867 | default: | ||
1868 | return 0; | ||
1996 | } | 1869 | } |
1997 | } | 1870 | } |
1998 | } | 1871 | } |
@@ -2044,27 +1917,19 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) | |||
2044 | va_list args; | 1917 | va_list args; |
2045 | int r; | 1918 | int r; |
2046 | 1919 | ||
2047 | if (compat20 && (ssh->compat & SSH_BUG_DEBUG)) | 1920 | if ((ssh->compat & SSH_BUG_DEBUG)) |
2048 | return; | 1921 | return; |
2049 | 1922 | ||
2050 | va_start(args, fmt); | 1923 | va_start(args, fmt); |
2051 | vsnprintf(buf, sizeof(buf), fmt, args); | 1924 | vsnprintf(buf, sizeof(buf), fmt, args); |
2052 | va_end(args); | 1925 | va_end(args); |
2053 | 1926 | ||
2054 | if (compat20) { | 1927 | if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
2055 | if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || | 1928 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
2056 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ | 1929 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
2057 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | 1930 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
2058 | (r = sshpkt_put_cstring(ssh, "")) != 0 || | 1931 | (r = sshpkt_send(ssh)) != 0 || |
2059 | (r = sshpkt_send(ssh)) != 0) | 1932 | (r = ssh_packet_write_wait(ssh)) != 0) |
2060 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2061 | } else { | ||
2062 | if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 || | ||
2063 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
2064 | (r = sshpkt_send(ssh)) != 0) | ||
2065 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2066 | } | ||
2067 | if ((r = ssh_packet_write_wait(ssh)) != 0) | ||
2068 | fatal("%s: %s", __func__, ssh_err(r)); | 1933 | fatal("%s: %s", __func__, ssh_err(r)); |
2069 | } | 1934 | } |
2070 | 1935 | ||
@@ -2385,8 +2250,7 @@ ssh_packet_send_ignore(struct ssh *ssh, int nbytes) | |||
2385 | u_int32_t rnd = 0; | 2250 | u_int32_t rnd = 0; |
2386 | int r, i; | 2251 | int r, i; |
2387 | 2252 | ||
2388 | if ((r = sshpkt_start(ssh, compat20 ? | 2253 | if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || |
2389 | SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 || | ||
2390 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | 2254 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) |
2391 | fatal("%s: %s", __func__, ssh_err(r)); | 2255 | fatal("%s: %s", __func__, ssh_err(r)); |
2392 | for (i = 0; i < nbytes; i++) { | 2256 | for (i = 0; i < nbytes; i++) { |
@@ -2531,38 +2395,22 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) | |||
2531 | struct session_state *state = ssh->state; | 2395 | struct session_state *state = ssh->state; |
2532 | u_char *p; | 2396 | u_char *p; |
2533 | size_t slen, rlen; | 2397 | size_t slen, rlen; |
2534 | int r, ssh1cipher; | 2398 | int r; |
2535 | 2399 | ||
2536 | if (!compat20) { | 2400 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || |
2537 | ssh1cipher = cipher_ctx_get_number(state->receive_context); | 2401 | (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || |
2538 | slen = cipher_get_keyiv_len(state->send_context); | 2402 | (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || |
2539 | rlen = cipher_get_keyiv_len(state->receive_context); | 2403 | (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || |
2540 | if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || | 2404 | (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || |
2541 | (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || | 2405 | (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || |
2542 | (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || | 2406 | (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || |
2543 | (r = sshbuf_put_u32(m, slen)) != 0 || | 2407 | (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || |
2544 | (r = sshbuf_reserve(m, slen, &p)) != 0 || | 2408 | (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || |
2545 | (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 || | 2409 | (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || |
2546 | (r = sshbuf_put_u32(m, rlen)) != 0 || | 2410 | (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || |
2547 | (r = sshbuf_reserve(m, rlen, &p)) != 0 || | 2411 | (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || |
2548 | (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0) | 2412 | (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) |
2549 | return r; | 2413 | return r; |
2550 | } else { | ||
2551 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || | ||
2552 | (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || | ||
2553 | (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || | ||
2554 | (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || | ||
2555 | (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || | ||
2556 | (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || | ||
2557 | (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || | ||
2558 | (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || | ||
2559 | (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || | ||
2560 | (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || | ||
2561 | (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || | ||
2562 | (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || | ||
2563 | (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) | ||
2564 | return r; | ||
2565 | } | ||
2566 | 2414 | ||
2567 | slen = cipher_get_keycontext(state->send_context, NULL); | 2415 | slen = cipher_get_keycontext(state->send_context, NULL); |
2568 | rlen = cipher_get_keycontext(state->receive_context, NULL); | 2416 | rlen = cipher_get_keycontext(state->receive_context, NULL); |
@@ -2701,53 +2549,34 @@ int | |||
2701 | ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) | 2549 | ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) |
2702 | { | 2550 | { |
2703 | struct session_state *state = ssh->state; | 2551 | struct session_state *state = ssh->state; |
2704 | const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output; | 2552 | const u_char *keyin, *keyout, *input, *output; |
2705 | size_t ssh1keylen, rlen, slen, ilen, olen; | 2553 | size_t rlen, slen, ilen, olen; |
2706 | int r; | 2554 | int r; |
2707 | u_int ssh1cipher = 0; | 2555 | |
2708 | 2556 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | |
2709 | if (!compat20) { | 2557 | (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || |
2710 | if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || | 2558 | (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || |
2711 | (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 || | 2559 | (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || |
2712 | (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 || | 2560 | (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || |
2713 | (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 || | 2561 | (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || |
2714 | (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0) | 2562 | (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || |
2715 | return r; | 2563 | (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || |
2716 | if (ssh1cipher > INT_MAX) | 2564 | (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || |
2717 | return SSH_ERR_KEY_UNKNOWN_CIPHER; | 2565 | (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || |
2718 | ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, | 2566 | (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || |
2719 | (int)ssh1cipher); | 2567 | (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || |
2720 | if (cipher_get_keyiv_len(state->send_context) != (int)slen || | 2568 | (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) |
2721 | cipher_get_keyiv_len(state->receive_context) != (int)rlen) | 2569 | return r; |
2722 | return SSH_ERR_INVALID_FORMAT; | 2570 | /* |
2723 | if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 || | 2571 | * We set the time here so that in post-auth privsep slave we |
2724 | (r = cipher_set_keyiv(state->receive_context, ivin)) != 0) | 2572 | * count from the completion of the authentication. |
2725 | return r; | 2573 | */ |
2726 | } else { | 2574 | state->rekey_time = monotime(); |
2727 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | 2575 | /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ |
2728 | (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || | 2576 | if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || |
2729 | (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || | 2577 | (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) |
2730 | (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || | 2578 | return r; |
2731 | (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || | 2579 | |
2732 | (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || | ||
2733 | (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || | ||
2734 | (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || | ||
2735 | (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || | ||
2736 | (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || | ||
2737 | (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || | ||
2738 | (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || | ||
2739 | (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) | ||
2740 | return r; | ||
2741 | /* | ||
2742 | * We set the time here so that in post-auth privsep slave we | ||
2743 | * count from the completion of the authentication. | ||
2744 | */ | ||
2745 | state->rekey_time = monotime(); | ||
2746 | /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ | ||
2747 | if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || | ||
2748 | (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) | ||
2749 | return r; | ||
2750 | } | ||
2751 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || | 2580 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || |
2752 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) | 2581 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) |
2753 | return r; | 2582 | return r; |
@@ -2925,15 +2754,13 @@ sshpkt_ptr(struct ssh *ssh, size_t *lenp) | |||
2925 | int | 2754 | int |
2926 | sshpkt_start(struct ssh *ssh, u_char type) | 2755 | sshpkt_start(struct ssh *ssh, u_char type) |
2927 | { | 2756 | { |
2928 | u_char buf[9]; | 2757 | u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */ |
2929 | int len; | ||
2930 | 2758 | ||
2931 | DBG(debug("packet_start[%d]", type)); | 2759 | DBG(debug("packet_start[%d]", type)); |
2932 | len = compat20 ? 6 : 9; | 2760 | memset(buf, 0, sizeof(buf)); |
2933 | memset(buf, 0, len - 1); | 2761 | buf[sizeof(buf) - 1] = type; |
2934 | buf[len - 1] = type; | ||
2935 | sshbuf_reset(ssh->state->outgoing_packet); | 2762 | sshbuf_reset(ssh->state->outgoing_packet); |
2936 | return sshbuf_put(ssh->state->outgoing_packet, buf, len); | 2763 | return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf)); |
2937 | } | 2764 | } |
2938 | 2765 | ||
2939 | static int | 2766 | static int |
@@ -2973,10 +2800,7 @@ sshpkt_send(struct ssh *ssh) | |||
2973 | { | 2800 | { |
2974 | if (ssh->state && ssh->state->mux) | 2801 | if (ssh->state && ssh->state->mux) |
2975 | return ssh_packet_send_mux(ssh); | 2802 | return ssh_packet_send_mux(ssh); |
2976 | if (compat20) | 2803 | return ssh_packet_send2(ssh); |
2977 | return ssh_packet_send2(ssh); | ||
2978 | else | ||
2979 | return ssh_packet_send1(ssh); | ||
2980 | } | 2804 | } |
2981 | 2805 | ||
2982 | int | 2806 | int |
@@ -2990,19 +2814,12 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) | |||
2990 | vsnprintf(buf, sizeof(buf), fmt, args); | 2814 | vsnprintf(buf, sizeof(buf), fmt, args); |
2991 | va_end(args); | 2815 | va_end(args); |
2992 | 2816 | ||
2993 | if (compat20) { | 2817 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || |
2994 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || | 2818 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || |
2995 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || | 2819 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
2996 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | 2820 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
2997 | (r = sshpkt_put_cstring(ssh, "")) != 0 || | 2821 | (r = sshpkt_send(ssh)) != 0) |
2998 | (r = sshpkt_send(ssh)) != 0) | 2822 | return r; |
2999 | return r; | ||
3000 | } else { | ||
3001 | if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 || | ||
3002 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
3003 | (r = sshpkt_send(ssh)) != 0) | ||
3004 | return r; | ||
3005 | } | ||
3006 | return 0; | 2823 | return 0; |
3007 | } | 2824 | } |
3008 | 2825 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.h,v 1.76 2017/02/03 23:03:33 djm Exp $ */ | 1 | /* $OpenBSD: packet.h,v 1.77 2017/04/30 23:13:25 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -112,7 +112,6 @@ int ssh_packet_set_log_preamble(struct ssh *, const char *, ...) | |||
112 | 112 | ||
113 | int ssh_packet_log_type(u_char); | 113 | int ssh_packet_log_type(u_char); |
114 | 114 | ||
115 | int ssh_packet_send1(struct ssh *); | ||
116 | int ssh_packet_send2_wrapped(struct ssh *); | 115 | int ssh_packet_send2_wrapped(struct ssh *); |
117 | int ssh_packet_send2(struct ssh *); | 116 | int ssh_packet_send2(struct ssh *); |
118 | 117 | ||
diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 3231ee342..6a9292487 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keyscan.c,v 1.110 2017/04/30 23:10:43 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keyscan.c,v 1.111 2017/04/30 23:13:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. | 3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. |
4 | * | 4 | * |
@@ -221,7 +221,6 @@ keygrab_ssh2(con *c) | |||
221 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; | 221 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; |
222 | int r; | 222 | int r; |
223 | 223 | ||
224 | enable_compat20(); | ||
225 | switch (c->c_keytype) { | 224 | switch (c->c_keytype) { |
226 | case KT_DSA: | 225 | case KT_DSA: |
227 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? | 226 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.454 2017/04/30 23:11:45 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.455 2017/04/30 23:13:25 djm 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,7 +209,6 @@ usage(void) | |||
209 | exit(255); | 209 | exit(255); |
210 | } | 210 | } |
211 | 211 | ||
212 | static int ssh_session(void); | ||
213 | static int ssh_session2(void); | 212 | static int ssh_session2(void); |
214 | static void load_public_identity_files(void); | 213 | static void load_public_identity_files(void); |
215 | static void main_sigchld_handler(int); | 214 | static void main_sigchld_handler(int); |
@@ -1243,7 +1242,6 @@ main(int ac, char **av) | |||
1243 | if ((sock = muxclient(options.control_path)) >= 0) { | 1242 | if ((sock = muxclient(options.control_path)) >= 0) { |
1244 | packet_set_connection(sock, sock); | 1243 | packet_set_connection(sock, sock); |
1245 | ssh = active_state; /* XXX */ | 1244 | ssh = active_state; /* XXX */ |
1246 | enable_compat20(); /* XXX */ | ||
1247 | packet_set_mux(); | 1245 | packet_set_mux(); |
1248 | goto skip_connect; | 1246 | goto skip_connect; |
1249 | } | 1247 | } |
@@ -1447,7 +1445,7 @@ main(int ac, char **av) | |||
1447 | } | 1445 | } |
1448 | 1446 | ||
1449 | skip_connect: | 1447 | skip_connect: |
1450 | exit_status = compat20 ? ssh_session2() : ssh_session(); | 1448 | exit_status = ssh_session2(); |
1451 | packet_close(); | 1449 | packet_close(); |
1452 | 1450 | ||
1453 | if (options.control_path != NULL && muxserver_sock != -1) | 1451 | if (options.control_path != NULL && muxserver_sock != -1) |
@@ -1591,8 +1589,6 @@ ssh_init_stdio_forwarding(void) | |||
1591 | 1589 | ||
1592 | if (options.stdio_forward_host == NULL) | 1590 | if (options.stdio_forward_host == NULL) |
1593 | return; | 1591 | return; |
1594 | if (!compat20) | ||
1595 | fatal("stdio forwarding require Protocol 2"); | ||
1596 | 1592 | ||
1597 | debug3("%s: %s:%d", __func__, options.stdio_forward_host, | 1593 | debug3("%s: %s:%d", __func__, options.stdio_forward_host, |
1598 | options.stdio_forward_port); | 1594 | options.stdio_forward_port); |
@@ -1691,172 +1687,6 @@ check_agent_present(void) | |||
1691 | } | 1687 | } |
1692 | } | 1688 | } |
1693 | 1689 | ||
1694 | static int | ||
1695 | ssh_session(void) | ||
1696 | { | ||
1697 | int type; | ||
1698 | int interactive = 0; | ||
1699 | int have_tty = 0; | ||
1700 | struct winsize ws; | ||
1701 | char *cp; | ||
1702 | const char *display; | ||
1703 | char *proto = NULL, *data = NULL; | ||
1704 | |||
1705 | /* Enable compression if requested. */ | ||
1706 | if (options.compression) { | ||
1707 | debug("Requesting compression at level %d.", | ||
1708 | options.compression_level); | ||
1709 | |||
1710 | if (options.compression_level < 1 || | ||
1711 | options.compression_level > 9) | ||
1712 | fatal("Compression level must be from 1 (fast) to " | ||
1713 | "9 (slow, best)."); | ||
1714 | |||
1715 | /* Send the request. */ | ||
1716 | packet_start(SSH_CMSG_REQUEST_COMPRESSION); | ||
1717 | packet_put_int(options.compression_level); | ||
1718 | packet_send(); | ||
1719 | packet_write_wait(); | ||
1720 | type = packet_read(); | ||
1721 | if (type == SSH_SMSG_SUCCESS) | ||
1722 | packet_start_compression(options.compression_level); | ||
1723 | else if (type == SSH_SMSG_FAILURE) | ||
1724 | logit("Warning: Remote host refused compression."); | ||
1725 | else | ||
1726 | packet_disconnect("Protocol error waiting for " | ||
1727 | "compression response."); | ||
1728 | } | ||
1729 | /* Allocate a pseudo tty if appropriate. */ | ||
1730 | if (tty_flag) { | ||
1731 | debug("Requesting pty."); | ||
1732 | |||
1733 | /* Start the packet. */ | ||
1734 | packet_start(SSH_CMSG_REQUEST_PTY); | ||
1735 | |||
1736 | /* Store TERM in the packet. There is no limit on the | ||
1737 | length of the string. */ | ||
1738 | cp = getenv("TERM"); | ||
1739 | if (!cp) | ||
1740 | cp = ""; | ||
1741 | packet_put_cstring(cp); | ||
1742 | |||
1743 | /* Store window size in the packet. */ | ||
1744 | if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) | ||
1745 | memset(&ws, 0, sizeof(ws)); | ||
1746 | packet_put_int((u_int)ws.ws_row); | ||
1747 | packet_put_int((u_int)ws.ws_col); | ||
1748 | packet_put_int((u_int)ws.ws_xpixel); | ||
1749 | packet_put_int((u_int)ws.ws_ypixel); | ||
1750 | |||
1751 | /* Store tty modes in the packet. */ | ||
1752 | tty_make_modes(fileno(stdin), NULL); | ||
1753 | |||
1754 | /* Send the packet, and wait for it to leave. */ | ||
1755 | packet_send(); | ||
1756 | packet_write_wait(); | ||
1757 | |||
1758 | /* Read response from the server. */ | ||
1759 | type = packet_read(); | ||
1760 | if (type == SSH_SMSG_SUCCESS) { | ||
1761 | interactive = 1; | ||
1762 | have_tty = 1; | ||
1763 | } else if (type == SSH_SMSG_FAILURE) | ||
1764 | logit("Warning: Remote host failed or refused to " | ||
1765 | "allocate a pseudo tty."); | ||
1766 | else | ||
1767 | packet_disconnect("Protocol error waiting for pty " | ||
1768 | "request response."); | ||
1769 | } | ||
1770 | /* Request X11 forwarding if enabled and DISPLAY is set. */ | ||
1771 | display = getenv("DISPLAY"); | ||
1772 | if (display == NULL && options.forward_x11) | ||
1773 | debug("X11 forwarding requested but DISPLAY not set"); | ||
1774 | if (options.forward_x11 && client_x11_get_proto(display, | ||
1775 | options.xauth_location, options.forward_x11_trusted, | ||
1776 | options.forward_x11_timeout, &proto, &data) == 0) { | ||
1777 | /* Request forwarding with authentication spoofing. */ | ||
1778 | debug("Requesting X11 forwarding with authentication " | ||
1779 | "spoofing."); | ||
1780 | x11_request_forwarding_with_spoofing(0, display, proto, | ||
1781 | data, 0); | ||
1782 | /* Read response from the server. */ | ||
1783 | type = packet_read(); | ||
1784 | if (type == SSH_SMSG_SUCCESS) { | ||
1785 | interactive = 1; | ||
1786 | } else if (type == SSH_SMSG_FAILURE) { | ||
1787 | logit("Warning: Remote host denied X11 forwarding."); | ||
1788 | } else { | ||
1789 | packet_disconnect("Protocol error waiting for X11 " | ||
1790 | "forwarding"); | ||
1791 | } | ||
1792 | } | ||
1793 | /* Tell the packet module whether this is an interactive session. */ | ||
1794 | packet_set_interactive(interactive, | ||
1795 | options.ip_qos_interactive, options.ip_qos_bulk); | ||
1796 | |||
1797 | /* Request authentication agent forwarding if appropriate. */ | ||
1798 | check_agent_present(); | ||
1799 | |||
1800 | if (options.forward_agent) { | ||
1801 | debug("Requesting authentication agent forwarding."); | ||
1802 | auth_request_forwarding(); | ||
1803 | |||
1804 | /* Read response from the server. */ | ||
1805 | type = packet_read(); | ||
1806 | packet_check_eom(); | ||
1807 | if (type != SSH_SMSG_SUCCESS) | ||
1808 | logit("Warning: Remote host denied authentication agent forwarding."); | ||
1809 | } | ||
1810 | |||
1811 | /* Initiate port forwardings. */ | ||
1812 | ssh_init_stdio_forwarding(); | ||
1813 | ssh_init_forwarding(); | ||
1814 | |||
1815 | /* Execute a local command */ | ||
1816 | if (options.local_command != NULL && | ||
1817 | options.permit_local_command) | ||
1818 | ssh_local_cmd(options.local_command); | ||
1819 | |||
1820 | /* | ||
1821 | * If requested and we are not interested in replies to remote | ||
1822 | * forwarding requests, then let ssh continue in the background. | ||
1823 | */ | ||
1824 | if (fork_after_authentication_flag) { | ||
1825 | if (options.exit_on_forward_failure && | ||
1826 | options.num_remote_forwards > 0) { | ||
1827 | debug("deferring postauth fork until remote forward " | ||
1828 | "confirmation received"); | ||
1829 | } else | ||
1830 | fork_postauth(); | ||
1831 | } | ||
1832 | |||
1833 | /* | ||
1834 | * If a command was specified on the command line, execute the | ||
1835 | * command now. Otherwise request the server to start a shell. | ||
1836 | */ | ||
1837 | if (buffer_len(&command) > 0) { | ||
1838 | int len = buffer_len(&command); | ||
1839 | if (len > 900) | ||
1840 | len = 900; | ||
1841 | debug("Sending command: %.*s", len, | ||
1842 | (u_char *)buffer_ptr(&command)); | ||
1843 | packet_start(SSH_CMSG_EXEC_CMD); | ||
1844 | packet_put_string(buffer_ptr(&command), buffer_len(&command)); | ||
1845 | packet_send(); | ||
1846 | packet_write_wait(); | ||
1847 | } else { | ||
1848 | debug("Requesting shell."); | ||
1849 | packet_start(SSH_CMSG_EXEC_SHELL); | ||
1850 | packet_send(); | ||
1851 | packet_write_wait(); | ||
1852 | } | ||
1853 | |||
1854 | /* Enter the interactive session. */ | ||
1855 | return client_loop(have_tty, tty_flag ? | ||
1856 | options.escape_char : SSH_ESCAPECHAR_NONE, 0); | ||
1857 | } | ||
1858 | |||
1859 | /* request pty/x11/agent/tcpfwd/shell for channel */ | ||
1860 | static void | 1690 | static void |
1861 | ssh_session2_setup(int id, int success, void *arg) | 1691 | ssh_session2_setup(int id, int success, void *arg) |
1862 | { | 1692 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh_api.c,v 1.7 2016/05/04 14:22:33 markus Exp $ */ | 1 | /* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -371,7 +371,6 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) | |||
371 | } | 371 | } |
372 | if (remote_major != 2) | 372 | if (remote_major != 2) |
373 | return SSH_ERR_PROTOCOL_MISMATCH; | 373 | return SSH_ERR_PROTOCOL_MISMATCH; |
374 | enable_compat20(); | ||
375 | chop(buf); | 374 | chop(buf); |
376 | debug("Remote version string %.100s", buf); | 375 | debug("Remote version string %.100s", buf); |
377 | if ((*bannerp = strdup(buf)) == NULL) | 376 | if ((*bannerp = strdup(buf)) == NULL) |
diff --git a/sshconnect.c b/sshconnect.c index d48f2e06c..d01d2c82d 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.275 2017/04/30 23:11:45 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.276 2017/04/30 23:13:25 djm 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 |
@@ -524,13 +524,8 @@ static void | |||
524 | send_client_banner(int connection_out, int minor1) | 524 | send_client_banner(int connection_out, int minor1) |
525 | { | 525 | { |
526 | /* Send our own protocol version identification. */ | 526 | /* Send our own protocol version identification. */ |
527 | if (compat20) { | 527 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", |
528 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", | 528 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); |
529 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); | ||
530 | } else { | ||
531 | xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n", | ||
532 | PROTOCOL_MAJOR_1, minor1, SSH_VERSION); | ||
533 | } | ||
534 | if (atomicio(vwrite, connection_out, client_version_string, | 529 | if (atomicio(vwrite, connection_out, client_version_string, |
535 | strlen(client_version_string)) != strlen(client_version_string)) | 530 | strlen(client_version_string)) != strlen(client_version_string)) |
536 | fatal("write: %.100s", strerror(errno)); | 531 | fatal("write: %.100s", strerror(errno)); |
@@ -559,7 +554,6 @@ ssh_exchange_identification(int timeout_ms) | |||
559 | fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask); | 554 | fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask); |
560 | fdset = xcalloc(1, fdsetsz); | 555 | fdset = xcalloc(1, fdsetsz); |
561 | 556 | ||
562 | enable_compat20(); | ||
563 | send_client_banner(connection_out, 0); | 557 | send_client_banner(connection_out, 0); |
564 | client_banner_sent = 1; | 558 | client_banner_sent = 1; |
565 | 559 | ||
@@ -628,15 +622,12 @@ ssh_exchange_identification(int timeout_ms) | |||
628 | mismatch = 0; | 622 | mismatch = 0; |
629 | 623 | ||
630 | switch (remote_major) { | 624 | switch (remote_major) { |
625 | case 2: | ||
626 | break; | ||
631 | case 1: | 627 | case 1: |
632 | if (remote_minor == 99) | 628 | if (remote_minor != 99) |
633 | enable_compat20(); | ||
634 | else | ||
635 | mismatch = 1; | 629 | mismatch = 1; |
636 | break; | 630 | break; |
637 | case 2: | ||
638 | enable_compat20(); | ||
639 | break; | ||
640 | default: | 631 | default: |
641 | mismatch = 1; | 632 | mismatch = 1; |
642 | break; | 633 | break; |
@@ -1243,8 +1234,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | |||
1243 | host_key->cert->principals[i]); | 1234 | host_key->cert->principals[i]); |
1244 | } | 1235 | } |
1245 | } else { | 1236 | } else { |
1246 | debug("Server host key: %s %s", compat20 ? | 1237 | debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); |
1247 | sshkey_ssh_name(host_key) : sshkey_type(host_key), fp); | ||
1248 | } | 1238 | } |
1249 | 1239 | ||
1250 | if (sshkey_equal(previous_host_key, host_key)) { | 1240 | if (sshkey_equal(previous_host_key, host_key)) { |
@@ -1349,12 +1339,8 @@ ssh_login(Sensitive *sensitive, const char *orighost, | |||
1349 | /* key exchange */ | 1339 | /* key exchange */ |
1350 | /* authenticate user */ | 1340 | /* authenticate user */ |
1351 | debug("Authenticating to %s:%d as '%s'", host, port, server_user); | 1341 | debug("Authenticating to %s:%d as '%s'", host, port, server_user); |
1352 | if (compat20) { | 1342 | ssh_kex2(host, hostaddr, port); |
1353 | ssh_kex2(host, hostaddr, port); | 1343 | ssh_userauth2(local_user, server_user, host, sensitive); |
1354 | ssh_userauth2(local_user, server_user, host, sensitive); | ||
1355 | } else { | ||
1356 | fatal("ssh1 is not supported"); | ||
1357 | } | ||
1358 | free(local_user); | 1344 | free(local_user); |
1359 | } | 1345 | } |
1360 | 1346 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.486 2017/04/30 23:13:25 djm 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 |
@@ -450,10 +450,8 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | |||
450 | chop(server_version_string); | 450 | chop(server_version_string); |
451 | debug("Local version string %.200s", server_version_string); | 451 | debug("Local version string %.200s", server_version_string); |
452 | 452 | ||
453 | if (remote_major == 2 || | 453 | if (remote_major != 2 || |
454 | (remote_major == 1 && remote_minor == 99)) { | 454 | (remote_major == 1 && remote_minor != 99)) { |
455 | enable_compat20(); | ||
456 | } else { | ||
457 | s = "Protocol major versions differ.\n"; | 455 | s = "Protocol major versions differ.\n"; |
458 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | 456 | (void) atomicio(vwrite, sock_out, s, strlen(s)); |
459 | close(sock_in); | 457 | close(sock_in); |
diff --git a/ttymodes.c b/ttymodes.c index db772c39c..2fc783b2f 100644 --- a/ttymodes.c +++ b/ttymodes.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ttymodes.c,v 1.30 2016/05/04 14:22:33 markus Exp $ */ | 1 | /* $OpenBSD: ttymodes.c,v 1.31 2017/04/30 23:13:25 djm 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 |
@@ -283,18 +283,10 @@ tty_make_modes(int fd, struct termios *tiop) | |||
283 | int baud; | 283 | int baud; |
284 | Buffer buf; | 284 | Buffer buf; |
285 | int tty_op_ospeed, tty_op_ispeed; | 285 | int tty_op_ospeed, tty_op_ispeed; |
286 | void (*put_arg)(Buffer *, u_int); | ||
287 | 286 | ||
288 | buffer_init(&buf); | 287 | buffer_init(&buf); |
289 | if (compat20) { | 288 | tty_op_ospeed = TTY_OP_OSPEED_PROTO2; |
290 | tty_op_ospeed = TTY_OP_OSPEED_PROTO2; | 289 | tty_op_ispeed = TTY_OP_ISPEED_PROTO2; |
291 | tty_op_ispeed = TTY_OP_ISPEED_PROTO2; | ||
292 | put_arg = buffer_put_int; | ||
293 | } else { | ||
294 | tty_op_ospeed = TTY_OP_OSPEED_PROTO1; | ||
295 | tty_op_ispeed = TTY_OP_ISPEED_PROTO1; | ||
296 | put_arg = (void (*)(Buffer *, u_int)) buffer_put_char; | ||
297 | } | ||
298 | 290 | ||
299 | if (tiop == NULL) { | 291 | if (tiop == NULL) { |
300 | if (fd == -1) { | 292 | if (fd == -1) { |
@@ -319,11 +311,11 @@ tty_make_modes(int fd, struct termios *tiop) | |||
319 | /* Store values of mode flags. */ | 311 | /* Store values of mode flags. */ |
320 | #define TTYCHAR(NAME, OP) \ | 312 | #define TTYCHAR(NAME, OP) \ |
321 | buffer_put_char(&buf, OP); \ | 313 | buffer_put_char(&buf, OP); \ |
322 | put_arg(&buf, special_char_encode(tio.c_cc[NAME])); | 314 | buffer_put_int(&buf, special_char_encode(tio.c_cc[NAME])); |
323 | 315 | ||
324 | #define TTYMODE(NAME, FIELD, OP) \ | 316 | #define TTYMODE(NAME, FIELD, OP) \ |
325 | buffer_put_char(&buf, OP); \ | 317 | buffer_put_char(&buf, OP); \ |
326 | put_arg(&buf, ((tio.FIELD & NAME) != 0)); | 318 | buffer_put_int(&buf, ((tio.FIELD & NAME) != 0)); |
327 | 319 | ||
328 | #include "ttymodes.h" | 320 | #include "ttymodes.h" |
329 | 321 | ||
@@ -333,10 +325,7 @@ tty_make_modes(int fd, struct termios *tiop) | |||
333 | end: | 325 | end: |
334 | /* Mark end of mode data. */ | 326 | /* Mark end of mode data. */ |
335 | buffer_put_char(&buf, TTY_OP_END); | 327 | buffer_put_char(&buf, TTY_OP_END); |
336 | if (compat20) | 328 | packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); |
337 | packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); | ||
338 | else | ||
339 | packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); | ||
340 | buffer_free(&buf); | 329 | buffer_free(&buf); |
341 | } | 330 | } |
342 | 331 | ||
@@ -351,19 +340,10 @@ tty_parse_modes(int fd, int *n_bytes_ptr) | |||
351 | int opcode, baud; | 340 | int opcode, baud; |
352 | int n_bytes = 0; | 341 | int n_bytes = 0; |
353 | int failure = 0; | 342 | int failure = 0; |
354 | u_int (*get_arg)(void); | 343 | |
355 | int arg_size; | 344 | *n_bytes_ptr = packet_get_int(); |
356 | 345 | if (*n_bytes_ptr == 0) | |
357 | if (compat20) { | 346 | return; |
358 | *n_bytes_ptr = packet_get_int(); | ||
359 | if (*n_bytes_ptr == 0) | ||
360 | return; | ||
361 | get_arg = packet_get_int; | ||
362 | arg_size = 4; | ||
363 | } else { | ||
364 | get_arg = packet_get_char; | ||
365 | arg_size = 1; | ||
366 | } | ||
367 | 347 | ||
368 | /* | 348 | /* |
369 | * Get old attributes for the terminal. We will modify these | 349 | * Get old attributes for the terminal. We will modify these |
@@ -404,13 +384,13 @@ tty_parse_modes(int fd, int *n_bytes_ptr) | |||
404 | 384 | ||
405 | #define TTYCHAR(NAME, OP) \ | 385 | #define TTYCHAR(NAME, OP) \ |
406 | case OP: \ | 386 | case OP: \ |
407 | n_bytes += arg_size; \ | 387 | n_bytes += 4; \ |
408 | tio.c_cc[NAME] = special_char_decode(get_arg()); \ | 388 | tio.c_cc[NAME] = special_char_decode(packet_get_int()); \ |
409 | break; | 389 | break; |
410 | #define TTYMODE(NAME, FIELD, OP) \ | 390 | #define TTYMODE(NAME, FIELD, OP) \ |
411 | case OP: \ | 391 | case OP: \ |
412 | n_bytes += arg_size; \ | 392 | n_bytes += 4; \ |
413 | if (get_arg()) \ | 393 | if (packet_get_int()) \ |
414 | tio.FIELD |= NAME; \ | 394 | tio.FIELD |= NAME; \ |
415 | else \ | 395 | else \ |
416 | tio.FIELD &= ~NAME; \ | 396 | tio.FIELD &= ~NAME; \ |
@@ -424,51 +404,21 @@ tty_parse_modes(int fd, int *n_bytes_ptr) | |||
424 | default: | 404 | default: |
425 | debug("Ignoring unsupported tty mode opcode %d (0x%x)", | 405 | debug("Ignoring unsupported tty mode opcode %d (0x%x)", |
426 | opcode, opcode); | 406 | opcode, opcode); |
427 | if (!compat20) { | 407 | /* |
428 | /* | 408 | * SSH2: |
429 | * SSH1: | 409 | * Opcodes 1 to 159 are defined to have a uint32 |
430 | * Opcodes 1 to 127 are defined to have | 410 | * argument. |
431 | * a one-byte argument. | 411 | * Opcodes 160 to 255 are undefined and cause parsing |
432 | * Opcodes 128 to 159 are defined to have | 412 | * to stop. |
433 | * an integer argument. | 413 | */ |
434 | */ | 414 | if (opcode > 0 && opcode < 160) { |
435 | if (opcode > 0 && opcode < 128) { | 415 | n_bytes += 4; |
436 | n_bytes += 1; | 416 | (void) packet_get_int(); |
437 | (void) packet_get_char(); | 417 | break; |
438 | break; | ||
439 | } else if (opcode >= 128 && opcode < 160) { | ||
440 | n_bytes += 4; | ||
441 | (void) packet_get_int(); | ||
442 | break; | ||
443 | } else { | ||
444 | /* | ||
445 | * It is a truly undefined opcode (160 to 255). | ||
446 | * We have no idea about its arguments. So we | ||
447 | * must stop parsing. Note that some data | ||
448 | * may be left in the packet; hopefully there | ||
449 | * is nothing more coming after the mode data. | ||
450 | */ | ||
451 | logit("parse_tty_modes: unknown opcode %d", | ||
452 | opcode); | ||
453 | goto set; | ||
454 | } | ||
455 | } else { | 418 | } else { |
456 | /* | 419 | logit("parse_tty_modes: unknown opcode %d", |
457 | * SSH2: | 420 | opcode); |
458 | * Opcodes 1 to 159 are defined to have | 421 | goto set; |
459 | * a uint32 argument. | ||
460 | * Opcodes 160 to 255 are undefined and | ||
461 | * cause parsing to stop. | ||
462 | */ | ||
463 | if (opcode > 0 && opcode < 160) { | ||
464 | n_bytes += 4; | ||
465 | (void) packet_get_int(); | ||
466 | break; | ||
467 | } else { | ||
468 | logit("parse_tty_modes: unknown opcode %d", | ||
469 | opcode); | ||
470 | goto set; | ||
471 | } | ||
472 | } | 422 | } |
473 | } | 423 | } |
474 | } | 424 | } |