diff options
author | markus@openbsd.org <markus@openbsd.org> | 2018-07-09 21:18:10 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-07-10 15:14:26 +1000 |
commit | f4608a7065480516ab46214f554e5f853fb7870f (patch) | |
tree | 6e084f7cc4dbbc358b063c4e366d1da3d8a6e9a7 /mux.c | |
parent | cecee2d607099a7bba0a84803e2325d15be4277b (diff) |
upstream: client: switch mux to sshbuf API; with & ok djm@
OpenBSD-Commit-ID: 5948fb98d704f9c4e075b92edda64e0290b5feb2
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 921 |
1 files changed, 507 insertions, 414 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.72 2018/07/09 21:03:30 markus Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.73 2018/07/09 21:18:10 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -70,7 +70,7 @@ | |||
70 | #include "pathnames.h" | 70 | #include "pathnames.h" |
71 | #include "misc.h" | 71 | #include "misc.h" |
72 | #include "match.h" | 72 | #include "match.h" |
73 | #include "buffer.h" | 73 | #include "sshbuf.h" |
74 | #include "channels.h" | 74 | #include "channels.h" |
75 | #include "msg.h" | 75 | #include "msg.h" |
76 | #include "packet.h" | 76 | #include "packet.h" |
@@ -96,7 +96,7 @@ struct mux_session_confirm_ctx { | |||
96 | u_int want_subsys; | 96 | u_int want_subsys; |
97 | u_int want_x_fwd; | 97 | u_int want_x_fwd; |
98 | u_int want_agent_fwd; | 98 | u_int want_agent_fwd; |
99 | Buffer cmd; | 99 | struct sshbuf *cmd; |
100 | char *term; | 100 | char *term; |
101 | struct termios tio; | 101 | struct termios tio; |
102 | char **env; | 102 | char **env; |
@@ -279,10 +279,11 @@ env_permitted(char *env) | |||
279 | 279 | ||
280 | static int | 280 | static int |
281 | process_mux_master_hello(struct ssh *ssh, u_int rid, | 281 | process_mux_master_hello(struct ssh *ssh, u_int rid, |
282 | Channel *c, Buffer *m, Buffer *r) | 282 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
283 | { | 283 | { |
284 | u_int ver; | 284 | u_int ver; |
285 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 285 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
286 | int r; | ||
286 | 287 | ||
287 | if (state == NULL) | 288 | if (state == NULL) |
288 | fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self); | 289 | fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self); |
@@ -290,9 +291,8 @@ process_mux_master_hello(struct ssh *ssh, u_int rid, | |||
290 | error("%s: HELLO received twice", __func__); | 291 | error("%s: HELLO received twice", __func__); |
291 | return -1; | 292 | return -1; |
292 | } | 293 | } |
293 | if (buffer_get_int_ret(&ver, m) != 0) { | 294 | if ((r = sshbuf_get_u32(m, &ver)) != 0) { |
294 | malf: | 295 | error("%s: malformed message: %s", __func__, ssh_err(r)); |
295 | error("%s: malformed message", __func__); | ||
296 | return -1; | 296 | return -1; |
297 | } | 297 | } |
298 | if (ver != SSHMUX_VER) { | 298 | if (ver != SSHMUX_VER) { |
@@ -303,51 +303,72 @@ process_mux_master_hello(struct ssh *ssh, u_int rid, | |||
303 | debug2("%s: channel %d slave version %u", __func__, c->self, ver); | 303 | debug2("%s: channel %d slave version %u", __func__, c->self, ver); |
304 | 304 | ||
305 | /* No extensions are presently defined */ | 305 | /* No extensions are presently defined */ |
306 | while (buffer_len(m) > 0) { | 306 | while (sshbuf_len(m) > 0) { |
307 | char *name = buffer_get_string_ret(m, NULL); | 307 | char *name = NULL; |
308 | char *value = buffer_get_string_ret(m, NULL); | ||
309 | 308 | ||
310 | if (name == NULL || value == NULL) { | 309 | if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || |
311 | free(name); | 310 | (r = sshbuf_skip_string(m)) != 0) { /* value */ |
312 | free(value); | 311 | error("%s: malformed extension: %s", |
313 | goto malf; | 312 | __func__, ssh_err(r)); |
313 | return -1; | ||
314 | } | 314 | } |
315 | debug2("Unrecognised slave extension \"%s\"", name); | 315 | debug2("Unrecognised slave extension \"%s\"", name); |
316 | free(name); | 316 | free(name); |
317 | free(value); | ||
318 | } | 317 | } |
319 | state->hello_rcvd = 1; | 318 | state->hello_rcvd = 1; |
320 | return 0; | 319 | return 0; |
321 | } | 320 | } |
322 | 321 | ||
322 | /* Enqueue a "ok" response to the reply buffer */ | ||
323 | static void | ||
324 | reply_ok(struct sshbuf *reply, u_int rid) | ||
325 | { | ||
326 | int r; | ||
327 | |||
328 | if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 || | ||
329 | (r = sshbuf_put_u32(reply, rid)) != 0) | ||
330 | fatal("%s: reply: %s", __func__, ssh_err(r)); | ||
331 | } | ||
332 | |||
333 | /* Enqueue an error response to the reply buffer */ | ||
334 | static void | ||
335 | reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg) | ||
336 | { | ||
337 | int r; | ||
338 | |||
339 | if ((r = sshbuf_put_u32(reply, type)) != 0 || | ||
340 | (r = sshbuf_put_u32(reply, rid)) != 0 || | ||
341 | (r = sshbuf_put_cstring(reply, msg)) != 0) | ||
342 | fatal("%s: reply: %s", __func__, ssh_err(r)); | ||
343 | } | ||
344 | |||
323 | static int | 345 | static int |
324 | process_mux_new_session(struct ssh *ssh, u_int rid, | 346 | process_mux_new_session(struct ssh *ssh, u_int rid, |
325 | Channel *c, Buffer *m, Buffer *r) | 347 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
326 | { | 348 | { |
327 | Channel *nc; | 349 | Channel *nc; |
328 | struct mux_session_confirm_ctx *cctx; | 350 | struct mux_session_confirm_ctx *cctx; |
329 | char *reserved, *cmd, *cp; | 351 | char *cmd, *cp; |
330 | u_int i, j, len, env_len, escape_char, window, packetmax; | 352 | u_int i, j, env_len, escape_char, window, packetmax; |
331 | int new_fd[3]; | 353 | int r, new_fd[3]; |
332 | 354 | ||
333 | /* Reply for SSHMUX_COMMAND_OPEN */ | 355 | /* Reply for SSHMUX_COMMAND_OPEN */ |
334 | cctx = xcalloc(1, sizeof(*cctx)); | 356 | cctx = xcalloc(1, sizeof(*cctx)); |
335 | cctx->term = NULL; | 357 | cctx->term = NULL; |
336 | cctx->rid = rid; | 358 | cctx->rid = rid; |
337 | cmd = reserved = NULL; | 359 | cmd = NULL; |
338 | cctx->env = NULL; | 360 | cctx->env = NULL; |
339 | env_len = 0; | 361 | env_len = 0; |
340 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || | 362 | if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ |
341 | buffer_get_int_ret(&cctx->want_tty, m) != 0 || | 363 | (r = sshbuf_get_u32(m, &cctx->want_tty)) != 0 || |
342 | buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 || | 364 | (r = sshbuf_get_u32(m, &cctx->want_x_fwd)) != 0 || |
343 | buffer_get_int_ret(&cctx->want_agent_fwd, m) != 0 || | 365 | (r = sshbuf_get_u32(m, &cctx->want_agent_fwd)) != 0 || |
344 | buffer_get_int_ret(&cctx->want_subsys, m) != 0 || | 366 | (r = sshbuf_get_u32(m, &cctx->want_subsys)) != 0 || |
345 | buffer_get_int_ret(&escape_char, m) != 0 || | 367 | (r = sshbuf_get_u32(m, &escape_char)) != 0 || |
346 | (cctx->term = buffer_get_string_ret(m, &len)) == NULL || | 368 | (r = sshbuf_get_cstring(m, &cctx->term, NULL)) != 0 || |
347 | (cmd = buffer_get_string_ret(m, &len)) == NULL) { | 369 | (r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) { |
348 | malf: | 370 | malf: |
349 | free(cmd); | 371 | free(cmd); |
350 | free(reserved); | ||
351 | for (j = 0; j < env_len; j++) | 372 | for (j = 0; j < env_len; j++) |
352 | free(cctx->env[j]); | 373 | free(cctx->env[j]); |
353 | free(cctx->env); | 374 | free(cctx->env); |
@@ -356,12 +377,10 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
356 | error("%s: malformed message", __func__); | 377 | error("%s: malformed message", __func__); |
357 | return -1; | 378 | return -1; |
358 | } | 379 | } |
359 | free(reserved); | ||
360 | reserved = NULL; | ||
361 | 380 | ||
362 | while (buffer_len(m) > 0) { | ||
363 | #define MUX_MAX_ENV_VARS 4096 | 381 | #define MUX_MAX_ENV_VARS 4096 |
364 | if ((cp = buffer_get_string_ret(m, &len)) == NULL) | 382 | while (sshbuf_len(m) > 0) { |
383 | if ((r = sshbuf_get_cstring(m, &cp, NULL)) != 0) | ||
365 | goto malf; | 384 | goto malf; |
366 | if (!env_permitted(cp)) { | 385 | if (!env_permitted(cp)) { |
367 | free(cp); | 386 | free(cp); |
@@ -383,8 +402,10 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
383 | cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd, | 402 | cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd, |
384 | cctx->want_subsys, cctx->term, cmd, env_len); | 403 | cctx->want_subsys, cctx->term, cmd, env_len); |
385 | 404 | ||
386 | buffer_init(&cctx->cmd); | 405 | if ((cctx->cmd = sshbuf_new()) == NULL) |
387 | buffer_append(&cctx->cmd, cmd, strlen(cmd)); | 406 | fatal("%s: sshbuf_new", __func__); |
407 | if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0) | ||
408 | fatal("%s: sshbuf_put: %s", __func__, ssh_err(r)); | ||
388 | free(cmd); | 409 | free(cmd); |
389 | cmd = NULL; | 410 | cmd = NULL; |
390 | 411 | ||
@@ -399,13 +420,9 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
399 | free(cctx->env[j]); | 420 | free(cctx->env[j]); |
400 | free(cctx->env); | 421 | free(cctx->env); |
401 | free(cctx->term); | 422 | free(cctx->term); |
402 | buffer_free(&cctx->cmd); | 423 | sshbuf_free(cctx->cmd); |
403 | free(cctx); | 424 | free(cctx); |
404 | 425 | reply_error(reply, MUX_S_FAILURE, rid, | |
405 | /* prepare reply */ | ||
406 | buffer_put_int(r, MUX_S_FAILURE); | ||
407 | buffer_put_int(r, rid); | ||
408 | buffer_put_cstring(r, | ||
409 | "did not receive file descriptors"); | 426 | "did not receive file descriptors"); |
410 | return -1; | 427 | return -1; |
411 | } | 428 | } |
@@ -417,10 +434,8 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
417 | /* XXX support multiple child sessions in future */ | 434 | /* XXX support multiple child sessions in future */ |
418 | if (c->have_remote_id) { | 435 | if (c->have_remote_id) { |
419 | debug2("%s: session already open", __func__); | 436 | debug2("%s: session already open", __func__); |
420 | /* prepare reply */ | 437 | reply_error(reply, MUX_S_FAILURE, rid, |
421 | buffer_put_int(r, MUX_S_FAILURE); | 438 | "Multiple sessions not supported"); |
422 | buffer_put_int(r, rid); | ||
423 | buffer_put_cstring(r, "Multiple sessions not supported"); | ||
424 | cleanup: | 439 | cleanup: |
425 | close(new_fd[0]); | 440 | close(new_fd[0]); |
426 | close(new_fd[1]); | 441 | close(new_fd[1]); |
@@ -431,7 +446,7 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
431 | free(cctx->env[i]); | 446 | free(cctx->env[i]); |
432 | free(cctx->env); | 447 | free(cctx->env); |
433 | } | 448 | } |
434 | buffer_free(&cctx->cmd); | 449 | sshbuf_free(cctx->cmd); |
435 | free(cctx); | 450 | free(cctx); |
436 | return 0; | 451 | return 0; |
437 | } | 452 | } |
@@ -440,10 +455,8 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
440 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { | 455 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { |
441 | if (!ask_permission("Allow shared connection to %s? ", host)) { | 456 | if (!ask_permission("Allow shared connection to %s? ", host)) { |
442 | debug2("%s: session refused by user", __func__); | 457 | debug2("%s: session refused by user", __func__); |
443 | /* prepare reply */ | 458 | reply_error(reply, MUX_S_PERMISSION_DENIED, rid, |
444 | buffer_put_int(r, MUX_S_PERMISSION_DENIED); | 459 | "Permission denied"); |
445 | buffer_put_int(r, rid); | ||
446 | buffer_put_cstring(r, "Permission denied"); | ||
447 | goto cleanup; | 460 | goto cleanup; |
448 | } | 461 | } |
449 | } | 462 | } |
@@ -497,21 +510,24 @@ process_mux_new_session(struct ssh *ssh, u_int rid, | |||
497 | 510 | ||
498 | static int | 511 | static int |
499 | process_mux_alive_check(struct ssh *ssh, u_int rid, | 512 | process_mux_alive_check(struct ssh *ssh, u_int rid, |
500 | Channel *c, Buffer *m, Buffer *r) | 513 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
501 | { | 514 | { |
515 | int r; | ||
516 | |||
502 | debug2("%s: channel %d: alive check", __func__, c->self); | 517 | debug2("%s: channel %d: alive check", __func__, c->self); |
503 | 518 | ||
504 | /* prepare reply */ | 519 | /* prepare reply */ |
505 | buffer_put_int(r, MUX_S_ALIVE); | 520 | if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 || |
506 | buffer_put_int(r, rid); | 521 | (r = sshbuf_put_u32(reply, rid)) != 0 || |
507 | buffer_put_int(r, (u_int)getpid()); | 522 | (r = sshbuf_put_u32(reply, (u_int)getpid())) != 0) |
523 | fatal("%s: reply: %s", __func__, ssh_err(r)); | ||
508 | 524 | ||
509 | return 0; | 525 | return 0; |
510 | } | 526 | } |
511 | 527 | ||
512 | static int | 528 | static int |
513 | process_mux_terminate(struct ssh *ssh, u_int rid, | 529 | process_mux_terminate(struct ssh *ssh, u_int rid, |
514 | Channel *c, Buffer *m, Buffer *r) | 530 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
515 | { | 531 | { |
516 | debug2("%s: channel %d: terminate request", __func__, c->self); | 532 | debug2("%s: channel %d: terminate request", __func__, c->self); |
517 | 533 | ||
@@ -520,16 +536,14 @@ process_mux_terminate(struct ssh *ssh, u_int rid, | |||
520 | if (!ask_permission("Terminate shared connection to %s? ", | 536 | if (!ask_permission("Terminate shared connection to %s? ", |
521 | host)) { | 537 | host)) { |
522 | debug2("%s: termination refused by user", __func__); | 538 | debug2("%s: termination refused by user", __func__); |
523 | buffer_put_int(r, MUX_S_PERMISSION_DENIED); | 539 | reply_error(reply, MUX_S_PERMISSION_DENIED, rid, |
524 | buffer_put_int(r, rid); | 540 | "Permission denied"); |
525 | buffer_put_cstring(r, "Permission denied"); | ||
526 | return 0; | 541 | return 0; |
527 | } | 542 | } |
528 | } | 543 | } |
529 | 544 | ||
530 | quit_pending = 1; | 545 | quit_pending = 1; |
531 | buffer_put_int(r, MUX_S_OK); | 546 | reply_ok(reply, rid); |
532 | buffer_put_int(r, rid); | ||
533 | /* XXX exit happens too soon - message never makes it to client */ | 547 | /* XXX exit happens too soon - message never makes it to client */ |
534 | return 0; | 548 | return 0; |
535 | } | 549 | } |
@@ -606,14 +620,16 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) | |||
606 | char *failmsg = NULL; | 620 | char *failmsg = NULL; |
607 | struct Forward *rfwd; | 621 | struct Forward *rfwd; |
608 | Channel *c; | 622 | Channel *c; |
609 | Buffer out; | 623 | struct sshbuf *out; |
624 | int r; | ||
610 | 625 | ||
611 | if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { | 626 | if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { |
612 | /* no channel for reply */ | 627 | /* no channel for reply */ |
613 | error("%s: unknown channel", __func__); | 628 | error("%s: unknown channel", __func__); |
614 | return; | 629 | return; |
615 | } | 630 | } |
616 | buffer_init(&out); | 631 | if ((out = sshbuf_new()) == NULL) |
632 | fatal("%s: sshbuf_new", __func__); | ||
617 | if (fctx->fid >= options.num_remote_forwards || | 633 | if (fctx->fid >= options.num_remote_forwards || |
618 | (options.remote_forwards[fctx->fid].connect_path == NULL && | 634 | (options.remote_forwards[fctx->fid].connect_path == NULL && |
619 | options.remote_forwards[fctx->fid].connect_host == NULL)) { | 635 | options.remote_forwards[fctx->fid].connect_host == NULL)) { |
@@ -631,14 +647,16 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) | |||
631 | debug("Allocated port %u for mux remote forward" | 647 | debug("Allocated port %u for mux remote forward" |
632 | " to %s:%d", rfwd->allocated_port, | 648 | " to %s:%d", rfwd->allocated_port, |
633 | rfwd->connect_host, rfwd->connect_port); | 649 | rfwd->connect_host, rfwd->connect_port); |
634 | buffer_put_int(&out, MUX_S_REMOTE_PORT); | 650 | if ((r = sshbuf_put_u32(out, |
635 | buffer_put_int(&out, fctx->rid); | 651 | MUX_S_REMOTE_PORT)) != 0 || |
636 | buffer_put_int(&out, rfwd->allocated_port); | 652 | (r = sshbuf_put_u32(out, fctx->rid)) != 0 || |
653 | (r = sshbuf_put_u32(out, | ||
654 | rfwd->allocated_port)) != 0) | ||
655 | fatal("%s: reply: %s", __func__, ssh_err(r)); | ||
637 | channel_update_permission(ssh, rfwd->handle, | 656 | channel_update_permission(ssh, rfwd->handle, |
638 | rfwd->allocated_port); | 657 | rfwd->allocated_port); |
639 | } else { | 658 | } else { |
640 | buffer_put_int(&out, MUX_S_OK); | 659 | reply_ok(out, fctx->rid); |
641 | buffer_put_int(&out, fctx->rid); | ||
642 | } | 660 | } |
643 | goto out; | 661 | goto out; |
644 | } else { | 662 | } else { |
@@ -664,13 +682,12 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) | |||
664 | } | 682 | } |
665 | fail: | 683 | fail: |
666 | error("%s: %s", __func__, failmsg); | 684 | error("%s: %s", __func__, failmsg); |
667 | buffer_put_int(&out, MUX_S_FAILURE); | 685 | reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg); |
668 | buffer_put_int(&out, fctx->rid); | ||
669 | buffer_put_cstring(&out, failmsg); | ||
670 | free(failmsg); | 686 | free(failmsg); |
671 | out: | 687 | out: |
672 | buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out)); | 688 | if ((r = sshbuf_put_stringb(c->output, out)) != 0) |
673 | buffer_free(&out); | 689 | fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); |
690 | sshbuf_free(out); | ||
674 | if (c->mux_pause <= 0) | 691 | if (c->mux_pause <= 0) |
675 | fatal("%s: mux_pause %d", __func__, c->mux_pause); | 692 | fatal("%s: mux_pause %d", __func__, c->mux_pause); |
676 | c->mux_pause = 0; /* start processing messages again */ | 693 | c->mux_pause = 0; /* start processing messages again */ |
@@ -678,23 +695,23 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) | |||
678 | 695 | ||
679 | static int | 696 | static int |
680 | process_mux_open_fwd(struct ssh *ssh, u_int rid, | 697 | process_mux_open_fwd(struct ssh *ssh, u_int rid, |
681 | Channel *c, Buffer *m, Buffer *r) | 698 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
682 | { | 699 | { |
683 | struct Forward fwd; | 700 | struct Forward fwd; |
684 | char *fwd_desc = NULL; | 701 | char *fwd_desc = NULL; |
685 | char *listen_addr, *connect_addr; | 702 | char *listen_addr, *connect_addr; |
686 | u_int ftype; | 703 | u_int ftype; |
687 | u_int lport, cport; | 704 | u_int lport, cport; |
688 | int i, ret = 0, freefwd = 1; | 705 | int r, i, ret = 0, freefwd = 1; |
689 | 706 | ||
690 | memset(&fwd, 0, sizeof(fwd)); | 707 | memset(&fwd, 0, sizeof(fwd)); |
691 | 708 | ||
692 | /* XXX - lport/cport check redundant */ | 709 | /* XXX - lport/cport check redundant */ |
693 | if (buffer_get_int_ret(&ftype, m) != 0 || | 710 | if ((r = sshbuf_get_u32(m, &ftype)) != 0 || |
694 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || | 711 | (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || |
695 | buffer_get_int_ret(&lport, m) != 0 || | 712 | (r = sshbuf_get_u32(m, &lport)) != 0 || |
696 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || | 713 | (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || |
697 | buffer_get_int_ret(&cport, m) != 0 || | 714 | (r = sshbuf_get_u32(m, &cport)) != 0 || |
698 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || | 715 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
699 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | 716 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { |
700 | error("%s: malformed message", __func__); | 717 | error("%s: malformed message", __func__); |
@@ -731,9 +748,8 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
731 | invalid: | 748 | invalid: |
732 | free(listen_addr); | 749 | free(listen_addr); |
733 | free(connect_addr); | 750 | free(connect_addr); |
734 | buffer_put_int(r, MUX_S_FAILURE); | 751 | reply_error(reply, MUX_S_FAILURE, rid, |
735 | buffer_put_int(r, rid); | 752 | "Invalid forwarding request"); |
736 | buffer_put_cstring(r, "Invalid forwarding request"); | ||
737 | return 0; | 753 | return 0; |
738 | } | 754 | } |
739 | if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { | 755 | if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { |
@@ -770,26 +786,25 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
770 | exists: | 786 | exists: |
771 | debug2("%s: found existing forwarding", | 787 | debug2("%s: found existing forwarding", |
772 | __func__); | 788 | __func__); |
773 | buffer_put_int(r, MUX_S_OK); | 789 | reply_ok(reply, rid); |
774 | buffer_put_int(r, rid); | ||
775 | goto out; | 790 | goto out; |
776 | } | 791 | } |
777 | } | 792 | } |
778 | break; | 793 | break; |
779 | case MUX_FWD_REMOTE: | 794 | case MUX_FWD_REMOTE: |
780 | for (i = 0; i < options.num_remote_forwards; i++) { | 795 | for (i = 0; i < options.num_remote_forwards; i++) { |
781 | if (compare_forward(&fwd, | 796 | if (!compare_forward(&fwd, options.remote_forwards + i)) |
782 | options.remote_forwards + i)) { | 797 | continue; |
783 | if (fwd.listen_port != 0) | 798 | if (fwd.listen_port != 0) |
784 | goto exists; | 799 | goto exists; |
785 | debug2("%s: found allocated port", | 800 | debug2("%s: found allocated port", __func__); |
786 | __func__); | 801 | if ((r = sshbuf_put_u32(reply, |
787 | buffer_put_int(r, MUX_S_REMOTE_PORT); | 802 | MUX_S_REMOTE_PORT)) != 0 || |
788 | buffer_put_int(r, rid); | 803 | (r = sshbuf_put_u32(reply, rid)) != 0 || |
789 | buffer_put_int(r, | 804 | (r = sshbuf_put_u32(reply, |
790 | options.remote_forwards[i].allocated_port); | 805 | options.remote_forwards[i].allocated_port)) != 0) |
791 | goto out; | 806 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
792 | } | 807 | goto out; |
793 | } | 808 | } |
794 | break; | 809 | break; |
795 | } | 810 | } |
@@ -798,9 +813,8 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
798 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { | 813 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { |
799 | if (!ask_permission("Open %s on %s?", fwd_desc, host)) { | 814 | if (!ask_permission("Open %s on %s?", fwd_desc, host)) { |
800 | debug2("%s: forwarding refused by user", __func__); | 815 | debug2("%s: forwarding refused by user", __func__); |
801 | buffer_put_int(r, MUX_S_PERMISSION_DENIED); | 816 | reply_error(reply, MUX_S_PERMISSION_DENIED, rid, |
802 | buffer_put_int(r, rid); | 817 | "Permission denied"); |
803 | buffer_put_cstring(r, "Permission denied"); | ||
804 | goto out; | 818 | goto out; |
805 | } | 819 | } |
806 | } | 820 | } |
@@ -810,9 +824,8 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
810 | &options.fwd_opts)) { | 824 | &options.fwd_opts)) { |
811 | fail: | 825 | fail: |
812 | logit("slave-requested %s failed", fwd_desc); | 826 | logit("slave-requested %s failed", fwd_desc); |
813 | buffer_put_int(r, MUX_S_FAILURE); | 827 | reply_error(reply, MUX_S_FAILURE, rid, |
814 | buffer_put_int(r, rid); | 828 | "Port forwarding failed"); |
815 | buffer_put_cstring(r, "Port forwarding failed"); | ||
816 | goto out; | 829 | goto out; |
817 | } | 830 | } |
818 | add_local_forward(&options, &fwd); | 831 | add_local_forward(&options, &fwd); |
@@ -835,8 +848,7 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
835 | /* delayed reply in mux_confirm_remote_forward */ | 848 | /* delayed reply in mux_confirm_remote_forward */ |
836 | goto out; | 849 | goto out; |
837 | } | 850 | } |
838 | buffer_put_int(r, MUX_S_OK); | 851 | reply_ok(reply, rid); |
839 | buffer_put_int(r, rid); | ||
840 | out: | 852 | out: |
841 | free(fwd_desc); | 853 | free(fwd_desc); |
842 | if (freefwd) { | 854 | if (freefwd) { |
@@ -850,23 +862,23 @@ process_mux_open_fwd(struct ssh *ssh, u_int rid, | |||
850 | 862 | ||
851 | static int | 863 | static int |
852 | process_mux_close_fwd(struct ssh *ssh, u_int rid, | 864 | process_mux_close_fwd(struct ssh *ssh, u_int rid, |
853 | Channel *c, Buffer *m, Buffer *r) | 865 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
854 | { | 866 | { |
855 | struct Forward fwd, *found_fwd; | 867 | struct Forward fwd, *found_fwd; |
856 | char *fwd_desc = NULL; | 868 | char *fwd_desc = NULL; |
857 | const char *error_reason = NULL; | 869 | const char *error_reason = NULL; |
858 | char *listen_addr = NULL, *connect_addr = NULL; | 870 | char *listen_addr = NULL, *connect_addr = NULL; |
859 | u_int ftype; | 871 | u_int ftype; |
860 | int i, ret = 0; | 872 | int r, i, ret = 0; |
861 | u_int lport, cport; | 873 | u_int lport, cport; |
862 | 874 | ||
863 | memset(&fwd, 0, sizeof(fwd)); | 875 | memset(&fwd, 0, sizeof(fwd)); |
864 | 876 | ||
865 | if (buffer_get_int_ret(&ftype, m) != 0 || | 877 | if ((r = sshbuf_get_u32(m, &ftype)) != 0 || |
866 | (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || | 878 | (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || |
867 | buffer_get_int_ret(&lport, m) != 0 || | 879 | (r = sshbuf_get_u32(m, &lport)) != 0 || |
868 | (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || | 880 | (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || |
869 | buffer_get_int_ret(&cport, m) != 0 || | 881 | (r = sshbuf_get_u32(m, &cport)) != 0 || |
870 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || | 882 | (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || |
871 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { | 883 | (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { |
872 | error("%s: malformed message", __func__); | 884 | error("%s: malformed message", __func__); |
@@ -940,10 +952,10 @@ process_mux_close_fwd(struct ssh *ssh, u_int rid, | |||
940 | error_reason = "port not found"; | 952 | error_reason = "port not found"; |
941 | } | 953 | } |
942 | 954 | ||
943 | if (error_reason == NULL) { | 955 | if (error_reason != NULL) |
944 | buffer_put_int(r, MUX_S_OK); | 956 | reply_error(reply, MUX_S_FAILURE, rid, error_reason); |
945 | buffer_put_int(r, rid); | 957 | else { |
946 | 958 | reply_ok(reply, rid); | |
947 | free(found_fwd->listen_host); | 959 | free(found_fwd->listen_host); |
948 | free(found_fwd->listen_path); | 960 | free(found_fwd->listen_path); |
949 | free(found_fwd->connect_host); | 961 | free(found_fwd->connect_host); |
@@ -951,10 +963,6 @@ process_mux_close_fwd(struct ssh *ssh, u_int rid, | |||
951 | found_fwd->listen_host = found_fwd->connect_host = NULL; | 963 | found_fwd->listen_host = found_fwd->connect_host = NULL; |
952 | found_fwd->listen_path = found_fwd->connect_path = NULL; | 964 | found_fwd->listen_path = found_fwd->connect_path = NULL; |
953 | found_fwd->listen_port = found_fwd->connect_port = 0; | 965 | found_fwd->listen_port = found_fwd->connect_port = 0; |
954 | } else { | ||
955 | buffer_put_int(r, MUX_S_FAILURE); | ||
956 | buffer_put_int(r, rid); | ||
957 | buffer_put_cstring(r, error_reason); | ||
958 | } | 966 | } |
959 | out: | 967 | out: |
960 | free(fwd_desc); | 968 | free(fwd_desc); |
@@ -966,24 +974,21 @@ process_mux_close_fwd(struct ssh *ssh, u_int rid, | |||
966 | 974 | ||
967 | static int | 975 | static int |
968 | process_mux_stdio_fwd(struct ssh *ssh, u_int rid, | 976 | process_mux_stdio_fwd(struct ssh *ssh, u_int rid, |
969 | Channel *c, Buffer *m, Buffer *r) | 977 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
970 | { | 978 | { |
971 | Channel *nc; | 979 | Channel *nc; |
972 | char *reserved, *chost; | 980 | char *chost = NULL; |
973 | u_int cport, i, j; | 981 | u_int cport, i, j; |
974 | int new_fd[2]; | 982 | int r, new_fd[2]; |
975 | struct mux_stdio_confirm_ctx *cctx; | 983 | struct mux_stdio_confirm_ctx *cctx; |
976 | 984 | ||
977 | chost = reserved = NULL; | 985 | if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ |
978 | if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || | 986 | (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || |
979 | (chost = buffer_get_string_ret(m, NULL)) == NULL || | 987 | (r = sshbuf_get_u32(m, &cport)) != 0) { |
980 | buffer_get_int_ret(&cport, m) != 0) { | ||
981 | free(reserved); | ||
982 | free(chost); | 988 | free(chost); |
983 | error("%s: malformed message", __func__); | 989 | error("%s: malformed message", __func__); |
984 | return -1; | 990 | return -1; |
985 | } | 991 | } |
986 | free(reserved); | ||
987 | 992 | ||
988 | debug2("%s: channel %d: request stdio fwd to %s:%u", | 993 | debug2("%s: channel %d: request stdio fwd to %s:%u", |
989 | __func__, c->self, chost, cport); | 994 | __func__, c->self, chost, cport); |
@@ -998,9 +1003,7 @@ process_mux_stdio_fwd(struct ssh *ssh, u_int rid, | |||
998 | free(chost); | 1003 | free(chost); |
999 | 1004 | ||
1000 | /* prepare reply */ | 1005 | /* prepare reply */ |
1001 | buffer_put_int(r, MUX_S_FAILURE); | 1006 | reply_error(reply, MUX_S_FAILURE, rid, |
1002 | buffer_put_int(r, rid); | ||
1003 | buffer_put_cstring(r, | ||
1004 | "did not receive file descriptors"); | 1007 | "did not receive file descriptors"); |
1005 | return -1; | 1008 | return -1; |
1006 | } | 1009 | } |
@@ -1012,10 +1015,8 @@ process_mux_stdio_fwd(struct ssh *ssh, u_int rid, | |||
1012 | /* XXX support multiple child sessions in future */ | 1015 | /* XXX support multiple child sessions in future */ |
1013 | if (c->have_remote_id) { | 1016 | if (c->have_remote_id) { |
1014 | debug2("%s: session already open", __func__); | 1017 | debug2("%s: session already open", __func__); |
1015 | /* prepare reply */ | 1018 | reply_error(reply, MUX_S_FAILURE, rid, |
1016 | buffer_put_int(r, MUX_S_FAILURE); | 1019 | "Multiple sessions not supported"); |
1017 | buffer_put_int(r, rid); | ||
1018 | buffer_put_cstring(r, "Multiple sessions not supported"); | ||
1019 | cleanup: | 1020 | cleanup: |
1020 | close(new_fd[0]); | 1021 | close(new_fd[0]); |
1021 | close(new_fd[1]); | 1022 | close(new_fd[1]); |
@@ -1028,10 +1029,8 @@ process_mux_stdio_fwd(struct ssh *ssh, u_int rid, | |||
1028 | if (!ask_permission("Allow forward to %s:%u? ", | 1029 | if (!ask_permission("Allow forward to %s:%u? ", |
1029 | chost, cport)) { | 1030 | chost, cport)) { |
1030 | debug2("%s: stdio fwd refused by user", __func__); | 1031 | debug2("%s: stdio fwd refused by user", __func__); |
1031 | /* prepare reply */ | 1032 | reply_error(reply, MUX_S_PERMISSION_DENIED, rid, |
1032 | buffer_put_int(r, MUX_S_PERMISSION_DENIED); | 1033 | "Permission denied"); |
1033 | buffer_put_int(r, rid); | ||
1034 | buffer_put_cstring(r, "Permission denied"); | ||
1035 | goto cleanup; | 1034 | goto cleanup; |
1036 | } | 1035 | } |
1037 | } | 1036 | } |
@@ -1069,7 +1068,8 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1069 | { | 1068 | { |
1070 | struct mux_stdio_confirm_ctx *cctx = arg; | 1069 | struct mux_stdio_confirm_ctx *cctx = arg; |
1071 | Channel *c, *cc; | 1070 | Channel *c, *cc; |
1072 | Buffer reply; | 1071 | struct sshbuf *reply; |
1072 | int r; | ||
1073 | 1073 | ||
1074 | if (cctx == NULL) | 1074 | if (cctx == NULL) |
1075 | fatal("%s: cctx == NULL", __func__); | 1075 | fatal("%s: cctx == NULL", __func__); |
@@ -1078,28 +1078,29 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1078 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) | 1078 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1079 | fatal("%s: channel %d lacks control channel %d", __func__, | 1079 | fatal("%s: channel %d lacks control channel %d", __func__, |
1080 | id, c->ctl_chan); | 1080 | id, c->ctl_chan); |
1081 | if ((reply = sshbuf_new()) == NULL) | ||
1082 | fatal("%s: sshbuf_new", __func__); | ||
1081 | 1083 | ||
1082 | if (!success) { | 1084 | if (!success) { |
1083 | debug3("%s: sending failure reply", __func__); | 1085 | debug3("%s: sending failure reply", __func__); |
1086 | reply_error(reply, MUX_S_FAILURE, cctx->rid, | ||
1087 | "Session open refused by peer"); | ||
1084 | /* prepare reply */ | 1088 | /* prepare reply */ |
1085 | buffer_init(&reply); | ||
1086 | buffer_put_int(&reply, MUX_S_FAILURE); | ||
1087 | buffer_put_int(&reply, cctx->rid); | ||
1088 | buffer_put_cstring(&reply, "Session open refused by peer"); | ||
1089 | goto done; | 1089 | goto done; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | debug3("%s: sending success reply", __func__); | 1092 | debug3("%s: sending success reply", __func__); |
1093 | /* prepare reply */ | 1093 | /* prepare reply */ |
1094 | buffer_init(&reply); | 1094 | if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 || |
1095 | buffer_put_int(&reply, MUX_S_SESSION_OPENED); | 1095 | (r = sshbuf_put_u32(reply, cctx->rid)) != 0 || |
1096 | buffer_put_int(&reply, cctx->rid); | 1096 | (r = sshbuf_put_u32(reply, c->self)) != 0) |
1097 | buffer_put_int(&reply, c->self); | 1097 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
1098 | 1098 | ||
1099 | done: | 1099 | done: |
1100 | /* Send reply */ | 1100 | /* Send reply */ |
1101 | buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); | 1101 | if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) |
1102 | buffer_free(&reply); | 1102 | fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); |
1103 | sshbuf_free(reply); | ||
1103 | 1104 | ||
1104 | if (cc->mux_pause <= 0) | 1105 | if (cc->mux_pause <= 0) |
1105 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); | 1106 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); |
@@ -1110,7 +1111,7 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1110 | 1111 | ||
1111 | static int | 1112 | static int |
1112 | process_mux_stop_listening(struct ssh *ssh, u_int rid, | 1113 | process_mux_stop_listening(struct ssh *ssh, u_int rid, |
1113 | Channel *c, Buffer *m, Buffer *r) | 1114 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
1114 | { | 1115 | { |
1115 | debug("%s: channel %d: stop listening", __func__, c->self); | 1116 | debug("%s: channel %d: stop listening", __func__, c->self); |
1116 | 1117 | ||
@@ -1119,9 +1120,8 @@ process_mux_stop_listening(struct ssh *ssh, u_int rid, | |||
1119 | if (!ask_permission("Disable further multiplexing on shared " | 1120 | if (!ask_permission("Disable further multiplexing on shared " |
1120 | "connection to %s? ", host)) { | 1121 | "connection to %s? ", host)) { |
1121 | debug2("%s: stop listen refused by user", __func__); | 1122 | debug2("%s: stop listen refused by user", __func__); |
1122 | buffer_put_int(r, MUX_S_PERMISSION_DENIED); | 1123 | reply_error(reply, MUX_S_PERMISSION_DENIED, rid, |
1123 | buffer_put_int(r, rid); | 1124 | "Permission denied"); |
1124 | buffer_put_cstring(r, "Permission denied"); | ||
1125 | return 0; | 1125 | return 0; |
1126 | } | 1126 | } |
1127 | } | 1127 | } |
@@ -1135,22 +1135,22 @@ process_mux_stop_listening(struct ssh *ssh, u_int rid, | |||
1135 | muxserver_sock = -1; | 1135 | muxserver_sock = -1; |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | /* prepare reply */ | 1138 | reply_ok(reply, rid); |
1139 | buffer_put_int(r, MUX_S_OK); | ||
1140 | buffer_put_int(r, rid); | ||
1141 | |||
1142 | return 0; | 1139 | return 0; |
1143 | } | 1140 | } |
1144 | 1141 | ||
1145 | static int | 1142 | static int |
1146 | process_mux_proxy(struct ssh *ssh, u_int rid, | 1143 | process_mux_proxy(struct ssh *ssh, u_int rid, |
1147 | Channel *c, Buffer *m, Buffer *r) | 1144 | Channel *c, struct sshbuf *m, struct sshbuf *reply) |
1148 | { | 1145 | { |
1146 | int r; | ||
1147 | |||
1149 | debug("%s: channel %d: proxy request", __func__, c->self); | 1148 | debug("%s: channel %d: proxy request", __func__, c->self); |
1150 | 1149 | ||
1151 | c->mux_rcb = channel_proxy_downstream; | 1150 | c->mux_rcb = channel_proxy_downstream; |
1152 | buffer_put_int(r, MUX_S_PROXY); | 1151 | if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 || |
1153 | buffer_put_int(r, rid); | 1152 | (r = sshbuf_put_u32(reply, rid)) != 0) |
1153 | fatal("%s: reply: %s", __func__, ssh_err(r)); | ||
1154 | 1154 | ||
1155 | return 0; | 1155 | return 0; |
1156 | } | 1156 | } |
@@ -1160,10 +1160,12 @@ static int | |||
1160 | mux_master_read_cb(struct ssh *ssh, Channel *c) | 1160 | mux_master_read_cb(struct ssh *ssh, Channel *c) |
1161 | { | 1161 | { |
1162 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 1162 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
1163 | Buffer in, out; | 1163 | struct sshbuf *in = NULL, *out = NULL; |
1164 | const u_char *ptr; | 1164 | u_int type, rid, i; |
1165 | u_int type, rid, have, i; | 1165 | int r, ret = -1; |
1166 | int ret = -1; | 1166 | |
1167 | if ((out = sshbuf_new()) == NULL) | ||
1168 | fatal("%s: sshbuf_new", __func__); | ||
1167 | 1169 | ||
1168 | /* Setup ctx and */ | 1170 | /* Setup ctx and */ |
1169 | if (c->mux_ctx == NULL) { | 1171 | if (c->mux_ctx == NULL) { |
@@ -1173,32 +1175,29 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) | |||
1173 | mux_master_control_cleanup_cb, 0); | 1175 | mux_master_control_cleanup_cb, 0); |
1174 | 1176 | ||
1175 | /* Send hello */ | 1177 | /* Send hello */ |
1176 | buffer_init(&out); | 1178 | if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 || |
1177 | buffer_put_int(&out, MUX_MSG_HELLO); | 1179 | (r = sshbuf_put_u32(out, SSHMUX_VER)) != 0) |
1178 | buffer_put_int(&out, SSHMUX_VER); | 1180 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
1179 | /* no extensions */ | 1181 | /* no extensions */ |
1180 | buffer_put_string(c->output, buffer_ptr(&out), | 1182 | if ((r = sshbuf_put_stringb(c->output, out)) != 0) |
1181 | buffer_len(&out)); | 1183 | fatal("%s: sshbuf_put_stringb: %s", |
1182 | buffer_free(&out); | 1184 | __func__, ssh_err(r)); |
1183 | debug3("%s: channel %d: hello sent", __func__, c->self); | 1185 | debug3("%s: channel %d: hello sent", __func__, c->self); |
1184 | return 0; | 1186 | ret = 0; |
1187 | goto out; | ||
1185 | } | 1188 | } |
1186 | 1189 | ||
1187 | buffer_init(&in); | ||
1188 | buffer_init(&out); | ||
1189 | |||
1190 | /* Channel code ensures that we receive whole packets */ | 1190 | /* Channel code ensures that we receive whole packets */ |
1191 | if ((ptr = buffer_get_string_ptr_ret(c->input, &have)) == NULL) { | 1191 | if ((r = sshbuf_froms(c->input, &in)) != 0) { |
1192 | malf: | 1192 | malf: |
1193 | error("%s: malformed message", __func__); | 1193 | error("%s: malformed message", __func__); |
1194 | goto out; | 1194 | goto out; |
1195 | } | 1195 | } |
1196 | buffer_append(&in, ptr, have); | ||
1197 | 1196 | ||
1198 | if (buffer_get_int_ret(&type, &in) != 0) | 1197 | if ((r = sshbuf_get_u32(in, &type)) != 0) |
1199 | goto malf; | 1198 | goto malf; |
1200 | debug3("%s: channel %d packet type 0x%08x len %u", | 1199 | debug3("%s: channel %d packet type 0x%08x len %zu", |
1201 | __func__, c->self, type, buffer_len(&in)); | 1200 | __func__, c->self, type, sshbuf_len(in)); |
1202 | 1201 | ||
1203 | if (type == MUX_MSG_HELLO) | 1202 | if (type == MUX_MSG_HELLO) |
1204 | rid = 0; | 1203 | rid = 0; |
@@ -1208,40 +1207,40 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) | |||
1208 | "received 0x%08x", __func__, MUX_MSG_HELLO, type); | 1207 | "received 0x%08x", __func__, MUX_MSG_HELLO, type); |
1209 | goto out; | 1208 | goto out; |
1210 | } | 1209 | } |
1211 | if (buffer_get_int_ret(&rid, &in) != 0) | 1210 | if ((r = sshbuf_get_u32(in, &rid)) != 0) |
1212 | goto malf; | 1211 | goto malf; |
1213 | } | 1212 | } |
1214 | 1213 | ||
1215 | for (i = 0; mux_master_handlers[i].handler != NULL; i++) { | 1214 | for (i = 0; mux_master_handlers[i].handler != NULL; i++) { |
1216 | if (type == mux_master_handlers[i].type) { | 1215 | if (type == mux_master_handlers[i].type) { |
1217 | ret = mux_master_handlers[i].handler(ssh, rid, | 1216 | ret = mux_master_handlers[i].handler(ssh, rid, |
1218 | c, &in, &out); | 1217 | c, in, out); |
1219 | break; | 1218 | break; |
1220 | } | 1219 | } |
1221 | } | 1220 | } |
1222 | if (mux_master_handlers[i].handler == NULL) { | 1221 | if (mux_master_handlers[i].handler == NULL) { |
1223 | error("%s: unsupported mux message 0x%08x", __func__, type); | 1222 | error("%s: unsupported mux message 0x%08x", __func__, type); |
1224 | buffer_put_int(&out, MUX_S_FAILURE); | 1223 | reply_error(out, MUX_S_FAILURE, rid, "unsupported request"); |
1225 | buffer_put_int(&out, rid); | ||
1226 | buffer_put_cstring(&out, "unsupported request"); | ||
1227 | ret = 0; | 1224 | ret = 0; |
1228 | } | 1225 | } |
1229 | /* Enqueue reply packet */ | 1226 | /* Enqueue reply packet */ |
1230 | if (buffer_len(&out) != 0) { | 1227 | if (sshbuf_len(out) != 0) { |
1231 | buffer_put_string(c->output, buffer_ptr(&out), | 1228 | if ((r = sshbuf_put_stringb(c->output, out)) != 0) |
1232 | buffer_len(&out)); | 1229 | fatal("%s: sshbuf_put_stringb: %s", |
1230 | __func__, ssh_err(r)); | ||
1233 | } | 1231 | } |
1234 | out: | 1232 | out: |
1235 | buffer_free(&in); | 1233 | sshbuf_free(in); |
1236 | buffer_free(&out); | 1234 | sshbuf_free(out); |
1237 | return ret; | 1235 | return ret; |
1238 | } | 1236 | } |
1239 | 1237 | ||
1240 | void | 1238 | void |
1241 | mux_exit_message(struct ssh *ssh, Channel *c, int exitval) | 1239 | mux_exit_message(struct ssh *ssh, Channel *c, int exitval) |
1242 | { | 1240 | { |
1243 | Buffer m; | 1241 | struct sshbuf *m; |
1244 | Channel *mux_chan; | 1242 | Channel *mux_chan; |
1243 | int r; | ||
1245 | 1244 | ||
1246 | debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, | 1245 | debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, |
1247 | exitval); | 1246 | exitval); |
@@ -1251,20 +1250,22 @@ mux_exit_message(struct ssh *ssh, Channel *c, int exitval) | |||
1251 | __func__, c->self, c->ctl_chan); | 1250 | __func__, c->self, c->ctl_chan); |
1252 | 1251 | ||
1253 | /* Append exit message packet to control socket output queue */ | 1252 | /* Append exit message packet to control socket output queue */ |
1254 | buffer_init(&m); | 1253 | if ((m = sshbuf_new()) == NULL) |
1255 | buffer_put_int(&m, MUX_S_EXIT_MESSAGE); | 1254 | fatal("%s: sshbuf_new", __func__); |
1256 | buffer_put_int(&m, c->self); | 1255 | if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 || |
1257 | buffer_put_int(&m, exitval); | 1256 | (r = sshbuf_put_u32(m, c->self)) != 0 || |
1258 | 1257 | (r = sshbuf_put_u32(m, exitval)) != 0 || | |
1259 | buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); | 1258 | (r = sshbuf_put_stringb(mux_chan->output, m)) != 0) |
1260 | buffer_free(&m); | 1259 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
1260 | sshbuf_free(m); | ||
1261 | } | 1261 | } |
1262 | 1262 | ||
1263 | void | 1263 | void |
1264 | mux_tty_alloc_failed(struct ssh *ssh, Channel *c) | 1264 | mux_tty_alloc_failed(struct ssh *ssh, Channel *c) |
1265 | { | 1265 | { |
1266 | Buffer m; | 1266 | struct sshbuf *m; |
1267 | Channel *mux_chan; | 1267 | Channel *mux_chan; |
1268 | int r; | ||
1268 | 1269 | ||
1269 | debug3("%s: channel %d: TTY alloc failed", __func__, c->self); | 1270 | debug3("%s: channel %d: TTY alloc failed", __func__, c->self); |
1270 | 1271 | ||
@@ -1273,12 +1274,13 @@ mux_tty_alloc_failed(struct ssh *ssh, Channel *c) | |||
1273 | __func__, c->self, c->ctl_chan); | 1274 | __func__, c->self, c->ctl_chan); |
1274 | 1275 | ||
1275 | /* Append exit message packet to control socket output queue */ | 1276 | /* Append exit message packet to control socket output queue */ |
1276 | buffer_init(&m); | 1277 | if ((m = sshbuf_new()) == NULL) |
1277 | buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL); | 1278 | fatal("%s: sshbuf_new", __func__); |
1278 | buffer_put_int(&m, c->self); | 1279 | if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 || |
1279 | 1280 | (r = sshbuf_put_u32(m, c->self)) != 0 || | |
1280 | buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); | 1281 | (r = sshbuf_put_stringb(mux_chan->output, m)) != 0) |
1281 | buffer_free(&m); | 1282 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
1283 | sshbuf_free(m); | ||
1282 | } | 1284 | } |
1283 | 1285 | ||
1284 | /* Prepare a mux master to listen on a Unix domain socket. */ | 1286 | /* Prepare a mux master to listen on a Unix domain socket. */ |
@@ -1372,8 +1374,8 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1372 | struct mux_session_confirm_ctx *cctx = arg; | 1374 | struct mux_session_confirm_ctx *cctx = arg; |
1373 | const char *display; | 1375 | const char *display; |
1374 | Channel *c, *cc; | 1376 | Channel *c, *cc; |
1375 | int i; | 1377 | int i, r; |
1376 | Buffer reply; | 1378 | struct sshbuf *reply; |
1377 | 1379 | ||
1378 | if (cctx == NULL) | 1380 | if (cctx == NULL) |
1379 | fatal("%s: cctx == NULL", __func__); | 1381 | fatal("%s: cctx == NULL", __func__); |
@@ -1382,14 +1384,13 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1382 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) | 1384 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1383 | fatal("%s: channel %d lacks control channel %d", __func__, | 1385 | fatal("%s: channel %d lacks control channel %d", __func__, |
1384 | id, c->ctl_chan); | 1386 | id, c->ctl_chan); |
1387 | if ((reply = sshbuf_new()) == NULL) | ||
1388 | fatal("%s: sshbuf_new", __func__); | ||
1385 | 1389 | ||
1386 | if (!success) { | 1390 | if (!success) { |
1387 | debug3("%s: sending failure reply", __func__); | 1391 | debug3("%s: sending failure reply", __func__); |
1388 | /* prepare reply */ | 1392 | reply_error(reply, MUX_S_FAILURE, cctx->rid, |
1389 | buffer_init(&reply); | 1393 | "Session open refused by peer"); |
1390 | buffer_put_int(&reply, MUX_S_FAILURE); | ||
1391 | buffer_put_int(&reply, cctx->rid); | ||
1392 | buffer_put_cstring(&reply, "Session open refused by peer"); | ||
1393 | goto done; | 1394 | goto done; |
1394 | } | 1395 | } |
1395 | 1396 | ||
@@ -1419,25 +1420,26 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) | |||
1419 | } | 1420 | } |
1420 | 1421 | ||
1421 | client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys, | 1422 | client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys, |
1422 | cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); | 1423 | cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env); |
1423 | 1424 | ||
1424 | debug3("%s: sending success reply", __func__); | 1425 | debug3("%s: sending success reply", __func__); |
1425 | /* prepare reply */ | 1426 | /* prepare reply */ |
1426 | buffer_init(&reply); | 1427 | if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 || |
1427 | buffer_put_int(&reply, MUX_S_SESSION_OPENED); | 1428 | (r = sshbuf_put_u32(reply, cctx->rid)) != 0 || |
1428 | buffer_put_int(&reply, cctx->rid); | 1429 | (r = sshbuf_put_u32(reply, c->self)) != 0) |
1429 | buffer_put_int(&reply, c->self); | 1430 | fatal("%s: reply: %s", __func__, ssh_err(r)); |
1430 | 1431 | ||
1431 | done: | 1432 | done: |
1432 | /* Send reply */ | 1433 | /* Send reply */ |
1433 | buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); | 1434 | if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) |
1434 | buffer_free(&reply); | 1435 | fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); |
1436 | sshbuf_free(reply); | ||
1435 | 1437 | ||
1436 | if (cc->mux_pause <= 0) | 1438 | if (cc->mux_pause <= 0) |
1437 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); | 1439 | fatal("%s: mux_pause %d", __func__, cc->mux_pause); |
1438 | cc->mux_pause = 0; /* start processing messages again */ | 1440 | cc->mux_pause = 0; /* start processing messages again */ |
1439 | c->open_confirm_ctx = NULL; | 1441 | c->open_confirm_ctx = NULL; |
1440 | buffer_free(&cctx->cmd); | 1442 | sshbuf_free(cctx->cmd); |
1441 | free(cctx->term); | 1443 | free(cctx->term); |
1442 | if (cctx->env != NULL) { | 1444 | if (cctx->env != NULL) { |
1443 | for (i = 0; cctx->env[i] != NULL; i++) | 1445 | for (i = 0; cctx->env[i] != NULL; i++) |
@@ -1472,16 +1474,18 @@ control_client_sigrelay(int signo) | |||
1472 | } | 1474 | } |
1473 | 1475 | ||
1474 | static int | 1476 | static int |
1475 | mux_client_read(int fd, Buffer *b, u_int need) | 1477 | mux_client_read(int fd, struct sshbuf *b, size_t need) |
1476 | { | 1478 | { |
1477 | u_int have; | 1479 | size_t have; |
1478 | ssize_t len; | 1480 | ssize_t len; |
1479 | u_char *p; | 1481 | u_char *p; |
1480 | struct pollfd pfd; | 1482 | struct pollfd pfd; |
1483 | int r; | ||
1481 | 1484 | ||
1482 | pfd.fd = fd; | 1485 | pfd.fd = fd; |
1483 | pfd.events = POLLIN; | 1486 | pfd.events = POLLIN; |
1484 | p = buffer_append_space(b, need); | 1487 | if ((r = sshbuf_reserve(b, need, &p)) != 0) |
1488 | fatal("%s: reserve: %s", __func__, ssh_err(r)); | ||
1485 | for (have = 0; have < need; ) { | 1489 | for (have = 0; have < need; ) { |
1486 | if (muxclient_terminate) { | 1490 | if (muxclient_terminate) { |
1487 | errno = EINTR; | 1491 | errno = EINTR; |
@@ -1506,31 +1510,33 @@ mux_client_read(int fd, Buffer *b, u_int need) | |||
1506 | errno = EPIPE; | 1510 | errno = EPIPE; |
1507 | return -1; | 1511 | return -1; |
1508 | } | 1512 | } |
1509 | have += (u_int)len; | 1513 | have += (size_t)len; |
1510 | } | 1514 | } |
1511 | return 0; | 1515 | return 0; |
1512 | } | 1516 | } |
1513 | 1517 | ||
1514 | static int | 1518 | static int |
1515 | mux_client_write_packet(int fd, Buffer *m) | 1519 | mux_client_write_packet(int fd, struct sshbuf *m) |
1516 | { | 1520 | { |
1517 | Buffer queue; | 1521 | struct sshbuf *queue; |
1518 | u_int have, need; | 1522 | u_int have, need; |
1519 | int oerrno, len; | 1523 | int r, oerrno, len; |
1520 | u_char *ptr; | 1524 | const u_char *ptr; |
1521 | struct pollfd pfd; | 1525 | struct pollfd pfd; |
1522 | 1526 | ||
1523 | pfd.fd = fd; | 1527 | pfd.fd = fd; |
1524 | pfd.events = POLLOUT; | 1528 | pfd.events = POLLOUT; |
1525 | buffer_init(&queue); | 1529 | if ((queue = sshbuf_new()) == NULL) |
1526 | buffer_put_string(&queue, buffer_ptr(m), buffer_len(m)); | 1530 | fatal("%s: sshbuf_new", __func__); |
1531 | if ((r = sshbuf_put_stringb(queue, m)) != 0) | ||
1532 | fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); | ||
1527 | 1533 | ||
1528 | need = buffer_len(&queue); | 1534 | need = sshbuf_len(queue); |
1529 | ptr = buffer_ptr(&queue); | 1535 | ptr = sshbuf_ptr(queue); |
1530 | 1536 | ||
1531 | for (have = 0; have < need; ) { | 1537 | for (have = 0; have < need; ) { |
1532 | if (muxclient_terminate) { | 1538 | if (muxclient_terminate) { |
1533 | buffer_free(&queue); | 1539 | sshbuf_free(queue); |
1534 | errno = EINTR; | 1540 | errno = EINTR; |
1535 | return -1; | 1541 | return -1; |
1536 | } | 1542 | } |
@@ -1547,85 +1553,91 @@ mux_client_write_packet(int fd, Buffer *m) | |||
1547 | continue; | 1553 | continue; |
1548 | default: | 1554 | default: |
1549 | oerrno = errno; | 1555 | oerrno = errno; |
1550 | buffer_free(&queue); | 1556 | sshbuf_free(queue); |
1551 | errno = oerrno; | 1557 | errno = oerrno; |
1552 | return -1; | 1558 | return -1; |
1553 | } | 1559 | } |
1554 | } | 1560 | } |
1555 | if (len == 0) { | 1561 | if (len == 0) { |
1556 | buffer_free(&queue); | 1562 | sshbuf_free(queue); |
1557 | errno = EPIPE; | 1563 | errno = EPIPE; |
1558 | return -1; | 1564 | return -1; |
1559 | } | 1565 | } |
1560 | have += (u_int)len; | 1566 | have += (u_int)len; |
1561 | } | 1567 | } |
1562 | buffer_free(&queue); | 1568 | sshbuf_free(queue); |
1563 | return 0; | 1569 | return 0; |
1564 | } | 1570 | } |
1565 | 1571 | ||
1566 | static int | 1572 | static int |
1567 | mux_client_read_packet(int fd, Buffer *m) | 1573 | mux_client_read_packet(int fd, struct sshbuf *m) |
1568 | { | 1574 | { |
1569 | Buffer queue; | 1575 | struct sshbuf *queue; |
1570 | u_int need, have; | 1576 | size_t need, have; |
1571 | const u_char *ptr; | 1577 | const u_char *ptr; |
1572 | int oerrno; | 1578 | int r, oerrno; |
1573 | 1579 | ||
1574 | buffer_init(&queue); | 1580 | if ((queue = sshbuf_new()) == NULL) |
1575 | if (mux_client_read(fd, &queue, 4) != 0) { | 1581 | fatal("%s: sshbuf_new", __func__); |
1582 | if (mux_client_read(fd, queue, 4) != 0) { | ||
1576 | if ((oerrno = errno) == EPIPE) | 1583 | if ((oerrno = errno) == EPIPE) |
1577 | debug3("%s: read header failed: %s", __func__, | 1584 | debug3("%s: read header failed: %s", __func__, |
1578 | strerror(errno)); | 1585 | strerror(errno)); |
1579 | buffer_free(&queue); | 1586 | sshbuf_free(queue); |
1580 | errno = oerrno; | 1587 | errno = oerrno; |
1581 | return -1; | 1588 | return -1; |
1582 | } | 1589 | } |
1583 | need = get_u32(buffer_ptr(&queue)); | 1590 | need = PEEK_U32(sshbuf_ptr(queue)); |
1584 | if (mux_client_read(fd, &queue, need) != 0) { | 1591 | if (mux_client_read(fd, queue, need) != 0) { |
1585 | oerrno = errno; | 1592 | oerrno = errno; |
1586 | debug3("%s: read body failed: %s", __func__, strerror(errno)); | 1593 | debug3("%s: read body failed: %s", __func__, strerror(errno)); |
1587 | buffer_free(&queue); | 1594 | sshbuf_free(queue); |
1588 | errno = oerrno; | 1595 | errno = oerrno; |
1589 | return -1; | 1596 | return -1; |
1590 | } | 1597 | } |
1591 | ptr = buffer_get_string_ptr(&queue, &have); | 1598 | if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 || |
1592 | buffer_append(m, ptr, have); | 1599 | (r = sshbuf_put(m, ptr, have)) != 0) |
1593 | buffer_free(&queue); | 1600 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1601 | sshbuf_free(queue); | ||
1594 | return 0; | 1602 | return 0; |
1595 | } | 1603 | } |
1596 | 1604 | ||
1597 | static int | 1605 | static int |
1598 | mux_client_hello_exchange(int fd) | 1606 | mux_client_hello_exchange(int fd) |
1599 | { | 1607 | { |
1600 | Buffer m; | 1608 | struct sshbuf *m; |
1601 | u_int type, ver; | 1609 | u_int type, ver; |
1602 | int ret = -1; | 1610 | int r, ret = -1; |
1603 | 1611 | ||
1604 | buffer_init(&m); | 1612 | if ((m = sshbuf_new()) == NULL) |
1605 | buffer_put_int(&m, MUX_MSG_HELLO); | 1613 | fatal("%s: sshbuf_new", __func__); |
1606 | buffer_put_int(&m, SSHMUX_VER); | 1614 | if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 || |
1615 | (r = sshbuf_put_u32(m, SSHMUX_VER)) != 0) | ||
1616 | fatal("%s: hello: %s", __func__, ssh_err(r)); | ||
1607 | /* no extensions */ | 1617 | /* no extensions */ |
1608 | 1618 | ||
1609 | if (mux_client_write_packet(fd, &m) != 0) { | 1619 | if (mux_client_write_packet(fd, m) != 0) { |
1610 | debug("%s: write packet: %s", __func__, strerror(errno)); | 1620 | debug("%s: write packet: %s", __func__, strerror(errno)); |
1611 | goto out; | 1621 | goto out; |
1612 | } | 1622 | } |
1613 | 1623 | ||
1614 | buffer_clear(&m); | 1624 | sshbuf_reset(m); |
1615 | 1625 | ||
1616 | /* Read their HELLO */ | 1626 | /* Read their HELLO */ |
1617 | if (mux_client_read_packet(fd, &m) != 0) { | 1627 | if (mux_client_read_packet(fd, m) != 0) { |
1618 | debug("%s: read packet failed", __func__); | 1628 | debug("%s: read packet failed", __func__); |
1619 | goto out; | 1629 | goto out; |
1620 | } | 1630 | } |
1621 | 1631 | ||
1622 | type = buffer_get_int(&m); | 1632 | if ((r = sshbuf_get_u32(m, &type)) != 0) |
1633 | fatal("%s: decode type: %s", __func__, ssh_err(r)); | ||
1623 | if (type != MUX_MSG_HELLO) { | 1634 | if (type != MUX_MSG_HELLO) { |
1624 | error("%s: expected HELLO (%u) received %u", | 1635 | error("%s: expected HELLO (%u) received %u", |
1625 | __func__, MUX_MSG_HELLO, type); | 1636 | __func__, MUX_MSG_HELLO, type); |
1626 | goto out; | 1637 | goto out; |
1627 | } | 1638 | } |
1628 | ver = buffer_get_int(&m); | 1639 | if ((r = sshbuf_get_u32(m, &ver)) != 0) |
1640 | fatal("%s: decode version: %s", __func__, ssh_err(r)); | ||
1629 | if (ver != SSHMUX_VER) { | 1641 | if (ver != SSHMUX_VER) { |
1630 | error("Unsupported multiplexing protocol version %d " | 1642 | error("Unsupported multiplexing protocol version %d " |
1631 | "(expected %d)", ver, SSHMUX_VER); | 1643 | "(expected %d)", ver, SSHMUX_VER); |
@@ -1633,56 +1645,68 @@ mux_client_hello_exchange(int fd) | |||
1633 | } | 1645 | } |
1634 | debug2("%s: master version %u", __func__, ver); | 1646 | debug2("%s: master version %u", __func__, ver); |
1635 | /* No extensions are presently defined */ | 1647 | /* No extensions are presently defined */ |
1636 | while (buffer_len(&m) > 0) { | 1648 | while (sshbuf_len(m) > 0) { |
1637 | char *name = buffer_get_string(&m, NULL); | 1649 | char *name = NULL; |
1638 | char *value = buffer_get_string(&m, NULL); | ||
1639 | 1650 | ||
1651 | if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || | ||
1652 | (r = sshbuf_skip_string(m)) != 0) { /* value */ | ||
1653 | error("%s: malformed extension: %s", | ||
1654 | __func__, ssh_err(r)); | ||
1655 | goto out; | ||
1656 | } | ||
1640 | debug2("Unrecognised master extension \"%s\"", name); | 1657 | debug2("Unrecognised master extension \"%s\"", name); |
1641 | free(name); | 1658 | free(name); |
1642 | free(value); | ||
1643 | } | 1659 | } |
1644 | /* success */ | 1660 | /* success */ |
1645 | ret = 0; | 1661 | ret = 0; |
1646 | out: | 1662 | out: |
1647 | buffer_free(&m); | 1663 | sshbuf_free(m); |
1648 | return ret; | 1664 | return ret; |
1649 | } | 1665 | } |
1650 | 1666 | ||
1651 | static u_int | 1667 | static u_int |
1652 | mux_client_request_alive(int fd) | 1668 | mux_client_request_alive(int fd) |
1653 | { | 1669 | { |
1654 | Buffer m; | 1670 | struct sshbuf *m; |
1655 | char *e; | 1671 | char *e; |
1656 | u_int pid, type, rid; | 1672 | u_int pid, type, rid; |
1673 | int r; | ||
1657 | 1674 | ||
1658 | debug3("%s: entering", __func__); | 1675 | debug3("%s: entering", __func__); |
1659 | 1676 | ||
1660 | buffer_init(&m); | 1677 | if ((m = sshbuf_new()) == NULL) |
1661 | buffer_put_int(&m, MUX_C_ALIVE_CHECK); | 1678 | fatal("%s: sshbuf_new", __func__); |
1662 | buffer_put_int(&m, muxclient_request_id); | 1679 | if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 || |
1680 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) | ||
1681 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1663 | 1682 | ||
1664 | if (mux_client_write_packet(fd, &m) != 0) | 1683 | if (mux_client_write_packet(fd, m) != 0) |
1665 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 1684 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
1666 | 1685 | ||
1667 | buffer_clear(&m); | 1686 | sshbuf_reset(m); |
1668 | 1687 | ||
1669 | /* Read their reply */ | 1688 | /* Read their reply */ |
1670 | if (mux_client_read_packet(fd, &m) != 0) { | 1689 | if (mux_client_read_packet(fd, m) != 0) { |
1671 | buffer_free(&m); | 1690 | sshbuf_free(m); |
1672 | return 0; | 1691 | return 0; |
1673 | } | 1692 | } |
1674 | 1693 | ||
1675 | type = buffer_get_int(&m); | 1694 | if ((r = sshbuf_get_u32(m, &type)) != 0) |
1695 | fatal("%s: decode type: %s", __func__, ssh_err(r)); | ||
1676 | if (type != MUX_S_ALIVE) { | 1696 | if (type != MUX_S_ALIVE) { |
1677 | e = buffer_get_string(&m, NULL); | 1697 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1698 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
1678 | fatal("%s: master returned error: %s", __func__, e); | 1699 | fatal("%s: master returned error: %s", __func__, e); |
1679 | } | 1700 | } |
1680 | 1701 | ||
1681 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 1702 | if ((r = sshbuf_get_u32(m, &rid)) != 0) |
1703 | fatal("%s: decode remote ID: %s", __func__, ssh_err(r)); | ||
1704 | if (rid != muxclient_request_id) | ||
1682 | fatal("%s: out of sequence reply: my id %u theirs %u", | 1705 | fatal("%s: out of sequence reply: my id %u theirs %u", |
1683 | __func__, muxclient_request_id, rid); | 1706 | __func__, muxclient_request_id, rid); |
1684 | pid = buffer_get_int(&m); | 1707 | if ((r = sshbuf_get_u32(m, &pid)) != 0) |
1685 | buffer_free(&m); | 1708 | fatal("%s: decode PID: %s", __func__, ssh_err(r)); |
1709 | sshbuf_free(m); | ||
1686 | 1710 | ||
1687 | debug3("%s: done pid = %u", __func__, pid); | 1711 | debug3("%s: done pid = %u", __func__, pid); |
1688 | 1712 | ||
@@ -1694,107 +1718,128 @@ mux_client_request_alive(int fd) | |||
1694 | static void | 1718 | static void |
1695 | mux_client_request_terminate(int fd) | 1719 | mux_client_request_terminate(int fd) |
1696 | { | 1720 | { |
1697 | Buffer m; | 1721 | struct sshbuf *m; |
1698 | char *e; | 1722 | char *e; |
1699 | u_int type, rid; | 1723 | u_int type, rid; |
1724 | int r; | ||
1700 | 1725 | ||
1701 | debug3("%s: entering", __func__); | 1726 | debug3("%s: entering", __func__); |
1702 | 1727 | ||
1703 | buffer_init(&m); | 1728 | if ((m = sshbuf_new()) == NULL) |
1704 | buffer_put_int(&m, MUX_C_TERMINATE); | 1729 | fatal("%s: sshbuf_new", __func__); |
1705 | buffer_put_int(&m, muxclient_request_id); | 1730 | if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 || |
1731 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) | ||
1732 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1706 | 1733 | ||
1707 | if (mux_client_write_packet(fd, &m) != 0) | 1734 | if (mux_client_write_packet(fd, m) != 0) |
1708 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 1735 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
1709 | 1736 | ||
1710 | buffer_clear(&m); | 1737 | sshbuf_reset(m); |
1711 | 1738 | ||
1712 | /* Read their reply */ | 1739 | /* Read their reply */ |
1713 | if (mux_client_read_packet(fd, &m) != 0) { | 1740 | if (mux_client_read_packet(fd, m) != 0) { |
1714 | /* Remote end exited already */ | 1741 | /* Remote end exited already */ |
1715 | if (errno == EPIPE) { | 1742 | if (errno == EPIPE) { |
1716 | buffer_free(&m); | 1743 | sshbuf_free(m); |
1717 | return; | 1744 | return; |
1718 | } | 1745 | } |
1719 | fatal("%s: read from master failed: %s", | 1746 | fatal("%s: read from master failed: %s", |
1720 | __func__, strerror(errno)); | 1747 | __func__, strerror(errno)); |
1721 | } | 1748 | } |
1722 | 1749 | ||
1723 | type = buffer_get_int(&m); | 1750 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
1724 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 1751 | (r = sshbuf_get_u32(m, &rid)) != 0) |
1752 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
1753 | if (rid != muxclient_request_id) | ||
1725 | fatal("%s: out of sequence reply: my id %u theirs %u", | 1754 | fatal("%s: out of sequence reply: my id %u theirs %u", |
1726 | __func__, muxclient_request_id, rid); | 1755 | __func__, muxclient_request_id, rid); |
1727 | switch (type) { | 1756 | switch (type) { |
1728 | case MUX_S_OK: | 1757 | case MUX_S_OK: |
1729 | break; | 1758 | break; |
1730 | case MUX_S_PERMISSION_DENIED: | 1759 | case MUX_S_PERMISSION_DENIED: |
1731 | e = buffer_get_string(&m, NULL); | 1760 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1761 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
1732 | fatal("Master refused termination request: %s", e); | 1762 | fatal("Master refused termination request: %s", e); |
1733 | case MUX_S_FAILURE: | 1763 | case MUX_S_FAILURE: |
1734 | e = buffer_get_string(&m, NULL); | 1764 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1765 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
1735 | fatal("%s: termination request failed: %s", __func__, e); | 1766 | fatal("%s: termination request failed: %s", __func__, e); |
1736 | default: | 1767 | default: |
1737 | fatal("%s: unexpected response from master 0x%08x", | 1768 | fatal("%s: unexpected response from master 0x%08x", |
1738 | __func__, type); | 1769 | __func__, type); |
1739 | } | 1770 | } |
1740 | buffer_free(&m); | 1771 | sshbuf_free(m); |
1741 | muxclient_request_id++; | 1772 | muxclient_request_id++; |
1742 | } | 1773 | } |
1743 | 1774 | ||
1744 | static int | 1775 | static int |
1745 | mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) | 1776 | mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) |
1746 | { | 1777 | { |
1747 | Buffer m; | 1778 | struct sshbuf *m; |
1748 | char *e, *fwd_desc; | 1779 | char *e, *fwd_desc; |
1780 | const char *lhost, *chost; | ||
1749 | u_int type, rid; | 1781 | u_int type, rid; |
1782 | int r; | ||
1750 | 1783 | ||
1751 | fwd_desc = format_forward(ftype, fwd); | 1784 | fwd_desc = format_forward(ftype, fwd); |
1752 | debug("Requesting %s %s", | 1785 | debug("Requesting %s %s", |
1753 | cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); | 1786 | cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); |
1754 | free(fwd_desc); | 1787 | free(fwd_desc); |
1755 | 1788 | ||
1756 | buffer_init(&m); | 1789 | type = cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD; |
1757 | buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); | 1790 | if (fwd->listen_path != NULL) |
1758 | buffer_put_int(&m, muxclient_request_id); | 1791 | lhost = fwd->listen_path; |
1759 | buffer_put_int(&m, ftype); | 1792 | else if (fwd->listen_host == NULL) |
1760 | if (fwd->listen_path != NULL) { | 1793 | lhost = ""; |
1761 | buffer_put_cstring(&m, fwd->listen_path); | 1794 | else if (*fwd->listen_host == '\0') |
1762 | } else { | 1795 | lhost = "*"; |
1763 | buffer_put_cstring(&m, | 1796 | else |
1764 | fwd->listen_host == NULL ? "" : | 1797 | lhost = fwd->listen_host; |
1765 | (*fwd->listen_host == '\0' ? "*" : fwd->listen_host)); | ||
1766 | } | ||
1767 | buffer_put_int(&m, fwd->listen_port); | ||
1768 | if (fwd->connect_path != NULL) { | ||
1769 | buffer_put_cstring(&m, fwd->connect_path); | ||
1770 | } else { | ||
1771 | buffer_put_cstring(&m, | ||
1772 | fwd->connect_host == NULL ? "" : fwd->connect_host); | ||
1773 | } | ||
1774 | buffer_put_int(&m, fwd->connect_port); | ||
1775 | 1798 | ||
1776 | if (mux_client_write_packet(fd, &m) != 0) | 1799 | if (fwd->connect_path != NULL) |
1800 | chost = fwd->connect_path; | ||
1801 | else if (fwd->connect_host == NULL) | ||
1802 | chost = ""; | ||
1803 | else | ||
1804 | chost = fwd->connect_host; | ||
1805 | |||
1806 | if ((m = sshbuf_new()) == NULL) | ||
1807 | fatal("%s: sshbuf_new", __func__); | ||
1808 | if ((r = sshbuf_put_u32(m, type)) != 0 || | ||
1809 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || | ||
1810 | (r = sshbuf_put_u32(m, ftype)) != 0 || | ||
1811 | (r = sshbuf_put_cstring(m, lhost)) != 0 || | ||
1812 | (r = sshbuf_put_u32(m, fwd->listen_port)) != 0 || | ||
1813 | (r = sshbuf_put_cstring(m, chost)) != 0 || | ||
1814 | (r = sshbuf_put_u32(m, fwd->connect_port)) != 0) | ||
1815 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1816 | |||
1817 | if (mux_client_write_packet(fd, m) != 0) | ||
1777 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 1818 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
1778 | 1819 | ||
1779 | buffer_clear(&m); | 1820 | sshbuf_reset(m); |
1780 | 1821 | ||
1781 | /* Read their reply */ | 1822 | /* Read their reply */ |
1782 | if (mux_client_read_packet(fd, &m) != 0) { | 1823 | if (mux_client_read_packet(fd, m) != 0) { |
1783 | buffer_free(&m); | 1824 | sshbuf_free(m); |
1784 | return -1; | 1825 | return -1; |
1785 | } | 1826 | } |
1786 | 1827 | ||
1787 | type = buffer_get_int(&m); | 1828 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
1788 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 1829 | (r = sshbuf_get_u32(m, &rid)) != 0) |
1830 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
1831 | if (rid != muxclient_request_id) | ||
1789 | fatal("%s: out of sequence reply: my id %u theirs %u", | 1832 | fatal("%s: out of sequence reply: my id %u theirs %u", |
1790 | __func__, muxclient_request_id, rid); | 1833 | __func__, muxclient_request_id, rid); |
1834 | |||
1791 | switch (type) { | 1835 | switch (type) { |
1792 | case MUX_S_OK: | 1836 | case MUX_S_OK: |
1793 | break; | 1837 | break; |
1794 | case MUX_S_REMOTE_PORT: | 1838 | case MUX_S_REMOTE_PORT: |
1795 | if (cancel_flag) | 1839 | if (cancel_flag) |
1796 | fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); | 1840 | fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); |
1797 | fwd->allocated_port = buffer_get_int(&m); | 1841 | if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0) |
1842 | fatal("%s: decode port: %s", __func__, ssh_err(r)); | ||
1798 | verbose("Allocated port %u for remote forward to %s:%d", | 1843 | verbose("Allocated port %u for remote forward to %s:%d", |
1799 | fwd->allocated_port, | 1844 | fwd->allocated_port, |
1800 | fwd->connect_host ? fwd->connect_host : "", | 1845 | fwd->connect_host ? fwd->connect_host : "", |
@@ -1803,20 +1848,22 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) | |||
1803 | fprintf(stdout, "%i\n", fwd->allocated_port); | 1848 | fprintf(stdout, "%i\n", fwd->allocated_port); |
1804 | break; | 1849 | break; |
1805 | case MUX_S_PERMISSION_DENIED: | 1850 | case MUX_S_PERMISSION_DENIED: |
1806 | e = buffer_get_string(&m, NULL); | 1851 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1807 | buffer_free(&m); | 1852 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
1853 | sshbuf_free(m); | ||
1808 | error("Master refused forwarding request: %s", e); | 1854 | error("Master refused forwarding request: %s", e); |
1809 | return -1; | 1855 | return -1; |
1810 | case MUX_S_FAILURE: | 1856 | case MUX_S_FAILURE: |
1811 | e = buffer_get_string(&m, NULL); | 1857 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1812 | buffer_free(&m); | 1858 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
1859 | sshbuf_free(m); | ||
1813 | error("%s: forwarding request failed: %s", __func__, e); | 1860 | error("%s: forwarding request failed: %s", __func__, e); |
1814 | return -1; | 1861 | return -1; |
1815 | default: | 1862 | default: |
1816 | fatal("%s: unexpected response from master 0x%08x", | 1863 | fatal("%s: unexpected response from master 0x%08x", |
1817 | __func__, type); | 1864 | __func__, type); |
1818 | } | 1865 | } |
1819 | buffer_free(&m); | 1866 | sshbuf_free(m); |
1820 | 1867 | ||
1821 | muxclient_request_id++; | 1868 | muxclient_request_id++; |
1822 | return 0; | 1869 | return 0; |
@@ -1850,11 +1897,12 @@ mux_client_forwards(int fd, int cancel_flag) | |||
1850 | static int | 1897 | static int |
1851 | mux_client_request_session(int fd) | 1898 | mux_client_request_session(int fd) |
1852 | { | 1899 | { |
1853 | Buffer m; | 1900 | struct sshbuf *m; |
1854 | char *e, *term; | 1901 | char *e; |
1855 | u_int rid, sid, esid, exitval, type, exitval_seen; | 1902 | const char *term; |
1903 | u_int echar, rid, sid, esid, exitval, type, exitval_seen; | ||
1856 | extern char **environ; | 1904 | extern char **environ; |
1857 | int i, devnull, rawmode; | 1905 | int r, i, devnull, rawmode; |
1858 | 1906 | ||
1859 | debug3("%s: entering", __func__); | 1907 | debug3("%s: entering", __func__); |
1860 | 1908 | ||
@@ -1874,33 +1922,41 @@ mux_client_request_session(int fd) | |||
1874 | close(devnull); | 1922 | close(devnull); |
1875 | } | 1923 | } |
1876 | 1924 | ||
1877 | term = getenv("TERM"); | 1925 | if ((term = getenv("TERM")) == NULL) |
1878 | 1926 | term = ""; | |
1879 | buffer_init(&m); | 1927 | echar = 0xffffffff; |
1880 | buffer_put_int(&m, MUX_C_NEW_SESSION); | 1928 | if (options.escape_char != SSH_ESCAPECHAR_NONE) |
1881 | buffer_put_int(&m, muxclient_request_id); | 1929 | echar = (u_int)options.escape_char; |
1882 | buffer_put_cstring(&m, ""); /* reserved */ | 1930 | |
1883 | buffer_put_int(&m, tty_flag); | 1931 | if ((m = sshbuf_new()) == NULL) |
1884 | buffer_put_int(&m, options.forward_x11); | 1932 | fatal("%s: sshbuf_new", __func__); |
1885 | buffer_put_int(&m, options.forward_agent); | 1933 | if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 || |
1886 | buffer_put_int(&m, subsystem_flag); | 1934 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || |
1887 | buffer_put_int(&m, options.escape_char == SSH_ESCAPECHAR_NONE ? | 1935 | (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */ |
1888 | 0xffffffff : (u_int)options.escape_char); | 1936 | (r = sshbuf_put_u32(m, tty_flag)) != 0 || |
1889 | buffer_put_cstring(&m, term == NULL ? "" : term); | 1937 | (r = sshbuf_put_u32(m, options.forward_x11)) != 0 || |
1890 | buffer_put_string(&m, buffer_ptr(command), buffer_len(command)); | 1938 | (r = sshbuf_put_u32(m, options.forward_agent)) != 0 || |
1939 | (r = sshbuf_put_u32(m, subsystem_flag)) != 0 || | ||
1940 | (r = sshbuf_put_u32(m, echar)) != 0 || | ||
1941 | (r = sshbuf_put_cstring(m, term)) != 0 || | ||
1942 | (r = sshbuf_put_stringb(m, command)) != 0) | ||
1943 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1891 | 1944 | ||
1892 | /* Pass environment */ | 1945 | /* Pass environment */ |
1893 | if (options.num_send_env > 0 && environ != NULL) { | 1946 | if (options.num_send_env > 0 && environ != NULL) { |
1894 | for (i = 0; environ[i] != NULL; i++) { | 1947 | for (i = 0; environ[i] != NULL; i++) { |
1895 | if (env_permitted(environ[i])) { | 1948 | if (!env_permitted(environ[i])) |
1896 | buffer_put_cstring(&m, environ[i]); | 1949 | continue; |
1897 | } | 1950 | if ((r = sshbuf_put_cstring(m, environ[i])) != 0) |
1951 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1898 | } | 1952 | } |
1899 | } | 1953 | } |
1900 | for (i = 0; i < options.num_setenv; i++) | 1954 | for (i = 0; i < options.num_setenv; i++) { |
1901 | buffer_put_cstring(&m, options.setenv[i]); | 1955 | if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0) |
1956 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
1957 | } | ||
1902 | 1958 | ||
1903 | if (mux_client_write_packet(fd, &m) != 0) | 1959 | if (mux_client_write_packet(fd, m) != 0) |
1904 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 1960 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
1905 | 1961 | ||
1906 | /* Send the stdio file descriptors */ | 1962 | /* Send the stdio file descriptors */ |
@@ -1912,35 +1968,40 @@ mux_client_request_session(int fd) | |||
1912 | debug3("%s: session request sent", __func__); | 1968 | debug3("%s: session request sent", __func__); |
1913 | 1969 | ||
1914 | /* Read their reply */ | 1970 | /* Read their reply */ |
1915 | buffer_clear(&m); | 1971 | sshbuf_reset(m); |
1916 | if (mux_client_read_packet(fd, &m) != 0) { | 1972 | if (mux_client_read_packet(fd, m) != 0) { |
1917 | error("%s: read from master failed: %s", | 1973 | error("%s: read from master failed: %s", |
1918 | __func__, strerror(errno)); | 1974 | __func__, strerror(errno)); |
1919 | buffer_free(&m); | 1975 | sshbuf_free(m); |
1920 | return -1; | 1976 | return -1; |
1921 | } | 1977 | } |
1922 | 1978 | ||
1923 | type = buffer_get_int(&m); | 1979 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
1924 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 1980 | (r = sshbuf_get_u32(m, &rid)) != 0) |
1981 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
1982 | if (rid != muxclient_request_id) | ||
1925 | fatal("%s: out of sequence reply: my id %u theirs %u", | 1983 | fatal("%s: out of sequence reply: my id %u theirs %u", |
1926 | __func__, muxclient_request_id, rid); | 1984 | __func__, muxclient_request_id, rid); |
1985 | |||
1927 | switch (type) { | 1986 | switch (type) { |
1928 | case MUX_S_SESSION_OPENED: | 1987 | case MUX_S_SESSION_OPENED: |
1929 | sid = buffer_get_int(&m); | 1988 | if ((r = sshbuf_get_u32(m, &sid)) != 0) |
1930 | debug("%s: master session id: %u", __func__, sid); | 1989 | fatal("%s: decode ID: %s", __func__, ssh_err(r)); |
1931 | break; | 1990 | break; |
1932 | case MUX_S_PERMISSION_DENIED: | 1991 | case MUX_S_PERMISSION_DENIED: |
1933 | e = buffer_get_string(&m, NULL); | 1992 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1934 | buffer_free(&m); | 1993 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
1935 | error("Master refused session request: %s", e); | 1994 | error("Master refused session request: %s", e); |
1995 | sshbuf_free(m); | ||
1936 | return -1; | 1996 | return -1; |
1937 | case MUX_S_FAILURE: | 1997 | case MUX_S_FAILURE: |
1938 | e = buffer_get_string(&m, NULL); | 1998 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
1939 | buffer_free(&m); | 1999 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
1940 | error("%s: session request failed: %s", __func__, e); | 2000 | error("%s: session request failed: %s", __func__, e); |
2001 | sshbuf_free(m); | ||
1941 | return -1; | 2002 | return -1; |
1942 | default: | 2003 | default: |
1943 | buffer_free(&m); | 2004 | sshbuf_free(m); |
1944 | error("%s: unexpected response from master 0x%08x", | 2005 | error("%s: unexpected response from master 0x%08x", |
1945 | __func__, type); | 2006 | __func__, type); |
1946 | return -1; | 2007 | return -1; |
@@ -1968,13 +2029,17 @@ mux_client_request_session(int fd) | |||
1968 | * terminate early too (possibly losing data). | 2029 | * terminate early too (possibly losing data). |
1969 | */ | 2030 | */ |
1970 | for (exitval = 255, exitval_seen = 0;;) { | 2031 | for (exitval = 255, exitval_seen = 0;;) { |
1971 | buffer_clear(&m); | 2032 | sshbuf_reset(m); |
1972 | if (mux_client_read_packet(fd, &m) != 0) | 2033 | if (mux_client_read_packet(fd, m) != 0) |
1973 | break; | 2034 | break; |
1974 | type = buffer_get_int(&m); | 2035 | if ((r = sshbuf_get_u32(m, &type)) != 0) |
2036 | fatal("%s: decode type: %s", __func__, ssh_err(r)); | ||
1975 | switch (type) { | 2037 | switch (type) { |
1976 | case MUX_S_TTY_ALLOC_FAIL: | 2038 | case MUX_S_TTY_ALLOC_FAIL: |
1977 | if ((esid = buffer_get_int(&m)) != sid) | 2039 | if ((r = sshbuf_get_u32(m, &esid)) != 0) |
2040 | fatal("%s: decode ID: %s", | ||
2041 | __func__, ssh_err(r)); | ||
2042 | if (esid != sid) | ||
1978 | fatal("%s: tty alloc fail on unknown session: " | 2043 | fatal("%s: tty alloc fail on unknown session: " |
1979 | "my id %u theirs %u", | 2044 | "my id %u theirs %u", |
1980 | __func__, sid, esid); | 2045 | __func__, sid, esid); |
@@ -1983,17 +2048,24 @@ mux_client_request_session(int fd) | |||
1983 | rawmode = 0; | 2048 | rawmode = 0; |
1984 | continue; | 2049 | continue; |
1985 | case MUX_S_EXIT_MESSAGE: | 2050 | case MUX_S_EXIT_MESSAGE: |
1986 | if ((esid = buffer_get_int(&m)) != sid) | 2051 | if ((r = sshbuf_get_u32(m, &esid)) != 0) |
2052 | fatal("%s: decode ID: %s", | ||
2053 | __func__, ssh_err(r)); | ||
2054 | if (esid != sid) | ||
1987 | fatal("%s: exit on unknown session: " | 2055 | fatal("%s: exit on unknown session: " |
1988 | "my id %u theirs %u", | 2056 | "my id %u theirs %u", |
1989 | __func__, sid, esid); | 2057 | __func__, sid, esid); |
1990 | if (exitval_seen) | 2058 | if (exitval_seen) |
1991 | fatal("%s: exitval sent twice", __func__); | 2059 | fatal("%s: exitval sent twice", __func__); |
1992 | exitval = buffer_get_int(&m); | 2060 | if ((r = sshbuf_get_u32(m, &exitval)) != 0) |
2061 | fatal("%s: decode exit value: %s", | ||
2062 | __func__, ssh_err(r)); | ||
1993 | exitval_seen = 1; | 2063 | exitval_seen = 1; |
1994 | continue; | 2064 | continue; |
1995 | default: | 2065 | default: |
1996 | e = buffer_get_string(&m, NULL); | 2066 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2067 | fatal("%s: decode error: %s", | ||
2068 | __func__, ssh_err(r)); | ||
1997 | fatal("%s: master returned error: %s", __func__, e); | 2069 | fatal("%s: master returned error: %s", __func__, e); |
1998 | } | 2070 | } |
1999 | } | 2071 | } |
@@ -2020,32 +2092,38 @@ mux_client_request_session(int fd) | |||
2020 | static int | 2092 | static int |
2021 | mux_client_proxy(int fd) | 2093 | mux_client_proxy(int fd) |
2022 | { | 2094 | { |
2023 | Buffer m; | 2095 | struct sshbuf *m; |
2024 | char *e; | 2096 | char *e; |
2025 | u_int type, rid; | 2097 | u_int type, rid; |
2026 | 2098 | int r; | |
2027 | buffer_init(&m); | 2099 | |
2028 | buffer_put_int(&m, MUX_C_PROXY); | 2100 | if ((m = sshbuf_new()) == NULL) |
2029 | buffer_put_int(&m, muxclient_request_id); | 2101 | fatal("%s: sshbuf_new", __func__); |
2030 | if (mux_client_write_packet(fd, &m) != 0) | 2102 | if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 || |
2103 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) | ||
2104 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
2105 | if (mux_client_write_packet(fd, m) != 0) | ||
2031 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 2106 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
2032 | 2107 | ||
2033 | buffer_clear(&m); | 2108 | sshbuf_reset(m); |
2034 | 2109 | ||
2035 | /* Read their reply */ | 2110 | /* Read their reply */ |
2036 | if (mux_client_read_packet(fd, &m) != 0) { | 2111 | if (mux_client_read_packet(fd, m) != 0) { |
2037 | buffer_free(&m); | 2112 | sshbuf_free(m); |
2038 | return 0; | 2113 | return 0; |
2039 | } | 2114 | } |
2040 | type = buffer_get_int(&m); | 2115 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
2116 | (r = sshbuf_get_u32(m, &rid)) != 0) | ||
2117 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
2118 | if (rid != muxclient_request_id) | ||
2119 | fatal("%s: out of sequence reply: my id %u theirs %u", | ||
2120 | __func__, muxclient_request_id, rid); | ||
2041 | if (type != MUX_S_PROXY) { | 2121 | if (type != MUX_S_PROXY) { |
2042 | e = buffer_get_string(&m, NULL); | 2122 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2123 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
2043 | fatal("%s: master returned error: %s", __func__, e); | 2124 | fatal("%s: master returned error: %s", __func__, e); |
2044 | } | 2125 | } |
2045 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 2126 | sshbuf_free(m); |
2046 | fatal("%s: out of sequence reply: my id %u theirs %u", | ||
2047 | __func__, muxclient_request_id, rid); | ||
2048 | buffer_free(&m); | ||
2049 | 2127 | ||
2050 | debug3("%s: done", __func__); | 2128 | debug3("%s: done", __func__); |
2051 | muxclient_request_id++; | 2129 | muxclient_request_id++; |
@@ -2055,10 +2133,10 @@ mux_client_proxy(int fd) | |||
2055 | static int | 2133 | static int |
2056 | mux_client_request_stdio_fwd(int fd) | 2134 | mux_client_request_stdio_fwd(int fd) |
2057 | { | 2135 | { |
2058 | Buffer m; | 2136 | struct sshbuf *m; |
2059 | char *e; | 2137 | char *e; |
2060 | u_int type, rid, sid; | 2138 | u_int type, rid, sid; |
2061 | int devnull; | 2139 | int r, devnull; |
2062 | 2140 | ||
2063 | debug3("%s: entering", __func__); | 2141 | debug3("%s: entering", __func__); |
2064 | 2142 | ||
@@ -2078,14 +2156,16 @@ mux_client_request_stdio_fwd(int fd) | |||
2078 | close(devnull); | 2156 | close(devnull); |
2079 | } | 2157 | } |
2080 | 2158 | ||
2081 | buffer_init(&m); | 2159 | if ((m = sshbuf_new()) == NULL) |
2082 | buffer_put_int(&m, MUX_C_NEW_STDIO_FWD); | 2160 | fatal("%s: sshbuf_new", __func__); |
2083 | buffer_put_int(&m, muxclient_request_id); | 2161 | if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 || |
2084 | buffer_put_cstring(&m, ""); /* reserved */ | 2162 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || |
2085 | buffer_put_cstring(&m, options.stdio_forward_host); | 2163 | (r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */ |
2086 | buffer_put_int(&m, options.stdio_forward_port); | 2164 | (r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 || |
2165 | (r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0) | ||
2166 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
2087 | 2167 | ||
2088 | if (mux_client_write_packet(fd, &m) != 0) | 2168 | if (mux_client_write_packet(fd, m) != 0) |
2089 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 2169 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
2090 | 2170 | ||
2091 | /* Send the stdio file descriptors */ | 2171 | /* Send the stdio file descriptors */ |
@@ -2100,34 +2180,39 @@ mux_client_request_stdio_fwd(int fd) | |||
2100 | debug3("%s: stdio forward request sent", __func__); | 2180 | debug3("%s: stdio forward request sent", __func__); |
2101 | 2181 | ||
2102 | /* Read their reply */ | 2182 | /* Read their reply */ |
2103 | buffer_clear(&m); | 2183 | sshbuf_reset(m); |
2104 | 2184 | ||
2105 | if (mux_client_read_packet(fd, &m) != 0) { | 2185 | if (mux_client_read_packet(fd, m) != 0) { |
2106 | error("%s: read from master failed: %s", | 2186 | error("%s: read from master failed: %s", |
2107 | __func__, strerror(errno)); | 2187 | __func__, strerror(errno)); |
2108 | buffer_free(&m); | 2188 | sshbuf_free(m); |
2109 | return -1; | 2189 | return -1; |
2110 | } | 2190 | } |
2111 | 2191 | ||
2112 | type = buffer_get_int(&m); | 2192 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
2113 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 2193 | (r = sshbuf_get_u32(m, &rid)) != 0) |
2194 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
2195 | if (rid != muxclient_request_id) | ||
2114 | fatal("%s: out of sequence reply: my id %u theirs %u", | 2196 | fatal("%s: out of sequence reply: my id %u theirs %u", |
2115 | __func__, muxclient_request_id, rid); | 2197 | __func__, muxclient_request_id, rid); |
2116 | switch (type) { | 2198 | switch (type) { |
2117 | case MUX_S_SESSION_OPENED: | 2199 | case MUX_S_SESSION_OPENED: |
2118 | sid = buffer_get_int(&m); | 2200 | if ((r = sshbuf_get_u32(m, &sid)) != 0) |
2201 | fatal("%s: decode ID: %s", __func__, ssh_err(r)); | ||
2119 | debug("%s: master session id: %u", __func__, sid); | 2202 | debug("%s: master session id: %u", __func__, sid); |
2120 | break; | 2203 | break; |
2121 | case MUX_S_PERMISSION_DENIED: | 2204 | case MUX_S_PERMISSION_DENIED: |
2122 | e = buffer_get_string(&m, NULL); | 2205 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2123 | buffer_free(&m); | 2206 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
2207 | sshbuf_free(m); | ||
2124 | fatal("Master refused stdio forwarding request: %s", e); | 2208 | fatal("Master refused stdio forwarding request: %s", e); |
2125 | case MUX_S_FAILURE: | 2209 | case MUX_S_FAILURE: |
2126 | e = buffer_get_string(&m, NULL); | 2210 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2127 | buffer_free(&m); | 2211 | fatal("%s: decode error: %s", __func__, ssh_err(r)); |
2212 | sshbuf_free(m); | ||
2128 | fatal("Stdio forwarding request failed: %s", e); | 2213 | fatal("Stdio forwarding request failed: %s", e); |
2129 | default: | 2214 | default: |
2130 | buffer_free(&m); | 2215 | sshbuf_free(m); |
2131 | error("%s: unexpected response from master 0x%08x", | 2216 | error("%s: unexpected response from master 0x%08x", |
2132 | __func__, type); | 2217 | __func__, type); |
2133 | return -1; | 2218 | return -1; |
@@ -2142,8 +2227,8 @@ mux_client_request_stdio_fwd(int fd) | |||
2142 | /* | 2227 | /* |
2143 | * Stick around until the controlee closes the client_fd. | 2228 | * Stick around until the controlee closes the client_fd. |
2144 | */ | 2229 | */ |
2145 | buffer_clear(&m); | 2230 | sshbuf_reset(m); |
2146 | if (mux_client_read_packet(fd, &m) != 0) { | 2231 | if (mux_client_read_packet(fd, m) != 0) { |
2147 | if (errno == EPIPE || | 2232 | if (errno == EPIPE || |
2148 | (errno == EINTR && muxclient_terminate != 0)) | 2233 | (errno == EINTR && muxclient_terminate != 0)) |
2149 | return 0; | 2234 | return 0; |
@@ -2156,44 +2241,52 @@ mux_client_request_stdio_fwd(int fd) | |||
2156 | static void | 2241 | static void |
2157 | mux_client_request_stop_listening(int fd) | 2242 | mux_client_request_stop_listening(int fd) |
2158 | { | 2243 | { |
2159 | Buffer m; | 2244 | struct sshbuf *m; |
2160 | char *e; | 2245 | char *e; |
2161 | u_int type, rid; | 2246 | u_int type, rid; |
2247 | int r; | ||
2162 | 2248 | ||
2163 | debug3("%s: entering", __func__); | 2249 | debug3("%s: entering", __func__); |
2164 | 2250 | ||
2165 | buffer_init(&m); | 2251 | if ((m = sshbuf_new()) == NULL) |
2166 | buffer_put_int(&m, MUX_C_STOP_LISTENING); | 2252 | fatal("%s: sshbuf_new", __func__); |
2167 | buffer_put_int(&m, muxclient_request_id); | 2253 | if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 || |
2254 | (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) | ||
2255 | fatal("%s: request: %s", __func__, ssh_err(r)); | ||
2168 | 2256 | ||
2169 | if (mux_client_write_packet(fd, &m) != 0) | 2257 | if (mux_client_write_packet(fd, m) != 0) |
2170 | fatal("%s: write packet: %s", __func__, strerror(errno)); | 2258 | fatal("%s: write packet: %s", __func__, strerror(errno)); |
2171 | 2259 | ||
2172 | buffer_clear(&m); | 2260 | sshbuf_reset(m); |
2173 | 2261 | ||
2174 | /* Read their reply */ | 2262 | /* Read their reply */ |
2175 | if (mux_client_read_packet(fd, &m) != 0) | 2263 | if (mux_client_read_packet(fd, m) != 0) |
2176 | fatal("%s: read from master failed: %s", | 2264 | fatal("%s: read from master failed: %s", |
2177 | __func__, strerror(errno)); | 2265 | __func__, strerror(errno)); |
2178 | 2266 | ||
2179 | type = buffer_get_int(&m); | 2267 | if ((r = sshbuf_get_u32(m, &type)) != 0 || |
2180 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | 2268 | (r = sshbuf_get_u32(m, &rid)) != 0) |
2269 | fatal("%s: decode: %s", __func__, ssh_err(r)); | ||
2270 | if (rid != muxclient_request_id) | ||
2181 | fatal("%s: out of sequence reply: my id %u theirs %u", | 2271 | fatal("%s: out of sequence reply: my id %u theirs %u", |
2182 | __func__, muxclient_request_id, rid); | 2272 | __func__, muxclient_request_id, rid); |
2273 | |||
2183 | switch (type) { | 2274 | switch (type) { |
2184 | case MUX_S_OK: | 2275 | case MUX_S_OK: |
2185 | break; | 2276 | break; |
2186 | case MUX_S_PERMISSION_DENIED: | 2277 | case MUX_S_PERMISSION_DENIED: |
2187 | e = buffer_get_string(&m, NULL); | 2278 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2279 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
2188 | fatal("Master refused stop listening request: %s", e); | 2280 | fatal("Master refused stop listening request: %s", e); |
2189 | case MUX_S_FAILURE: | 2281 | case MUX_S_FAILURE: |
2190 | e = buffer_get_string(&m, NULL); | 2282 | if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) |
2283 | fatal("%s: decode error: %s", __func__, ssh_err(r)); | ||
2191 | fatal("%s: stop listening request failed: %s", __func__, e); | 2284 | fatal("%s: stop listening request failed: %s", __func__, e); |
2192 | default: | 2285 | default: |
2193 | fatal("%s: unexpected response from master 0x%08x", | 2286 | fatal("%s: unexpected response from master 0x%08x", |
2194 | __func__, type); | 2287 | __func__, type); |
2195 | } | 2288 | } |
2196 | buffer_free(&m); | 2289 | sshbuf_free(m); |
2197 | muxclient_request_id++; | 2290 | muxclient_request_id++; |
2198 | } | 2291 | } |
2199 | 2292 | ||