diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-01-19 21:40:48 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-01-20 09:45:17 +1100 |
commit | 7ec5cb4d15ed2f2c5c9f5d00e6b361d136fc1e2d (patch) | |
tree | aa9adf28c7a89c64d8441b4d7f134095a4391ef9 /serverloop.c | |
parent | 64c9598ac05332d1327cbf55334dee4172d216c4 (diff) |
upstream: convert serverloop.c to new packet API
with & ok markus@
OpenBSD-Commit-ID: c92dd19b55457541478f95c0d6b318426d86d885
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 356 |
1 files changed, 204 insertions, 152 deletions
diff --git a/serverloop.c b/serverloop.c index e0c26bbbc..c60758e88 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: serverloop.c,v 1.210 2019/01/19 21:31:32 djm Exp $ */ | 1 | /* $OpenBSD: serverloop.c,v 1.211 2019/01/19 21:40:48 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -49,6 +49,7 @@ | |||
49 | #include <errno.h> | 49 | #include <errno.h> |
50 | #include <fcntl.h> | 50 | #include <fcntl.h> |
51 | #include <pwd.h> | 51 | #include <pwd.h> |
52 | #include <limits.h> | ||
52 | #include <signal.h> | 53 | #include <signal.h> |
53 | #include <string.h> | 54 | #include <string.h> |
54 | #include <termios.h> | 55 | #include <termios.h> |
@@ -78,9 +79,6 @@ | |||
78 | #include "serverloop.h" | 79 | #include "serverloop.h" |
79 | #include "ssherr.h" | 80 | #include "ssherr.h" |
80 | 81 | ||
81 | #include "opacket.h" /* XXX */ | ||
82 | extern struct ssh *active_state; /* XXX */ | ||
83 | |||
84 | extern ServerOptions options; | 82 | extern ServerOptions options; |
85 | 83 | ||
86 | /* XXX */ | 84 | /* XXX */ |
@@ -101,7 +99,7 @@ static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. | |||
101 | static volatile sig_atomic_t received_sigterm = 0; | 99 | static volatile sig_atomic_t received_sigterm = 0; |
102 | 100 | ||
103 | /* prototypes */ | 101 | /* prototypes */ |
104 | static void server_init_dispatch(void); | 102 | static void server_init_dispatch(struct ssh *); |
105 | 103 | ||
106 | /* requested tunnel forwarding interface(s), shared with session.c */ | 104 | /* requested tunnel forwarding interface(s), shared with session.c */ |
107 | char *tun_fwd_ifnames = NULL; | 105 | char *tun_fwd_ifnames = NULL; |
@@ -182,11 +180,12 @@ sigterm_handler(int sig) | |||
182 | static void | 180 | static void |
183 | client_alive_check(struct ssh *ssh) | 181 | client_alive_check(struct ssh *ssh) |
184 | { | 182 | { |
185 | int channel_id; | ||
186 | char remote_id[512]; | 183 | char remote_id[512]; |
184 | int r, channel_id; | ||
187 | 185 | ||
188 | /* timeout, check to see how many we have had */ | 186 | /* timeout, check to see how many we have had */ |
189 | if (packet_inc_alive_timeouts() > options.client_alive_count_max) { | 187 | if (ssh_packet_inc_alive_timeouts(ssh) > |
188 | options.client_alive_count_max) { | ||
190 | sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); | 189 | sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
191 | logit("Timeout, client not responding from %s", remote_id); | 190 | logit("Timeout, client not responding from %s", remote_id); |
192 | cleanup_exit(255); | 191 | cleanup_exit(255); |
@@ -197,14 +196,17 @@ client_alive_check(struct ssh *ssh) | |||
197 | * we should get back a failure | 196 | * we should get back a failure |
198 | */ | 197 | */ |
199 | if ((channel_id = channel_find_open(ssh)) == -1) { | 198 | if ((channel_id = channel_find_open(ssh)) == -1) { |
200 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 199 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
201 | packet_put_cstring("keepalive@openssh.com"); | 200 | (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) |
202 | packet_put_char(1); /* boolean: want reply */ | 201 | != 0 || |
202 | (r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */ | ||
203 | fatal("%s: %s", __func__, ssh_err(r)); | ||
203 | } else { | 204 | } else { |
204 | channel_request_start(ssh, channel_id, | 205 | channel_request_start(ssh, channel_id, |
205 | "keepalive@openssh.com", 1); | 206 | "keepalive@openssh.com", 1); |
206 | } | 207 | } |
207 | packet_send(); | 208 | if ((r = sshpkt_send(ssh)) != 0) |
209 | fatal("%s: %s", __func__, ssh_err(r)); | ||
208 | } | 210 | } |
209 | 211 | ||
210 | /* | 212 | /* |
@@ -261,14 +263,14 @@ wait_until_can_do_something(struct ssh *ssh, | |||
261 | * If we have buffered packet data going to the client, mark that | 263 | * If we have buffered packet data going to the client, mark that |
262 | * descriptor. | 264 | * descriptor. |
263 | */ | 265 | */ |
264 | if (packet_have_data_to_write()) | 266 | if (ssh_packet_have_data_to_write(ssh)) |
265 | FD_SET(connection_out, *writesetp); | 267 | FD_SET(connection_out, *writesetp); |
266 | 268 | ||
267 | /* | 269 | /* |
268 | * If child has terminated and there is enough buffer space to read | 270 | * If child has terminated and there is enough buffer space to read |
269 | * from it, then read as much as is available and exit. | 271 | * from it, then read as much as is available and exit. |
270 | */ | 272 | */ |
271 | if (child_terminated && packet_not_very_much_data_to_write()) | 273 | if (child_terminated && ssh_packet_not_very_much_data_to_write(ssh)) |
272 | if (max_time_ms == 0 || client_alive_scheduled) | 274 | if (max_time_ms == 0 || client_alive_scheduled) |
273 | max_time_ms = 100; | 275 | max_time_ms = 100; |
274 | 276 | ||
@@ -312,7 +314,7 @@ wait_until_can_do_something(struct ssh *ssh, | |||
312 | static int | 314 | static int |
313 | process_input(struct ssh *ssh, fd_set *readset, int connection_in) | 315 | process_input(struct ssh *ssh, fd_set *readset, int connection_in) |
314 | { | 316 | { |
315 | int len; | 317 | int r, len; |
316 | char buf[16384]; | 318 | char buf[16384]; |
317 | 319 | ||
318 | /* Read and buffer any input data from the client. */ | 320 | /* Read and buffer any input data from the client. */ |
@@ -333,7 +335,10 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in) | |||
333 | } | 335 | } |
334 | } else { | 336 | } else { |
335 | /* Buffer any received data. */ | 337 | /* Buffer any received data. */ |
336 | packet_process_incoming(buf, len); | 338 | if ((r = ssh_packet_process_incoming(ssh, buf, len)) |
339 | != 0) | ||
340 | fatal("%s: ssh_packet_process_incoming: %s", | ||
341 | __func__, ssh_err(r)); | ||
337 | } | 342 | } |
338 | } | 343 | } |
339 | return 0; | 344 | return 0; |
@@ -343,11 +348,16 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in) | |||
343 | * Sends data from internal buffers to client program stdin. | 348 | * Sends data from internal buffers to client program stdin. |
344 | */ | 349 | */ |
345 | static void | 350 | static void |
346 | process_output(fd_set *writeset, int connection_out) | 351 | process_output(struct ssh *ssh, fd_set *writeset, int connection_out) |
347 | { | 352 | { |
353 | int r; | ||
354 | |||
348 | /* Send any buffered packet data to the client. */ | 355 | /* Send any buffered packet data to the client. */ |
349 | if (FD_ISSET(connection_out, writeset)) | 356 | if (FD_ISSET(connection_out, writeset)) { |
350 | packet_write_poll(); | 357 | if ((r = ssh_packet_write_poll(ssh)) != 0) |
358 | fatal("%s: ssh_packet_write_poll: %s", | ||
359 | __func__, ssh_err(r)); | ||
360 | } | ||
351 | } | 361 | } |
352 | 362 | ||
353 | static void | 363 | static void |
@@ -390,8 +400,8 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) | |||
390 | 400 | ||
391 | signal(SIGCHLD, sigchld_handler); | 401 | signal(SIGCHLD, sigchld_handler); |
392 | child_terminated = 0; | 402 | child_terminated = 0; |
393 | connection_in = packet_get_connection_in(); | 403 | connection_in = ssh_packet_get_connection_in(ssh); |
394 | connection_out = packet_get_connection_out(); | 404 | connection_out = ssh_packet_get_connection_out(ssh); |
395 | 405 | ||
396 | if (!use_privsep) { | 406 | if (!use_privsep) { |
397 | signal(SIGTERM, sigterm_handler); | 407 | signal(SIGTERM, sigterm_handler); |
@@ -404,18 +414,21 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) | |||
404 | max_fd = MAXIMUM(connection_in, connection_out); | 414 | max_fd = MAXIMUM(connection_in, connection_out); |
405 | max_fd = MAXIMUM(max_fd, notify_pipe[0]); | 415 | max_fd = MAXIMUM(max_fd, notify_pipe[0]); |
406 | 416 | ||
407 | server_init_dispatch(); | 417 | server_init_dispatch(ssh); |
408 | 418 | ||
409 | for (;;) { | 419 | for (;;) { |
410 | process_buffered_input_packets(ssh); | 420 | process_buffered_input_packets(ssh); |
411 | 421 | ||
412 | if (!ssh_packet_is_rekeying(ssh) && | 422 | if (!ssh_packet_is_rekeying(ssh) && |
413 | packet_not_very_much_data_to_write()) | 423 | ssh_packet_not_very_much_data_to_write(ssh)) |
414 | channel_output_poll(ssh); | 424 | channel_output_poll(ssh); |
415 | if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) | 425 | if (options.rekey_interval > 0 && |
416 | rekey_timeout_ms = packet_get_rekey_timeout() * 1000; | 426 | !ssh_packet_is_rekeying(ssh)) { |
417 | else | 427 | rekey_timeout_ms = ssh_packet_get_rekey_timeout(ssh) * |
428 | 1000; | ||
429 | } else { | ||
418 | rekey_timeout_ms = 0; | 430 | rekey_timeout_ms = 0; |
431 | } | ||
419 | 432 | ||
420 | wait_until_can_do_something(ssh, connection_in, connection_out, | 433 | wait_until_can_do_something(ssh, connection_in, connection_out, |
421 | &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); | 434 | &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); |
@@ -431,7 +444,7 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) | |||
431 | channel_after_select(ssh, readset, writeset); | 444 | channel_after_select(ssh, readset, writeset); |
432 | if (process_input(ssh, readset, connection_in) < 0) | 445 | if (process_input(ssh, readset, connection_in) < 0) |
433 | break; | 446 | break; |
434 | process_output(writeset, connection_out); | 447 | process_output(ssh, writeset, connection_out); |
435 | } | 448 | } |
436 | collect_children(ssh); | 449 | collect_children(ssh); |
437 | 450 | ||
@@ -454,7 +467,7 @@ server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh) | |||
454 | * even if this was generated by something other than | 467 | * even if this was generated by something other than |
455 | * the bogus CHANNEL_REQUEST we send for keepalives. | 468 | * the bogus CHANNEL_REQUEST we send for keepalives. |
456 | */ | 469 | */ |
457 | packet_set_alive_timeouts(0); | 470 | ssh_packet_set_alive_timeouts(ssh, 0); |
458 | return 0; | 471 | return 0; |
459 | } | 472 | } |
460 | 473 | ||
@@ -462,16 +475,28 @@ static Channel * | |||
462 | server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) | 475 | server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) |
463 | { | 476 | { |
464 | Channel *c = NULL; | 477 | Channel *c = NULL; |
465 | char *target, *originator; | 478 | char *target = NULL, *originator = NULL; |
466 | u_short target_port, originator_port; | 479 | u_int target_port = 0, originator_port = 0; |
467 | 480 | int r; | |
468 | target = packet_get_string(NULL); | 481 | |
469 | target_port = packet_get_int(); | 482 | if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 || |
470 | originator = packet_get_string(NULL); | 483 | (r = sshpkt_get_u32(ssh, &target_port)) != 0 || |
471 | originator_port = packet_get_int(); | 484 | (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || |
472 | packet_check_eom(); | 485 | (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || |
486 | (r = sshpkt_get_end(ssh)) != 0) | ||
487 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
488 | if (target_port > 0xFFFF) { | ||
489 | error("%s: invalid target port", __func__); | ||
490 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | ||
491 | goto out; | ||
492 | } | ||
493 | if (originator_port > 0xFFFF) { | ||
494 | error("%s: invalid originator port", __func__); | ||
495 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | ||
496 | goto out; | ||
497 | } | ||
473 | 498 | ||
474 | debug("%s: originator %s port %d, target %s port %d", __func__, | 499 | debug("%s: originator %s port %u, target %s port %u", __func__, |
475 | originator, originator_port, target, target_port); | 500 | originator, originator_port, target, target_port); |
476 | 501 | ||
477 | /* XXX fine grained permissions */ | 502 | /* XXX fine grained permissions */ |
@@ -488,9 +513,9 @@ server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) | |||
488 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | 513 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; |
489 | } | 514 | } |
490 | 515 | ||
516 | out: | ||
491 | free(originator); | 517 | free(originator); |
492 | free(target); | 518 | free(target); |
493 | |||
494 | return c; | 519 | return c; |
495 | } | 520 | } |
496 | 521 | ||
@@ -498,17 +523,23 @@ static Channel * | |||
498 | server_request_direct_streamlocal(struct ssh *ssh) | 523 | server_request_direct_streamlocal(struct ssh *ssh) |
499 | { | 524 | { |
500 | Channel *c = NULL; | 525 | Channel *c = NULL; |
501 | char *target, *originator; | 526 | char *target = NULL, *originator = NULL; |
502 | u_short originator_port; | 527 | u_int originator_port = 0; |
503 | struct passwd *pw = the_authctxt->pw; | 528 | struct passwd *pw = the_authctxt->pw; |
529 | int r; | ||
504 | 530 | ||
505 | if (pw == NULL || !the_authctxt->valid) | 531 | if (pw == NULL || !the_authctxt->valid) |
506 | fatal("%s: no/invalid user", __func__); | 532 | fatal("%s: no/invalid user", __func__); |
507 | 533 | ||
508 | target = packet_get_string(NULL); | 534 | if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 || |
509 | originator = packet_get_string(NULL); | 535 | (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || |
510 | originator_port = packet_get_int(); | 536 | (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || |
511 | packet_check_eom(); | 537 | (r = sshpkt_get_end(ssh)) != 0) |
538 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
539 | if (originator_port > 0xFFFF) { | ||
540 | error("%s: invalid originator port", __func__); | ||
541 | goto out; | ||
542 | } | ||
512 | 543 | ||
513 | debug("%s: originator %s port %d, target %s", __func__, | 544 | debug("%s: originator %s port %d, target %s", __func__, |
514 | originator, originator_port, target); | 545 | originator, originator_port, target); |
@@ -525,9 +556,9 @@ server_request_direct_streamlocal(struct ssh *ssh) | |||
525 | originator, originator_port, target); | 556 | originator, originator_port, target); |
526 | } | 557 | } |
527 | 558 | ||
559 | out: | ||
528 | free(originator); | 560 | free(originator); |
529 | free(target); | 561 | free(target); |
530 | |||
531 | return c; | 562 | return c; |
532 | } | 563 | } |
533 | 564 | ||
@@ -535,27 +566,35 @@ static Channel * | |||
535 | server_request_tun(struct ssh *ssh) | 566 | server_request_tun(struct ssh *ssh) |
536 | { | 567 | { |
537 | Channel *c = NULL; | 568 | Channel *c = NULL; |
538 | int mode, tun, sock; | 569 | u_int mode, tun; |
570 | int r, sock; | ||
539 | char *tmp, *ifname = NULL; | 571 | char *tmp, *ifname = NULL; |
540 | 572 | ||
541 | mode = packet_get_int(); | 573 | if ((r = sshpkt_get_u32(ssh, &mode)) != 0) |
574 | sshpkt_fatal(ssh, r, "%s: parse mode", __func__); | ||
542 | switch (mode) { | 575 | switch (mode) { |
543 | case SSH_TUNMODE_POINTOPOINT: | 576 | case SSH_TUNMODE_POINTOPOINT: |
544 | case SSH_TUNMODE_ETHERNET: | 577 | case SSH_TUNMODE_ETHERNET: |
545 | break; | 578 | break; |
546 | default: | 579 | default: |
547 | packet_send_debug("Unsupported tunnel device mode."); | 580 | ssh_packet_send_debug(ssh, "Unsupported tunnel device mode."); |
548 | return NULL; | 581 | return NULL; |
549 | } | 582 | } |
550 | if ((options.permit_tun & mode) == 0) { | 583 | if ((options.permit_tun & mode) == 0) { |
551 | packet_send_debug("Server has rejected tunnel device " | 584 | ssh_packet_send_debug(ssh, "Server has rejected tunnel device " |
552 | "forwarding"); | 585 | "forwarding"); |
553 | return NULL; | 586 | return NULL; |
554 | } | 587 | } |
555 | 588 | ||
556 | tun = packet_get_int(); | 589 | if ((r = sshpkt_get_u32(ssh, &tun)) != 0) |
590 | sshpkt_fatal(ssh, r, "%s: parse device", __func__); | ||
591 | if (tun > INT_MAX) { | ||
592 | debug("%s: invalid tun", __func__); | ||
593 | goto done; | ||
594 | } | ||
557 | if (auth_opts->force_tun_device != -1) { | 595 | if (auth_opts->force_tun_device != -1) { |
558 | if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun) | 596 | if (tun != SSH_TUNID_ANY && |
597 | auth_opts->force_tun_device != (int)tun) | ||
559 | goto done; | 598 | goto done; |
560 | tun = auth_opts->force_tun_device; | 599 | tun = auth_opts->force_tun_device; |
561 | } | 600 | } |
@@ -588,7 +627,7 @@ server_request_tun(struct ssh *ssh) | |||
588 | 627 | ||
589 | done: | 628 | done: |
590 | if (c == NULL) | 629 | if (c == NULL) |
591 | packet_send_debug("Failed to open the tunnel device."); | 630 | ssh_packet_send_debug(ssh, "Failed to open the tunnel device."); |
592 | return c; | 631 | return c; |
593 | } | 632 | } |
594 | 633 | ||
@@ -596,13 +635,15 @@ static Channel * | |||
596 | server_request_session(struct ssh *ssh) | 635 | server_request_session(struct ssh *ssh) |
597 | { | 636 | { |
598 | Channel *c; | 637 | Channel *c; |
638 | int r; | ||
599 | 639 | ||
600 | debug("input_session_request"); | 640 | debug("input_session_request"); |
601 | packet_check_eom(); | 641 | if ((r = sshpkt_get_end(ssh)) != 0) |
642 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
602 | 643 | ||
603 | if (no_more_sessions) { | 644 | if (no_more_sessions) { |
604 | packet_disconnect("Possible attack: attempt to open a session " | 645 | sshpkt_disconnect(ssh, "Possible attack: attempt to open a " |
605 | "after additional sessions disabled"); | 646 | "session after additional sessions disabled"); |
606 | } | 647 | } |
607 | 648 | ||
608 | /* | 649 | /* |
@@ -627,20 +668,22 @@ static int | |||
627 | server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | 668 | server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) |
628 | { | 669 | { |
629 | Channel *c = NULL; | 670 | Channel *c = NULL; |
630 | char *ctype; | 671 | char *ctype = NULL; |
631 | const char *errmsg = NULL; | 672 | const char *errmsg = NULL; |
632 | int rchan, reason = SSH2_OPEN_CONNECT_FAILED; | 673 | int r, reason = SSH2_OPEN_CONNECT_FAILED; |
633 | u_int rmaxpack, rwindow, len; | 674 | u_int rchan = 0, rmaxpack = 0, rwindow = 0; |
634 | 675 | ||
635 | ctype = packet_get_string(&len); | 676 | if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 || |
636 | rchan = packet_get_int(); | 677 | (r = sshpkt_get_u32(ssh, &rchan)) != 0 || |
637 | rwindow = packet_get_int(); | 678 | (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || |
638 | rmaxpack = packet_get_int(); | 679 | (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) |
639 | 680 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | |
640 | debug("%s: ctype %s rchan %d win %d max %d", __func__, | 681 | debug("%s: ctype %s rchan %u win %u max %u", __func__, |
641 | ctype, rchan, rwindow, rmaxpack); | 682 | ctype, rchan, rwindow, rmaxpack); |
642 | 683 | ||
643 | if (strcmp(ctype, "session") == 0) { | 684 | if (rchan > INT_MAX) { |
685 | error("%s: invalid remote channel ID", __func__); | ||
686 | } else if (strcmp(ctype, "session") == 0) { | ||
644 | c = server_request_session(ssh); | 687 | c = server_request_session(ssh); |
645 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 688 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
646 | c = server_request_direct_tcpip(ssh, &reason, &errmsg); | 689 | c = server_request_direct_tcpip(ssh, &reason, &errmsg); |
@@ -651,26 +694,32 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | |||
651 | } | 694 | } |
652 | if (c != NULL) { | 695 | if (c != NULL) { |
653 | debug("%s: confirm %s", __func__, ctype); | 696 | debug("%s: confirm %s", __func__, ctype); |
654 | c->remote_id = rchan; | 697 | c->remote_id = (int)rchan; |
655 | c->have_remote_id = 1; | 698 | c->have_remote_id = 1; |
656 | c->remote_window = rwindow; | 699 | c->remote_window = rwindow; |
657 | c->remote_maxpacket = rmaxpack; | 700 | c->remote_maxpacket = rmaxpack; |
658 | if (c->type != SSH_CHANNEL_CONNECTING) { | 701 | if (c->type != SSH_CHANNEL_CONNECTING) { |
659 | packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); | 702 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || |
660 | packet_put_int(c->remote_id); | 703 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
661 | packet_put_int(c->self); | 704 | (r = sshpkt_put_u32(ssh, c->self)) != 0 || |
662 | packet_put_int(c->local_window); | 705 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || |
663 | packet_put_int(c->local_maxpacket); | 706 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || |
664 | packet_send(); | 707 | (r = sshpkt_send(ssh)) != 0) { |
708 | sshpkt_fatal(ssh, r, | ||
709 | "%s: send open confirm", __func__); | ||
710 | } | ||
665 | } | 711 | } |
666 | } else { | 712 | } else { |
667 | debug("%s: failure %s", __func__, ctype); | 713 | debug("%s: failure %s", __func__, ctype); |
668 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 714 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || |
669 | packet_put_int(rchan); | 715 | (r = sshpkt_put_u32(ssh, rchan)) != 0 || |
670 | packet_put_int(reason); | 716 | (r = sshpkt_put_u32(ssh, reason)) != 0 || |
671 | packet_put_cstring(errmsg ? errmsg : "open failed"); | 717 | (r = sshpkt_put_cstring(ssh, errmsg ? errmsg : "open failed")) != 0 || |
672 | packet_put_cstring(""); | 718 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
673 | packet_send(); | 719 | (r = sshpkt_send(ssh)) != 0) { |
720 | sshpkt_fatal(ssh, r, | ||
721 | "%s: send open failure", __func__); | ||
722 | } | ||
674 | } | 723 | } |
675 | free(ctype); | 724 | free(ctype); |
676 | return 0; | 725 | return 0; |
@@ -757,65 +806,66 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) | |||
757 | static int | 806 | static int |
758 | server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | 807 | server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) |
759 | { | 808 | { |
760 | char *rtype; | 809 | char *rtype = NULL; |
761 | int want_reply; | 810 | u_char want_reply = 0; |
762 | int r, success = 0, allocated_listen_port = 0; | 811 | int r, success = 0, allocated_listen_port = 0; |
812 | u_int port = 0; | ||
763 | struct sshbuf *resp = NULL; | 813 | struct sshbuf *resp = NULL; |
764 | struct passwd *pw = the_authctxt->pw; | 814 | struct passwd *pw = the_authctxt->pw; |
815 | struct Forward fwd; | ||
765 | 816 | ||
817 | memset(&fwd, 0, sizeof(fwd)); | ||
766 | if (pw == NULL || !the_authctxt->valid) | 818 | if (pw == NULL || !the_authctxt->valid) |
767 | fatal("%s: no/invalid user", __func__); | 819 | fatal("%s: no/invalid user", __func__); |
768 | 820 | ||
769 | rtype = packet_get_string(NULL); | 821 | if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || |
770 | want_reply = packet_get_char(); | 822 | (r = sshpkt_get_u8(ssh, &want_reply)) != 0) |
823 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
771 | debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply); | 824 | debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply); |
772 | 825 | ||
773 | /* -R style forwarding */ | 826 | /* -R style forwarding */ |
774 | if (strcmp(rtype, "tcpip-forward") == 0) { | 827 | if (strcmp(rtype, "tcpip-forward") == 0) { |
775 | struct Forward fwd; | 828 | if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || |
776 | 829 | (r = sshpkt_get_u32(ssh, &port)) != 0) | |
777 | memset(&fwd, 0, sizeof(fwd)); | 830 | sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__); |
778 | fwd.listen_host = packet_get_string(NULL); | 831 | debug("%s: tcpip-forward listen %s port %u", __func__, |
779 | fwd.listen_port = (u_short)packet_get_int(); | 832 | fwd.listen_host, port); |
780 | debug("%s: tcpip-forward listen %s port %d", __func__, | 833 | if (port <= INT_MAX) |
781 | fwd.listen_host, fwd.listen_port); | 834 | fwd.listen_port = (int)port; |
782 | |||
783 | /* check permissions */ | 835 | /* check permissions */ |
784 | if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || | 836 | if (port > INT_MAX || |
837 | (options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || | ||
785 | !auth_opts->permit_port_forwarding_flag || | 838 | !auth_opts->permit_port_forwarding_flag || |
786 | options.disable_forwarding || | 839 | options.disable_forwarding || |
787 | (!want_reply && fwd.listen_port == 0) || | 840 | (!want_reply && fwd.listen_port == 0) || |
788 | (fwd.listen_port != 0 && | 841 | (fwd.listen_port != 0 && |
789 | !bind_permitted(fwd.listen_port, pw->pw_uid))) { | 842 | !bind_permitted(fwd.listen_port, pw->pw_uid))) { |
790 | success = 0; | 843 | success = 0; |
791 | packet_send_debug("Server has disabled port forwarding."); | 844 | ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); |
792 | } else { | 845 | } else { |
793 | /* Start listening on the port */ | 846 | /* Start listening on the port */ |
794 | success = channel_setup_remote_fwd_listener(ssh, &fwd, | 847 | success = channel_setup_remote_fwd_listener(ssh, &fwd, |
795 | &allocated_listen_port, &options.fwd_opts); | 848 | &allocated_listen_port, &options.fwd_opts); |
796 | } | 849 | } |
797 | free(fwd.listen_host); | ||
798 | if ((resp = sshbuf_new()) == NULL) | 850 | if ((resp = sshbuf_new()) == NULL) |
799 | fatal("%s: sshbuf_new", __func__); | 851 | fatal("%s: sshbuf_new", __func__); |
800 | if (allocated_listen_port != 0 && | 852 | if (allocated_listen_port != 0 && |
801 | (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) | 853 | (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) |
802 | fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); | 854 | fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); |
803 | } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { | 855 | } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { |
804 | struct Forward fwd; | 856 | if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || |
857 | (r = sshpkt_get_u32(ssh, &port)) != 0) | ||
858 | sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__); | ||
805 | 859 | ||
806 | memset(&fwd, 0, sizeof(fwd)); | ||
807 | fwd.listen_host = packet_get_string(NULL); | ||
808 | fwd.listen_port = (u_short)packet_get_int(); | ||
809 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, | 860 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, |
810 | fwd.listen_host, fwd.listen_port); | 861 | fwd.listen_host, port); |
811 | 862 | if (port <= INT_MAX) { | |
812 | success = channel_cancel_rport_listener(ssh, &fwd); | 863 | fwd.listen_port = (int)port; |
813 | free(fwd.listen_host); | 864 | success = channel_cancel_rport_listener(ssh, &fwd); |
865 | } | ||
814 | } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { | 866 | } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { |
815 | struct Forward fwd; | 867 | if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) |
816 | 868 | sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward@openssh.com", __func__); | |
817 | memset(&fwd, 0, sizeof(fwd)); | ||
818 | fwd.listen_path = packet_get_string(NULL); | ||
819 | debug("%s: streamlocal-forward listen path %s", __func__, | 869 | debug("%s: streamlocal-forward listen path %s", __func__, |
820 | fwd.listen_path); | 870 | fwd.listen_path); |
821 | 871 | ||
@@ -825,39 +875,37 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
825 | options.disable_forwarding || | 875 | options.disable_forwarding || |
826 | (pw->pw_uid != 0 && !use_privsep)) { | 876 | (pw->pw_uid != 0 && !use_privsep)) { |
827 | success = 0; | 877 | success = 0; |
828 | packet_send_debug("Server has disabled " | 878 | ssh_packet_send_debug(ssh, "Server has disabled " |
829 | "streamlocal forwarding."); | 879 | "streamlocal forwarding."); |
830 | } else { | 880 | } else { |
831 | /* Start listening on the socket */ | 881 | /* Start listening on the socket */ |
832 | success = channel_setup_remote_fwd_listener(ssh, | 882 | success = channel_setup_remote_fwd_listener(ssh, |
833 | &fwd, NULL, &options.fwd_opts); | 883 | &fwd, NULL, &options.fwd_opts); |
834 | } | 884 | } |
835 | free(fwd.listen_path); | ||
836 | } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { | 885 | } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { |
837 | struct Forward fwd; | 886 | if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) |
838 | 887 | sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward@openssh.com", __func__); | |
839 | memset(&fwd, 0, sizeof(fwd)); | ||
840 | fwd.listen_path = packet_get_string(NULL); | ||
841 | debug("%s: cancel-streamlocal-forward path %s", __func__, | 888 | debug("%s: cancel-streamlocal-forward path %s", __func__, |
842 | fwd.listen_path); | 889 | fwd.listen_path); |
843 | 890 | ||
844 | success = channel_cancel_rport_listener(ssh, &fwd); | 891 | success = channel_cancel_rport_listener(ssh, &fwd); |
845 | free(fwd.listen_path); | ||
846 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { | 892 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { |
847 | no_more_sessions = 1; | 893 | no_more_sessions = 1; |
848 | success = 1; | 894 | success = 1; |
849 | } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { | 895 | } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { |
850 | success = server_input_hostkeys_prove(ssh, &resp); | 896 | success = server_input_hostkeys_prove(ssh, &resp); |
851 | } | 897 | } |
898 | /* XXX sshpkt_get_end() */ | ||
852 | if (want_reply) { | 899 | if (want_reply) { |
853 | packet_start(success ? | 900 | if ((r = sshpkt_start(ssh, success ? |
854 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); | 901 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 || |
855 | if (success && resp != NULL) | 902 | (success && resp != NULL && (r = sshpkt_putb(ssh, resp)) != 0) || |
856 | ssh_packet_put_raw(ssh, sshbuf_ptr(resp), | 903 | (r = sshpkt_send(ssh)) != 0 || |
857 | sshbuf_len(resp)); | 904 | (r = ssh_packet_write_wait(ssh)) != 0) |
858 | packet_send(); | 905 | sshpkt_fatal(ssh, r, "%s: send reply", __func__); |
859 | packet_write_wait(); | ||
860 | } | 906 | } |
907 | free(fwd.listen_host); | ||
908 | free(fwd.listen_path); | ||
861 | free(rtype); | 909 | free(rtype); |
862 | sshbuf_free(resp); | 910 | sshbuf_free(resp); |
863 | return 0; | 911 | return 0; |
@@ -867,58 +915,62 @@ static int | |||
867 | server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | 915 | server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) |
868 | { | 916 | { |
869 | Channel *c; | 917 | Channel *c; |
870 | int id, reply, success = 0; | 918 | int r, success = 0; |
871 | char *rtype; | 919 | char *rtype = NULL; |
920 | u_char want_reply = 0; | ||
921 | u_int id = 0; | ||
872 | 922 | ||
873 | id = packet_get_int(); | 923 | if ((r = sshpkt_get_u32(ssh, &id)) != 0 || |
874 | rtype = packet_get_string(NULL); | 924 | (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || |
875 | reply = packet_get_char(); | 925 | (r = sshpkt_get_u8(ssh, &want_reply)) != 0) |
926 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
876 | 927 | ||
877 | debug("server_input_channel_req: channel %d request %s reply %d", | 928 | debug("server_input_channel_req: channel %u request %s reply %d", |
878 | id, rtype, reply); | 929 | id, rtype, want_reply); |
879 | 930 | ||
880 | if ((c = channel_lookup(ssh, id)) == NULL) | 931 | if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) |
881 | packet_disconnect("server_input_channel_req: " | 932 | sshpkt_disconnect(ssh, "%s: unknown channel %d", __func__, id); |
882 | "unknown channel %d", id); | ||
883 | if (!strcmp(rtype, "eow@openssh.com")) { | 933 | if (!strcmp(rtype, "eow@openssh.com")) { |
884 | packet_check_eom(); | 934 | if ((r = sshpkt_get_end(ssh)) != 0) |
935 | sshpkt_fatal(ssh, r, "%s: parse packet", __func__); | ||
885 | chan_rcvd_eow(ssh, c); | 936 | chan_rcvd_eow(ssh, c); |
886 | } else if ((c->type == SSH_CHANNEL_LARVAL || | 937 | } else if ((c->type == SSH_CHANNEL_LARVAL || |
887 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) | 938 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) |
888 | success = session_input_channel_req(ssh, c, rtype); | 939 | success = session_input_channel_req(ssh, c, rtype); |
889 | if (reply && !(c->flags & CHAN_CLOSE_SENT)) { | 940 | if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) { |
890 | if (!c->have_remote_id) | 941 | if (!c->have_remote_id) |
891 | fatal("%s: channel %d: no remote_id", | 942 | fatal("%s: channel %d: no remote_id", |
892 | __func__, c->self); | 943 | __func__, c->self); |
893 | packet_start(success ? | 944 | if ((r = sshpkt_start(ssh, success ? |
894 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 945 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || |
895 | packet_put_int(c->remote_id); | 946 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
896 | packet_send(); | 947 | (r = sshpkt_send(ssh)) != 0) |
948 | sshpkt_fatal(ssh, r, "%s: send reply", __func__); | ||
897 | } | 949 | } |
898 | free(rtype); | 950 | free(rtype); |
899 | return 0; | 951 | return 0; |
900 | } | 952 | } |
901 | 953 | ||
902 | static void | 954 | static void |
903 | server_init_dispatch(void) | 955 | server_init_dispatch(struct ssh *ssh) |
904 | { | 956 | { |
905 | debug("server_init_dispatch"); | 957 | debug("server_init_dispatch"); |
906 | dispatch_init(&dispatch_protocol_error); | 958 | ssh_dispatch_init(ssh, &dispatch_protocol_error); |
907 | dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); | 959 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); |
908 | dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); | 960 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data); |
909 | dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); | 961 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); |
910 | dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); | 962 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); |
911 | dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open); | 963 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open); |
912 | dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); | 964 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); |
913 | dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); | 965 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); |
914 | dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); | 966 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); |
915 | dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); | 967 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); |
916 | dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); | 968 | ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); |
917 | /* client_alive */ | 969 | /* client_alive */ |
918 | dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive); | 970 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive); |
919 | dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive); | 971 | ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive); |
920 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); | 972 | ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); |
921 | dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); | 973 | ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); |
922 | /* rekeying */ | 974 | /* rekeying */ |
923 | dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); | 975 | ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); |
924 | } | 976 | } |