diff options
-rw-r--r-- | clientloop.c | 287 |
1 files changed, 166 insertions, 121 deletions
diff --git a/clientloop.c b/clientloop.c index d29ec00bc..5f87b24a2 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.319 2019/01/19 21:31:32 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.320 2019/01/19 21:33:57 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 |
@@ -478,21 +478,24 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) | |||
478 | free(gc); | 478 | free(gc); |
479 | } | 479 | } |
480 | 480 | ||
481 | packet_set_alive_timeouts(0); | 481 | ssh_packet_set_alive_timeouts(ssh, 0); |
482 | return 0; | 482 | return 0; |
483 | } | 483 | } |
484 | 484 | ||
485 | static void | 485 | static void |
486 | server_alive_check(void) | 486 | server_alive_check(struct ssh *ssh) |
487 | { | 487 | { |
488 | if (packet_inc_alive_timeouts() > options.server_alive_count_max) { | 488 | int r; |
489 | |||
490 | if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) { | ||
489 | logit("Timeout, server %s not responding.", host); | 491 | logit("Timeout, server %s not responding.", host); |
490 | cleanup_exit(255); | 492 | cleanup_exit(255); |
491 | } | 493 | } |
492 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 494 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
493 | packet_put_cstring("keepalive@openssh.com"); | 495 | (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 || |
494 | packet_put_char(1); /* boolean: want reply */ | 496 | (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */ |
495 | packet_send(); | 497 | (r = sshpkt_send(ssh)) != 0) |
498 | fatal("%s: %s", __func__, ssh_err(r)); | ||
496 | /* Insert an empty placeholder to maintain ordering */ | 499 | /* Insert an empty placeholder to maintain ordering */ |
497 | client_register_global_confirm(NULL, NULL); | 500 | client_register_global_confirm(NULL, NULL); |
498 | } | 501 | } |
@@ -517,7 +520,7 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
517 | 520 | ||
518 | /* channel_prepare_select could have closed the last channel */ | 521 | /* channel_prepare_select could have closed the last channel */ |
519 | if (session_closed && !channel_still_open(ssh) && | 522 | if (session_closed && !channel_still_open(ssh) && |
520 | !packet_have_data_to_write()) { | 523 | !ssh_packet_have_data_to_write(ssh)) { |
521 | /* clear mask since we did not call select() */ | 524 | /* clear mask since we did not call select() */ |
522 | memset(*readsetp, 0, *nallocp); | 525 | memset(*readsetp, 0, *nallocp); |
523 | memset(*writesetp, 0, *nallocp); | 526 | memset(*writesetp, 0, *nallocp); |
@@ -527,7 +530,7 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
527 | FD_SET(connection_in, *readsetp); | 530 | FD_SET(connection_in, *readsetp); |
528 | 531 | ||
529 | /* Select server connection if have data to write to the server. */ | 532 | /* Select server connection if have data to write to the server. */ |
530 | if (packet_have_data_to_write()) | 533 | if (ssh_packet_have_data_to_write(ssh)) |
531 | FD_SET(connection_out, *writesetp); | 534 | FD_SET(connection_out, *writesetp); |
532 | 535 | ||
533 | /* | 536 | /* |
@@ -542,7 +545,8 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
542 | server_alive_time = now + options.server_alive_interval; | 545 | server_alive_time = now + options.server_alive_interval; |
543 | } | 546 | } |
544 | if (options.rekey_interval > 0 && !rekeying) | 547 | if (options.rekey_interval > 0 && !rekeying) |
545 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); | 548 | timeout_secs = MINIMUM(timeout_secs, |
549 | ssh_packet_get_rekey_timeout(ssh)); | ||
546 | set_control_persist_exit_time(ssh); | 550 | set_control_persist_exit_time(ssh); |
547 | if (control_persist_exit_time > 0) { | 551 | if (control_persist_exit_time > 0) { |
548 | timeout_secs = MINIMUM(timeout_secs, | 552 | timeout_secs = MINIMUM(timeout_secs, |
@@ -583,7 +587,7 @@ client_wait_until_can_do_something(struct ssh *ssh, | |||
583 | * Keepalive we check here, rekeying is checked in clientloop. | 587 | * Keepalive we check here, rekeying is checked in clientloop. |
584 | */ | 588 | */ |
585 | if (server_alive_time != 0 && server_alive_time <= monotime()) | 589 | if (server_alive_time != 0 && server_alive_time <= monotime()) |
586 | server_alive_check(); | 590 | server_alive_check(ssh); |
587 | } | 591 | } |
588 | 592 | ||
589 | } | 593 | } |
@@ -615,7 +619,7 @@ client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr | |||
615 | } | 619 | } |
616 | 620 | ||
617 | static void | 621 | static void |
618 | client_process_net_input(fd_set *readset) | 622 | client_process_net_input(struct ssh *ssh, fd_set *readset) |
619 | { | 623 | { |
620 | char buf[SSH_IOBUFSZ]; | 624 | char buf[SSH_IOBUFSZ]; |
621 | int r, len; | 625 | int r, len; |
@@ -661,7 +665,7 @@ client_process_net_input(fd_set *readset) | |||
661 | quit_pending = 1; | 665 | quit_pending = 1; |
662 | return; | 666 | return; |
663 | } | 667 | } |
664 | packet_process_incoming(buf, len); | 668 | ssh_packet_process_incoming(ssh, buf, len); |
665 | } | 669 | } |
666 | } | 670 | } |
667 | 671 | ||
@@ -1284,8 +1288,8 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1284 | /* Initialize variables. */ | 1288 | /* Initialize variables. */ |
1285 | last_was_cr = 1; | 1289 | last_was_cr = 1; |
1286 | exit_status = -1; | 1290 | exit_status = -1; |
1287 | connection_in = packet_get_connection_in(); | 1291 | connection_in = ssh_packet_get_connection_in(ssh); |
1288 | connection_out = packet_get_connection_out(); | 1292 | connection_out = ssh_packet_get_connection_out(ssh); |
1289 | max_fd = MAXIMUM(connection_in, connection_out); | 1293 | max_fd = MAXIMUM(connection_in, connection_out); |
1290 | 1294 | ||
1291 | quit_pending = 0; | 1295 | quit_pending = 0; |
@@ -1349,7 +1353,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1349 | * Make packets from buffered channel data, and | 1353 | * Make packets from buffered channel data, and |
1350 | * enqueue them for sending to the server. | 1354 | * enqueue them for sending to the server. |
1351 | */ | 1355 | */ |
1352 | if (packet_not_very_much_data_to_write()) | 1356 | if (ssh_packet_not_very_much_data_to_write(ssh)) |
1353 | channel_output_poll(ssh); | 1357 | channel_output_poll(ssh); |
1354 | 1358 | ||
1355 | /* | 1359 | /* |
@@ -1377,7 +1381,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1377 | channel_after_select(ssh, readset, writeset); | 1381 | channel_after_select(ssh, readset, writeset); |
1378 | 1382 | ||
1379 | /* Buffer input from the connection. */ | 1383 | /* Buffer input from the connection. */ |
1380 | client_process_net_input(readset); | 1384 | client_process_net_input(ssh, readset); |
1381 | 1385 | ||
1382 | if (quit_pending) | 1386 | if (quit_pending) |
1383 | break; | 1387 | break; |
@@ -1387,7 +1391,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1387 | * sender. | 1391 | * sender. |
1388 | */ | 1392 | */ |
1389 | if (FD_ISSET(connection_out, writeset)) | 1393 | if (FD_ISSET(connection_out, writeset)) |
1390 | packet_write_poll(); | 1394 | ssh_packet_write_poll(ssh); |
1391 | 1395 | ||
1392 | /* | 1396 | /* |
1393 | * If we are a backgrounded control master, and the | 1397 | * If we are a backgrounded control master, and the |
@@ -1409,12 +1413,13 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1409 | /* Stop watching for window change. */ | 1413 | /* Stop watching for window change. */ |
1410 | signal(SIGWINCH, SIG_DFL); | 1414 | signal(SIGWINCH, SIG_DFL); |
1411 | 1415 | ||
1412 | packet_start(SSH2_MSG_DISCONNECT); | 1416 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || |
1413 | packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); | 1417 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 || |
1414 | packet_put_cstring("disconnected by user"); | 1418 | (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 || |
1415 | packet_put_cstring(""); /* language tag */ | 1419 | (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */ |
1416 | packet_send(); | 1420 | (r = sshpkt_send(ssh)) != 0 || |
1417 | packet_write_wait(); | 1421 | (r = ssh_packet_write_wait(ssh)) != 0) |
1422 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1418 | 1423 | ||
1419 | channel_free_all(ssh); | 1424 | channel_free_all(ssh); |
1420 | 1425 | ||
@@ -1471,7 +1476,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, | |||
1471 | 1476 | ||
1472 | /* Report bytes transferred, and transfer rates. */ | 1477 | /* Report bytes transferred, and transfer rates. */ |
1473 | total_time = monotime_double() - start_time; | 1478 | total_time = monotime_double() - start_time; |
1474 | packet_get_bytes(&ibytes, &obytes); | 1479 | ssh_packet_get_bytes(ssh, &ibytes, &obytes); |
1475 | verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", | 1480 | verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", |
1476 | (unsigned long long)obytes, (unsigned long long)ibytes, total_time); | 1481 | (unsigned long long)obytes, (unsigned long long)ibytes, total_time); |
1477 | if (total_time > 0) | 1482 | if (total_time > 0) |
@@ -1491,21 +1496,29 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, | |||
1491 | Channel *c = NULL; | 1496 | Channel *c = NULL; |
1492 | struct sshbuf *b = NULL; | 1497 | struct sshbuf *b = NULL; |
1493 | char *listen_address, *originator_address; | 1498 | char *listen_address, *originator_address; |
1494 | u_short listen_port, originator_port; | 1499 | u_int listen_port, originator_port; |
1495 | int r; | 1500 | int r; |
1496 | 1501 | ||
1497 | /* Get rest of the packet */ | 1502 | /* Get rest of the packet */ |
1498 | listen_address = packet_get_string(NULL); | 1503 | if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL)) != 0 || |
1499 | listen_port = packet_get_int(); | 1504 | (r = sshpkt_get_u32(ssh, &listen_port)) != 0 || |
1500 | originator_address = packet_get_string(NULL); | 1505 | (r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 || |
1501 | originator_port = packet_get_int(); | 1506 | (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || |
1502 | packet_check_eom(); | 1507 | (r = sshpkt_get_end(ssh)) != 0) |
1508 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1503 | 1509 | ||
1504 | debug("%s: listen %s port %d, originator %s port %d", __func__, | 1510 | debug("%s: listen %s port %d, originator %s port %d", __func__, |
1505 | listen_address, listen_port, originator_address, originator_port); | 1511 | listen_address, listen_port, originator_address, originator_port); |
1506 | 1512 | ||
1507 | c = channel_connect_by_listen_address(ssh, listen_address, listen_port, | 1513 | if (listen_port > 0xffff) |
1508 | "forwarded-tcpip", originator_address); | 1514 | error("%s: invalid listen port", __func__); |
1515 | else if (originator_port > 0xffff) | ||
1516 | error("%s: invalid originator port", __func__); | ||
1517 | else { | ||
1518 | c = channel_connect_by_listen_address(ssh, | ||
1519 | listen_address, listen_port, "forwarded-tcpip", | ||
1520 | originator_address); | ||
1521 | } | ||
1509 | 1522 | ||
1510 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { | 1523 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
1511 | if ((b = sshbuf_new()) == NULL) { | 1524 | if ((b = sshbuf_new()) == NULL) { |
@@ -1543,13 +1556,13 @@ client_request_forwarded_streamlocal(struct ssh *ssh, | |||
1543 | { | 1556 | { |
1544 | Channel *c = NULL; | 1557 | Channel *c = NULL; |
1545 | char *listen_path; | 1558 | char *listen_path; |
1559 | int r; | ||
1546 | 1560 | ||
1547 | /* Get the remote path. */ | 1561 | /* Get the remote path. */ |
1548 | listen_path = packet_get_string(NULL); | 1562 | if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 || |
1549 | /* XXX: Skip reserved field for now. */ | 1563 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */ |
1550 | if (packet_get_string_ptr(NULL) == NULL) | 1564 | (r = sshpkt_get_end(ssh)) != 0) |
1551 | fatal("%s: packet_get_string_ptr failed", __func__); | 1565 | fatal("%s: %s", __func__, ssh_err(r)); |
1552 | packet_check_eom(); | ||
1553 | 1566 | ||
1554 | debug("%s: %s", __func__, listen_path); | 1567 | debug("%s: %s", __func__, listen_path); |
1555 | 1568 | ||
@@ -1564,8 +1577,8 @@ client_request_x11(struct ssh *ssh, const char *request_type, int rchan) | |||
1564 | { | 1577 | { |
1565 | Channel *c = NULL; | 1578 | Channel *c = NULL; |
1566 | char *originator; | 1579 | char *originator; |
1567 | u_short originator_port; | 1580 | int originator_port; |
1568 | int sock; | 1581 | int r, sock; |
1569 | 1582 | ||
1570 | if (!options.forward_x11) { | 1583 | if (!options.forward_x11) { |
1571 | error("Warning: ssh server tried X11 forwarding."); | 1584 | error("Warning: ssh server tried X11 forwarding."); |
@@ -1578,9 +1591,10 @@ client_request_x11(struct ssh *ssh, const char *request_type, int rchan) | |||
1578 | "expired"); | 1591 | "expired"); |
1579 | return NULL; | 1592 | return NULL; |
1580 | } | 1593 | } |
1581 | originator = packet_get_string(NULL); | 1594 | if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || |
1582 | originator_port = packet_get_int(); | 1595 | (r = sshpkt_get_u32(ssh, (u_int *)&originator_port)) != 0 || |
1583 | packet_check_eom(); | 1596 | (r = sshpkt_get_end(ssh)) != 0) |
1597 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1584 | /* XXX check permission */ | 1598 | /* XXX check permission */ |
1585 | debug("client_request_x11: request from %s %d", originator, | 1599 | debug("client_request_x11: request from %s %d", originator, |
1586 | originator_port); | 1600 | originator_port); |
@@ -1626,7 +1640,7 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode, | |||
1626 | int local_tun, int remote_tun) | 1640 | int local_tun, int remote_tun) |
1627 | { | 1641 | { |
1628 | Channel *c; | 1642 | Channel *c; |
1629 | int fd; | 1643 | int r, fd; |
1630 | char *ifname = NULL; | 1644 | char *ifname = NULL; |
1631 | 1645 | ||
1632 | if (tun_mode == SSH_TUNMODE_NO) | 1646 | if (tun_mode == SSH_TUNMODE_NO) |
@@ -1651,14 +1665,15 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode, | |||
1651 | sys_tun_outfilter, NULL, NULL); | 1665 | sys_tun_outfilter, NULL, NULL); |
1652 | #endif | 1666 | #endif |
1653 | 1667 | ||
1654 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 1668 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || |
1655 | packet_put_cstring("tun@openssh.com"); | 1669 | (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 || |
1656 | packet_put_int(c->self); | 1670 | (r = sshpkt_put_u32(ssh, c->self)) != 0 || |
1657 | packet_put_int(c->local_window_max); | 1671 | (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 || |
1658 | packet_put_int(c->local_maxpacket); | 1672 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || |
1659 | packet_put_int(tun_mode); | 1673 | (r = sshpkt_put_u32(ssh, tun_mode)) != 0 || |
1660 | packet_put_int(remote_tun); | 1674 | (r = sshpkt_put_u32(ssh, remote_tun)) != 0 || |
1661 | packet_send(); | 1675 | (r = sshpkt_send(ssh)) != 0) |
1676 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1662 | 1677 | ||
1663 | return ifname; | 1678 | return ifname; |
1664 | } | 1679 | } |
@@ -1668,14 +1683,17 @@ static int | |||
1668 | client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | 1683 | client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) |
1669 | { | 1684 | { |
1670 | Channel *c = NULL; | 1685 | Channel *c = NULL; |
1671 | char *ctype; | 1686 | char *ctype = NULL; |
1672 | int rchan; | 1687 | int r; |
1673 | u_int rmaxpack, rwindow, len; | 1688 | u_int rchan; |
1674 | 1689 | size_t len; | |
1675 | ctype = packet_get_string(&len); | 1690 | u_int rmaxpack, rwindow; |
1676 | rchan = packet_get_int(); | 1691 | |
1677 | rwindow = packet_get_int(); | 1692 | if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 || |
1678 | rmaxpack = packet_get_int(); | 1693 | (r = sshpkt_get_u32(ssh, &rchan)) != 0 || |
1694 | (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || | ||
1695 | (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) | ||
1696 | goto out; | ||
1679 | 1697 | ||
1680 | debug("client_input_channel_open: ctype %s rchan %d win %d max %d", | 1698 | debug("client_input_channel_open: ctype %s rchan %d win %d max %d", |
1681 | ctype, rchan, rwindow, rmaxpack); | 1699 | ctype, rchan, rwindow, rmaxpack); |
@@ -1699,57 +1717,66 @@ client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | |||
1699 | c->remote_window = rwindow; | 1717 | c->remote_window = rwindow; |
1700 | c->remote_maxpacket = rmaxpack; | 1718 | c->remote_maxpacket = rmaxpack; |
1701 | if (c->type != SSH_CHANNEL_CONNECTING) { | 1719 | if (c->type != SSH_CHANNEL_CONNECTING) { |
1702 | packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); | 1720 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || |
1703 | packet_put_int(c->remote_id); | 1721 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
1704 | packet_put_int(c->self); | 1722 | (r = sshpkt_put_u32(ssh, c->self)) != 0 || |
1705 | packet_put_int(c->local_window); | 1723 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || |
1706 | packet_put_int(c->local_maxpacket); | 1724 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || |
1707 | packet_send(); | 1725 | (r = sshpkt_send(ssh)) != 0) |
1726 | sshpkt_fatal(ssh, r, "%s: send reply", __func__); | ||
1708 | } | 1727 | } |
1709 | } else { | 1728 | } else { |
1710 | debug("failure %s", ctype); | 1729 | debug("failure %s", ctype); |
1711 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 1730 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || |
1712 | packet_put_int(rchan); | 1731 | (r = sshpkt_put_u32(ssh, rchan)) != 0 || |
1713 | packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); | 1732 | (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 || |
1714 | packet_put_cstring("open failed"); | 1733 | (r = sshpkt_put_cstring(ssh, "open failed")) != 0 || |
1715 | packet_put_cstring(""); | 1734 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
1716 | packet_send(); | 1735 | (r = sshpkt_send(ssh)) != 0) |
1736 | sshpkt_fatal(ssh, r, "%s: send failure", __func__); | ||
1717 | } | 1737 | } |
1738 | r = 0; | ||
1739 | out: | ||
1718 | free(ctype); | 1740 | free(ctype); |
1719 | return 0; | 1741 | return r; |
1720 | } | 1742 | } |
1721 | 1743 | ||
1722 | static int | 1744 | static int |
1723 | client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | 1745 | client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) |
1724 | { | 1746 | { |
1725 | Channel *c = NULL; | 1747 | Channel *c = NULL; |
1726 | int exitval, id, reply, success = 0; | 1748 | char *rtype = NULL; |
1727 | char *rtype; | 1749 | u_char reply; |
1728 | 1750 | u_int id, exitval; | |
1729 | id = packet_get_int(); | 1751 | int r, success = 0; |
1730 | c = channel_lookup(ssh, id); | 1752 | |
1753 | if ((r = sshpkt_get_u32(ssh, &id)) != 0) | ||
1754 | return r; | ||
1755 | if (id <= INT_MAX) | ||
1756 | c = channel_lookup(ssh, id); | ||
1731 | if (channel_proxy_upstream(c, type, seq, ssh)) | 1757 | if (channel_proxy_upstream(c, type, seq, ssh)) |
1732 | return 0; | 1758 | return 0; |
1733 | rtype = packet_get_string(NULL); | 1759 | if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || |
1734 | reply = packet_get_char(); | 1760 | (r = sshpkt_get_u8(ssh, &reply)) != 0) |
1761 | goto out; | ||
1735 | 1762 | ||
1736 | debug("client_input_channel_req: channel %d rtype %s reply %d", | 1763 | debug("client_input_channel_req: channel %u rtype %s reply %d", |
1737 | id, rtype, reply); | 1764 | id, rtype, reply); |
1738 | 1765 | ||
1739 | if (id == -1) { | 1766 | if (c == NULL) { |
1740 | error("client_input_channel_req: request for channel -1"); | ||
1741 | } else if (c == NULL) { | ||
1742 | error("client_input_channel_req: channel %d: " | 1767 | error("client_input_channel_req: channel %d: " |
1743 | "unknown channel", id); | 1768 | "unknown channel", id); |
1744 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { | 1769 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { |
1745 | packet_check_eom(); | 1770 | if ((r = sshpkt_get_end(ssh)) != 0) |
1771 | goto out; | ||
1746 | chan_rcvd_eow(ssh, c); | 1772 | chan_rcvd_eow(ssh, c); |
1747 | } else if (strcmp(rtype, "exit-status") == 0) { | 1773 | } else if (strcmp(rtype, "exit-status") == 0) { |
1748 | exitval = packet_get_int(); | 1774 | if ((r = sshpkt_get_u32(ssh, &exitval)) != 0) |
1775 | goto out; | ||
1749 | if (c->ctl_chan != -1) { | 1776 | if (c->ctl_chan != -1) { |
1750 | mux_exit_message(ssh, c, exitval); | 1777 | mux_exit_message(ssh, c, exitval); |
1751 | success = 1; | 1778 | success = 1; |
1752 | } else if (id == session_ident) { | 1779 | } else if ((int)id == session_ident) { |
1753 | /* Record exit value of local session */ | 1780 | /* Record exit value of local session */ |
1754 | success = 1; | 1781 | success = 1; |
1755 | exit_status = exitval; | 1782 | exit_status = exitval; |
@@ -1758,19 +1785,23 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | |||
1758 | debug("%s: no sink for exit-status on channel %d", | 1785 | debug("%s: no sink for exit-status on channel %d", |
1759 | __func__, id); | 1786 | __func__, id); |
1760 | } | 1787 | } |
1761 | packet_check_eom(); | 1788 | if ((r = sshpkt_get_end(ssh)) != 0) |
1789 | goto out; | ||
1762 | } | 1790 | } |
1763 | if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { | 1791 | if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { |
1764 | if (!c->have_remote_id) | 1792 | if (!c->have_remote_id) |
1765 | fatal("%s: channel %d: no remote_id", | 1793 | fatal("%s: channel %d: no remote_id", |
1766 | __func__, c->self); | 1794 | __func__, c->self); |
1767 | packet_start(success ? | 1795 | if ((r = sshpkt_start(ssh, success ? |
1768 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 1796 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || |
1769 | packet_put_int(c->remote_id); | 1797 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
1770 | packet_send(); | 1798 | (r = sshpkt_send(ssh)) != 0) |
1799 | sshpkt_fatal(ssh, r, "%s: send failure", __func__); | ||
1771 | } | 1800 | } |
1801 | r = 0; | ||
1802 | out: | ||
1772 | free(rtype); | 1803 | free(rtype); |
1773 | return 0; | 1804 | return r; |
1774 | } | 1805 | } |
1775 | 1806 | ||
1776 | struct hostkeys_update_ctx { | 1807 | struct hostkeys_update_ctx { |
@@ -1987,7 +2018,10 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, | |||
1987 | if (ndone != ctx->nnew) | 2018 | if (ndone != ctx->nnew) |
1988 | fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__, | 2019 | fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__, |
1989 | ndone, ctx->nnew); /* Shouldn't happen */ | 2020 | ndone, ctx->nnew); /* Shouldn't happen */ |
1990 | ssh_packet_check_eom(ssh); | 2021 | if ((r = sshpkt_get_end(ssh)) != 0) { |
2022 | error("%s: protocol error", __func__); | ||
2023 | goto out; | ||
2024 | } | ||
1991 | 2025 | ||
1992 | /* Make the edits to known_hosts */ | 2026 | /* Make the edits to known_hosts */ |
1993 | update_known_hosts(ctx); | 2027 | update_known_hosts(ctx); |
@@ -2174,23 +2208,27 @@ static int | |||
2174 | client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | 2208 | client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) |
2175 | { | 2209 | { |
2176 | char *rtype; | 2210 | char *rtype; |
2177 | int want_reply; | 2211 | u_char want_reply; |
2178 | int success = 0; | 2212 | int r, success = 0; |
2179 | 2213 | ||
2180 | rtype = packet_get_cstring(NULL); | 2214 | if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || |
2181 | want_reply = packet_get_char(); | 2215 | (r = sshpkt_get_u8(ssh, &want_reply)) != 0) |
2216 | goto out; | ||
2182 | debug("client_input_global_request: rtype %s want_reply %d", | 2217 | debug("client_input_global_request: rtype %s want_reply %d", |
2183 | rtype, want_reply); | 2218 | rtype, want_reply); |
2184 | if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) | 2219 | if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) |
2185 | success = client_input_hostkeys(); | 2220 | success = client_input_hostkeys(); |
2186 | if (want_reply) { | 2221 | if (want_reply) { |
2187 | packet_start(success ? | 2222 | if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS : |
2188 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); | 2223 | SSH2_MSG_REQUEST_FAILURE)) != 0 || |
2189 | packet_send(); | 2224 | (r = sshpkt_send(ssh)) != 0 || |
2190 | packet_write_wait(); | 2225 | (r = ssh_packet_write_wait(ssh)) != 0) |
2226 | goto out; | ||
2191 | } | 2227 | } |
2228 | r = 0; | ||
2229 | out: | ||
2192 | free(rtype); | 2230 | free(rtype); |
2193 | return 0; | 2231 | return r; |
2194 | } | 2232 | } |
2195 | 2233 | ||
2196 | void | 2234 | void |
@@ -2198,7 +2236,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2198 | const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd, | 2236 | const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd, |
2199 | char **env) | 2237 | char **env) |
2200 | { | 2238 | { |
2201 | int i, j, matched, len; | 2239 | int i, j, matched, len, r; |
2202 | char *name, *val; | 2240 | char *name, *val; |
2203 | Channel *c = NULL; | 2241 | Channel *c = NULL; |
2204 | 2242 | ||
@@ -2207,7 +2245,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2207 | if ((c = channel_lookup(ssh, id)) == NULL) | 2245 | if ((c = channel_lookup(ssh, id)) == NULL) |
2208 | fatal("%s: channel %d: unknown channel", __func__, id); | 2246 | fatal("%s: channel %d: unknown channel", __func__, id); |
2209 | 2247 | ||
2210 | packet_set_interactive(want_tty, | 2248 | ssh_packet_set_interactive(ssh, want_tty, |
2211 | options.ip_qos_interactive, options.ip_qos_bulk); | 2249 | options.ip_qos_interactive, options.ip_qos_bulk); |
2212 | 2250 | ||
2213 | if (want_tty) { | 2251 | if (want_tty) { |
@@ -2219,15 +2257,18 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2219 | 2257 | ||
2220 | channel_request_start(ssh, id, "pty-req", 1); | 2258 | channel_request_start(ssh, id, "pty-req", 1); |
2221 | client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); | 2259 | client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); |
2222 | packet_put_cstring(term != NULL ? term : ""); | 2260 | if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : "")) |
2223 | packet_put_int((u_int)ws.ws_col); | 2261 | != 0 || |
2224 | packet_put_int((u_int)ws.ws_row); | 2262 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || |
2225 | packet_put_int((u_int)ws.ws_xpixel); | 2263 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || |
2226 | packet_put_int((u_int)ws.ws_ypixel); | 2264 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || |
2265 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0) | ||
2266 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2227 | if (tiop == NULL) | 2267 | if (tiop == NULL) |
2228 | tiop = get_saved_tio(); | 2268 | tiop = get_saved_tio(); |
2229 | ssh_tty_make_modes(ssh, -1, tiop); | 2269 | ssh_tty_make_modes(ssh, -1, tiop); |
2230 | packet_send(); | 2270 | if ((r = sshpkt_send(ssh)) != 0) |
2271 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2231 | /* XXX wait for reply */ | 2272 | /* XXX wait for reply */ |
2232 | c->client_tty = 1; | 2273 | c->client_tty = 1; |
2233 | } | 2274 | } |
@@ -2259,9 +2300,10 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2259 | 2300 | ||
2260 | debug("Sending env %s = %s", name, val); | 2301 | debug("Sending env %s = %s", name, val); |
2261 | channel_request_start(ssh, id, "env", 0); | 2302 | channel_request_start(ssh, id, "env", 0); |
2262 | packet_put_cstring(name); | 2303 | if ((r = sshpkt_put_cstring(ssh, name)) != 0 || |
2263 | packet_put_cstring(val); | 2304 | (r = sshpkt_put_cstring(ssh, val)) != 0 || |
2264 | packet_send(); | 2305 | (r = sshpkt_send(ssh)) != 0) |
2306 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2265 | free(name); | 2307 | free(name); |
2266 | } | 2308 | } |
2267 | } | 2309 | } |
@@ -2276,9 +2318,10 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2276 | 2318 | ||
2277 | debug("Setting env %s = %s", name, val); | 2319 | debug("Setting env %s = %s", name, val); |
2278 | channel_request_start(ssh, id, "env", 0); | 2320 | channel_request_start(ssh, id, "env", 0); |
2279 | packet_put_cstring(name); | 2321 | if ((r = sshpkt_put_cstring(ssh, name)) != 0 || |
2280 | packet_put_cstring(val); | 2322 | (r = sshpkt_put_cstring(ssh, val)) != 0 || |
2281 | packet_send(); | 2323 | (r = sshpkt_send(ssh)) != 0) |
2324 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2282 | free(name); | 2325 | free(name); |
2283 | } | 2326 | } |
2284 | 2327 | ||
@@ -2298,12 +2341,14 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, | |||
2298 | channel_request_start(ssh, id, "exec", 1); | 2341 | channel_request_start(ssh, id, "exec", 1); |
2299 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); | 2342 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); |
2300 | } | 2343 | } |
2301 | packet_put_string(sshbuf_ptr(cmd), sshbuf_len(cmd)); | 2344 | if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 || |
2302 | packet_send(); | 2345 | (r = sshpkt_send(ssh)) != 0) |
2346 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2303 | } else { | 2347 | } else { |
2304 | channel_request_start(ssh, id, "shell", 1); | 2348 | channel_request_start(ssh, id, "shell", 1); |
2305 | client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); | 2349 | client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); |
2306 | packet_send(); | 2350 | if ((r = sshpkt_send(ssh)) != 0) |
2351 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2307 | } | 2352 | } |
2308 | } | 2353 | } |
2309 | 2354 | ||