summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/channels.c b/channels.c
index c85d46abd..657381b80 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.386 2018/10/04 01:04:52 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.389 2019/01/19 21:37:13 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
@@ -227,11 +227,7 @@ channel_init_channels(struct ssh *ssh)
227{ 227{
228 struct ssh_channels *sc; 228 struct ssh_channels *sc;
229 229
230 if ((sc = calloc(1, sizeof(*sc))) == NULL || 230 if ((sc = calloc(1, sizeof(*sc))) == NULL)
231 (sc->channel_pre = calloc(SSH_CHANNEL_MAX_TYPE,
232 sizeof(*sc->channel_pre))) == NULL ||
233 (sc->channel_post = calloc(SSH_CHANNEL_MAX_TYPE,
234 sizeof(*sc->channel_post))) == NULL)
235 fatal("%s: allocation failed", __func__); 231 fatal("%s: allocation failed", __func__);
236 sc->channels_alloc = 10; 232 sc->channels_alloc = 10;
237 sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); 233 sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels));
@@ -2104,16 +2100,18 @@ channel_handle_efd_read(struct ssh *ssh, Channel *c,
2104 fd_set *readset, fd_set *writeset) 2100 fd_set *readset, fd_set *writeset)
2105{ 2101{
2106 char buf[CHAN_RBUF]; 2102 char buf[CHAN_RBUF];
2107 int r;
2108 ssize_t len; 2103 ssize_t len;
2104 int r, force;
2105
2106 force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
2109 2107
2110 if (!c->detach_close && !FD_ISSET(c->efd, readset)) 2108 if (c->efd == -1 || (!force && !FD_ISSET(c->efd, readset)))
2111 return 1; 2109 return 1;
2112 2110
2113 len = read(c->efd, buf, sizeof(buf)); 2111 len = read(c->efd, buf, sizeof(buf));
2114 debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); 2112 debug2("channel %d: read %zd from efd %d", c->self, len, c->efd);
2115 if (len < 0 && (errno == EINTR || ((errno == EAGAIN || 2113 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
2116 errno == EWOULDBLOCK) && !c->detach_close))) 2114 errno == EWOULDBLOCK) && !force)))
2117 return 1; 2115 return 1;
2118 if (len <= 0) { 2116 if (len <= 0) {
2119 debug2("channel %d: closing read-efd %d", 2117 debug2("channel %d: closing read-efd %d",
@@ -2995,10 +2993,10 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
2995 return 0; 2993 return 0;
2996 2994
2997 /* Get the data. */ 2995 /* Get the data. */
2998 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) 2996 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
2997 (r = sshpkt_get_end(ssh)) != 0)
2999 fatal("%s: channel %d: get data: %s", __func__, 2998 fatal("%s: channel %d: get data: %s", __func__,
3000 c->self, ssh_err(r)); 2999 c->self, ssh_err(r));
3001 ssh_packet_check_eom(ssh);
3002 3000
3003 win_len = data_len; 3001 win_len = data_len;
3004 if (c->datagram) 3002 if (c->datagram)
@@ -3072,11 +3070,11 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
3072 logit("channel %d: bad ext data", c->self); 3070 logit("channel %d: bad ext data", c->self);
3073 return 0; 3071 return 0;
3074 } 3072 }
3075 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) { 3073 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
3074 (r = sshpkt_get_end(ssh)) != 0) {
3076 error("%s: parse data: %s", __func__, ssh_err(r)); 3075 error("%s: parse data: %s", __func__, ssh_err(r));
3077 ssh_packet_disconnect(ssh, "Invalid extended_data message"); 3076 ssh_packet_disconnect(ssh, "Invalid extended_data message");
3078 } 3077 }
3079 ssh_packet_check_eom(ssh);
3080 3078
3081 if (data_len > c->local_window) { 3079 if (data_len > c->local_window) {
3082 logit("channel %d: rcvd too much extended_data %zu, win %u", 3080 logit("channel %d: rcvd too much extended_data %zu, win %u",
@@ -3095,8 +3093,12 @@ int
3095channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) 3093channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh)
3096{ 3094{
3097 Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); 3095 Channel *c = channel_from_packet_id(ssh, __func__, "ieof");
3096 int r;
3098 3097
3099 ssh_packet_check_eom(ssh); 3098 if ((r = sshpkt_get_end(ssh)) != 0) {
3099 error("%s: parse data: %s", __func__, ssh_err(r));
3100 ssh_packet_disconnect(ssh, "Invalid ieof message");
3101 }
3100 3102
3101 if (channel_proxy_upstream(c, type, seq, ssh)) 3103 if (channel_proxy_upstream(c, type, seq, ssh))
3102 return 0; 3104 return 0;
@@ -3116,10 +3118,14 @@ int
3116channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) 3118channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh)
3117{ 3119{
3118 Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); 3120 Channel *c = channel_from_packet_id(ssh, __func__, "oclose");
3121 int r;
3119 3122
3120 if (channel_proxy_upstream(c, type, seq, ssh)) 3123 if (channel_proxy_upstream(c, type, seq, ssh))
3121 return 0; 3124 return 0;
3122 ssh_packet_check_eom(ssh); 3125 if ((r = sshpkt_get_end(ssh)) != 0) {
3126 error("%s: parse data: %s", __func__, ssh_err(r));
3127 ssh_packet_disconnect(ssh, "Invalid oclose message");
3128 }
3123 chan_rcvd_oclose(ssh, c); 3129 chan_rcvd_oclose(ssh, c);
3124 return 0; 3130 return 0;
3125} 3131}
@@ -3134,7 +3140,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
3134 if (channel_proxy_upstream(c, type, seq, ssh)) 3140 if (channel_proxy_upstream(c, type, seq, ssh))
3135 return 0; 3141 return 0;
3136 if (c->type != SSH_CHANNEL_OPENING) 3142 if (c->type != SSH_CHANNEL_OPENING)
3137 packet_disconnect("Received open confirmation for " 3143 ssh_packet_disconnect(ssh, "Received open confirmation for "
3138 "non-opening channel %d.", c->self); 3144 "non-opening channel %d.", c->self);
3139 /* 3145 /*
3140 * Record the remote channel number and mark that the channel 3146 * Record the remote channel number and mark that the channel
@@ -3142,11 +3148,11 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
3142 */ 3148 */
3143 if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || 3149 if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 ||
3144 (r = sshpkt_get_u32(ssh, &remote_window)) != 0 || 3150 (r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||
3145 (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { 3151 (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 ||
3152 (r = sshpkt_get_end(ssh)) != 0) {
3146 error("%s: window/maxpacket: %s", __func__, ssh_err(r)); 3153 error("%s: window/maxpacket: %s", __func__, ssh_err(r));
3147 packet_disconnect("Invalid open confirmation message"); 3154 ssh_packet_disconnect(ssh, "Invalid open confirmation message");
3148 } 3155 }
3149 ssh_packet_check_eom(ssh);
3150 3156
3151 c->have_remote_id = 1; 3157 c->have_remote_id = 1;
3152 c->remote_window = remote_window; 3158 c->remote_window = remote_window;
@@ -3189,19 +3195,19 @@ channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh)
3189 if (channel_proxy_upstream(c, type, seq, ssh)) 3195 if (channel_proxy_upstream(c, type, seq, ssh))
3190 return 0; 3196 return 0;
3191 if (c->type != SSH_CHANNEL_OPENING) 3197 if (c->type != SSH_CHANNEL_OPENING)
3192 packet_disconnect("Received open failure for " 3198 ssh_packet_disconnect(ssh, "Received open failure for "
3193 "non-opening channel %d.", c->self); 3199 "non-opening channel %d.", c->self);
3194 if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { 3200 if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {
3195 error("%s: reason: %s", __func__, ssh_err(r)); 3201 error("%s: reason: %s", __func__, ssh_err(r));
3196 packet_disconnect("Invalid open failure message"); 3202 ssh_packet_disconnect(ssh, "Invalid open failure message");
3197 } 3203 }
3198 /* skip language */ 3204 /* skip language */
3199 if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || 3205 if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||
3200 (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0) { 3206 (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0 ||
3207 (r = sshpkt_get_end(ssh)) != 0) {
3201 error("%s: message/lang: %s", __func__, ssh_err(r)); 3208 error("%s: message/lang: %s", __func__, ssh_err(r));
3202 packet_disconnect("Invalid open failure message"); 3209 ssh_packet_disconnect(ssh, "Invalid open failure message");
3203 } 3210 }
3204 ssh_packet_check_eom(ssh);
3205 logit("channel %d: open failed: %s%s%s", c->self, 3211 logit("channel %d: open failed: %s%s%s", c->self,
3206 reason2txt(reason), msg ? ": ": "", msg ? msg : ""); 3212 reason2txt(reason), msg ? ": ": "", msg ? msg : "");
3207 free(msg); 3213 free(msg);
@@ -3231,11 +3237,11 @@ channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
3231 3237
3232 if (channel_proxy_upstream(c, type, seq, ssh)) 3238 if (channel_proxy_upstream(c, type, seq, ssh))
3233 return 0; 3239 return 0;
3234 if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) { 3240 if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 ||
3241 (r = sshpkt_get_end(ssh)) != 0) {
3235 error("%s: adjust: %s", __func__, ssh_err(r)); 3242 error("%s: adjust: %s", __func__, ssh_err(r));
3236 packet_disconnect("Invalid window adjust message"); 3243 ssh_packet_disconnect(ssh, "Invalid window adjust message");
3237 } 3244 }
3238 ssh_packet_check_eom(ssh);
3239 debug2("channel %d: rcvd adjust %u", c->self, adjust); 3245 debug2("channel %d: rcvd adjust %u", c->self, adjust);
3240 if ((new_rwin = c->remote_window + adjust) < c->remote_window) { 3246 if ((new_rwin = c->remote_window + adjust) < c->remote_window) {
3241 fatal("channel %d: adjust %u overflows remote window %u", 3247 fatal("channel %d: adjust %u overflows remote window %u",
@@ -3251,9 +3257,10 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
3251 int id = channel_parse_id(ssh, __func__, "status confirm"); 3257 int id = channel_parse_id(ssh, __func__, "status confirm");
3252 Channel *c; 3258 Channel *c;
3253 struct channel_confirm *cc; 3259 struct channel_confirm *cc;
3260 int r;
3254 3261
3255 /* Reset keepalive timeout */ 3262 /* Reset keepalive timeout */
3256 packet_set_alive_timeouts(0); 3263 ssh_packet_set_alive_timeouts(ssh, 0);
3257 3264
3258 debug2("%s: type %d id %d", __func__, type, id); 3265 debug2("%s: type %d id %d", __func__, type, id);
3259 3266
@@ -3263,7 +3270,8 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
3263 } 3270 }
3264 if (channel_proxy_upstream(c, type, seq, ssh)) 3271 if (channel_proxy_upstream(c, type, seq, ssh))
3265 return 0; 3272 return 0;
3266 ssh_packet_check_eom(ssh); 3273 if ((r = sshpkt_get_end(ssh)) != 0)
3274 ssh_packet_disconnect(ssh, "Invalid status confirm message");
3267 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) 3275 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
3268 return 0; 3276 return 0;
3269 cc->cb(ssh, type, c, cc->ctx); 3277 cc->cb(ssh, type, c, cc->ctx);
@@ -3298,7 +3306,7 @@ channel_set_af(struct ssh *ssh, int af)
3298 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set 3306 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
3299 */ 3307 */
3300static const char * 3308static const char *
3301channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, 3309channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp,
3302 int is_client, struct ForwardOptions *fwd_opts) 3310 int is_client, struct ForwardOptions *fwd_opts)
3303{ 3311{
3304 const char *addr = NULL; 3312 const char *addr = NULL;
@@ -3321,7 +3329,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
3321 if (*listen_addr != '\0' && 3329 if (*listen_addr != '\0' &&
3322 strcmp(listen_addr, "0.0.0.0") != 0 && 3330 strcmp(listen_addr, "0.0.0.0") != 0 &&
3323 strcmp(listen_addr, "*") != 0) { 3331 strcmp(listen_addr, "*") != 0) {
3324 packet_send_debug("Forwarding listen address " 3332 ssh_packet_send_debug(ssh,
3333 "Forwarding listen address "
3325 "\"%s\" overridden by server " 3334 "\"%s\" overridden by server "
3326 "GatewayPorts", listen_addr); 3335 "GatewayPorts", listen_addr);
3327 } 3336 }
@@ -3375,7 +3384,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
3375 } 3384 }
3376 3385
3377 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ 3386 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
3378 addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard, 3387 addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard,
3379 is_client, fwd_opts); 3388 is_client, fwd_opts);
3380 debug3("%s: type %d wildcard %d addr %s", __func__, 3389 debug3("%s: type %d wildcard %d addr %s", __func__,
3381 type, wildcard, (addr == NULL) ? "NULL" : addr); 3390 type, wildcard, (addr == NULL) ? "NULL" : addr);
@@ -3392,7 +3401,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
3392 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { 3401 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
3393 if (addr == NULL) { 3402 if (addr == NULL) {
3394 /* This really shouldn't happen */ 3403 /* This really shouldn't happen */
3395 packet_disconnect("getaddrinfo: fatal error: %s", 3404 ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s",
3396 ssh_gai_strerror(r)); 3405 ssh_gai_strerror(r));
3397 } else { 3406 } else {
3398 error("%s: getaddrinfo(%.64s): %s", __func__, addr, 3407 error("%s: getaddrinfo(%.64s): %s", __func__, addr,
@@ -3641,7 +3650,7 @@ channel_cancel_lport_listener_tcpip(struct ssh *ssh,
3641{ 3650{
3642 u_int i; 3651 u_int i;
3643 int found = 0; 3652 int found = 0;
3644 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); 3653 const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts);
3645 3654
3646 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { 3655 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
3647 Channel *c = ssh->chanctxt->channels[i]; 3656 Channel *c = ssh->chanctxt->channels[i];
@@ -3793,7 +3802,7 @@ channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
3793 int *allocated_listen_port, struct ForwardOptions *fwd_opts) 3802 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
3794{ 3803{
3795 if (!check_rfwd_permission(ssh, fwd)) { 3804 if (!check_rfwd_permission(ssh, fwd)) {
3796 packet_send_debug("port forwarding refused"); 3805 ssh_packet_send_debug(ssh, "port forwarding refused");
3797 return 0; 3806 return 0;
3798 } 3807 }
3799 if (fwd->listen_path != NULL) { 3808 if (fwd->listen_path != NULL) {