10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 30Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 40Sstevel@tonic-gate * All rights reserved 50Sstevel@tonic-gate * This file contains code implementing the packet protocol and communication 60Sstevel@tonic-gate * with the other side. This same code is used both on client and server side. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 90Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 100Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 110Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 120Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * 150Sstevel@tonic-gate * SSH2 packet format added by Markus Friedl. 160Sstevel@tonic-gate * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 190Sstevel@tonic-gate * modification, are permitted provided that the following conditions 200Sstevel@tonic-gate * are met: 210Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 220Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 230Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 240Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 250Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 260Sstevel@tonic-gate * 270Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 280Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 290Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 300Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 310Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 320Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 330Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 340Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 350Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 360Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate /* 39*6375Sjp161948 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 400Sstevel@tonic-gate * Use is subject to license terms. 410Sstevel@tonic-gate */ 420Sstevel@tonic-gate 435562Sjp161948 /* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */ 440Sstevel@tonic-gate 450Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 460Sstevel@tonic-gate 475562Sjp161948 #include "includes.h" 485562Sjp161948 495562Sjp161948 #include "sys-queue.h" 500Sstevel@tonic-gate #include "xmalloc.h" 510Sstevel@tonic-gate #include "buffer.h" 520Sstevel@tonic-gate #include "packet.h" 530Sstevel@tonic-gate #include "bufaux.h" 540Sstevel@tonic-gate #include "crc32.h" 550Sstevel@tonic-gate #include "getput.h" 560Sstevel@tonic-gate #include "compress.h" 570Sstevel@tonic-gate #include "deattack.h" 580Sstevel@tonic-gate #include "channels.h" 590Sstevel@tonic-gate #include "compat.h" 600Sstevel@tonic-gate #include "ssh1.h" 610Sstevel@tonic-gate #include "ssh2.h" 620Sstevel@tonic-gate #include "cipher.h" 630Sstevel@tonic-gate #include "kex.h" 640Sstevel@tonic-gate #include "mac.h" 650Sstevel@tonic-gate #include "log.h" 660Sstevel@tonic-gate #include "canohost.h" 670Sstevel@tonic-gate #include "misc.h" 680Sstevel@tonic-gate #include "ssh.h" 690Sstevel@tonic-gate 700Sstevel@tonic-gate #ifdef ALTPRIVSEP 710Sstevel@tonic-gate static int packet_server = 0; 720Sstevel@tonic-gate static int packet_monitor = 0; 730Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 740Sstevel@tonic-gate 750Sstevel@tonic-gate #ifdef PACKET_DEBUG 760Sstevel@tonic-gate #define DBG(x) x 770Sstevel@tonic-gate #else 780Sstevel@tonic-gate #define DBG(x) 790Sstevel@tonic-gate #endif 800Sstevel@tonic-gate 810Sstevel@tonic-gate /* 820Sstevel@tonic-gate * This variable contains the file descriptors used for communicating with 830Sstevel@tonic-gate * the other side. connection_in is used for reading; connection_out for 840Sstevel@tonic-gate * writing. These can be the same descriptor, in which case it is assumed to 850Sstevel@tonic-gate * be a socket. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate static int connection_in = -1; 880Sstevel@tonic-gate static int connection_out = -1; 890Sstevel@tonic-gate 900Sstevel@tonic-gate /* Protocol flags for the remote side. */ 910Sstevel@tonic-gate static u_int remote_protocol_flags = 0; 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* Encryption context for receiving data. This is only used for decryption. */ 940Sstevel@tonic-gate static CipherContext receive_context; 950Sstevel@tonic-gate 960Sstevel@tonic-gate /* Encryption context for sending data. This is only used for encryption. */ 970Sstevel@tonic-gate static CipherContext send_context; 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* Buffer for raw input data from the socket. */ 1000Sstevel@tonic-gate Buffer input; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* Buffer for raw output data going to the socket. */ 1030Sstevel@tonic-gate Buffer output; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate /* Buffer for the partial outgoing packet being constructed. */ 1060Sstevel@tonic-gate static Buffer outgoing_packet; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* Buffer for the incoming packet currently being processed. */ 1090Sstevel@tonic-gate static Buffer incoming_packet; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* Scratch buffer for packet compression/decompression. */ 1120Sstevel@tonic-gate static Buffer compression_buffer; 1130Sstevel@tonic-gate static int compression_buffer_ready = 0; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* Flag indicating whether packet compression/decompression is enabled. */ 1160Sstevel@tonic-gate static int packet_compression = 0; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* default maximum packet size */ 1190Sstevel@tonic-gate int max_packet_size = 32768; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate /* Flag indicating whether this module has been initialized. */ 1220Sstevel@tonic-gate static int initialized = 0; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate /* Set to true if the connection is interactive. */ 1250Sstevel@tonic-gate static int interactive_mode = 0; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* Session key information for Encryption and MAC */ 1280Sstevel@tonic-gate Newkeys *newkeys[MODE_MAX]; 1295562Sjp161948 static struct packet_state { 1305562Sjp161948 u_int32_t seqnr; 1315562Sjp161948 u_int32_t packets; 1325562Sjp161948 u_int64_t blocks; 1335562Sjp161948 } p_read, p_send; 1345562Sjp161948 1355562Sjp161948 static u_int64_t max_blocks_in, max_blocks_out; 1365562Sjp161948 static u_int32_t rekey_limit; 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate /* Session key for protocol v1 */ 1390Sstevel@tonic-gate static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 1400Sstevel@tonic-gate static u_int ssh1_keylen; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* roundup current message to extra_pad bytes */ 1430Sstevel@tonic-gate static u_char extra_pad = 0; 1440Sstevel@tonic-gate 1455562Sjp161948 struct packet { 1465562Sjp161948 TAILQ_ENTRY(packet) next; 1475562Sjp161948 u_char type; 1485562Sjp161948 Buffer payload; 1495562Sjp161948 }; 1505562Sjp161948 TAILQ_HEAD(, packet) outgoing; 1515562Sjp161948 1520Sstevel@tonic-gate /* 1530Sstevel@tonic-gate * Sets the descriptors used for communication. Disables encryption until 1540Sstevel@tonic-gate * packet_set_encryption_key is called. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate void 1570Sstevel@tonic-gate packet_set_connection(int fd_in, int fd_out) 1580Sstevel@tonic-gate { 1590Sstevel@tonic-gate Cipher *none = cipher_by_name("none"); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate if (none == NULL) 1620Sstevel@tonic-gate fatal("packet_set_connection: cannot load cipher 'none'"); 1630Sstevel@tonic-gate connection_in = fd_in; 1640Sstevel@tonic-gate connection_out = fd_out; 1650Sstevel@tonic-gate cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT); 1660Sstevel@tonic-gate cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT); 1670Sstevel@tonic-gate newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 1680Sstevel@tonic-gate if (!initialized) { 1690Sstevel@tonic-gate initialized = 1; 1700Sstevel@tonic-gate buffer_init(&input); 1710Sstevel@tonic-gate buffer_init(&output); 1720Sstevel@tonic-gate buffer_init(&outgoing_packet); 1730Sstevel@tonic-gate buffer_init(&incoming_packet); 1745562Sjp161948 TAILQ_INIT(&outgoing); 1750Sstevel@tonic-gate } else { 1760Sstevel@tonic-gate buffer_clear(&input); 1770Sstevel@tonic-gate buffer_clear(&output); 1780Sstevel@tonic-gate buffer_clear(&outgoing_packet); 1790Sstevel@tonic-gate buffer_clear(&incoming_packet); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * Prime the cache for get_remote_ipaddr() while we have a 1840Sstevel@tonic-gate * socket on which to do a getpeername(). 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate (void) get_remote_ipaddr(); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* Kludge: arrange the close function to be called from fatal(). */ 1890Sstevel@tonic-gate fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* Returns 1 if remote host is connected via socket, 0 if not. */ 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate int 1950Sstevel@tonic-gate packet_connection_is_on_socket(void) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate struct sockaddr_storage from, to; 1980Sstevel@tonic-gate socklen_t fromlen, tolen; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* filedescriptors in and out are the same, so it's a socket */ 2010Sstevel@tonic-gate if (connection_in != -1 && connection_in == connection_out) 2020Sstevel@tonic-gate return 1; 2030Sstevel@tonic-gate fromlen = sizeof(from); 2040Sstevel@tonic-gate memset(&from, 0, sizeof(from)); 2050Sstevel@tonic-gate if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 2060Sstevel@tonic-gate return 0; 2070Sstevel@tonic-gate tolen = sizeof(to); 2080Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 2090Sstevel@tonic-gate if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 2100Sstevel@tonic-gate return 0; 2110Sstevel@tonic-gate if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 2120Sstevel@tonic-gate return 0; 2130Sstevel@tonic-gate if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 2140Sstevel@tonic-gate return 0; 2150Sstevel@tonic-gate return 1; 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* returns 1 if connection is via ipv4 */ 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate int 2210Sstevel@tonic-gate packet_connection_is_ipv4(void) 2220Sstevel@tonic-gate { 2230Sstevel@tonic-gate struct sockaddr_storage to; 2240Sstevel@tonic-gate socklen_t tolen = sizeof(to); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 2270Sstevel@tonic-gate if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 2280Sstevel@tonic-gate return 0; 2290Sstevel@tonic-gate if (to.ss_family == AF_INET) 2300Sstevel@tonic-gate return 1; 2310Sstevel@tonic-gate #ifdef IPV4_IN_IPV6 2320Sstevel@tonic-gate if (to.ss_family == AF_INET6 && 2330Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 2340Sstevel@tonic-gate return 1; 2350Sstevel@tonic-gate #endif 2360Sstevel@tonic-gate return 0; 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* Sets the connection into non-blocking mode. */ 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate void 2420Sstevel@tonic-gate packet_set_nonblocking(void) 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate /* Set the socket into non-blocking mode. */ 2450Sstevel@tonic-gate if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) 2460Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate if (connection_out != connection_in) { 2490Sstevel@tonic-gate if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) 2500Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate /* Returns the socket used for reading. */ 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate int 2570Sstevel@tonic-gate packet_get_connection_in(void) 2580Sstevel@tonic-gate { 2590Sstevel@tonic-gate return connection_in; 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* Returns the descriptor used for writing. */ 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate int 2650Sstevel@tonic-gate packet_get_connection_out(void) 2660Sstevel@tonic-gate { 2670Sstevel@tonic-gate return connection_out; 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* Closes the connection and clears and frees internal data structures. */ 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate void 2730Sstevel@tonic-gate packet_close(void) 2740Sstevel@tonic-gate { 2750Sstevel@tonic-gate if (!initialized) 2760Sstevel@tonic-gate return; 2770Sstevel@tonic-gate initialized = 0; 2780Sstevel@tonic-gate if (connection_in == connection_out) { 2790Sstevel@tonic-gate shutdown(connection_out, SHUT_RDWR); 2800Sstevel@tonic-gate close(connection_out); 2810Sstevel@tonic-gate } else { 2820Sstevel@tonic-gate close(connection_in); 2830Sstevel@tonic-gate close(connection_out); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate buffer_free(&input); 2860Sstevel@tonic-gate buffer_free(&output); 2870Sstevel@tonic-gate buffer_free(&outgoing_packet); 2880Sstevel@tonic-gate buffer_free(&incoming_packet); 2890Sstevel@tonic-gate if (compression_buffer_ready) { 2900Sstevel@tonic-gate buffer_free(&compression_buffer); 2910Sstevel@tonic-gate buffer_compress_uninit(); 2920Sstevel@tonic-gate compression_buffer_ready = 0; 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate cipher_cleanup(&send_context); 2950Sstevel@tonic-gate cipher_cleanup(&receive_context); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* Sets remote side protocol flags. */ 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate void 3010Sstevel@tonic-gate packet_set_protocol_flags(u_int protocol_flags) 3020Sstevel@tonic-gate { 3030Sstevel@tonic-gate remote_protocol_flags = protocol_flags; 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* Returns the remote protocol flags set earlier by the above function. */ 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate u_int 3090Sstevel@tonic-gate packet_get_protocol_flags(void) 3100Sstevel@tonic-gate { 3110Sstevel@tonic-gate return remote_protocol_flags; 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * Starts packet compression from the next packet on in both directions. 3160Sstevel@tonic-gate * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate static void 3200Sstevel@tonic-gate packet_init_compression(void) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate if (compression_buffer_ready == 1) 3230Sstevel@tonic-gate return; 3240Sstevel@tonic-gate compression_buffer_ready = 1; 3250Sstevel@tonic-gate buffer_init(&compression_buffer); 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate void 3290Sstevel@tonic-gate packet_start_compression(int level) 3300Sstevel@tonic-gate { 3310Sstevel@tonic-gate #ifdef ALTPRIVSEP 3320Sstevel@tonic-gate /* shouldn't happen! */ 3330Sstevel@tonic-gate if (packet_monitor) 3340Sstevel@tonic-gate fatal("INTERNAL ERROR: The monitor cannot compress."); 3350Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate if (packet_compression && !compat20) 3380Sstevel@tonic-gate fatal("Compression already enabled."); 3390Sstevel@tonic-gate packet_compression = 1; 3400Sstevel@tonic-gate packet_init_compression(); 3410Sstevel@tonic-gate buffer_compress_init_send(level); 3420Sstevel@tonic-gate buffer_compress_init_recv(); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * Causes any further packets to be encrypted using the given key. The same 3470Sstevel@tonic-gate * key is used for both sending and reception. However, both directions are 3480Sstevel@tonic-gate * encrypted independently of each other. 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate void 3520Sstevel@tonic-gate packet_set_encryption_key(const u_char *key, u_int keylen, 3530Sstevel@tonic-gate int number) 3540Sstevel@tonic-gate { 3550Sstevel@tonic-gate Cipher *cipher = cipher_by_number(number); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate if (cipher == NULL) 3580Sstevel@tonic-gate fatal("packet_set_encryption_key: unknown cipher number %d", number); 3590Sstevel@tonic-gate if (keylen < 20) 3600Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too small: %d", keylen); 3610Sstevel@tonic-gate if (keylen > SSH_SESSION_KEY_LENGTH) 3620Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too big: %d", keylen); 3630Sstevel@tonic-gate memcpy(ssh1_key, key, keylen); 3640Sstevel@tonic-gate ssh1_keylen = keylen; 3650Sstevel@tonic-gate cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 3660Sstevel@tonic-gate cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate u_int 3700Sstevel@tonic-gate packet_get_encryption_key(u_char *key) 3710Sstevel@tonic-gate { 3720Sstevel@tonic-gate if (key == NULL) 3730Sstevel@tonic-gate return (ssh1_keylen); 3740Sstevel@tonic-gate memcpy(key, ssh1_key, ssh1_keylen); 3750Sstevel@tonic-gate return (ssh1_keylen); 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* Start constructing a packet to send. */ 3790Sstevel@tonic-gate void 3800Sstevel@tonic-gate packet_start(u_char type) 3810Sstevel@tonic-gate { 3820Sstevel@tonic-gate u_char buf[9]; 3830Sstevel@tonic-gate int len; 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate DBG(debug("packet_start[%d]", type)); 3860Sstevel@tonic-gate len = compat20 ? 6 : 9; 3870Sstevel@tonic-gate memset(buf, 0, len - 1); 3880Sstevel@tonic-gate buf[len - 1] = type; 3890Sstevel@tonic-gate buffer_clear(&outgoing_packet); 3900Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate /* Append payload. */ 3940Sstevel@tonic-gate void 3950Sstevel@tonic-gate packet_put_char(int value) 3960Sstevel@tonic-gate { 3970Sstevel@tonic-gate char ch = value; 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate buffer_append(&outgoing_packet, &ch, 1); 4000Sstevel@tonic-gate } 4015562Sjp161948 4020Sstevel@tonic-gate void 4030Sstevel@tonic-gate packet_put_int(u_int value) 4040Sstevel@tonic-gate { 4050Sstevel@tonic-gate buffer_put_int(&outgoing_packet, value); 4060Sstevel@tonic-gate } 4075562Sjp161948 4080Sstevel@tonic-gate void 4090Sstevel@tonic-gate packet_put_string(const void *buf, u_int len) 4100Sstevel@tonic-gate { 4110Sstevel@tonic-gate buffer_put_string(&outgoing_packet, buf, len); 4120Sstevel@tonic-gate } 4135562Sjp161948 4140Sstevel@tonic-gate void 4150Sstevel@tonic-gate packet_put_cstring(const char *str) 4160Sstevel@tonic-gate { 4170Sstevel@tonic-gate buffer_put_cstring(&outgoing_packet, str); 4180Sstevel@tonic-gate } 4195562Sjp161948 4200Sstevel@tonic-gate void 4210Sstevel@tonic-gate packet_put_ascii_cstring(const char *str) 4220Sstevel@tonic-gate { 4230Sstevel@tonic-gate buffer_put_ascii_cstring(&outgoing_packet, str); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate void 4260Sstevel@tonic-gate packet_put_utf8_cstring(const u_char *str) 4270Sstevel@tonic-gate { 4280Sstevel@tonic-gate buffer_put_utf8_cstring(&outgoing_packet, str); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate #if 0 4310Sstevel@tonic-gate void 4320Sstevel@tonic-gate packet_put_ascii_string(const void *buf, u_int len) 4330Sstevel@tonic-gate { 4340Sstevel@tonic-gate buffer_put_ascii_string(&outgoing_packet, buf, len); 4350Sstevel@tonic-gate } 4360Sstevel@tonic-gate void 4370Sstevel@tonic-gate packet_put_utf8_string(const void *buf, u_int len) 4380Sstevel@tonic-gate { 4390Sstevel@tonic-gate buffer_put_utf8_string(&outgoing_packet, buf, len); 4400Sstevel@tonic-gate } 4410Sstevel@tonic-gate #endif 4420Sstevel@tonic-gate void 4430Sstevel@tonic-gate packet_put_raw(const void *buf, u_int len) 4440Sstevel@tonic-gate { 4450Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 4460Sstevel@tonic-gate } 4475562Sjp161948 4480Sstevel@tonic-gate void 4490Sstevel@tonic-gate packet_put_bignum(BIGNUM * value) 4500Sstevel@tonic-gate { 4510Sstevel@tonic-gate buffer_put_bignum(&outgoing_packet, value); 4520Sstevel@tonic-gate } 4535562Sjp161948 4540Sstevel@tonic-gate void 4550Sstevel@tonic-gate packet_put_bignum2(BIGNUM * value) 4560Sstevel@tonic-gate { 4570Sstevel@tonic-gate buffer_put_bignum2(&outgoing_packet, value); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * Finalizes and sends the packet. If the encryption key has been set, 4620Sstevel@tonic-gate * encrypts the packet before sending. 4630Sstevel@tonic-gate */ 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate static void 4660Sstevel@tonic-gate packet_send1(void) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate u_char buf[8], *cp; 4690Sstevel@tonic-gate int i, padding, len; 4700Sstevel@tonic-gate u_int checksum; 4715562Sjp161948 u_int32_t rnd = 0; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate /* 4740Sstevel@tonic-gate * If using packet compression, compress the payload of the outgoing 4750Sstevel@tonic-gate * packet. 4760Sstevel@tonic-gate */ 4770Sstevel@tonic-gate if (packet_compression) { 4780Sstevel@tonic-gate buffer_clear(&compression_buffer); 4790Sstevel@tonic-gate /* Skip padding. */ 4800Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8); 4810Sstevel@tonic-gate /* padding */ 4820Sstevel@tonic-gate buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 4830Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 4840Sstevel@tonic-gate buffer_clear(&outgoing_packet); 4850Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 4860Sstevel@tonic-gate buffer_len(&compression_buffer)); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate /* Compute packet length without padding (add checksum, remove padding). */ 4890Sstevel@tonic-gate len = buffer_len(&outgoing_packet) + 4 - 8; 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate /* Insert padding. Initialized to zero in packet_start1() */ 4920Sstevel@tonic-gate padding = 8 - len % 8; 4930Sstevel@tonic-gate if (!send_context.plaintext) { 4940Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 4950Sstevel@tonic-gate for (i = 0; i < padding; i++) { 4960Sstevel@tonic-gate if (i % 4 == 0) 4975562Sjp161948 rnd = arc4random(); 4985562Sjp161948 cp[7 - i] = rnd & 0xff; 4995562Sjp161948 rnd >>= 8; 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8 - padding); 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* Add check bytes. */ 5050Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 5060Sstevel@tonic-gate buffer_len(&outgoing_packet)); 5070Sstevel@tonic-gate PUT_32BIT(buf, checksum); 5080Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, 4); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate #ifdef PACKET_DEBUG 5110Sstevel@tonic-gate fprintf(stderr, "packet_send plain: "); 5120Sstevel@tonic-gate buffer_dump(&outgoing_packet); 5130Sstevel@tonic-gate #endif 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* Append to output. */ 5160Sstevel@tonic-gate PUT_32BIT(buf, len); 5170Sstevel@tonic-gate buffer_append(&output, buf, 4); 5180Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 5190Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 5200Sstevel@tonic-gate buffer_len(&outgoing_packet)); 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate #ifdef PACKET_DEBUG 5230Sstevel@tonic-gate fprintf(stderr, "encrypted: "); 5240Sstevel@tonic-gate buffer_dump(&output); 5250Sstevel@tonic-gate #endif 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate buffer_clear(&outgoing_packet); 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * Note that the packet is now only buffered in output. It won\'t be 5310Sstevel@tonic-gate * actually sent until packet_write_wait or packet_write_poll is 5320Sstevel@tonic-gate * called. 5330Sstevel@tonic-gate */ 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate void 5370Sstevel@tonic-gate set_newkeys(int mode) 5380Sstevel@tonic-gate { 5390Sstevel@tonic-gate Enc *enc; 5400Sstevel@tonic-gate Mac *mac; 5410Sstevel@tonic-gate Comp *comp; 5420Sstevel@tonic-gate CipherContext *cc; 5435562Sjp161948 u_int64_t *max_blocks; 5445562Sjp161948 int crypt_type; 5450Sstevel@tonic-gate 5465562Sjp161948 debug2("set_newkeys: mode %d", mode); 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate if (mode == MODE_OUT) { 5490Sstevel@tonic-gate cc = &send_context; 5505562Sjp161948 crypt_type = CIPHER_ENCRYPT; 5515562Sjp161948 p_send.packets = p_send.blocks = 0; 5525562Sjp161948 max_blocks = &max_blocks_out; 5530Sstevel@tonic-gate } else { 5540Sstevel@tonic-gate cc = &receive_context; 5555562Sjp161948 crypt_type = CIPHER_DECRYPT; 5565562Sjp161948 p_read.packets = p_read.blocks = 0; 5575562Sjp161948 max_blocks = &max_blocks_in; 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate if (newkeys[mode] != NULL) { 560*6375Sjp161948 debug("set_newkeys: setting new keys for '%s' mode", 561*6375Sjp161948 mode == MODE_IN ? "in" : "out"); 5620Sstevel@tonic-gate cipher_cleanup(cc); 5635562Sjp161948 free_keys(newkeys[mode]); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate newkeys[mode] = kex_get_newkeys(mode); 5660Sstevel@tonic-gate if (newkeys[mode] == NULL) 5670Sstevel@tonic-gate fatal("newkeys: no keys for mode %d", mode); 5680Sstevel@tonic-gate enc = &newkeys[mode]->enc; 5690Sstevel@tonic-gate mac = &newkeys[mode]->mac; 5700Sstevel@tonic-gate comp = &newkeys[mode]->comp; 5710Sstevel@tonic-gate if (mac->md != NULL) 5720Sstevel@tonic-gate mac->enabled = 1; 5730Sstevel@tonic-gate DBG(debug("cipher_init_context: %d", mode)); 5740Sstevel@tonic-gate cipher_init(cc, enc->cipher, enc->key, enc->key_len, 5755562Sjp161948 enc->iv, enc->block_size, crypt_type); 5760Sstevel@tonic-gate /* Deleting the keys does not gain extra security */ 5770Sstevel@tonic-gate /* memset(enc->iv, 0, enc->block_size); 5780Sstevel@tonic-gate memset(enc->key, 0, enc->key_len); */ 5790Sstevel@tonic-gate if (comp->type != 0 && comp->enabled == 0) { 5800Sstevel@tonic-gate packet_init_compression(); 5810Sstevel@tonic-gate if (mode == MODE_OUT) 5820Sstevel@tonic-gate buffer_compress_init_send(6); 5830Sstevel@tonic-gate else 5840Sstevel@tonic-gate buffer_compress_init_recv(); 5850Sstevel@tonic-gate comp->enabled = 1; 5860Sstevel@tonic-gate } 5875562Sjp161948 5885562Sjp161948 /* 5895562Sjp161948 * In accordance to the RFCs listed below we enforce the key 5905562Sjp161948 * re-exchange for: 5915562Sjp161948 * 5925562Sjp161948 * - every 1GB of transmitted data if the selected cipher block size 5935562Sjp161948 * is less than 16 bytes (3DES, Blowfish) 5945562Sjp161948 * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes) 5955562Sjp161948 * if the cipher block size is greater than or equal to 16 bytes (AES) 5965562Sjp161948 * - and we never send more than 2^32 SSH packets using the same keys. 5975562Sjp161948 * The recommendation of 2^31 packets is not enforced here but in 5985562Sjp161948 * packet_need_rekeying(). There is also a hard check in 5995562Sjp161948 * packet_send2_wrapped() that we don't send more than 2^32 packets. 6005562Sjp161948 * 6015562Sjp161948 * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no 6025562Sjp161948 * automatic rekeying is performed nor do we enforce the 3rd rule. 6035562Sjp161948 * This means that we can be always forced by the opposite side to never 6045562Sjp161948 * initiate automatic key re-exchange. This might change in the future. 6055562Sjp161948 * 6065562Sjp161948 * The RekeyLimit option keyword may only enforce more frequent key 6075562Sjp161948 * renegotiation, never less. For more information on key renegotiation, 6085562Sjp161948 * see: 6095562Sjp161948 * 6105562Sjp161948 * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key 6115562Sjp161948 * Re-Exchange" 6125562Sjp161948 * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3. 6135562Sjp161948 * Rekeying" and "6.1 Rekeying Considerations" 6145562Sjp161948 */ 6155562Sjp161948 if (enc->block_size >= 16) 6165562Sjp161948 *max_blocks = (u_int64_t)1 << (enc->block_size * 2); 6175562Sjp161948 else 6185562Sjp161948 *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 6195562Sjp161948 6205562Sjp161948 if (rekey_limit) 6215562Sjp161948 *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 6225562Sjp161948 } 6235562Sjp161948 6245562Sjp161948 void 6255562Sjp161948 free_keys(Newkeys *keys) 6265562Sjp161948 { 6275562Sjp161948 Enc *enc; 6285562Sjp161948 Mac *mac; 6295562Sjp161948 Comp *comp; 6305562Sjp161948 6315562Sjp161948 enc = &keys->enc; 6325562Sjp161948 mac = &keys->mac; 6335562Sjp161948 comp = &keys->comp; 6345562Sjp161948 memset(mac->key, 0, mac->key_len); 6355562Sjp161948 xfree(enc->name); 6365562Sjp161948 xfree(enc->iv); 6375562Sjp161948 xfree(enc->key); 6385562Sjp161948 xfree(mac->name); 6395562Sjp161948 xfree(mac->key); 6405562Sjp161948 xfree(comp->name); 6415562Sjp161948 xfree(keys); 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate /* 6450Sstevel@tonic-gate * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 6460Sstevel@tonic-gate */ 6470Sstevel@tonic-gate static void 6485562Sjp161948 packet_send2_wrapped(void) 6490Sstevel@tonic-gate { 6500Sstevel@tonic-gate u_char type, *cp, *macbuf = NULL; 6510Sstevel@tonic-gate u_char padlen, pad; 6520Sstevel@tonic-gate u_int packet_length = 0; 6530Sstevel@tonic-gate u_int i, len; 6545562Sjp161948 u_int32_t rnd = 0; 6550Sstevel@tonic-gate Enc *enc = NULL; 6560Sstevel@tonic-gate Mac *mac = NULL; 6570Sstevel@tonic-gate Comp *comp = NULL; 6580Sstevel@tonic-gate int block_size; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate if (newkeys[MODE_OUT] != NULL) { 6610Sstevel@tonic-gate enc = &newkeys[MODE_OUT]->enc; 6620Sstevel@tonic-gate mac = &newkeys[MODE_OUT]->mac; 6630Sstevel@tonic-gate comp = &newkeys[MODE_OUT]->comp; 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 6680Sstevel@tonic-gate type = cp[5]; 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate #ifdef PACKET_DEBUG 6710Sstevel@tonic-gate fprintf(stderr, "plain: "); 6720Sstevel@tonic-gate buffer_dump(&outgoing_packet); 6730Sstevel@tonic-gate #endif 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate if (comp && comp->enabled) { 6760Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 6770Sstevel@tonic-gate /* skip header, compress only payload */ 6780Sstevel@tonic-gate buffer_consume(&outgoing_packet, 5); 6790Sstevel@tonic-gate buffer_clear(&compression_buffer); 6800Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 6810Sstevel@tonic-gate buffer_clear(&outgoing_packet); 6820Sstevel@tonic-gate buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 6830Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 6840Sstevel@tonic-gate buffer_len(&compression_buffer)); 6850Sstevel@tonic-gate DBG(debug("compression: raw %d compressed %d", len, 6860Sstevel@tonic-gate buffer_len(&outgoing_packet))); 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate /* sizeof (packet_len + pad_len + payload) */ 6900Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate /* 6930Sstevel@tonic-gate * calc size of padding, alloc space, get random data, 6940Sstevel@tonic-gate * minimum padding is 4 bytes 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate padlen = block_size - (len % block_size); 6970Sstevel@tonic-gate if (padlen < 4) 6980Sstevel@tonic-gate padlen += block_size; 6990Sstevel@tonic-gate if (extra_pad) { 7000Sstevel@tonic-gate /* will wrap if extra_pad+padlen > 255 */ 7010Sstevel@tonic-gate extra_pad = roundup(extra_pad, block_size); 7020Sstevel@tonic-gate pad = extra_pad - ((len + padlen) % extra_pad); 7030Sstevel@tonic-gate debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 7040Sstevel@tonic-gate pad, len, padlen, extra_pad); 7050Sstevel@tonic-gate padlen += pad; 7060Sstevel@tonic-gate extra_pad = 0; 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate cp = buffer_append_space(&outgoing_packet, padlen); 7090Sstevel@tonic-gate if (enc && !send_context.plaintext) { 7100Sstevel@tonic-gate /* random padding */ 7110Sstevel@tonic-gate for (i = 0; i < padlen; i++) { 7120Sstevel@tonic-gate if (i % 4 == 0) 7135562Sjp161948 rnd = arc4random(); 7145562Sjp161948 cp[i] = rnd & 0xff; 7155562Sjp161948 rnd >>= 8; 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate } else { 7180Sstevel@tonic-gate /* clear padding */ 7190Sstevel@tonic-gate memset(cp, 0, padlen); 7200Sstevel@tonic-gate } 7210Sstevel@tonic-gate /* packet_length includes payload, padding and padding length field */ 7220Sstevel@tonic-gate packet_length = buffer_len(&outgoing_packet) - 4; 7230Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 7240Sstevel@tonic-gate PUT_32BIT(cp, packet_length); 7250Sstevel@tonic-gate cp[4] = padlen; 7260Sstevel@tonic-gate DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate /* compute MAC over seqnr and packet(length fields, payload, padding) */ 7290Sstevel@tonic-gate if (mac && mac->enabled) { 7305562Sjp161948 macbuf = mac_compute(mac, p_send.seqnr, 7310Sstevel@tonic-gate buffer_ptr(&outgoing_packet), 7320Sstevel@tonic-gate buffer_len(&outgoing_packet)); 7335562Sjp161948 DBG(debug("done calc MAC out #%d", p_send.seqnr)); 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate /* encrypt packet and append to output buffer. */ 7360Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 7370Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 7380Sstevel@tonic-gate buffer_len(&outgoing_packet)); 7390Sstevel@tonic-gate /* append unencrypted MAC */ 7400Sstevel@tonic-gate if (mac && mac->enabled) 7410Sstevel@tonic-gate buffer_append(&output, (char *)macbuf, mac->mac_len); 7420Sstevel@tonic-gate #ifdef PACKET_DEBUG 7430Sstevel@tonic-gate fprintf(stderr, "encrypted: "); 7440Sstevel@tonic-gate buffer_dump(&output); 7450Sstevel@tonic-gate #endif 7460Sstevel@tonic-gate /* increment sequence number for outgoing packets */ 7475562Sjp161948 if (++p_send.seqnr == 0) 7480Sstevel@tonic-gate log("outgoing seqnr wraps around"); 7495562Sjp161948 7505562Sjp161948 /* 7515562Sjp161948 * RFC 4344: 3.1. First Rekeying Recommendation 7525562Sjp161948 * 7535562Sjp161948 * "Because of possible information leakage through the MAC tag after a 7545562Sjp161948 * key exchange, .... an SSH implementation SHOULD NOT send more than 7555562Sjp161948 * 2**32 packets before rekeying again." 7565562Sjp161948 * 7575562Sjp161948 * The code below is a hard check so that we are sure we don't go across 7585562Sjp161948 * the suggestion. However, since the largest cipher block size we have 7595562Sjp161948 * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the 7605562Sjp161948 * same key while performing periodic rekeying. 7615562Sjp161948 */ 7625562Sjp161948 if (++p_send.packets == 0) 7635562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 7645562Sjp161948 fatal("too many packets encrypted with same key"); 7655562Sjp161948 p_send.blocks += (packet_length + 4) / block_size; 7660Sstevel@tonic-gate buffer_clear(&outgoing_packet); 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 7690Sstevel@tonic-gate #ifdef ALTPRIVSEP 7700Sstevel@tonic-gate /* set_newkeys(MODE_OUT) in client, server, but not monitor */ 7710Sstevel@tonic-gate if (!packet_is_server() && !packet_is_monitor()) 7720Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 7730Sstevel@tonic-gate set_newkeys(MODE_OUT); 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate 7765562Sjp161948 static void 7775562Sjp161948 packet_send2(void) 7785562Sjp161948 { 7795562Sjp161948 static int rekeying = 0; 7805562Sjp161948 struct packet *p; 7815562Sjp161948 u_char type, *cp; 7825562Sjp161948 7835562Sjp161948 cp = buffer_ptr(&outgoing_packet); 7845562Sjp161948 type = cp[5]; 7855562Sjp161948 7865562Sjp161948 /* during rekeying we can only send key exchange messages */ 7875562Sjp161948 if (rekeying) { 7885562Sjp161948 if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 7895562Sjp161948 (type <= SSH2_MSG_TRANSPORT_MAX))) { 7905562Sjp161948 debug("enqueue packet: %u", type); 7915562Sjp161948 p = xmalloc(sizeof(*p)); 7925562Sjp161948 p->type = type; 7935562Sjp161948 memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 7945562Sjp161948 buffer_init(&outgoing_packet); 7955562Sjp161948 TAILQ_INSERT_TAIL(&outgoing, p, next); 7965562Sjp161948 return; 7975562Sjp161948 } 7985562Sjp161948 } 7995562Sjp161948 8005562Sjp161948 /* rekeying starts with sending KEXINIT */ 8015562Sjp161948 if (type == SSH2_MSG_KEXINIT) 8025562Sjp161948 rekeying = 1; 8035562Sjp161948 8045562Sjp161948 packet_send2_wrapped(); 8055562Sjp161948 8065562Sjp161948 /* after a NEWKEYS message we can send the complete queue */ 8075562Sjp161948 if (type == SSH2_MSG_NEWKEYS) { 8085562Sjp161948 rekeying = 0; 8095562Sjp161948 while ((p = TAILQ_FIRST(&outgoing)) != NULL) { 8105562Sjp161948 type = p->type; 8115562Sjp161948 debug("dequeue packet: %u", type); 8125562Sjp161948 buffer_free(&outgoing_packet); 8135562Sjp161948 memcpy(&outgoing_packet, &p->payload, sizeof(Buffer)); 8145562Sjp161948 TAILQ_REMOVE(&outgoing, p, next); 8155562Sjp161948 xfree(p); 8165562Sjp161948 packet_send2_wrapped(); 8175562Sjp161948 } 8185562Sjp161948 } 8195562Sjp161948 } 8205562Sjp161948 8210Sstevel@tonic-gate void 8220Sstevel@tonic-gate packet_send(void) 8230Sstevel@tonic-gate { 8240Sstevel@tonic-gate if (compat20) 8250Sstevel@tonic-gate packet_send2(); 8260Sstevel@tonic-gate else 8270Sstevel@tonic-gate packet_send1(); 8280Sstevel@tonic-gate DBG(debug("packet_send done")); 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate /* 8320Sstevel@tonic-gate * Waits until a packet has been received, and returns its type. Note that 8330Sstevel@tonic-gate * no other data is processed until this returns, so this function should not 8340Sstevel@tonic-gate * be used during the interactive session. 8350Sstevel@tonic-gate */ 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate int 8380Sstevel@tonic-gate packet_read_seqnr(u_int32_t *seqnr_p) 8390Sstevel@tonic-gate { 8400Sstevel@tonic-gate int type, len; 8410Sstevel@tonic-gate fd_set *setp; 8420Sstevel@tonic-gate char buf[8192]; 8430Sstevel@tonic-gate DBG(debug("packet_read()")); 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 8460Sstevel@tonic-gate sizeof(fd_mask)); 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate /* Since we are blocking, ensure that all written packets have been sent. */ 8490Sstevel@tonic-gate packet_write_wait(); 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate /* Stay in the loop until we have received a complete packet. */ 8520Sstevel@tonic-gate for (;;) { 8530Sstevel@tonic-gate /* Try to read a packet from the buffer. */ 8540Sstevel@tonic-gate type = packet_read_poll_seqnr(seqnr_p); 8550Sstevel@tonic-gate if (!compat20 && ( 8560Sstevel@tonic-gate type == SSH_SMSG_SUCCESS 8570Sstevel@tonic-gate || type == SSH_SMSG_FAILURE 8580Sstevel@tonic-gate || type == SSH_CMSG_EOF 8590Sstevel@tonic-gate || type == SSH_CMSG_EXIT_CONFIRMATION)) 8600Sstevel@tonic-gate packet_check_eom(); 8610Sstevel@tonic-gate /* If we got a packet, return it. */ 8620Sstevel@tonic-gate if (type != SSH_MSG_NONE) { 8630Sstevel@tonic-gate xfree(setp); 8640Sstevel@tonic-gate return type; 8650Sstevel@tonic-gate } 8660Sstevel@tonic-gate /* 8670Sstevel@tonic-gate * Otherwise, wait for some data to arrive, add it to the 8680Sstevel@tonic-gate * buffer, and try again. 8690Sstevel@tonic-gate */ 8700Sstevel@tonic-gate memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 8710Sstevel@tonic-gate sizeof(fd_mask)); 8720Sstevel@tonic-gate FD_SET(connection_in, setp); 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate /* Wait for some data to arrive. */ 8750Sstevel@tonic-gate while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 8760Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 8770Sstevel@tonic-gate ; 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate /* Read data from the socket. */ 8800Sstevel@tonic-gate len = read(connection_in, buf, sizeof(buf)); 8810Sstevel@tonic-gate if (len == 0) { 8820Sstevel@tonic-gate log("Connection closed by %.200s", get_remote_ipaddr()); 8830Sstevel@tonic-gate fatal_cleanup(); 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate if (len < 0) 8860Sstevel@tonic-gate fatal("Read from socket failed: %.100s", strerror(errno)); 8870Sstevel@tonic-gate /* Append it to the buffer. */ 8880Sstevel@tonic-gate packet_process_incoming(buf, len); 8890Sstevel@tonic-gate } 8900Sstevel@tonic-gate /* NOTREACHED */ 8910Sstevel@tonic-gate } 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate int 8940Sstevel@tonic-gate packet_read(void) 8950Sstevel@tonic-gate { 8960Sstevel@tonic-gate return packet_read_seqnr(NULL); 8970Sstevel@tonic-gate } 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate /* 9000Sstevel@tonic-gate * Waits until a packet has been received, verifies that its type matches 9010Sstevel@tonic-gate * that given, and gives a fatal error and exits if there is a mismatch. 9020Sstevel@tonic-gate */ 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate void 9050Sstevel@tonic-gate packet_read_expect(int expected_type) 9060Sstevel@tonic-gate { 9070Sstevel@tonic-gate int type; 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate type = packet_read(); 9100Sstevel@tonic-gate if (type != expected_type) 9110Sstevel@tonic-gate packet_disconnect("Protocol error: expected packet type %d, got %d", 9120Sstevel@tonic-gate expected_type, type); 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate /* Checks if a full packet is available in the data received so far via 9160Sstevel@tonic-gate * packet_process_incoming. If so, reads the packet; otherwise returns 9170Sstevel@tonic-gate * SSH_MSG_NONE. This does not wait for data from the connection. 9180Sstevel@tonic-gate * 9190Sstevel@tonic-gate * SSH_MSG_DISCONNECT is handled specially here. Also, 9200Sstevel@tonic-gate * SSH_MSG_IGNORE messages are skipped by this function and are never returned 9210Sstevel@tonic-gate * to higher levels. 9220Sstevel@tonic-gate */ 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate static int 9250Sstevel@tonic-gate packet_read_poll1(void) 9260Sstevel@tonic-gate { 9270Sstevel@tonic-gate u_int len, padded_len; 9280Sstevel@tonic-gate u_char *cp, type; 9290Sstevel@tonic-gate u_int checksum, stored_checksum; 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate /* Check if input size is less than minimum packet size. */ 9320Sstevel@tonic-gate if (buffer_len(&input) < 4 + 8) 9330Sstevel@tonic-gate return SSH_MSG_NONE; 9340Sstevel@tonic-gate /* Get length of incoming packet. */ 9350Sstevel@tonic-gate cp = buffer_ptr(&input); 9360Sstevel@tonic-gate len = GET_32BIT(cp); 9370Sstevel@tonic-gate if (len < 1 + 2 + 2 || len > 256 * 1024) 9380Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", len); 9390Sstevel@tonic-gate padded_len = (len + 8) & ~7; 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate /* Check if the packet has been entirely received. */ 9420Sstevel@tonic-gate if (buffer_len(&input) < 4 + padded_len) 9430Sstevel@tonic-gate return SSH_MSG_NONE; 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate /* The entire packet is in buffer. */ 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate /* Consume packet length. */ 9480Sstevel@tonic-gate buffer_consume(&input, 4); 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate /* 9510Sstevel@tonic-gate * Cryptographic attack detector for ssh 9520Sstevel@tonic-gate * (C)1998 CORE-SDI, Buenos Aires Argentina 9530Sstevel@tonic-gate * Ariel Futoransky(futo@core-sdi.com) 9540Sstevel@tonic-gate */ 9553102Sjp161948 if (!receive_context.plaintext) { 9563102Sjp161948 switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) { 9573102Sjp161948 case DEATTACK_DETECTED: 9583102Sjp161948 packet_disconnect("crc32 compensation attack: " 9593102Sjp161948 "network attack detected"); 9603102Sjp161948 break; 9613102Sjp161948 case DEATTACK_DOS_DETECTED: 9623102Sjp161948 packet_disconnect("deattack denial of " 9633102Sjp161948 "service detected"); 9643102Sjp161948 break; 9653102Sjp161948 } 9663102Sjp161948 } 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate /* Decrypt data to incoming_packet. */ 9690Sstevel@tonic-gate buffer_clear(&incoming_packet); 9700Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, padded_len); 9710Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 9720Sstevel@tonic-gate 9730Sstevel@tonic-gate buffer_consume(&input, padded_len); 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate #ifdef PACKET_DEBUG 9760Sstevel@tonic-gate fprintf(stderr, "read_poll plain: "); 9770Sstevel@tonic-gate buffer_dump(&incoming_packet); 9780Sstevel@tonic-gate #endif 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate /* Compute packet checksum. */ 9810Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&incoming_packet), 9820Sstevel@tonic-gate buffer_len(&incoming_packet) - 4); 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate /* Skip padding. */ 9850Sstevel@tonic-gate buffer_consume(&incoming_packet, 8 - len % 8); 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate /* Test check bytes. */ 9880Sstevel@tonic-gate if (len != buffer_len(&incoming_packet)) 9890Sstevel@tonic-gate packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 9900Sstevel@tonic-gate len, buffer_len(&incoming_packet)); 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 9930Sstevel@tonic-gate stored_checksum = GET_32BIT(cp); 9940Sstevel@tonic-gate if (checksum != stored_checksum) 9950Sstevel@tonic-gate packet_disconnect("Corrupted check bytes on input."); 9960Sstevel@tonic-gate buffer_consume_end(&incoming_packet, 4); 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate if (packet_compression) { 9990Sstevel@tonic-gate buffer_clear(&compression_buffer); 10000Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 10010Sstevel@tonic-gate buffer_clear(&incoming_packet); 10020Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 10030Sstevel@tonic-gate buffer_len(&compression_buffer)); 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 10060Sstevel@tonic-gate return type; 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate static int 10100Sstevel@tonic-gate packet_read_poll2(u_int32_t *seqnr_p) 10110Sstevel@tonic-gate { 10120Sstevel@tonic-gate static u_int packet_length = 0; 10130Sstevel@tonic-gate u_int padlen, need; 10140Sstevel@tonic-gate u_char *macbuf, *cp, type; 10150Sstevel@tonic-gate int maclen, block_size; 10160Sstevel@tonic-gate Enc *enc = NULL; 10170Sstevel@tonic-gate Mac *mac = NULL; 10180Sstevel@tonic-gate Comp *comp = NULL; 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate if (newkeys[MODE_IN] != NULL) { 10210Sstevel@tonic-gate enc = &newkeys[MODE_IN]->enc; 10220Sstevel@tonic-gate mac = &newkeys[MODE_IN]->mac; 10230Sstevel@tonic-gate comp = &newkeys[MODE_IN]->comp; 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate maclen = mac && mac->enabled ? mac->mac_len : 0; 10260Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 10270Sstevel@tonic-gate 10280Sstevel@tonic-gate if (packet_length == 0) { 10290Sstevel@tonic-gate /* 10300Sstevel@tonic-gate * check if input size is less than the cipher block size, 10310Sstevel@tonic-gate * decrypt first block and extract length of incoming packet 10320Sstevel@tonic-gate */ 10330Sstevel@tonic-gate if (buffer_len(&input) < block_size) 10340Sstevel@tonic-gate return SSH_MSG_NONE; 10350Sstevel@tonic-gate buffer_clear(&incoming_packet); 10360Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, block_size); 10370Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), 10380Sstevel@tonic-gate block_size); 10390Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 10400Sstevel@tonic-gate packet_length = GET_32BIT(cp); 10410Sstevel@tonic-gate if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 10420Sstevel@tonic-gate buffer_dump(&incoming_packet); 10430Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", packet_length); 10440Sstevel@tonic-gate } 10455562Sjp161948 DBG(debug("input: packet len %u", packet_length + 4)); 10460Sstevel@tonic-gate buffer_consume(&input, block_size); 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate /* we have a partial packet of block_size bytes */ 10490Sstevel@tonic-gate need = 4 + packet_length - block_size; 10500Sstevel@tonic-gate DBG(debug("partial packet %d, need %d, maclen %d", block_size, 10510Sstevel@tonic-gate need, maclen)); 10520Sstevel@tonic-gate if (need % block_size != 0) 10530Sstevel@tonic-gate fatal("padding error: need %d block %d mod %d", 10540Sstevel@tonic-gate need, block_size, need % block_size); 10550Sstevel@tonic-gate /* 10560Sstevel@tonic-gate * check if the entire packet has been received and 10570Sstevel@tonic-gate * decrypt into incoming_packet 10580Sstevel@tonic-gate */ 10590Sstevel@tonic-gate if (buffer_len(&input) < need + maclen) 10600Sstevel@tonic-gate return SSH_MSG_NONE; 10610Sstevel@tonic-gate #ifdef PACKET_DEBUG 10620Sstevel@tonic-gate fprintf(stderr, "read_poll enc/full: "); 10630Sstevel@tonic-gate buffer_dump(&input); 10640Sstevel@tonic-gate #endif 10650Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, need); 10660Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 10670Sstevel@tonic-gate buffer_consume(&input, need); 10680Sstevel@tonic-gate /* 10690Sstevel@tonic-gate * compute MAC over seqnr and packet, 10700Sstevel@tonic-gate * increment sequence number for incoming packet 10710Sstevel@tonic-gate */ 10720Sstevel@tonic-gate if (mac && mac->enabled) { 10735562Sjp161948 macbuf = mac_compute(mac, p_read.seqnr, 10740Sstevel@tonic-gate buffer_ptr(&incoming_packet), 10750Sstevel@tonic-gate buffer_len(&incoming_packet)); 10760Sstevel@tonic-gate if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 10770Sstevel@tonic-gate packet_disconnect("Corrupted MAC on input."); 10785562Sjp161948 DBG(debug("MAC #%d ok", p_read.seqnr)); 10790Sstevel@tonic-gate buffer_consume(&input, mac->mac_len); 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate if (seqnr_p != NULL) 10825562Sjp161948 *seqnr_p = p_read.seqnr; 10835562Sjp161948 if (++p_read.seqnr == 0) 10840Sstevel@tonic-gate log("incoming seqnr wraps around"); 10850Sstevel@tonic-gate 10865562Sjp161948 /* see above for the comment on "First Rekeying Recommendation" */ 10875562Sjp161948 if (++p_read.packets == 0) 10885562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 10895562Sjp161948 fatal("too many packets with same key"); 10905562Sjp161948 p_read.blocks += (packet_length + 4) / block_size; 10915562Sjp161948 10920Sstevel@tonic-gate /* get padlen */ 10930Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 10940Sstevel@tonic-gate padlen = cp[4]; 10950Sstevel@tonic-gate DBG(debug("input: padlen %d", padlen)); 10960Sstevel@tonic-gate if (padlen < 4) 10970Sstevel@tonic-gate packet_disconnect("Corrupted padlen %d on input.", padlen); 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate /* skip packet size + padlen, discard padding */ 11000Sstevel@tonic-gate buffer_consume(&incoming_packet, 4 + 1); 11010Sstevel@tonic-gate buffer_consume_end(&incoming_packet, padlen); 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 11040Sstevel@tonic-gate if (comp && comp->enabled) { 11050Sstevel@tonic-gate buffer_clear(&compression_buffer); 11060Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 11070Sstevel@tonic-gate buffer_clear(&incoming_packet); 11080Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 11090Sstevel@tonic-gate buffer_len(&compression_buffer)); 11100Sstevel@tonic-gate DBG(debug("input: len after de-compress %d", 11110Sstevel@tonic-gate buffer_len(&incoming_packet))); 11120Sstevel@tonic-gate } 11130Sstevel@tonic-gate /* 11140Sstevel@tonic-gate * get packet type, implies consume. 11150Sstevel@tonic-gate * return length of payload (without type field) 11160Sstevel@tonic-gate */ 11170Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 11180Sstevel@tonic-gate #ifdef ALTPRIVSEP 11190Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 11200Sstevel@tonic-gate /* set_newkeys(MODE_OUT) in client, server, but not monitor */ 11210Sstevel@tonic-gate if (!packet_is_server() && !packet_is_monitor()) 11220Sstevel@tonic-gate set_newkeys(MODE_IN); 11230Sstevel@tonic-gate #else /* ALTPRIVSEP */ 11240Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 11250Sstevel@tonic-gate set_newkeys(MODE_IN); 11260Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 11270Sstevel@tonic-gate #ifdef PACKET_DEBUG 11280Sstevel@tonic-gate fprintf(stderr, "read/plain[%d]:\r\n", type); 11290Sstevel@tonic-gate buffer_dump(&incoming_packet); 11300Sstevel@tonic-gate #endif 11310Sstevel@tonic-gate /* reset for next packet */ 11320Sstevel@tonic-gate packet_length = 0; 11330Sstevel@tonic-gate return type; 11340Sstevel@tonic-gate } 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate int 11370Sstevel@tonic-gate packet_read_poll_seqnr(u_int32_t *seqnr_p) 11380Sstevel@tonic-gate { 11390Sstevel@tonic-gate u_int reason, seqnr; 11400Sstevel@tonic-gate u_char type; 11410Sstevel@tonic-gate char *msg; 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate for (;;) { 11440Sstevel@tonic-gate if (compat20) { 11450Sstevel@tonic-gate type = packet_read_poll2(seqnr_p); 11460Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 11470Sstevel@tonic-gate switch (type) { 11480Sstevel@tonic-gate case SSH2_MSG_IGNORE: 11490Sstevel@tonic-gate break; 11500Sstevel@tonic-gate case SSH2_MSG_DEBUG: 11510Sstevel@tonic-gate packet_get_char(); 11520Sstevel@tonic-gate msg = packet_get_string(NULL); 11530Sstevel@tonic-gate debug("Remote: %.900s", msg); 11540Sstevel@tonic-gate xfree(msg); 11550Sstevel@tonic-gate msg = packet_get_string(NULL); 11560Sstevel@tonic-gate xfree(msg); 11570Sstevel@tonic-gate break; 11580Sstevel@tonic-gate case SSH2_MSG_DISCONNECT: 11590Sstevel@tonic-gate reason = packet_get_int(); 11600Sstevel@tonic-gate msg = packet_get_string(NULL); 11610Sstevel@tonic-gate log("Received disconnect from %s: %u: %.400s", 11620Sstevel@tonic-gate get_remote_ipaddr(), reason, msg); 11630Sstevel@tonic-gate xfree(msg); 11640Sstevel@tonic-gate fatal_cleanup(); 11650Sstevel@tonic-gate break; 11660Sstevel@tonic-gate case SSH2_MSG_UNIMPLEMENTED: 11670Sstevel@tonic-gate seqnr = packet_get_int(); 11680Sstevel@tonic-gate debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 11690Sstevel@tonic-gate seqnr); 11700Sstevel@tonic-gate break; 11710Sstevel@tonic-gate default: 11720Sstevel@tonic-gate return type; 11730Sstevel@tonic-gate break; 11740Sstevel@tonic-gate } 11750Sstevel@tonic-gate } else { 11760Sstevel@tonic-gate type = packet_read_poll1(); 11770Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 11780Sstevel@tonic-gate switch (type) { 11790Sstevel@tonic-gate case SSH_MSG_IGNORE: 11800Sstevel@tonic-gate break; 11810Sstevel@tonic-gate case SSH_MSG_DEBUG: 11820Sstevel@tonic-gate msg = packet_get_string(NULL); 11830Sstevel@tonic-gate debug("Remote: %.900s", msg); 11840Sstevel@tonic-gate xfree(msg); 11850Sstevel@tonic-gate break; 11860Sstevel@tonic-gate case SSH_MSG_DISCONNECT: 11870Sstevel@tonic-gate msg = packet_get_string(NULL); 11880Sstevel@tonic-gate log("Received disconnect from %s: %.400s", 11890Sstevel@tonic-gate get_remote_ipaddr(), msg); 11900Sstevel@tonic-gate fatal_cleanup(); 11910Sstevel@tonic-gate xfree(msg); 11920Sstevel@tonic-gate break; 11930Sstevel@tonic-gate default: 11940Sstevel@tonic-gate return type; 11950Sstevel@tonic-gate break; 11960Sstevel@tonic-gate } 11970Sstevel@tonic-gate } 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate int 12020Sstevel@tonic-gate packet_read_poll(void) 12030Sstevel@tonic-gate { 12040Sstevel@tonic-gate return packet_read_poll_seqnr(NULL); 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate /* 12080Sstevel@tonic-gate * Buffers the given amount of input characters. This is intended to be used 12090Sstevel@tonic-gate * together with packet_read_poll. 12100Sstevel@tonic-gate */ 12110Sstevel@tonic-gate 12120Sstevel@tonic-gate void 12130Sstevel@tonic-gate packet_process_incoming(const char *buf, u_int len) 12140Sstevel@tonic-gate { 12150Sstevel@tonic-gate buffer_append(&input, buf, len); 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate /* Returns a character from the packet. */ 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate u_int 12210Sstevel@tonic-gate packet_get_char(void) 12220Sstevel@tonic-gate { 12230Sstevel@tonic-gate char ch; 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate buffer_get(&incoming_packet, &ch, 1); 12260Sstevel@tonic-gate return (u_char) ch; 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate /* Returns an integer from the packet data. */ 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate u_int 12320Sstevel@tonic-gate packet_get_int(void) 12330Sstevel@tonic-gate { 12340Sstevel@tonic-gate return buffer_get_int(&incoming_packet); 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate /* 12380Sstevel@tonic-gate * Returns an arbitrary precision integer from the packet data. The integer 12390Sstevel@tonic-gate * must have been initialized before this call. 12400Sstevel@tonic-gate */ 12410Sstevel@tonic-gate 12420Sstevel@tonic-gate void 12430Sstevel@tonic-gate packet_get_bignum(BIGNUM * value) 12440Sstevel@tonic-gate { 12450Sstevel@tonic-gate buffer_get_bignum(&incoming_packet, value); 12460Sstevel@tonic-gate } 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate void 12490Sstevel@tonic-gate packet_get_bignum2(BIGNUM * value) 12500Sstevel@tonic-gate { 12510Sstevel@tonic-gate buffer_get_bignum2(&incoming_packet, value); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate void * 12550Sstevel@tonic-gate packet_get_raw(u_int *length_ptr) 12560Sstevel@tonic-gate { 12570Sstevel@tonic-gate u_int bytes = buffer_len(&incoming_packet); 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate if (length_ptr != NULL) 12600Sstevel@tonic-gate *length_ptr = bytes; 12610Sstevel@tonic-gate return buffer_ptr(&incoming_packet); 12620Sstevel@tonic-gate } 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate int 12650Sstevel@tonic-gate packet_remaining(void) 12660Sstevel@tonic-gate { 12670Sstevel@tonic-gate return buffer_len(&incoming_packet); 12680Sstevel@tonic-gate } 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate /* 12710Sstevel@tonic-gate * Returns a string from the packet data. The string is allocated using 12720Sstevel@tonic-gate * xmalloc; it is the responsibility of the calling program to free it when 12730Sstevel@tonic-gate * no longer needed. The length_ptr argument may be NULL, or point to an 12740Sstevel@tonic-gate * integer into which the length of the string is stored. 12750Sstevel@tonic-gate */ 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate void * 12780Sstevel@tonic-gate packet_get_string(u_int *length_ptr) 12790Sstevel@tonic-gate { 12800Sstevel@tonic-gate return buffer_get_string(&incoming_packet, length_ptr); 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate char * 12830Sstevel@tonic-gate packet_get_ascii_cstring() 12840Sstevel@tonic-gate { 12850Sstevel@tonic-gate return buffer_get_ascii_cstring(&incoming_packet); 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate u_char * 12880Sstevel@tonic-gate packet_get_utf8_cstring() 12890Sstevel@tonic-gate { 12900Sstevel@tonic-gate return buffer_get_utf8_cstring(&incoming_packet); 12910Sstevel@tonic-gate } 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate /* 12940Sstevel@tonic-gate * Sends a diagnostic message from the server to the client. This message 12950Sstevel@tonic-gate * can be sent at any time (but not while constructing another message). The 12960Sstevel@tonic-gate * message is printed immediately, but only if the client is being executed 12970Sstevel@tonic-gate * in verbose mode. These messages are primarily intended to ease debugging 12980Sstevel@tonic-gate * authentication problems. The length of the formatted message must not 12990Sstevel@tonic-gate * exceed 1024 bytes. This will automatically call packet_write_wait. 13000Sstevel@tonic-gate */ 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate void 13030Sstevel@tonic-gate packet_send_debug(const char *fmt,...) 13040Sstevel@tonic-gate { 13050Sstevel@tonic-gate char buf[1024]; 13060Sstevel@tonic-gate va_list args; 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate if (compat20 && (datafellows & SSH_BUG_DEBUG)) 13090Sstevel@tonic-gate return; 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate va_start(args, fmt); 13120Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), gettext(fmt), args); 13130Sstevel@tonic-gate va_end(args); 13140Sstevel@tonic-gate 13150Sstevel@tonic-gate #ifdef ALTPRIVSEP 13160Sstevel@tonic-gate /* shouldn't happen */ 13170Sstevel@tonic-gate if (packet_monitor) { 13180Sstevel@tonic-gate debug("packet_send_debug: %s", buf); 13190Sstevel@tonic-gate return; 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 13220Sstevel@tonic-gate 13230Sstevel@tonic-gate if (compat20) { 13240Sstevel@tonic-gate packet_start(SSH2_MSG_DEBUG); 13250Sstevel@tonic-gate packet_put_char(0); /* bool: always display */ 13260Sstevel@tonic-gate packet_put_cstring(buf); 13270Sstevel@tonic-gate packet_put_cstring(""); 13280Sstevel@tonic-gate } else { 13290Sstevel@tonic-gate packet_start(SSH_MSG_DEBUG); 13300Sstevel@tonic-gate packet_put_cstring(buf); 13310Sstevel@tonic-gate } 13320Sstevel@tonic-gate packet_send(); 13330Sstevel@tonic-gate packet_write_wait(); 13340Sstevel@tonic-gate } 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate /* 13370Sstevel@tonic-gate * Logs the error plus constructs and sends a disconnect packet, closes the 13380Sstevel@tonic-gate * connection, and exits. This function never returns. The error message 13390Sstevel@tonic-gate * should not contain a newline. The length of the formatted message must 13400Sstevel@tonic-gate * not exceed 1024 bytes. 13410Sstevel@tonic-gate */ 13420Sstevel@tonic-gate 13430Sstevel@tonic-gate void 13440Sstevel@tonic-gate packet_disconnect(const char *fmt,...) 13450Sstevel@tonic-gate { 13460Sstevel@tonic-gate char buf[1024]; 13470Sstevel@tonic-gate va_list args; 13480Sstevel@tonic-gate static int disconnecting = 0; 13490Sstevel@tonic-gate 13500Sstevel@tonic-gate if (disconnecting) /* Guard against recursive invocations. */ 13510Sstevel@tonic-gate fatal("packet_disconnect called recursively."); 13520Sstevel@tonic-gate disconnecting = 1; 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate /* 13550Sstevel@tonic-gate * Format the message. Note that the caller must make sure the 13560Sstevel@tonic-gate * message is of limited size. 13570Sstevel@tonic-gate */ 13580Sstevel@tonic-gate va_start(args, fmt); 13590Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), fmt, args); 13600Sstevel@tonic-gate va_end(args); 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate #ifdef ALTPRIVSEP 13630Sstevel@tonic-gate /* 13640Sstevel@tonic-gate * If we packet_disconnect() in the monitor the fatal cleanups will take 13650Sstevel@tonic-gate * care of the child. See main() in sshd.c. We don't send the packet 13660Sstevel@tonic-gate * disconnect message here because: a) the child might not be looking 13670Sstevel@tonic-gate * for it and b) because we don't really know if the child is compat20 13680Sstevel@tonic-gate * or not as we lost that information when packet_set_monitor() was 13690Sstevel@tonic-gate * called. 13700Sstevel@tonic-gate */ 13710Sstevel@tonic-gate if (packet_monitor) 13720Sstevel@tonic-gate goto close_stuff; 13730Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 13740Sstevel@tonic-gate 13750Sstevel@tonic-gate /* Send the disconnect message to the other side, and wait for it to get sent. */ 13760Sstevel@tonic-gate if (compat20) { 13770Sstevel@tonic-gate packet_start(SSH2_MSG_DISCONNECT); 13780Sstevel@tonic-gate packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 13790Sstevel@tonic-gate packet_put_cstring(buf); 13800Sstevel@tonic-gate packet_put_cstring(""); 13810Sstevel@tonic-gate } else { 13820Sstevel@tonic-gate packet_start(SSH_MSG_DISCONNECT); 13830Sstevel@tonic-gate packet_put_cstring(buf); 13840Sstevel@tonic-gate } 13850Sstevel@tonic-gate packet_send(); 13860Sstevel@tonic-gate packet_write_wait(); 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate #ifdef ALTPRIVSEP 13890Sstevel@tonic-gate close_stuff: 13900Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 13910Sstevel@tonic-gate /* Stop listening for connections. */ 13920Sstevel@tonic-gate channel_close_all(); 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate /* Close the connection. */ 13950Sstevel@tonic-gate packet_close(); 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate /* Display the error locally and exit. */ 13980Sstevel@tonic-gate log("Disconnecting: %.100s", buf); 13990Sstevel@tonic-gate fatal_cleanup(); 14000Sstevel@tonic-gate } 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate /* Checks if there is any buffered output, and tries to write some of the output. */ 14030Sstevel@tonic-gate 14040Sstevel@tonic-gate void 14050Sstevel@tonic-gate packet_write_poll(void) 14060Sstevel@tonic-gate { 14070Sstevel@tonic-gate int len = buffer_len(&output); 14080Sstevel@tonic-gate 14090Sstevel@tonic-gate if (len > 0) { 14100Sstevel@tonic-gate len = write(connection_out, buffer_ptr(&output), len); 14110Sstevel@tonic-gate if (len <= 0) { 14120Sstevel@tonic-gate if (errno == EAGAIN) 14130Sstevel@tonic-gate return; 14140Sstevel@tonic-gate else 14150Sstevel@tonic-gate fatal("Write failed: %.100s", strerror(errno)); 14160Sstevel@tonic-gate } 14170Sstevel@tonic-gate buffer_consume(&output, len); 14180Sstevel@tonic-gate } 14190Sstevel@tonic-gate } 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate /* 14220Sstevel@tonic-gate * Calls packet_write_poll repeatedly until all pending output data has been 14230Sstevel@tonic-gate * written. 14240Sstevel@tonic-gate */ 14250Sstevel@tonic-gate 14260Sstevel@tonic-gate void 14270Sstevel@tonic-gate packet_write_wait(void) 14280Sstevel@tonic-gate { 14290Sstevel@tonic-gate fd_set *setp; 14300Sstevel@tonic-gate 14310Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 14320Sstevel@tonic-gate sizeof(fd_mask)); 14330Sstevel@tonic-gate packet_write_poll(); 14340Sstevel@tonic-gate while (packet_have_data_to_write()) { 14350Sstevel@tonic-gate memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 14360Sstevel@tonic-gate sizeof(fd_mask)); 14370Sstevel@tonic-gate FD_SET(connection_out, setp); 14380Sstevel@tonic-gate while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 14390Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 14400Sstevel@tonic-gate ; 14410Sstevel@tonic-gate packet_write_poll(); 14420Sstevel@tonic-gate } 14430Sstevel@tonic-gate xfree(setp); 14440Sstevel@tonic-gate } 14450Sstevel@tonic-gate 14460Sstevel@tonic-gate /* Returns true if there is buffered data to write to the connection. */ 14470Sstevel@tonic-gate 14480Sstevel@tonic-gate int 14490Sstevel@tonic-gate packet_have_data_to_write(void) 14500Sstevel@tonic-gate { 14510Sstevel@tonic-gate return buffer_len(&output) != 0; 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate /* Returns true if there is not too much data to write to the connection. */ 14550Sstevel@tonic-gate 14560Sstevel@tonic-gate int 14570Sstevel@tonic-gate packet_not_very_much_data_to_write(void) 14580Sstevel@tonic-gate { 14590Sstevel@tonic-gate if (interactive_mode) 14600Sstevel@tonic-gate return buffer_len(&output) < 16384; 14610Sstevel@tonic-gate else 14620Sstevel@tonic-gate return buffer_len(&output) < 128 * 1024; 14630Sstevel@tonic-gate } 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate /* Informs that the current session is interactive. Sets IP flags for that. */ 14660Sstevel@tonic-gate 14670Sstevel@tonic-gate void 14680Sstevel@tonic-gate packet_set_interactive(int interactive) 14690Sstevel@tonic-gate { 14700Sstevel@tonic-gate static int called = 0; 14710Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 14720Sstevel@tonic-gate int lowdelay = IPTOS_LOWDELAY; 14730Sstevel@tonic-gate int throughput = IPTOS_THROUGHPUT; 14740Sstevel@tonic-gate #endif 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate if (called) 14770Sstevel@tonic-gate return; 14780Sstevel@tonic-gate called = 1; 14790Sstevel@tonic-gate 14800Sstevel@tonic-gate /* Record that we are in interactive mode. */ 14810Sstevel@tonic-gate interactive_mode = interactive; 14820Sstevel@tonic-gate 14830Sstevel@tonic-gate /* Only set socket options if using a socket. */ 14840Sstevel@tonic-gate if (!packet_connection_is_on_socket()) 14850Sstevel@tonic-gate return; 14860Sstevel@tonic-gate /* 14870Sstevel@tonic-gate * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only 14880Sstevel@tonic-gate */ 14890Sstevel@tonic-gate if (interactive) { 14900Sstevel@tonic-gate /* 14910Sstevel@tonic-gate * Set IP options for an interactive connection. Use 14920Sstevel@tonic-gate * IPTOS_LOWDELAY and TCP_NODELAY. 14930Sstevel@tonic-gate */ 14940Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 14950Sstevel@tonic-gate if (packet_connection_is_ipv4()) { 14960Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, 14970Sstevel@tonic-gate &lowdelay, sizeof(lowdelay)) < 0) 14980Sstevel@tonic-gate error("setsockopt IPTOS_LOWDELAY: %.100s", 14990Sstevel@tonic-gate strerror(errno)); 15000Sstevel@tonic-gate } 15010Sstevel@tonic-gate #endif 15020Sstevel@tonic-gate set_nodelay(connection_in); 15030Sstevel@tonic-gate } 15040Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 15050Sstevel@tonic-gate else if (packet_connection_is_ipv4()) { 15060Sstevel@tonic-gate /* 15070Sstevel@tonic-gate * Set IP options for a non-interactive connection. Use 15080Sstevel@tonic-gate * IPTOS_THROUGHPUT. 15090Sstevel@tonic-gate */ 15100Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, 15110Sstevel@tonic-gate sizeof(throughput)) < 0) 15120Sstevel@tonic-gate error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); 15130Sstevel@tonic-gate } 15140Sstevel@tonic-gate #endif 15150Sstevel@tonic-gate } 15160Sstevel@tonic-gate 15170Sstevel@tonic-gate /* Returns true if the current connection is interactive. */ 15180Sstevel@tonic-gate 15190Sstevel@tonic-gate int 15200Sstevel@tonic-gate packet_is_interactive(void) 15210Sstevel@tonic-gate { 15220Sstevel@tonic-gate return interactive_mode; 15230Sstevel@tonic-gate } 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate int 15260Sstevel@tonic-gate packet_set_maxsize(int s) 15270Sstevel@tonic-gate { 15280Sstevel@tonic-gate static int called = 0; 15290Sstevel@tonic-gate 15300Sstevel@tonic-gate if (called) { 15310Sstevel@tonic-gate log("packet_set_maxsize: called twice: old %d new %d", 15320Sstevel@tonic-gate max_packet_size, s); 15330Sstevel@tonic-gate return -1; 15340Sstevel@tonic-gate } 15350Sstevel@tonic-gate if (s < 4 * 1024 || s > 1024 * 1024) { 15360Sstevel@tonic-gate log("packet_set_maxsize: bad size %d", s); 15370Sstevel@tonic-gate return -1; 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate called = 1; 15400Sstevel@tonic-gate debug("packet_set_maxsize: setting to %d", s); 15410Sstevel@tonic-gate max_packet_size = s; 15420Sstevel@tonic-gate return s; 15430Sstevel@tonic-gate } 15440Sstevel@tonic-gate 15450Sstevel@tonic-gate /* roundup current message to pad bytes */ 15460Sstevel@tonic-gate void 15470Sstevel@tonic-gate packet_add_padding(u_char pad) 15480Sstevel@tonic-gate { 15490Sstevel@tonic-gate extra_pad = pad; 15500Sstevel@tonic-gate } 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate /* 15530Sstevel@tonic-gate * 9.2. Ignored Data Message 15540Sstevel@tonic-gate * 15550Sstevel@tonic-gate * byte SSH_MSG_IGNORE 15560Sstevel@tonic-gate * string data 15570Sstevel@tonic-gate * 15580Sstevel@tonic-gate * All implementations MUST understand (and ignore) this message at any 15590Sstevel@tonic-gate * time (after receiving the protocol version). No implementation is 15600Sstevel@tonic-gate * required to send them. This message can be used as an additional 15610Sstevel@tonic-gate * protection measure against advanced traffic analysis techniques. 15620Sstevel@tonic-gate */ 15630Sstevel@tonic-gate void 15640Sstevel@tonic-gate packet_send_ignore(int nbytes) 15650Sstevel@tonic-gate { 15665562Sjp161948 u_int32_t rnd = 0; 15670Sstevel@tonic-gate int i; 15680Sstevel@tonic-gate 15690Sstevel@tonic-gate #ifdef ALTPRIVSEP 15700Sstevel@tonic-gate /* shouldn't happen -- see packet_set_monitor() */ 15710Sstevel@tonic-gate if (packet_monitor) 15720Sstevel@tonic-gate return; 15730Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 15760Sstevel@tonic-gate packet_put_int(nbytes); 15770Sstevel@tonic-gate for (i = 0; i < nbytes; i++) { 15780Sstevel@tonic-gate if (i % 4 == 0) 15795562Sjp161948 rnd = arc4random(); 15805562Sjp161948 packet_put_char((u_char)rnd & 0xff); 15815562Sjp161948 rnd >>= 8; 15820Sstevel@tonic-gate } 15830Sstevel@tonic-gate } 15840Sstevel@tonic-gate 15855562Sjp161948 #define MAX_PACKETS (1U<<31) 15865562Sjp161948 int 15875562Sjp161948 packet_need_rekeying(void) 15885562Sjp161948 { 15895562Sjp161948 if (datafellows & SSH_BUG_NOREKEY) 15905562Sjp161948 return 0; 15915562Sjp161948 return 15925562Sjp161948 (p_send.packets > MAX_PACKETS) || 15935562Sjp161948 (p_read.packets > MAX_PACKETS) || 15945562Sjp161948 (max_blocks_out && (p_send.blocks > max_blocks_out)) || 15955562Sjp161948 (max_blocks_in && (p_read.blocks > max_blocks_in)); 15965562Sjp161948 } 15975562Sjp161948 15985562Sjp161948 void 15995562Sjp161948 packet_set_rekey_limit(u_int32_t bytes) 16005562Sjp161948 { 16015562Sjp161948 rekey_limit = bytes; 16025562Sjp161948 } 16035562Sjp161948 16040Sstevel@tonic-gate #ifdef ALTPRIVSEP 16050Sstevel@tonic-gate void 16060Sstevel@tonic-gate packet_set_server(void) 16070Sstevel@tonic-gate { 16080Sstevel@tonic-gate packet_server = 1; 16090Sstevel@tonic-gate } 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate void 16120Sstevel@tonic-gate packet_set_no_monitor(void) 16130Sstevel@tonic-gate { 16140Sstevel@tonic-gate packet_server = 0; 16150Sstevel@tonic-gate } 16160Sstevel@tonic-gate 16170Sstevel@tonic-gate int 16180Sstevel@tonic-gate packet_is_server(void) 16190Sstevel@tonic-gate { 16200Sstevel@tonic-gate return (packet_server); 16210Sstevel@tonic-gate } 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate void 16240Sstevel@tonic-gate packet_set_monitor(int pipe) 16250Sstevel@tonic-gate { 16260Sstevel@tonic-gate int dup_fd; 16270Sstevel@tonic-gate 16280Sstevel@tonic-gate packet_server = 1; 16290Sstevel@tonic-gate packet_monitor = 1; 16300Sstevel@tonic-gate 16310Sstevel@tonic-gate /* 16320Sstevel@tonic-gate * Awful hack follows. 16330Sstevel@tonic-gate * 16340Sstevel@tonic-gate * For SSHv1 the monitor does not process any SSHv1 packets, only 16350Sstevel@tonic-gate * ALTPRIVSEP packets. We take advantage of that here to keep changes 16360Sstevel@tonic-gate * to packet.c to a minimum by using the SSHv2 binary packet protocol, 16370Sstevel@tonic-gate * with cipher "none," mac "none" and compression alg "none," as the 16380Sstevel@tonic-gate * basis for the monitor protocol. And so to force packet.c to treat 16390Sstevel@tonic-gate * packets as SSHv2 we force compat20 == 1 here. 16400Sstevel@tonic-gate * 16410Sstevel@tonic-gate * For completeness and to help future developers catch this we also 16420Sstevel@tonic-gate * force compat20 == 1 in the monitor loop, in serverloop.c. 16430Sstevel@tonic-gate */ 16440Sstevel@tonic-gate compat20 = 1; 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate /* 16470Sstevel@tonic-gate * NOTE: Assumptions below! 16480Sstevel@tonic-gate * 16490Sstevel@tonic-gate * - lots of packet.c code assumes that (connection_in == 16500Sstevel@tonic-gate * connection_out) -> connection is socket 16510Sstevel@tonic-gate * 16520Sstevel@tonic-gate * - packet_close() does not shutdown() the connection fildes 16530Sstevel@tonic-gate * if connection_in != connection_out 16540Sstevel@tonic-gate * 16550Sstevel@tonic-gate * - other code assumes the connection is a socket if 16560Sstevel@tonic-gate * connection_in == connection_out 16570Sstevel@tonic-gate */ 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate if ((dup_fd = dup(pipe)) < 0) 16600Sstevel@tonic-gate fatal("Monitor failed to start: %s", strerror(errno)); 16610Sstevel@tonic-gate 16620Sstevel@tonic-gate /* 16630Sstevel@tonic-gate * make sure that the monitor's child's socket is not shutdown(3SOCKET) 16640Sstevel@tonic-gate * when we packet_close() 16650Sstevel@tonic-gate */ 16660Sstevel@tonic-gate if (packet_connection_is_on_socket()) 16670Sstevel@tonic-gate connection_out = -1; 16680Sstevel@tonic-gate 16690Sstevel@tonic-gate /* now cleanup state related to ssh socket */ 16700Sstevel@tonic-gate packet_close(); 16710Sstevel@tonic-gate 16720Sstevel@tonic-gate /* now make the monitor pipe look like the ssh connection */ 16730Sstevel@tonic-gate packet_set_connection(pipe, dup_fd); 16740Sstevel@tonic-gate } 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate int 16770Sstevel@tonic-gate packet_is_monitor(void) 16780Sstevel@tonic-gate { 16790Sstevel@tonic-gate return (packet_monitor); 16800Sstevel@tonic-gate } 16810Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1682