diff options
author | Colin Watson <cjwatson@debian.org> | 2018-08-24 12:49:36 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2018-08-24 12:49:36 +0100 |
commit | e6547182a54f0f268ee36e7c99319eeddffbaff2 (patch) | |
tree | 417527229ad3f3764ba71ea383f478a168895087 /clientloop.c | |
parent | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 (diff) | |
parent | 71508e06fab14bc415a79a08f5535ad7bffa93d9 (diff) |
Import openssh_7.8p1.orig.tar.gz
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 236 |
1 files changed, 137 insertions, 99 deletions
diff --git a/clientloop.c b/clientloop.c index 7bcf22e38..ad35cb7ba 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.311 2018/02/11 21:16:56 dtucker Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.317 2018/07/11 18:53:29 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -91,11 +91,11 @@ | |||
91 | #include "ssh.h" | 91 | #include "ssh.h" |
92 | #include "ssh2.h" | 92 | #include "ssh2.h" |
93 | #include "packet.h" | 93 | #include "packet.h" |
94 | #include "buffer.h" | 94 | #include "sshbuf.h" |
95 | #include "compat.h" | 95 | #include "compat.h" |
96 | #include "channels.h" | 96 | #include "channels.h" |
97 | #include "dispatch.h" | 97 | #include "dispatch.h" |
98 | #include "key.h" | 98 | #include "sshkey.h" |
99 | #include "cipher.h" | 99 | #include "cipher.h" |
100 | #include "kex.h" | 100 | #include "kex.h" |
101 | #include "myproposal.h" | 101 | #include "myproposal.h" |
@@ -153,7 +153,7 @@ static time_t control_persist_exit_time = 0; | |||
153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
154 | static int last_was_cr; /* Last character was a newline. */ | 154 | static int last_was_cr; /* Last character was a newline. */ |
155 | static int exit_status; /* Used to store the command exit status. */ | 155 | static int exit_status; /* Used to store the command exit status. */ |
156 | static Buffer stderr_buffer; /* Used for final exit message. */ | 156 | static struct sshbuf *stderr_buffer; /* Used for final exit message. */ |
157 | static int connection_in; /* Connection to server (input). */ | 157 | static int connection_in; /* Connection to server (input). */ |
158 | static int connection_out; /* Connection to server (output). */ | 158 | static int connection_out; /* Connection to server (output). */ |
159 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ | 159 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
@@ -188,7 +188,7 @@ TAILQ_HEAD(global_confirms, global_confirm); | |||
188 | static struct global_confirms global_confirms = | 188 | static struct global_confirms global_confirms = |
189 | TAILQ_HEAD_INITIALIZER(global_confirms); | 189 | TAILQ_HEAD_INITIALIZER(global_confirms); |
190 | 190 | ||
191 | void ssh_process_session2_setup(int, int, int, Buffer *); | 191 | void ssh_process_session2_setup(int, int, int, struct sshbuf *); |
192 | 192 | ||
193 | /* Restores stdin to blocking mode. */ | 193 | /* Restores stdin to blocking mode. */ |
194 | 194 | ||
@@ -493,7 +493,7 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
493 | struct timeval tv, *tvp; | 493 | struct timeval tv, *tvp; |
494 | int timeout_secs; | 494 | int timeout_secs; |
495 | time_t minwait_secs = 0, server_alive_time = 0, now = monotime(); | 495 | time_t minwait_secs = 0, server_alive_time = 0, now = monotime(); |
496 | int ret; | 496 | int r, ret; |
497 | 497 | ||
498 | /* Add any selections by the channel mechanism. */ | 498 | /* Add any selections by the channel mechanism. */ |
499 | channel_prepare_select(active_state, readsetp, writesetp, maxfdp, | 499 | channel_prepare_select(active_state, readsetp, writesetp, maxfdp, |
@@ -546,8 +546,6 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
546 | 546 | ||
547 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); | 547 | ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); |
548 | if (ret < 0) { | 548 | if (ret < 0) { |
549 | char buf[100]; | ||
550 | |||
551 | /* | 549 | /* |
552 | * We have to clear the select masks, because we return. | 550 | * We have to clear the select masks, because we return. |
553 | * We have to return, because the mainloop checks for the flags | 551 | * We have to return, because the mainloop checks for the flags |
@@ -559,8 +557,9 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
559 | if (errno == EINTR) | 557 | if (errno == EINTR) |
560 | return; | 558 | return; |
561 | /* Note: we might still have data in the buffers. */ | 559 | /* Note: we might still have data in the buffers. */ |
562 | snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); | 560 | if ((r = sshbuf_putf(stderr_buffer, |
563 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 561 | "select: %s\r\n", strerror(errno))) != 0) |
562 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
564 | quit_pending = 1; | 563 | quit_pending = 1; |
565 | } else if (ret == 0) { | 564 | } else if (ret == 0) { |
566 | /* | 565 | /* |
@@ -574,15 +573,15 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
574 | } | 573 | } |
575 | 574 | ||
576 | static void | 575 | static void |
577 | client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | 576 | client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr) |
578 | { | 577 | { |
579 | /* Flush stdout and stderr buffers. */ | 578 | /* Flush stdout and stderr buffers. */ |
580 | if (buffer_len(bout) > 0) | 579 | if (sshbuf_len(bout) > 0) |
581 | atomicio(vwrite, fileno(stdout), buffer_ptr(bout), | 580 | atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout), |
582 | buffer_len(bout)); | 581 | sshbuf_len(bout)); |
583 | if (buffer_len(berr) > 0) | 582 | if (sshbuf_len(berr) > 0) |
584 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), | 583 | atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr), |
585 | buffer_len(berr)); | 584 | sshbuf_len(berr)); |
586 | 585 | ||
587 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 586 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
588 | 587 | ||
@@ -602,8 +601,8 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
602 | static void | 601 | static void |
603 | client_process_net_input(fd_set *readset) | 602 | client_process_net_input(fd_set *readset) |
604 | { | 603 | { |
605 | int len; | ||
606 | char buf[SSH_IOBUFSZ]; | 604 | char buf[SSH_IOBUFSZ]; |
605 | int r, len; | ||
607 | 606 | ||
608 | /* | 607 | /* |
609 | * Read input from the server, and add any such data to the buffer of | 608 | * Read input from the server, and add any such data to the buffer of |
@@ -617,10 +616,11 @@ client_process_net_input(fd_set *readset) | |||
617 | * Received EOF. The remote host has closed the | 616 | * Received EOF. The remote host has closed the |
618 | * connection. | 617 | * connection. |
619 | */ | 618 | */ |
620 | snprintf(buf, sizeof buf, | 619 | if ((r = sshbuf_putf(stderr_buffer, |
621 | "Connection to %.300s closed by remote host.\r\n", | 620 | "Connection to %.300s closed by remote host.\r\n", |
622 | host); | 621 | host)) != 0) |
623 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 622 | fatal("%s: buffer error: %s", |
623 | __func__, ssh_err(r)); | ||
624 | quit_pending = 1; | 624 | quit_pending = 1; |
625 | return; | 625 | return; |
626 | } | 626 | } |
@@ -637,10 +637,11 @@ client_process_net_input(fd_set *readset) | |||
637 | * An error has encountered. Perhaps there is a | 637 | * An error has encountered. Perhaps there is a |
638 | * network problem. | 638 | * network problem. |
639 | */ | 639 | */ |
640 | snprintf(buf, sizeof buf, | 640 | if ((r = sshbuf_putf(stderr_buffer, |
641 | "Read from remote host %.300s: %.100s\r\n", | 641 | "Read from remote host %.300s: %.100s\r\n", |
642 | host, strerror(errno)); | 642 | host, strerror(errno))) != 0) |
643 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 643 | fatal("%s: buffer error: %s", |
644 | __func__, ssh_err(r)); | ||
644 | quit_pending = 1; | 645 | quit_pending = 1; |
645 | return; | 646 | return; |
646 | } | 647 | } |
@@ -653,7 +654,7 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) | |||
653 | { | 654 | { |
654 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; | 655 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
655 | char errmsg[256]; | 656 | char errmsg[256]; |
656 | int tochan; | 657 | int r, tochan; |
657 | 658 | ||
658 | /* | 659 | /* |
659 | * If a TTY was explicitly requested, then a failure to allocate | 660 | * If a TTY was explicitly requested, then a failure to allocate |
@@ -664,7 +665,7 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) | |||
664 | options.request_tty == REQUEST_TTY_YES)) | 665 | options.request_tty == REQUEST_TTY_YES)) |
665 | cr->action = CONFIRM_CLOSE; | 666 | cr->action = CONFIRM_CLOSE; |
666 | 667 | ||
667 | /* XXX supress on mux _client_ quietmode */ | 668 | /* XXX suppress on mux _client_ quietmode */ |
668 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | 669 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
669 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | 670 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
670 | 671 | ||
@@ -688,7 +689,10 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) | |||
688 | * their stderr. | 689 | * their stderr. |
689 | */ | 690 | */ |
690 | if (tochan) { | 691 | if (tochan) { |
691 | buffer_append(c->extended, errmsg, strlen(errmsg)); | 692 | if ((r = sshbuf_put(c->extended, errmsg, |
693 | strlen(errmsg))) != 0) | ||
694 | fatal("%s: buffer error %s", __func__, | ||
695 | ssh_err(r)); | ||
692 | } else | 696 | } else |
693 | error("%s", errmsg); | 697 | error("%s", errmsg); |
694 | if (cr->action == CONFIRM_TTY) { | 698 | if (cr->action == CONFIRM_TTY) { |
@@ -892,14 +896,15 @@ static struct escape_help_text esc_txt[] = { | |||
892 | }; | 896 | }; |
893 | 897 | ||
894 | static void | 898 | static void |
895 | print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) | 899 | print_escape_help(struct sshbuf *b, int escape_char, int mux_client, |
900 | int using_stderr) | ||
896 | { | 901 | { |
897 | unsigned int i, suppress_flags; | 902 | unsigned int i, suppress_flags; |
898 | char string[1024]; | 903 | int r; |
899 | 904 | ||
900 | snprintf(string, sizeof string, "%c?\r\n" | 905 | if ((r = sshbuf_putf(b, |
901 | "Supported escape sequences:\r\n", escape_char); | 906 | "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0) |
902 | buffer_append(b, string, strlen(string)); | 907 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
903 | 908 | ||
904 | suppress_flags = | 909 | suppress_flags = |
905 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | | 910 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | |
@@ -909,29 +914,28 @@ print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) | |||
909 | for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) { | 914 | for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) { |
910 | if (esc_txt[i].flags & suppress_flags) | 915 | if (esc_txt[i].flags & suppress_flags) |
911 | continue; | 916 | continue; |
912 | snprintf(string, sizeof string, " %c%-3s - %s\r\n", | 917 | if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n", |
913 | escape_char, esc_txt[i].cmd, esc_txt[i].text); | 918 | escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0) |
914 | buffer_append(b, string, strlen(string)); | 919 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
915 | } | 920 | } |
916 | 921 | ||
917 | snprintf(string, sizeof string, | 922 | if ((r = sshbuf_putf(b, |
918 | " %c%c - send the escape character by typing it twice\r\n" | 923 | " %c%c - send the escape character by typing it twice\r\n" |
919 | "(Note that escapes are only recognized immediately after " | 924 | "(Note that escapes are only recognized immediately after " |
920 | "newline.)\r\n", escape_char, escape_char); | 925 | "newline.)\r\n", escape_char, escape_char)) != 0) |
921 | buffer_append(b, string, strlen(string)); | 926 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
922 | } | 927 | } |
923 | 928 | ||
924 | /* | 929 | /* |
925 | * Process the characters one by one. | 930 | * Process the characters one by one. |
926 | */ | 931 | */ |
927 | static int | 932 | static int |
928 | process_escapes(struct ssh *ssh, Channel *c, | 933 | process_escapes(struct ssh *ssh, Channel *c, |
929 | Buffer *bin, Buffer *bout, Buffer *berr, | 934 | struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr, |
930 | char *buf, int len) | 935 | char *buf, int len) |
931 | { | 936 | { |
932 | char string[1024]; | ||
933 | pid_t pid; | 937 | pid_t pid; |
934 | int bytes = 0; | 938 | int r, bytes = 0; |
935 | u_int i; | 939 | u_int i; |
936 | u_char ch; | 940 | u_char ch; |
937 | char *s; | 941 | char *s; |
@@ -940,7 +944,7 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
940 | 944 | ||
941 | if (c->filter_ctx == NULL) | 945 | if (c->filter_ctx == NULL) |
942 | return 0; | 946 | return 0; |
943 | 947 | ||
944 | if (len <= 0) | 948 | if (len <= 0) |
945 | return (0); | 949 | return (0); |
946 | 950 | ||
@@ -957,10 +961,10 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
957 | switch (ch) { | 961 | switch (ch) { |
958 | case '.': | 962 | case '.': |
959 | /* Terminate the connection. */ | 963 | /* Terminate the connection. */ |
960 | snprintf(string, sizeof string, "%c.\r\n", | 964 | if ((r = sshbuf_putf(berr, "%c.\r\n", |
961 | efc->escape_char); | 965 | efc->escape_char)) != 0) |
962 | buffer_append(berr, string, strlen(string)); | 966 | fatal("%s: buffer error: %s", |
963 | 967 | __func__, ssh_err(r)); | |
964 | if (c && c->ctl_chan != -1) { | 968 | if (c && c->ctl_chan != -1) { |
965 | chan_read_failed(ssh, c); | 969 | chan_read_failed(ssh, c); |
966 | chan_write_failed(ssh, c); | 970 | chan_write_failed(ssh, c); |
@@ -969,7 +973,7 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
969 | c->self, NULL); | 973 | c->self, NULL); |
970 | } | 974 | } |
971 | c->type = SSH_CHANNEL_ABANDONED; | 975 | c->type = SSH_CHANNEL_ABANDONED; |
972 | buffer_clear(c->input); | 976 | sshbuf_reset(c->input); |
973 | chan_ibuf_empty(ssh, c); | 977 | chan_ibuf_empty(ssh, c); |
974 | return 0; | 978 | return 0; |
975 | } else | 979 | } else |
@@ -985,18 +989,20 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
985 | snprintf(b, sizeof b, "^Z"); | 989 | snprintf(b, sizeof b, "^Z"); |
986 | else | 990 | else |
987 | snprintf(b, sizeof b, "%c", ch); | 991 | snprintf(b, sizeof b, "%c", ch); |
988 | snprintf(string, sizeof string, | 992 | if ((r = sshbuf_putf(berr, |
989 | "%c%s escape not available to " | 993 | "%c%s escape not available to " |
990 | "multiplexed sessions\r\n", | 994 | "multiplexed sessions\r\n", |
991 | efc->escape_char, b); | 995 | efc->escape_char, b)) != 0) |
992 | buffer_append(berr, string, | 996 | fatal("%s: buffer error: %s", |
993 | strlen(string)); | 997 | __func__, ssh_err(r)); |
994 | continue; | 998 | continue; |
995 | } | 999 | } |
996 | /* Suspend the program. Inform the user */ | 1000 | /* Suspend the program. Inform the user */ |
997 | snprintf(string, sizeof string, | 1001 | if ((r = sshbuf_putf(berr, |
998 | "%c^Z [suspend ssh]\r\n", efc->escape_char); | 1002 | "%c^Z [suspend ssh]\r\n", |
999 | buffer_append(berr, string, strlen(string)); | 1003 | efc->escape_char)) != 0) |
1004 | fatal("%s: buffer error: %s", | ||
1005 | __func__, ssh_err(r)); | ||
1000 | 1006 | ||
1001 | /* Restore terminal modes and suspend. */ | 1007 | /* Restore terminal modes and suspend. */ |
1002 | client_suspend_self(bin, bout, berr); | 1008 | client_suspend_self(bin, bout, berr); |
@@ -1005,12 +1011,15 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1005 | continue; | 1011 | continue; |
1006 | 1012 | ||
1007 | case 'B': | 1013 | case 'B': |
1008 | snprintf(string, sizeof string, | 1014 | if ((r = sshbuf_putf(berr, |
1009 | "%cB\r\n", efc->escape_char); | 1015 | "%cB\r\n", efc->escape_char)) != 0) |
1010 | buffer_append(berr, string, strlen(string)); | 1016 | fatal("%s: buffer error: %s", |
1017 | __func__, ssh_err(r)); | ||
1011 | channel_request_start(ssh, c->self, "break", 0); | 1018 | channel_request_start(ssh, c->self, "break", 0); |
1012 | packet_put_int(1000); | 1019 | if ((r = sshpkt_put_u32(ssh, 1000)) != 0 || |
1013 | packet_send(); | 1020 | (r = sshpkt_send(ssh)) != 0) |
1021 | fatal("%s: %s", __func__, | ||
1022 | ssh_err(r)); | ||
1014 | continue; | 1023 | continue; |
1015 | 1024 | ||
1016 | case 'R': | 1025 | case 'R': |
@@ -1027,11 +1036,11 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1027 | if (c && c->ctl_chan != -1) | 1036 | if (c && c->ctl_chan != -1) |
1028 | goto noescape; | 1037 | goto noescape; |
1029 | if (!log_is_on_stderr()) { | 1038 | if (!log_is_on_stderr()) { |
1030 | snprintf(string, sizeof string, | 1039 | if ((r = sshbuf_putf(berr, |
1031 | "%c%c [Logging to syslog]\r\n", | 1040 | "%c%c [Logging to syslog]\r\n", |
1032 | efc->escape_char, ch); | 1041 | efc->escape_char, ch)) != 0) |
1033 | buffer_append(berr, string, | 1042 | fatal("%s: buffer error: %s", |
1034 | strlen(string)); | 1043 | __func__, ssh_err(r)); |
1035 | continue; | 1044 | continue; |
1036 | } | 1045 | } |
1037 | if (ch == 'V' && options.log_level > | 1046 | if (ch == 'V' && options.log_level > |
@@ -1040,11 +1049,12 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1040 | if (ch == 'v' && options.log_level < | 1049 | if (ch == 'v' && options.log_level < |
1041 | SYSLOG_LEVEL_DEBUG3) | 1050 | SYSLOG_LEVEL_DEBUG3) |
1042 | log_change_level(++options.log_level); | 1051 | log_change_level(++options.log_level); |
1043 | snprintf(string, sizeof string, | 1052 | if ((r = sshbuf_putf(berr, |
1044 | "%c%c [LogLevel %s]\r\n", | 1053 | "%c%c [LogLevel %s]\r\n", |
1045 | efc->escape_char, ch, | 1054 | efc->escape_char, ch, |
1046 | log_level_name(options.log_level)); | 1055 | log_level_name(options.log_level))) != 0) |
1047 | buffer_append(berr, string, strlen(string)); | 1056 | fatal("%s: buffer error: %s", |
1057 | __func__, ssh_err(r)); | ||
1048 | continue; | 1058 | continue; |
1049 | 1059 | ||
1050 | case '&': | 1060 | case '&': |
@@ -1062,9 +1072,11 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1062 | /* Stop listening for new connections. */ | 1072 | /* Stop listening for new connections. */ |
1063 | channel_stop_listening(ssh); | 1073 | channel_stop_listening(ssh); |
1064 | 1074 | ||
1065 | snprintf(string, sizeof string, | 1075 | if ((r = sshbuf_putf(berr, |
1066 | "%c& [backgrounded]\n", efc->escape_char); | 1076 | "%c& [backgrounded]\n", efc->escape_char)) |
1067 | buffer_append(berr, string, strlen(string)); | 1077 | != 0) |
1078 | fatal("%s: buffer error: %s", | ||
1079 | __func__, ssh_err(r)); | ||
1068 | 1080 | ||
1069 | /* Fork into background. */ | 1081 | /* Fork into background. */ |
1070 | pid = fork(); | 1082 | pid = fork(); |
@@ -1077,8 +1089,10 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1077 | exit(0); | 1089 | exit(0); |
1078 | } | 1090 | } |
1079 | /* The child continues serving connections. */ | 1091 | /* The child continues serving connections. */ |
1080 | buffer_append(bin, "\004", 1); | ||
1081 | /* fake EOF on stdin */ | 1092 | /* fake EOF on stdin */ |
1093 | if ((r = sshbuf_put_u8(bin, 4)) != 0) | ||
1094 | fatal("%s: buffer error: %s", | ||
1095 | __func__, ssh_err(r)); | ||
1082 | return -1; | 1096 | return -1; |
1083 | case '?': | 1097 | case '?': |
1084 | print_escape_help(berr, efc->escape_char, | 1098 | print_escape_help(berr, efc->escape_char, |
@@ -1087,11 +1101,14 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1087 | continue; | 1101 | continue; |
1088 | 1102 | ||
1089 | case '#': | 1103 | case '#': |
1090 | snprintf(string, sizeof string, "%c#\r\n", | 1104 | if ((r = sshbuf_putf(berr, "%c#\r\n", |
1091 | efc->escape_char); | 1105 | efc->escape_char)) != 0) |
1092 | buffer_append(berr, string, strlen(string)); | 1106 | fatal("%s: buffer error: %s", |
1107 | __func__, ssh_err(r)); | ||
1093 | s = channel_open_message(ssh); | 1108 | s = channel_open_message(ssh); |
1094 | buffer_append(berr, s, strlen(s)); | 1109 | if ((r = sshbuf_put(berr, s, strlen(s))) != 0) |
1110 | fatal("%s: buffer error: %s", | ||
1111 | __func__, ssh_err(r)); | ||
1095 | free(s); | 1112 | free(s); |
1096 | continue; | 1113 | continue; |
1097 | 1114 | ||
@@ -1103,7 +1120,10 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1103 | 1120 | ||
1104 | default: | 1121 | default: |
1105 | if (ch != efc->escape_char) { | 1122 | if (ch != efc->escape_char) { |
1106 | buffer_put_char(bin, efc->escape_char); | 1123 | if ((r = sshbuf_put_u8(bin, |
1124 | efc->escape_char)) != 0) | ||
1125 | fatal("%s: buffer error: %s", | ||
1126 | __func__, ssh_err(r)); | ||
1107 | bytes++; | 1127 | bytes++; |
1108 | } | 1128 | } |
1109 | /* Escaped characters fall through here */ | 1129 | /* Escaped characters fall through here */ |
@@ -1129,7 +1149,8 @@ process_escapes(struct ssh *ssh, Channel *c, | |||
1129 | * and append it to the buffer. | 1149 | * and append it to the buffer. |
1130 | */ | 1150 | */ |
1131 | last_was_cr = (ch == '\r' || ch == '\n'); | 1151 | last_was_cr = (ch == '\r' || ch == '\n'); |
1132 | buffer_put_char(bin, ch); | 1152 | if ((r = sshbuf_put_u8(bin, ch)) != 0) |
1153 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1133 | bytes++; | 1154 | bytes++; |
1134 | } | 1155 | } |
1135 | return bytes; | 1156 | return bytes; |
@@ -1253,8 +1274,9 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1253 | 1274 | ||
1254 | quit_pending = 0; | 1275 | quit_pending = 0; |
1255 | 1276 | ||
1256 | /* Initialize buffers. */ | 1277 | /* Initialize buffer. */ |
1257 | buffer_init(&stderr_buffer); | 1278 | if ((stderr_buffer = sshbuf_new()) == NULL) |
1279 | fatal("%s: sshbuf_new failed", __func__); | ||
1258 | 1280 | ||
1259 | client_init_dispatch(); | 1281 | client_init_dispatch(); |
1260 | 1282 | ||
@@ -1411,24 +1433,25 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1411 | * that the connection has been closed. | 1433 | * that the connection has been closed. |
1412 | */ | 1434 | */ |
1413 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { | 1435 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { |
1414 | snprintf(buf, sizeof buf, | 1436 | if ((r = sshbuf_putf(stderr_buffer, |
1415 | "Connection to %.64s closed.\r\n", host); | 1437 | "Connection to %.64s closed.\r\n", host)) != 0) |
1416 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1438 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1417 | } | 1439 | } |
1418 | 1440 | ||
1419 | /* Output any buffered data for stderr. */ | 1441 | /* Output any buffered data for stderr. */ |
1420 | if (buffer_len(&stderr_buffer) > 0) { | 1442 | if (sshbuf_len(stderr_buffer) > 0) { |
1421 | len = atomicio(vwrite, fileno(stderr), | 1443 | len = atomicio(vwrite, fileno(stderr), |
1422 | buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer)); | 1444 | (u_char *)sshbuf_ptr(stderr_buffer), |
1423 | if (len < 0 || (u_int)len != buffer_len(&stderr_buffer)) | 1445 | sshbuf_len(stderr_buffer)); |
1446 | if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer)) | ||
1424 | error("Write failed flushing stderr buffer."); | 1447 | error("Write failed flushing stderr buffer."); |
1425 | else | 1448 | else if ((r = sshbuf_consume(stderr_buffer, len)) != 0) |
1426 | buffer_consume(&stderr_buffer, len); | 1449 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1427 | } | 1450 | } |
1428 | 1451 | ||
1429 | /* Clear and free any buffers. */ | 1452 | /* Clear and free any buffers. */ |
1430 | explicit_bzero(buf, sizeof(buf)); | 1453 | explicit_bzero(buf, sizeof(buf)); |
1431 | buffer_free(&stderr_buffer); | 1454 | sshbuf_free(stderr_buffer); |
1432 | 1455 | ||
1433 | /* Report bytes transferred, and transfer rates. */ | 1456 | /* Report bytes transferred, and transfer rates. */ |
1434 | total_time = monotime_double() - start_time; | 1457 | total_time = monotime_double() - start_time; |
@@ -1746,7 +1769,7 @@ struct hostkeys_update_ctx { | |||
1746 | */ | 1769 | */ |
1747 | struct sshkey **keys; | 1770 | struct sshkey **keys; |
1748 | int *keys_seen; | 1771 | int *keys_seen; |
1749 | size_t nkeys, nnew; | 1772 | size_t nkeys, nnew; |
1750 | 1773 | ||
1751 | /* | 1774 | /* |
1752 | * Keys that are in known_hosts, but were not present in the update | 1775 | * Keys that are in known_hosts, but were not present in the update |
@@ -2156,9 +2179,11 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
2156 | 2179 | ||
2157 | void | 2180 | void |
2158 | client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | 2181 | client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, |
2159 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) | 2182 | const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd, |
2183 | char **env) | ||
2160 | { | 2184 | { |
2161 | int len; | 2185 | int i, j, matched, len; |
2186 | char *name, *val; | ||
2162 | Channel *c = NULL; | 2187 | Channel *c = NULL; |
2163 | 2188 | ||
2164 | debug2("%s: id %d", __func__, id); | 2189 | debug2("%s: id %d", __func__, id); |
@@ -2185,7 +2210,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2185 | packet_put_int((u_int)ws.ws_ypixel); | 2210 | packet_put_int((u_int)ws.ws_ypixel); |
2186 | if (tiop == NULL) | 2211 | if (tiop == NULL) |
2187 | tiop = get_saved_tio(); | 2212 | tiop = get_saved_tio(); |
2188 | tty_make_modes(-1, tiop); | 2213 | ssh_tty_make_modes(ssh, -1, tiop); |
2189 | packet_send(); | 2214 | packet_send(); |
2190 | /* XXX wait for reply */ | 2215 | /* XXX wait for reply */ |
2191 | c->client_tty = 1; | 2216 | c->client_tty = 1; |
@@ -2193,9 +2218,6 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2193 | 2218 | ||
2194 | /* Transfer any environment variables from client to server */ | 2219 | /* Transfer any environment variables from client to server */ |
2195 | if (options.num_send_env != 0 && env != NULL) { | 2220 | if (options.num_send_env != 0 && env != NULL) { |
2196 | int i, j, matched; | ||
2197 | char *name, *val; | ||
2198 | |||
2199 | debug("Sending environment."); | 2221 | debug("Sending environment."); |
2200 | for (i = 0; env[i] != NULL; i++) { | 2222 | for (i = 0; env[i] != NULL; i++) { |
2201 | /* Split */ | 2223 | /* Split */ |
@@ -2227,24 +2249,40 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2227 | free(name); | 2249 | free(name); |
2228 | } | 2250 | } |
2229 | } | 2251 | } |
2252 | for (i = 0; i < options.num_setenv; i++) { | ||
2253 | /* Split */ | ||
2254 | name = xstrdup(options.setenv[i]); | ||
2255 | if ((val = strchr(name, '=')) == NULL) { | ||
2256 | free(name); | ||
2257 | continue; | ||
2258 | } | ||
2259 | *val++ = '\0'; | ||
2260 | |||
2261 | debug("Setting env %s = %s", name, val); | ||
2262 | channel_request_start(ssh, id, "env", 0); | ||
2263 | packet_put_cstring(name); | ||
2264 | packet_put_cstring(val); | ||
2265 | packet_send(); | ||
2266 | free(name); | ||
2267 | } | ||
2230 | 2268 | ||
2231 | len = buffer_len(cmd); | 2269 | len = sshbuf_len(cmd); |
2232 | if (len > 0) { | 2270 | if (len > 0) { |
2233 | if (len > 900) | 2271 | if (len > 900) |
2234 | len = 900; | 2272 | len = 900; |
2235 | if (want_subsystem) { | 2273 | if (want_subsystem) { |
2236 | debug("Sending subsystem: %.*s", | 2274 | debug("Sending subsystem: %.*s", |
2237 | len, (u_char*)buffer_ptr(cmd)); | 2275 | len, (const u_char*)sshbuf_ptr(cmd)); |
2238 | channel_request_start(ssh, id, "subsystem", 1); | 2276 | channel_request_start(ssh, id, "subsystem", 1); |
2239 | client_expect_confirm(ssh, id, "subsystem", | 2277 | client_expect_confirm(ssh, id, "subsystem", |
2240 | CONFIRM_CLOSE); | 2278 | CONFIRM_CLOSE); |
2241 | } else { | 2279 | } else { |
2242 | debug("Sending command: %.*s", | 2280 | debug("Sending command: %.*s", |
2243 | len, (u_char*)buffer_ptr(cmd)); | 2281 | len, (const u_char*)sshbuf_ptr(cmd)); |
2244 | channel_request_start(ssh, id, "exec", 1); | 2282 | channel_request_start(ssh, id, "exec", 1); |
2245 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); | 2283 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); |
2246 | } | 2284 | } |
2247 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2285 | packet_put_string(sshbuf_ptr(cmd), sshbuf_len(cmd)); |
2248 | packet_send(); | 2286 | packet_send(); |
2249 | } else { | 2287 | } else { |
2250 | channel_request_start(ssh, id, "shell", 1); | 2288 | channel_request_start(ssh, id, "shell", 1); |