diff options
Diffstat (limited to 'nchan.c')
-rw-r--r-- | nchan.c | 114 |
1 files changed, 62 insertions, 52 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: nchan.c,v 1.65 2017/04/30 23:28:42 djm Exp $ */ | 1 | /* $OpenBSD: nchan.c,v 1.66 2017/09/12 06:32:07 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 | * |
@@ -34,7 +34,8 @@ | |||
34 | 34 | ||
35 | #include "openbsd-compat/sys-queue.h" | 35 | #include "openbsd-compat/sys-queue.h" |
36 | #include "ssh2.h" | 36 | #include "ssh2.h" |
37 | #include "buffer.h" | 37 | #include "sshbuf.h" |
38 | #include "ssherr.h" | ||
38 | #include "packet.h" | 39 | #include "packet.h" |
39 | #include "channels.h" | 40 | #include "channels.h" |
40 | #include "compat.h" | 41 | #include "compat.h" |
@@ -73,15 +74,15 @@ | |||
73 | /* | 74 | /* |
74 | * ACTIONS: should never update the channel states | 75 | * ACTIONS: should never update the channel states |
75 | */ | 76 | */ |
76 | static void chan_send_eof2(Channel *); | 77 | static void chan_send_eof2(struct ssh *, Channel *); |
77 | static void chan_send_eow2(Channel *); | 78 | static void chan_send_eow2(struct ssh *, Channel *); |
78 | 79 | ||
79 | /* helper */ | 80 | /* helper */ |
80 | static void chan_shutdown_write(Channel *); | 81 | static void chan_shutdown_write(struct ssh *, Channel *); |
81 | static void chan_shutdown_read(Channel *); | 82 | static void chan_shutdown_read(struct ssh *, Channel *); |
82 | 83 | ||
83 | static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; | 84 | static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; |
84 | static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; | 85 | static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; |
85 | 86 | ||
86 | static void | 87 | static void |
87 | chan_set_istate(Channel *c, u_int next) | 88 | chan_set_istate(Channel *c, u_int next) |
@@ -104,12 +105,12 @@ chan_set_ostate(Channel *c, u_int next) | |||
104 | } | 105 | } |
105 | 106 | ||
106 | void | 107 | void |
107 | chan_read_failed(Channel *c) | 108 | chan_read_failed(struct ssh *ssh, Channel *c) |
108 | { | 109 | { |
109 | debug2("channel %d: read failed", c->self); | 110 | debug2("channel %d: read failed", c->self); |
110 | switch (c->istate) { | 111 | switch (c->istate) { |
111 | case CHAN_INPUT_OPEN: | 112 | case CHAN_INPUT_OPEN: |
112 | chan_shutdown_read(c); | 113 | chan_shutdown_read(ssh, c); |
113 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); | 114 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); |
114 | break; | 115 | break; |
115 | default: | 116 | default: |
@@ -120,10 +121,10 @@ chan_read_failed(Channel *c) | |||
120 | } | 121 | } |
121 | 122 | ||
122 | void | 123 | void |
123 | chan_ibuf_empty(Channel *c) | 124 | chan_ibuf_empty(struct ssh *ssh, Channel *c) |
124 | { | 125 | { |
125 | debug2("channel %d: ibuf empty", c->self); | 126 | debug2("channel %d: ibuf empty", c->self); |
126 | if (buffer_len(&c->input)) { | 127 | if (sshbuf_len(c->input)) { |
127 | error("channel %d: chan_ibuf_empty for non empty buffer", | 128 | error("channel %d: chan_ibuf_empty for non empty buffer", |
128 | c->self); | 129 | c->self); |
129 | return; | 130 | return; |
@@ -131,7 +132,7 @@ chan_ibuf_empty(Channel *c) | |||
131 | switch (c->istate) { | 132 | switch (c->istate) { |
132 | case CHAN_INPUT_WAIT_DRAIN: | 133 | case CHAN_INPUT_WAIT_DRAIN: |
133 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) | 134 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) |
134 | chan_send_eof2(c); | 135 | chan_send_eof2(ssh, c); |
135 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 136 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
136 | break; | 137 | break; |
137 | default: | 138 | default: |
@@ -142,17 +143,17 @@ chan_ibuf_empty(Channel *c) | |||
142 | } | 143 | } |
143 | 144 | ||
144 | void | 145 | void |
145 | chan_obuf_empty(Channel *c) | 146 | chan_obuf_empty(struct ssh *ssh, Channel *c) |
146 | { | 147 | { |
147 | debug2("channel %d: obuf empty", c->self); | 148 | debug2("channel %d: obuf empty", c->self); |
148 | if (buffer_len(&c->output)) { | 149 | if (sshbuf_len(c->output)) { |
149 | error("channel %d: chan_obuf_empty for non empty buffer", | 150 | error("channel %d: chan_obuf_empty for non empty buffer", |
150 | c->self); | 151 | c->self); |
151 | return; | 152 | return; |
152 | } | 153 | } |
153 | switch (c->ostate) { | 154 | switch (c->ostate) { |
154 | case CHAN_OUTPUT_WAIT_DRAIN: | 155 | case CHAN_OUTPUT_WAIT_DRAIN: |
155 | chan_shutdown_write(c); | 156 | chan_shutdown_write(ssh, c); |
156 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 157 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
157 | break; | 158 | break; |
158 | default: | 159 | default: |
@@ -163,26 +164,29 @@ chan_obuf_empty(Channel *c) | |||
163 | } | 164 | } |
164 | 165 | ||
165 | void | 166 | void |
166 | chan_rcvd_eow(Channel *c) | 167 | chan_rcvd_eow(struct ssh *ssh, Channel *c) |
167 | { | 168 | { |
168 | debug2("channel %d: rcvd eow", c->self); | 169 | debug2("channel %d: rcvd eow", c->self); |
169 | switch (c->istate) { | 170 | switch (c->istate) { |
170 | case CHAN_INPUT_OPEN: | 171 | case CHAN_INPUT_OPEN: |
171 | chan_shutdown_read(c); | 172 | chan_shutdown_read(ssh, c); |
172 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 173 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
173 | break; | 174 | break; |
174 | } | 175 | } |
175 | } | 176 | } |
176 | 177 | ||
177 | static void | 178 | static void |
178 | chan_send_eof2(Channel *c) | 179 | chan_send_eof2(struct ssh *ssh, Channel *c) |
179 | { | 180 | { |
181 | int r; | ||
182 | |||
180 | debug2("channel %d: send eof", c->self); | 183 | debug2("channel %d: send eof", c->self); |
181 | switch (c->istate) { | 184 | switch (c->istate) { |
182 | case CHAN_INPUT_WAIT_DRAIN: | 185 | case CHAN_INPUT_WAIT_DRAIN: |
183 | packet_start(SSH2_MSG_CHANNEL_EOF); | 186 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || |
184 | packet_put_int(c->remote_id); | 187 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
185 | packet_send(); | 188 | (r = sshpkt_send(ssh)) != 0) |
189 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
186 | c->flags |= CHAN_EOF_SENT; | 190 | c->flags |= CHAN_EOF_SENT; |
187 | break; | 191 | break; |
188 | default: | 192 | default: |
@@ -193,8 +197,10 @@ chan_send_eof2(Channel *c) | |||
193 | } | 197 | } |
194 | 198 | ||
195 | static void | 199 | static void |
196 | chan_send_close2(Channel *c) | 200 | chan_send_close2(struct ssh *ssh, Channel *c) |
197 | { | 201 | { |
202 | int r; | ||
203 | |||
198 | debug2("channel %d: send close", c->self); | 204 | debug2("channel %d: send close", c->self); |
199 | if (c->ostate != CHAN_OUTPUT_CLOSED || | 205 | if (c->ostate != CHAN_OUTPUT_CLOSED || |
200 | c->istate != CHAN_INPUT_CLOSED) { | 206 | c->istate != CHAN_INPUT_CLOSED) { |
@@ -203,16 +209,19 @@ chan_send_close2(Channel *c) | |||
203 | } else if (c->flags & CHAN_CLOSE_SENT) { | 209 | } else if (c->flags & CHAN_CLOSE_SENT) { |
204 | error("channel %d: already sent close", c->self); | 210 | error("channel %d: already sent close", c->self); |
205 | } else { | 211 | } else { |
206 | packet_start(SSH2_MSG_CHANNEL_CLOSE); | 212 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || |
207 | packet_put_int(c->remote_id); | 213 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
208 | packet_send(); | 214 | (r = sshpkt_send(ssh)) != 0) |
215 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
209 | c->flags |= CHAN_CLOSE_SENT; | 216 | c->flags |= CHAN_CLOSE_SENT; |
210 | } | 217 | } |
211 | } | 218 | } |
212 | 219 | ||
213 | static void | 220 | static void |
214 | chan_send_eow2(Channel *c) | 221 | chan_send_eow2(struct ssh *ssh, Channel *c) |
215 | { | 222 | { |
223 | int r; | ||
224 | |||
216 | debug2("channel %d: send eow", c->self); | 225 | debug2("channel %d: send eow", c->self); |
217 | if (c->ostate == CHAN_OUTPUT_CLOSED) { | 226 | if (c->ostate == CHAN_OUTPUT_CLOSED) { |
218 | error("channel %d: must not sent eow on closed output", | 227 | error("channel %d: must not sent eow on closed output", |
@@ -221,30 +230,31 @@ chan_send_eow2(Channel *c) | |||
221 | } | 230 | } |
222 | if (!(datafellows & SSH_NEW_OPENSSH)) | 231 | if (!(datafellows & SSH_NEW_OPENSSH)) |
223 | return; | 232 | return; |
224 | packet_start(SSH2_MSG_CHANNEL_REQUEST); | 233 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || |
225 | packet_put_int(c->remote_id); | 234 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
226 | packet_put_cstring("eow@openssh.com"); | 235 | (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || |
227 | packet_put_char(0); | 236 | (r = sshpkt_put_u8(ssh, 0)) != 0 || |
228 | packet_send(); | 237 | (r = sshpkt_send(ssh)) != 0) |
238 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
229 | } | 239 | } |
230 | 240 | ||
231 | /* shared */ | 241 | /* shared */ |
232 | 242 | ||
233 | void | 243 | void |
234 | chan_rcvd_ieof(Channel *c) | 244 | chan_rcvd_ieof(struct ssh *ssh, Channel *c) |
235 | { | 245 | { |
236 | debug2("channel %d: rcvd eof", c->self); | 246 | debug2("channel %d: rcvd eof", c->self); |
237 | c->flags |= CHAN_EOF_RCVD; | 247 | c->flags |= CHAN_EOF_RCVD; |
238 | if (c->ostate == CHAN_OUTPUT_OPEN) | 248 | if (c->ostate == CHAN_OUTPUT_OPEN) |
239 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | 249 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
240 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | 250 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && |
241 | buffer_len(&c->output) == 0 && | 251 | sshbuf_len(c->output) == 0 && |
242 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | 252 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
243 | chan_obuf_empty(c); | 253 | chan_obuf_empty(ssh, c); |
244 | } | 254 | } |
245 | 255 | ||
246 | void | 256 | void |
247 | chan_rcvd_oclose(Channel *c) | 257 | chan_rcvd_oclose(struct ssh *ssh, Channel *c) |
248 | { | 258 | { |
249 | debug2("channel %d: rcvd close", c->self); | 259 | debug2("channel %d: rcvd close", c->self); |
250 | if (!(c->flags & CHAN_LOCAL)) { | 260 | if (!(c->flags & CHAN_LOCAL)) { |
@@ -270,27 +280,27 @@ chan_rcvd_oclose(Channel *c) | |||
270 | } | 280 | } |
271 | switch (c->istate) { | 281 | switch (c->istate) { |
272 | case CHAN_INPUT_OPEN: | 282 | case CHAN_INPUT_OPEN: |
273 | chan_shutdown_read(c); | 283 | chan_shutdown_read(ssh, c); |
274 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 284 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
275 | break; | 285 | break; |
276 | case CHAN_INPUT_WAIT_DRAIN: | 286 | case CHAN_INPUT_WAIT_DRAIN: |
277 | if (!(c->flags & CHAN_LOCAL)) | 287 | if (!(c->flags & CHAN_LOCAL)) |
278 | chan_send_eof2(c); | 288 | chan_send_eof2(ssh, c); |
279 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 289 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
280 | break; | 290 | break; |
281 | } | 291 | } |
282 | } | 292 | } |
283 | 293 | ||
284 | void | 294 | void |
285 | chan_write_failed(Channel *c) | 295 | chan_write_failed(struct ssh *ssh, Channel *c) |
286 | { | 296 | { |
287 | debug2("channel %d: write failed", c->self); | 297 | debug2("channel %d: write failed", c->self); |
288 | switch (c->ostate) { | 298 | switch (c->ostate) { |
289 | case CHAN_OUTPUT_OPEN: | 299 | case CHAN_OUTPUT_OPEN: |
290 | case CHAN_OUTPUT_WAIT_DRAIN: | 300 | case CHAN_OUTPUT_WAIT_DRAIN: |
291 | chan_shutdown_write(c); | 301 | chan_shutdown_write(ssh, c); |
292 | if (strcmp(c->ctype, "session") == 0) | 302 | if (strcmp(c->ctype, "session") == 0) |
293 | chan_send_eow2(c); | 303 | chan_send_eow2(ssh, c); |
294 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 304 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
295 | break; | 305 | break; |
296 | default: | 306 | default: |
@@ -301,13 +311,13 @@ chan_write_failed(Channel *c) | |||
301 | } | 311 | } |
302 | 312 | ||
303 | void | 313 | void |
304 | chan_mark_dead(Channel *c) | 314 | chan_mark_dead(struct ssh *ssh, Channel *c) |
305 | { | 315 | { |
306 | c->type = SSH_CHANNEL_ZOMBIE; | 316 | c->type = SSH_CHANNEL_ZOMBIE; |
307 | } | 317 | } |
308 | 318 | ||
309 | int | 319 | int |
310 | chan_is_dead(Channel *c, int do_send) | 320 | chan_is_dead(struct ssh *ssh, Channel *c, int do_send) |
311 | { | 321 | { |
312 | if (c->type == SSH_CHANNEL_ZOMBIE) { | 322 | if (c->type == SSH_CHANNEL_ZOMBIE) { |
313 | debug2("channel %d: zombie", c->self); | 323 | debug2("channel %d: zombie", c->self); |
@@ -318,9 +328,9 @@ chan_is_dead(Channel *c, int do_send) | |||
318 | if ((datafellows & SSH_BUG_EXTEOF) && | 328 | if ((datafellows & SSH_BUG_EXTEOF) && |
319 | c->extended_usage == CHAN_EXTENDED_WRITE && | 329 | c->extended_usage == CHAN_EXTENDED_WRITE && |
320 | c->efd != -1 && | 330 | c->efd != -1 && |
321 | buffer_len(&c->extended) > 0) { | 331 | sshbuf_len(c->extended) > 0) { |
322 | debug2("channel %d: active efd: %d len %d", | 332 | debug2("channel %d: active efd: %d len %zu", |
323 | c->self, c->efd, buffer_len(&c->extended)); | 333 | c->self, c->efd, sshbuf_len(c->extended)); |
324 | return 0; | 334 | return 0; |
325 | } | 335 | } |
326 | if (c->flags & CHAN_LOCAL) { | 336 | if (c->flags & CHAN_LOCAL) { |
@@ -329,7 +339,7 @@ chan_is_dead(Channel *c, int do_send) | |||
329 | } | 339 | } |
330 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 340 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
331 | if (do_send) { | 341 | if (do_send) { |
332 | chan_send_close2(c); | 342 | chan_send_close2(ssh, c); |
333 | } else { | 343 | } else { |
334 | /* channel would be dead if we sent a close */ | 344 | /* channel would be dead if we sent a close */ |
335 | if (c->flags & CHAN_CLOSE_RCVD) { | 345 | if (c->flags & CHAN_CLOSE_RCVD) { |
@@ -349,9 +359,9 @@ chan_is_dead(Channel *c, int do_send) | |||
349 | 359 | ||
350 | /* helper */ | 360 | /* helper */ |
351 | static void | 361 | static void |
352 | chan_shutdown_write(Channel *c) | 362 | chan_shutdown_write(struct ssh *ssh, Channel *c) |
353 | { | 363 | { |
354 | buffer_clear(&c->output); | 364 | sshbuf_reset(c->output); |
355 | if (c->type == SSH_CHANNEL_LARVAL) | 365 | if (c->type == SSH_CHANNEL_LARVAL) |
356 | return; | 366 | return; |
357 | /* shutdown failure is allowed if write failed already */ | 367 | /* shutdown failure is allowed if write failed already */ |
@@ -362,7 +372,7 @@ chan_shutdown_write(Channel *c) | |||
362 | "shutdown() failed for fd %d: %.100s", | 372 | "shutdown() failed for fd %d: %.100s", |
363 | c->self, c->sock, strerror(errno)); | 373 | c->self, c->sock, strerror(errno)); |
364 | } else { | 374 | } else { |
365 | if (channel_close_fd(&c->wfd) < 0) | 375 | if (channel_close_fd(ssh, &c->wfd) < 0) |
366 | logit("channel %d: chan_shutdown_write: " | 376 | logit("channel %d: chan_shutdown_write: " |
367 | "close() failed for fd %d: %.100s", | 377 | "close() failed for fd %d: %.100s", |
368 | c->self, c->wfd, strerror(errno)); | 378 | c->self, c->wfd, strerror(errno)); |
@@ -370,7 +380,7 @@ chan_shutdown_write(Channel *c) | |||
370 | } | 380 | } |
371 | 381 | ||
372 | static void | 382 | static void |
373 | chan_shutdown_read(Channel *c) | 383 | chan_shutdown_read(struct ssh *ssh, Channel *c) |
374 | { | 384 | { |
375 | if (c->type == SSH_CHANNEL_LARVAL) | 385 | if (c->type == SSH_CHANNEL_LARVAL) |
376 | return; | 386 | return; |
@@ -388,7 +398,7 @@ chan_shutdown_read(Channel *c) | |||
388 | c->self, c->sock, c->istate, c->ostate, | 398 | c->self, c->sock, c->istate, c->ostate, |
389 | strerror(errno)); | 399 | strerror(errno)); |
390 | } else { | 400 | } else { |
391 | if (channel_close_fd(&c->rfd) < 0) | 401 | if (channel_close_fd(ssh, &c->rfd) < 0) |
392 | logit("channel %d: chan_shutdown_read: " | 402 | logit("channel %d: chan_shutdown_read: " |
393 | "close() failed for fd %d: %.100s", | 403 | "close() failed for fd %d: %.100s", |
394 | c->self, c->rfd, strerror(errno)); | 404 | c->self, c->rfd, strerror(errno)); |