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 /* 396375Sjp161948 * 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 455562Sjp161948 #include "includes.h" 465562Sjp161948 475562Sjp161948 #include "sys-queue.h" 480Sstevel@tonic-gate #include "xmalloc.h" 490Sstevel@tonic-gate #include "buffer.h" 500Sstevel@tonic-gate #include "packet.h" 510Sstevel@tonic-gate #include "bufaux.h" 520Sstevel@tonic-gate #include "crc32.h" 530Sstevel@tonic-gate #include "getput.h" 540Sstevel@tonic-gate #include "compress.h" 550Sstevel@tonic-gate #include "deattack.h" 560Sstevel@tonic-gate #include "channels.h" 570Sstevel@tonic-gate #include "compat.h" 580Sstevel@tonic-gate #include "ssh1.h" 590Sstevel@tonic-gate #include "ssh2.h" 600Sstevel@tonic-gate #include "cipher.h" 610Sstevel@tonic-gate #include "kex.h" 620Sstevel@tonic-gate #include "mac.h" 630Sstevel@tonic-gate #include "log.h" 640Sstevel@tonic-gate #include "canohost.h" 650Sstevel@tonic-gate #include "misc.h" 660Sstevel@tonic-gate #include "ssh.h" 677574SJan.Pechanec@Sun.COM #include "engine.h" 687574SJan.Pechanec@Sun.COM 697574SJan.Pechanec@Sun.COM /* PKCS#11 engine */ 707574SJan.Pechanec@Sun.COM ENGINE *e; 710Sstevel@tonic-gate 720Sstevel@tonic-gate #ifdef ALTPRIVSEP 730Sstevel@tonic-gate static int packet_server = 0; 740Sstevel@tonic-gate static int packet_monitor = 0; 750Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 760Sstevel@tonic-gate 770Sstevel@tonic-gate #ifdef PACKET_DEBUG 780Sstevel@tonic-gate #define DBG(x) x 790Sstevel@tonic-gate #else 800Sstevel@tonic-gate #define DBG(x) 810Sstevel@tonic-gate #endif 820Sstevel@tonic-gate 837574SJan.Pechanec@Sun.COM static void packet_send2(void); 847574SJan.Pechanec@Sun.COM 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * This variable contains the file descriptors used for communicating with 870Sstevel@tonic-gate * the other side. connection_in is used for reading; connection_out for 880Sstevel@tonic-gate * writing. These can be the same descriptor, in which case it is assumed to 890Sstevel@tonic-gate * be a socket. 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate static int connection_in = -1; 920Sstevel@tonic-gate static int connection_out = -1; 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* Protocol flags for the remote side. */ 950Sstevel@tonic-gate static u_int remote_protocol_flags = 0; 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* Encryption context for receiving data. This is only used for decryption. */ 980Sstevel@tonic-gate static CipherContext receive_context; 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* Encryption context for sending data. This is only used for encryption. */ 1010Sstevel@tonic-gate static CipherContext send_context; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* Buffer for raw input data from the socket. */ 1040Sstevel@tonic-gate Buffer input; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate /* Buffer for raw output data going to the socket. */ 1070Sstevel@tonic-gate Buffer output; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* Buffer for the partial outgoing packet being constructed. */ 1100Sstevel@tonic-gate static Buffer outgoing_packet; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* Buffer for the incoming packet currently being processed. */ 1130Sstevel@tonic-gate static Buffer incoming_packet; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* Scratch buffer for packet compression/decompression. */ 1160Sstevel@tonic-gate static Buffer compression_buffer; 1170Sstevel@tonic-gate static int compression_buffer_ready = 0; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* Flag indicating whether packet compression/decompression is enabled. */ 1200Sstevel@tonic-gate static int packet_compression = 0; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* default maximum packet size */ 1230Sstevel@tonic-gate int max_packet_size = 32768; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* Flag indicating whether this module has been initialized. */ 1260Sstevel@tonic-gate static int initialized = 0; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* Set to true if the connection is interactive. */ 1290Sstevel@tonic-gate static int interactive_mode = 0; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* Session key information for Encryption and MAC */ 1320Sstevel@tonic-gate Newkeys *newkeys[MODE_MAX]; 1335562Sjp161948 static struct packet_state { 1345562Sjp161948 u_int32_t seqnr; 1355562Sjp161948 u_int32_t packets; 1365562Sjp161948 u_int64_t blocks; 1375562Sjp161948 } p_read, p_send; 1385562Sjp161948 1395562Sjp161948 static u_int64_t max_blocks_in, max_blocks_out; 1405562Sjp161948 static u_int32_t rekey_limit; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* Session key for protocol v1 */ 1430Sstevel@tonic-gate static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 1440Sstevel@tonic-gate static u_int ssh1_keylen; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate /* roundup current message to extra_pad bytes */ 1470Sstevel@tonic-gate static u_char extra_pad = 0; 1480Sstevel@tonic-gate 1495562Sjp161948 struct packet { 1505562Sjp161948 TAILQ_ENTRY(packet) next; 1515562Sjp161948 u_char type; 1525562Sjp161948 Buffer payload; 1535562Sjp161948 }; 1545562Sjp161948 TAILQ_HEAD(, packet) outgoing; 1555562Sjp161948 1560Sstevel@tonic-gate /* 1577574SJan.Pechanec@Sun.COM * Part of what -f option and ~& escape sequence do in the client is that they 1587574SJan.Pechanec@Sun.COM * will force it to daemonize itself. Due to the fork safety rules inherent in 1597574SJan.Pechanec@Sun.COM * any PKCS#11 environment, if the engine is used we must do a key re-exchange 1607574SJan.Pechanec@Sun.COM * before forking a child to negotiate the new keys. Those keys will be used to 1617574SJan.Pechanec@Sun.COM * inicialize the new crypto contexts. This involves finishing the engine in the 1627574SJan.Pechanec@Sun.COM * parent and reinitializing it again in both processes after fork() returns. 1637574SJan.Pechanec@Sun.COM * This approach also leaves protocol 1 out since it doesn't support rekeying. 1647574SJan.Pechanec@Sun.COM */ 1657574SJan.Pechanec@Sun.COM int will_daemonize; 1667574SJan.Pechanec@Sun.COM 1677574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 1687574SJan.Pechanec@Sun.COM /* This function dumps data onto stderr. This is for debugging only. */ 1697574SJan.Pechanec@Sun.COM void 1707574SJan.Pechanec@Sun.COM data_dump(void *data, u_int len) 1717574SJan.Pechanec@Sun.COM { 1727574SJan.Pechanec@Sun.COM Buffer buf; 1737574SJan.Pechanec@Sun.COM 1747574SJan.Pechanec@Sun.COM buffer_init(&buf); 1757574SJan.Pechanec@Sun.COM buffer_append(&buf, data, len); 1767574SJan.Pechanec@Sun.COM buffer_dump(&buf); 1777574SJan.Pechanec@Sun.COM buffer_free(&buf); 1787574SJan.Pechanec@Sun.COM } 1797574SJan.Pechanec@Sun.COM #endif 1807574SJan.Pechanec@Sun.COM 1817574SJan.Pechanec@Sun.COM /* 1820Sstevel@tonic-gate * Sets the descriptors used for communication. Disables encryption until 1830Sstevel@tonic-gate * packet_set_encryption_key is called. 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate void 1860Sstevel@tonic-gate packet_set_connection(int fd_in, int fd_out) 1870Sstevel@tonic-gate { 1880Sstevel@tonic-gate Cipher *none = cipher_by_name("none"); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if (none == NULL) 1910Sstevel@tonic-gate fatal("packet_set_connection: cannot load cipher 'none'"); 1920Sstevel@tonic-gate connection_in = fd_in; 1930Sstevel@tonic-gate connection_out = fd_out; 1940Sstevel@tonic-gate cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT); 1950Sstevel@tonic-gate cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT); 1960Sstevel@tonic-gate newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 1970Sstevel@tonic-gate if (!initialized) { 1980Sstevel@tonic-gate initialized = 1; 1990Sstevel@tonic-gate buffer_init(&input); 2000Sstevel@tonic-gate buffer_init(&output); 2010Sstevel@tonic-gate buffer_init(&outgoing_packet); 2020Sstevel@tonic-gate buffer_init(&incoming_packet); 2035562Sjp161948 TAILQ_INIT(&outgoing); 2040Sstevel@tonic-gate } else { 2050Sstevel@tonic-gate buffer_clear(&input); 2060Sstevel@tonic-gate buffer_clear(&output); 2070Sstevel@tonic-gate buffer_clear(&outgoing_packet); 2080Sstevel@tonic-gate buffer_clear(&incoming_packet); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate /* 2120Sstevel@tonic-gate * Prime the cache for get_remote_ipaddr() while we have a 2130Sstevel@tonic-gate * socket on which to do a getpeername(). 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate (void) get_remote_ipaddr(); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* Kludge: arrange the close function to be called from fatal(). */ 2180Sstevel@tonic-gate fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* Returns 1 if remote host is connected via socket, 0 if not. */ 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate int 2240Sstevel@tonic-gate packet_connection_is_on_socket(void) 2250Sstevel@tonic-gate { 2260Sstevel@tonic-gate struct sockaddr_storage from, to; 2270Sstevel@tonic-gate socklen_t fromlen, tolen; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* filedescriptors in and out are the same, so it's a socket */ 2300Sstevel@tonic-gate if (connection_in != -1 && connection_in == connection_out) 2310Sstevel@tonic-gate return 1; 2320Sstevel@tonic-gate fromlen = sizeof(from); 2330Sstevel@tonic-gate memset(&from, 0, sizeof(from)); 2340Sstevel@tonic-gate if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 2350Sstevel@tonic-gate return 0; 2360Sstevel@tonic-gate tolen = sizeof(to); 2370Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 2380Sstevel@tonic-gate if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 2390Sstevel@tonic-gate return 0; 2400Sstevel@tonic-gate if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 2410Sstevel@tonic-gate return 0; 2420Sstevel@tonic-gate if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 2430Sstevel@tonic-gate return 0; 2440Sstevel@tonic-gate return 1; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* returns 1 if connection is via ipv4 */ 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate int 2500Sstevel@tonic-gate packet_connection_is_ipv4(void) 2510Sstevel@tonic-gate { 2520Sstevel@tonic-gate struct sockaddr_storage to; 2530Sstevel@tonic-gate socklen_t tolen = sizeof(to); 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 2560Sstevel@tonic-gate if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 2570Sstevel@tonic-gate return 0; 2580Sstevel@tonic-gate if (to.ss_family == AF_INET) 2590Sstevel@tonic-gate return 1; 2600Sstevel@tonic-gate #ifdef IPV4_IN_IPV6 2610Sstevel@tonic-gate if (to.ss_family == AF_INET6 && 2620Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 2630Sstevel@tonic-gate return 1; 2640Sstevel@tonic-gate #endif 2650Sstevel@tonic-gate return 0; 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /* Sets the connection into non-blocking mode. */ 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate void 2710Sstevel@tonic-gate packet_set_nonblocking(void) 2720Sstevel@tonic-gate { 2730Sstevel@tonic-gate /* Set the socket into non-blocking mode. */ 2740Sstevel@tonic-gate if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) 2750Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate if (connection_out != connection_in) { 2780Sstevel@tonic-gate if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) 2790Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* Returns the socket used for reading. */ 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate int 2860Sstevel@tonic-gate packet_get_connection_in(void) 2870Sstevel@tonic-gate { 2880Sstevel@tonic-gate return connection_in; 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* Returns the descriptor used for writing. */ 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate int 2940Sstevel@tonic-gate packet_get_connection_out(void) 2950Sstevel@tonic-gate { 2960Sstevel@tonic-gate return connection_out; 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* Closes the connection and clears and frees internal data structures. */ 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate void 3020Sstevel@tonic-gate packet_close(void) 3030Sstevel@tonic-gate { 3040Sstevel@tonic-gate if (!initialized) 3050Sstevel@tonic-gate return; 3060Sstevel@tonic-gate initialized = 0; 3070Sstevel@tonic-gate if (connection_in == connection_out) { 3080Sstevel@tonic-gate shutdown(connection_out, SHUT_RDWR); 3090Sstevel@tonic-gate close(connection_out); 3100Sstevel@tonic-gate } else { 3110Sstevel@tonic-gate close(connection_in); 3120Sstevel@tonic-gate close(connection_out); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate buffer_free(&input); 3150Sstevel@tonic-gate buffer_free(&output); 3160Sstevel@tonic-gate buffer_free(&outgoing_packet); 3170Sstevel@tonic-gate buffer_free(&incoming_packet); 3180Sstevel@tonic-gate if (compression_buffer_ready) { 3190Sstevel@tonic-gate buffer_free(&compression_buffer); 3200Sstevel@tonic-gate buffer_compress_uninit(); 3210Sstevel@tonic-gate compression_buffer_ready = 0; 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate cipher_cleanup(&send_context); 3240Sstevel@tonic-gate cipher_cleanup(&receive_context); 3250Sstevel@tonic-gate } 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /* Sets remote side protocol flags. */ 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate void 3300Sstevel@tonic-gate packet_set_protocol_flags(u_int protocol_flags) 3310Sstevel@tonic-gate { 3320Sstevel@tonic-gate remote_protocol_flags = protocol_flags; 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* Returns the remote protocol flags set earlier by the above function. */ 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate u_int 3380Sstevel@tonic-gate packet_get_protocol_flags(void) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate return remote_protocol_flags; 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate /* 3440Sstevel@tonic-gate * Starts packet compression from the next packet on in both directions. 3450Sstevel@tonic-gate * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate static void 3490Sstevel@tonic-gate packet_init_compression(void) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate if (compression_buffer_ready == 1) 3520Sstevel@tonic-gate return; 3530Sstevel@tonic-gate compression_buffer_ready = 1; 3540Sstevel@tonic-gate buffer_init(&compression_buffer); 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate void 3580Sstevel@tonic-gate packet_start_compression(int level) 3590Sstevel@tonic-gate { 3600Sstevel@tonic-gate #ifdef ALTPRIVSEP 3610Sstevel@tonic-gate /* shouldn't happen! */ 3620Sstevel@tonic-gate if (packet_monitor) 3630Sstevel@tonic-gate fatal("INTERNAL ERROR: The monitor cannot compress."); 3640Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate if (packet_compression && !compat20) 3670Sstevel@tonic-gate fatal("Compression already enabled."); 3680Sstevel@tonic-gate packet_compression = 1; 3690Sstevel@tonic-gate packet_init_compression(); 3700Sstevel@tonic-gate buffer_compress_init_send(level); 3710Sstevel@tonic-gate buffer_compress_init_recv(); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate /* 3750Sstevel@tonic-gate * Causes any further packets to be encrypted using the given key. The same 3760Sstevel@tonic-gate * key is used for both sending and reception. However, both directions are 3770Sstevel@tonic-gate * encrypted independently of each other. 3780Sstevel@tonic-gate */ 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate void 3810Sstevel@tonic-gate packet_set_encryption_key(const u_char *key, u_int keylen, 3820Sstevel@tonic-gate int number) 3830Sstevel@tonic-gate { 3840Sstevel@tonic-gate Cipher *cipher = cipher_by_number(number); 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate if (cipher == NULL) 3870Sstevel@tonic-gate fatal("packet_set_encryption_key: unknown cipher number %d", number); 3880Sstevel@tonic-gate if (keylen < 20) 3890Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too small: %d", keylen); 3900Sstevel@tonic-gate if (keylen > SSH_SESSION_KEY_LENGTH) 3910Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too big: %d", keylen); 3920Sstevel@tonic-gate memcpy(ssh1_key, key, keylen); 3930Sstevel@tonic-gate ssh1_keylen = keylen; 3940Sstevel@tonic-gate cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 3950Sstevel@tonic-gate cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate u_int 3990Sstevel@tonic-gate packet_get_encryption_key(u_char *key) 4000Sstevel@tonic-gate { 4010Sstevel@tonic-gate if (key == NULL) 4020Sstevel@tonic-gate return (ssh1_keylen); 4030Sstevel@tonic-gate memcpy(key, ssh1_key, ssh1_keylen); 4040Sstevel@tonic-gate return (ssh1_keylen); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate /* Start constructing a packet to send. */ 4080Sstevel@tonic-gate void 4090Sstevel@tonic-gate packet_start(u_char type) 4100Sstevel@tonic-gate { 4110Sstevel@tonic-gate u_char buf[9]; 4120Sstevel@tonic-gate int len; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate DBG(debug("packet_start[%d]", type)); 4150Sstevel@tonic-gate len = compat20 ? 6 : 9; 4160Sstevel@tonic-gate memset(buf, 0, len - 1); 4170Sstevel@tonic-gate buf[len - 1] = type; 4180Sstevel@tonic-gate buffer_clear(&outgoing_packet); 4190Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate /* Append payload. */ 4230Sstevel@tonic-gate void 4240Sstevel@tonic-gate packet_put_char(int value) 4250Sstevel@tonic-gate { 4260Sstevel@tonic-gate char ch = value; 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate buffer_append(&outgoing_packet, &ch, 1); 4290Sstevel@tonic-gate } 4305562Sjp161948 4310Sstevel@tonic-gate void 4320Sstevel@tonic-gate packet_put_int(u_int value) 4330Sstevel@tonic-gate { 4340Sstevel@tonic-gate buffer_put_int(&outgoing_packet, value); 4350Sstevel@tonic-gate } 4365562Sjp161948 4370Sstevel@tonic-gate void 4380Sstevel@tonic-gate packet_put_string(const void *buf, u_int len) 4390Sstevel@tonic-gate { 4400Sstevel@tonic-gate buffer_put_string(&outgoing_packet, buf, len); 4410Sstevel@tonic-gate } 4425562Sjp161948 4430Sstevel@tonic-gate void 4440Sstevel@tonic-gate packet_put_cstring(const char *str) 4450Sstevel@tonic-gate { 4460Sstevel@tonic-gate buffer_put_cstring(&outgoing_packet, str); 4470Sstevel@tonic-gate } 4485562Sjp161948 4490Sstevel@tonic-gate void 4500Sstevel@tonic-gate packet_put_ascii_cstring(const char *str) 4510Sstevel@tonic-gate { 4520Sstevel@tonic-gate buffer_put_ascii_cstring(&outgoing_packet, str); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate void 4550Sstevel@tonic-gate packet_put_utf8_cstring(const u_char *str) 4560Sstevel@tonic-gate { 4570Sstevel@tonic-gate buffer_put_utf8_cstring(&outgoing_packet, str); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate #if 0 4600Sstevel@tonic-gate void 4610Sstevel@tonic-gate packet_put_ascii_string(const void *buf, u_int len) 4620Sstevel@tonic-gate { 4630Sstevel@tonic-gate buffer_put_ascii_string(&outgoing_packet, buf, len); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate void 4660Sstevel@tonic-gate packet_put_utf8_string(const void *buf, u_int len) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate buffer_put_utf8_string(&outgoing_packet, buf, len); 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate #endif 4710Sstevel@tonic-gate void 4720Sstevel@tonic-gate packet_put_raw(const void *buf, u_int len) 4730Sstevel@tonic-gate { 4740Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 4750Sstevel@tonic-gate } 4765562Sjp161948 4770Sstevel@tonic-gate void 4780Sstevel@tonic-gate packet_put_bignum(BIGNUM * value) 4790Sstevel@tonic-gate { 4800Sstevel@tonic-gate buffer_put_bignum(&outgoing_packet, value); 4810Sstevel@tonic-gate } 4825562Sjp161948 4830Sstevel@tonic-gate void 4840Sstevel@tonic-gate packet_put_bignum2(BIGNUM * value) 4850Sstevel@tonic-gate { 4860Sstevel@tonic-gate buffer_put_bignum2(&outgoing_packet, value); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate /* 4900Sstevel@tonic-gate * Finalizes and sends the packet. If the encryption key has been set, 4910Sstevel@tonic-gate * encrypts the packet before sending. 4920Sstevel@tonic-gate */ 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate static void 4950Sstevel@tonic-gate packet_send1(void) 4960Sstevel@tonic-gate { 4970Sstevel@tonic-gate u_char buf[8], *cp; 4980Sstevel@tonic-gate int i, padding, len; 4990Sstevel@tonic-gate u_int checksum; 5005562Sjp161948 u_int32_t rnd = 0; 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate /* 5030Sstevel@tonic-gate * If using packet compression, compress the payload of the outgoing 5040Sstevel@tonic-gate * packet. 5050Sstevel@tonic-gate */ 5060Sstevel@tonic-gate if (packet_compression) { 5070Sstevel@tonic-gate buffer_clear(&compression_buffer); 5080Sstevel@tonic-gate /* Skip padding. */ 5090Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8); 5100Sstevel@tonic-gate /* padding */ 5110Sstevel@tonic-gate buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 5120Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 5130Sstevel@tonic-gate buffer_clear(&outgoing_packet); 5140Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 5150Sstevel@tonic-gate buffer_len(&compression_buffer)); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate /* Compute packet length without padding (add checksum, remove padding). */ 5180Sstevel@tonic-gate len = buffer_len(&outgoing_packet) + 4 - 8; 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate /* Insert padding. Initialized to zero in packet_start1() */ 5210Sstevel@tonic-gate padding = 8 - len % 8; 5220Sstevel@tonic-gate if (!send_context.plaintext) { 5230Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 5240Sstevel@tonic-gate for (i = 0; i < padding; i++) { 5250Sstevel@tonic-gate if (i % 4 == 0) 5265562Sjp161948 rnd = arc4random(); 5275562Sjp161948 cp[7 - i] = rnd & 0xff; 5285562Sjp161948 rnd >>= 8; 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate } 5310Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8 - padding); 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* Add check bytes. */ 5340Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 5350Sstevel@tonic-gate buffer_len(&outgoing_packet)); 5360Sstevel@tonic-gate PUT_32BIT(buf, checksum); 5370Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, 4); 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate #ifdef PACKET_DEBUG 5400Sstevel@tonic-gate fprintf(stderr, "packet_send plain: "); 5410Sstevel@tonic-gate buffer_dump(&outgoing_packet); 5420Sstevel@tonic-gate #endif 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate /* Append to output. */ 5450Sstevel@tonic-gate PUT_32BIT(buf, len); 5460Sstevel@tonic-gate buffer_append(&output, buf, 4); 5470Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 5480Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 5490Sstevel@tonic-gate buffer_len(&outgoing_packet)); 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate #ifdef PACKET_DEBUG 5527574SJan.Pechanec@Sun.COM debug("encrypted output queue now contains (%d bytes):\n", 5537574SJan.Pechanec@Sun.COM buffer_len(&output)); 5540Sstevel@tonic-gate buffer_dump(&output); 5550Sstevel@tonic-gate #endif 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate buffer_clear(&outgoing_packet); 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate /* 5600Sstevel@tonic-gate * Note that the packet is now only buffered in output. It won\'t be 5610Sstevel@tonic-gate * actually sent until packet_write_wait or packet_write_poll is 5620Sstevel@tonic-gate * called. 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate void 5670Sstevel@tonic-gate set_newkeys(int mode) 5680Sstevel@tonic-gate { 5690Sstevel@tonic-gate Enc *enc; 5700Sstevel@tonic-gate Mac *mac; 5710Sstevel@tonic-gate Comp *comp; 5720Sstevel@tonic-gate CipherContext *cc; 5735562Sjp161948 u_int64_t *max_blocks; 5745562Sjp161948 int crypt_type; 5750Sstevel@tonic-gate 5765562Sjp161948 debug2("set_newkeys: mode %d", mode); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if (mode == MODE_OUT) { 5790Sstevel@tonic-gate cc = &send_context; 5805562Sjp161948 crypt_type = CIPHER_ENCRYPT; 5815562Sjp161948 p_send.packets = p_send.blocks = 0; 5825562Sjp161948 max_blocks = &max_blocks_out; 5830Sstevel@tonic-gate } else { 5840Sstevel@tonic-gate cc = &receive_context; 5855562Sjp161948 crypt_type = CIPHER_DECRYPT; 5865562Sjp161948 p_read.packets = p_read.blocks = 0; 5875562Sjp161948 max_blocks = &max_blocks_in; 5880Sstevel@tonic-gate } 5897574SJan.Pechanec@Sun.COM 5907574SJan.Pechanec@Sun.COM debug("set_newkeys: setting new keys for '%s' mode", 5917574SJan.Pechanec@Sun.COM mode == MODE_IN ? "in" : "out"); 5927574SJan.Pechanec@Sun.COM 5930Sstevel@tonic-gate if (newkeys[mode] != NULL) { 5940Sstevel@tonic-gate cipher_cleanup(cc); 5955562Sjp161948 free_keys(newkeys[mode]); 5960Sstevel@tonic-gate } 5977574SJan.Pechanec@Sun.COM 5980Sstevel@tonic-gate newkeys[mode] = kex_get_newkeys(mode); 5990Sstevel@tonic-gate if (newkeys[mode] == NULL) 6000Sstevel@tonic-gate fatal("newkeys: no keys for mode %d", mode); 6010Sstevel@tonic-gate enc = &newkeys[mode]->enc; 6020Sstevel@tonic-gate mac = &newkeys[mode]->mac; 6030Sstevel@tonic-gate comp = &newkeys[mode]->comp; 6040Sstevel@tonic-gate if (mac->md != NULL) 6050Sstevel@tonic-gate mac->enabled = 1; 6067574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 6077574SJan.Pechanec@Sun.COM debug("new encryption key:\n"); 6087574SJan.Pechanec@Sun.COM data_dump(enc->key, enc->key_len); 6097574SJan.Pechanec@Sun.COM debug("new encryption IV:\n"); 6107574SJan.Pechanec@Sun.COM data_dump(enc->iv, enc->block_size); 6117574SJan.Pechanec@Sun.COM debug("new MAC key:\n"); 6127574SJan.Pechanec@Sun.COM data_dump(mac->key, mac->key_len); 6137574SJan.Pechanec@Sun.COM #endif 6140Sstevel@tonic-gate cipher_init(cc, enc->cipher, enc->key, enc->key_len, 6155562Sjp161948 enc->iv, enc->block_size, crypt_type); 6160Sstevel@tonic-gate /* Deleting the keys does not gain extra security */ 6170Sstevel@tonic-gate /* memset(enc->iv, 0, enc->block_size); 6180Sstevel@tonic-gate memset(enc->key, 0, enc->key_len); */ 6190Sstevel@tonic-gate if (comp->type != 0 && comp->enabled == 0) { 6200Sstevel@tonic-gate packet_init_compression(); 6210Sstevel@tonic-gate if (mode == MODE_OUT) 6220Sstevel@tonic-gate buffer_compress_init_send(6); 6230Sstevel@tonic-gate else 6240Sstevel@tonic-gate buffer_compress_init_recv(); 6250Sstevel@tonic-gate comp->enabled = 1; 6260Sstevel@tonic-gate } 6275562Sjp161948 6285562Sjp161948 /* 6295562Sjp161948 * In accordance to the RFCs listed below we enforce the key 6305562Sjp161948 * re-exchange for: 6315562Sjp161948 * 6325562Sjp161948 * - every 1GB of transmitted data if the selected cipher block size 6335562Sjp161948 * is less than 16 bytes (3DES, Blowfish) 6345562Sjp161948 * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes) 6355562Sjp161948 * if the cipher block size is greater than or equal to 16 bytes (AES) 6365562Sjp161948 * - and we never send more than 2^32 SSH packets using the same keys. 6375562Sjp161948 * The recommendation of 2^31 packets is not enforced here but in 6385562Sjp161948 * packet_need_rekeying(). There is also a hard check in 6395562Sjp161948 * packet_send2_wrapped() that we don't send more than 2^32 packets. 6405562Sjp161948 * 6415562Sjp161948 * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no 6425562Sjp161948 * automatic rekeying is performed nor do we enforce the 3rd rule. 6435562Sjp161948 * This means that we can be always forced by the opposite side to never 6445562Sjp161948 * initiate automatic key re-exchange. This might change in the future. 6455562Sjp161948 * 6465562Sjp161948 * The RekeyLimit option keyword may only enforce more frequent key 6475562Sjp161948 * renegotiation, never less. For more information on key renegotiation, 6485562Sjp161948 * see: 6495562Sjp161948 * 6505562Sjp161948 * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key 6515562Sjp161948 * Re-Exchange" 6525562Sjp161948 * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3. 6535562Sjp161948 * Rekeying" and "6.1 Rekeying Considerations" 6545562Sjp161948 */ 6555562Sjp161948 if (enc->block_size >= 16) 6565562Sjp161948 *max_blocks = (u_int64_t)1 << (enc->block_size * 2); 6575562Sjp161948 else 6585562Sjp161948 *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 6595562Sjp161948 6605562Sjp161948 if (rekey_limit) 6615562Sjp161948 *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 6625562Sjp161948 } 6635562Sjp161948 6645562Sjp161948 void 6655562Sjp161948 free_keys(Newkeys *keys) 6665562Sjp161948 { 6675562Sjp161948 Enc *enc; 6685562Sjp161948 Mac *mac; 6695562Sjp161948 Comp *comp; 6705562Sjp161948 6715562Sjp161948 enc = &keys->enc; 6725562Sjp161948 mac = &keys->mac; 6735562Sjp161948 comp = &keys->comp; 6745562Sjp161948 memset(mac->key, 0, mac->key_len); 6755562Sjp161948 xfree(enc->name); 6765562Sjp161948 xfree(enc->iv); 6775562Sjp161948 xfree(enc->key); 6785562Sjp161948 xfree(mac->name); 6795562Sjp161948 xfree(mac->key); 6805562Sjp161948 xfree(comp->name); 6815562Sjp161948 xfree(keys); 6820Sstevel@tonic-gate } 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate /* 6857574SJan.Pechanec@Sun.COM * Process SSH2_MSG_NEWKEYS message. If we are using the engine we must have 6867574SJan.Pechanec@Sun.COM * both SSH2_MSG_NEWKEYS processed before we can finish the engine, fork, and 6877574SJan.Pechanec@Sun.COM * reinitialize the crypto contexts. We can't fork before processing the 2nd 6887574SJan.Pechanec@Sun.COM * message otherwise we couldn't encrypt/decrypt that message at all - note that 6897574SJan.Pechanec@Sun.COM * parent's PKCS#11 sessions are useless after the fork and we must process 6907574SJan.Pechanec@Sun.COM * both SSH2_MSG_NEWKEYS messages using the old keys. 6917574SJan.Pechanec@Sun.COM */ 6927574SJan.Pechanec@Sun.COM void 6937574SJan.Pechanec@Sun.COM process_newkeys(int mode) 6947574SJan.Pechanec@Sun.COM { 695*7733SJan.Pechanec@Sun.COM /* this function is for the client only */ 6967574SJan.Pechanec@Sun.COM if (packet_is_server() != 0) 6977574SJan.Pechanec@Sun.COM return; 6987574SJan.Pechanec@Sun.COM 6997574SJan.Pechanec@Sun.COM if (will_daemonize == FIRST_NEWKEYS_PROCESSED) { 7007574SJan.Pechanec@Sun.COM debug3("both SSH2_MSG_NEWKEYS processed, will daemonize now"); 7017574SJan.Pechanec@Sun.COM cipher_cleanup(&send_context); 7027574SJan.Pechanec@Sun.COM cipher_cleanup(&receive_context); 7037574SJan.Pechanec@Sun.COM pkcs11_engine_finish(e); 7047574SJan.Pechanec@Sun.COM if (daemon(1, 1) < 0) { 7057574SJan.Pechanec@Sun.COM fatal("daemon() failed: %.200s", 7067574SJan.Pechanec@Sun.COM strerror(errno)); 7077574SJan.Pechanec@Sun.COM } 7087574SJan.Pechanec@Sun.COM e = pkcs11_engine_load(e != NULL ? 1 : 0); 7097574SJan.Pechanec@Sun.COM 7107574SJan.Pechanec@Sun.COM set_newkeys(MODE_OUT); 7117574SJan.Pechanec@Sun.COM set_newkeys(MODE_IN); 7127574SJan.Pechanec@Sun.COM will_daemonize = SECOND_NEWKEYS_PROCESSED; 7137574SJan.Pechanec@Sun.COM packet_send2(); 7147574SJan.Pechanec@Sun.COM } else { 7157574SJan.Pechanec@Sun.COM if (will_daemonize == DAEMONIZING_REQUESTED) 7167574SJan.Pechanec@Sun.COM will_daemonize = FIRST_NEWKEYS_PROCESSED; 7177574SJan.Pechanec@Sun.COM else 7187574SJan.Pechanec@Sun.COM set_newkeys(mode); 7197574SJan.Pechanec@Sun.COM } 7207574SJan.Pechanec@Sun.COM } 7217574SJan.Pechanec@Sun.COM 7227574SJan.Pechanec@Sun.COM /* 7230Sstevel@tonic-gate * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 7240Sstevel@tonic-gate */ 7250Sstevel@tonic-gate static void 7265562Sjp161948 packet_send2_wrapped(void) 7270Sstevel@tonic-gate { 7280Sstevel@tonic-gate u_char type, *cp, *macbuf = NULL; 7290Sstevel@tonic-gate u_char padlen, pad; 7300Sstevel@tonic-gate u_int packet_length = 0; 7310Sstevel@tonic-gate u_int i, len; 7325562Sjp161948 u_int32_t rnd = 0; 7330Sstevel@tonic-gate Enc *enc = NULL; 7340Sstevel@tonic-gate Mac *mac = NULL; 7350Sstevel@tonic-gate Comp *comp = NULL; 7360Sstevel@tonic-gate int block_size; 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate if (newkeys[MODE_OUT] != NULL) { 7390Sstevel@tonic-gate enc = &newkeys[MODE_OUT]->enc; 7400Sstevel@tonic-gate mac = &newkeys[MODE_OUT]->mac; 7410Sstevel@tonic-gate comp = &newkeys[MODE_OUT]->comp; 7420Sstevel@tonic-gate } 7430Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 7460Sstevel@tonic-gate type = cp[5]; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate #ifdef PACKET_DEBUG 7497574SJan.Pechanec@Sun.COM debug("plain output packet to be processed (%d bytes):\n", 7507574SJan.Pechanec@Sun.COM buffer_len(&outgoing_packet)); 7510Sstevel@tonic-gate buffer_dump(&outgoing_packet); 7520Sstevel@tonic-gate #endif 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate if (comp && comp->enabled) { 7550Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 7560Sstevel@tonic-gate /* skip header, compress only payload */ 7570Sstevel@tonic-gate buffer_consume(&outgoing_packet, 5); 7580Sstevel@tonic-gate buffer_clear(&compression_buffer); 7590Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 7600Sstevel@tonic-gate buffer_clear(&outgoing_packet); 7610Sstevel@tonic-gate buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 7620Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 7630Sstevel@tonic-gate buffer_len(&compression_buffer)); 7640Sstevel@tonic-gate DBG(debug("compression: raw %d compressed %d", len, 7650Sstevel@tonic-gate buffer_len(&outgoing_packet))); 7660Sstevel@tonic-gate } 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate /* sizeof (packet_len + pad_len + payload) */ 7690Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate /* 7720Sstevel@tonic-gate * calc size of padding, alloc space, get random data, 7730Sstevel@tonic-gate * minimum padding is 4 bytes 7740Sstevel@tonic-gate */ 7750Sstevel@tonic-gate padlen = block_size - (len % block_size); 7760Sstevel@tonic-gate if (padlen < 4) 7770Sstevel@tonic-gate padlen += block_size; 7780Sstevel@tonic-gate if (extra_pad) { 7790Sstevel@tonic-gate /* will wrap if extra_pad+padlen > 255 */ 7800Sstevel@tonic-gate extra_pad = roundup(extra_pad, block_size); 7810Sstevel@tonic-gate pad = extra_pad - ((len + padlen) % extra_pad); 7820Sstevel@tonic-gate debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 7830Sstevel@tonic-gate pad, len, padlen, extra_pad); 7840Sstevel@tonic-gate padlen += pad; 7850Sstevel@tonic-gate extra_pad = 0; 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate cp = buffer_append_space(&outgoing_packet, padlen); 7880Sstevel@tonic-gate if (enc && !send_context.plaintext) { 7890Sstevel@tonic-gate /* random padding */ 7900Sstevel@tonic-gate for (i = 0; i < padlen; i++) { 7910Sstevel@tonic-gate if (i % 4 == 0) 7925562Sjp161948 rnd = arc4random(); 7935562Sjp161948 cp[i] = rnd & 0xff; 7945562Sjp161948 rnd >>= 8; 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate } else { 7970Sstevel@tonic-gate /* clear padding */ 7980Sstevel@tonic-gate memset(cp, 0, padlen); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate /* packet_length includes payload, padding and padding length field */ 8010Sstevel@tonic-gate packet_length = buffer_len(&outgoing_packet) - 4; 8020Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 8030Sstevel@tonic-gate PUT_32BIT(cp, packet_length); 8040Sstevel@tonic-gate cp[4] = padlen; 8057574SJan.Pechanec@Sun.COM DBG(debug("will send %d bytes (includes padlen %d)", 8067574SJan.Pechanec@Sun.COM packet_length + 4, padlen)); 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate /* compute MAC over seqnr and packet(length fields, payload, padding) */ 8090Sstevel@tonic-gate if (mac && mac->enabled) { 8105562Sjp161948 macbuf = mac_compute(mac, p_send.seqnr, 8110Sstevel@tonic-gate buffer_ptr(&outgoing_packet), 8120Sstevel@tonic-gate buffer_len(&outgoing_packet)); 8135562Sjp161948 DBG(debug("done calc MAC out #%d", p_send.seqnr)); 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate /* encrypt packet and append to output buffer. */ 8160Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 8170Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 8180Sstevel@tonic-gate buffer_len(&outgoing_packet)); 8190Sstevel@tonic-gate /* append unencrypted MAC */ 8200Sstevel@tonic-gate if (mac && mac->enabled) 8210Sstevel@tonic-gate buffer_append(&output, (char *)macbuf, mac->mac_len); 8220Sstevel@tonic-gate #ifdef PACKET_DEBUG 8237574SJan.Pechanec@Sun.COM debug("encrypted output queue now contains (%d bytes):\n", 8247574SJan.Pechanec@Sun.COM buffer_len(&output)); 8250Sstevel@tonic-gate buffer_dump(&output); 8260Sstevel@tonic-gate #endif 8270Sstevel@tonic-gate /* increment sequence number for outgoing packets */ 8285562Sjp161948 if (++p_send.seqnr == 0) 8290Sstevel@tonic-gate log("outgoing seqnr wraps around"); 8305562Sjp161948 8315562Sjp161948 /* 8325562Sjp161948 * RFC 4344: 3.1. First Rekeying Recommendation 8335562Sjp161948 * 8345562Sjp161948 * "Because of possible information leakage through the MAC tag after a 8355562Sjp161948 * key exchange, .... an SSH implementation SHOULD NOT send more than 8365562Sjp161948 * 2**32 packets before rekeying again." 8375562Sjp161948 * 8385562Sjp161948 * The code below is a hard check so that we are sure we don't go across 8395562Sjp161948 * the suggestion. However, since the largest cipher block size we have 8405562Sjp161948 * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the 8415562Sjp161948 * same key while performing periodic rekeying. 8425562Sjp161948 */ 8435562Sjp161948 if (++p_send.packets == 0) 8445562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 8455562Sjp161948 fatal("too many packets encrypted with same key"); 8465562Sjp161948 p_send.blocks += (packet_length + 4) / block_size; 8470Sstevel@tonic-gate buffer_clear(&outgoing_packet); 8480Sstevel@tonic-gate 8497574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_NEWKEYS) { 8507574SJan.Pechanec@Sun.COM /* 8517574SJan.Pechanec@Sun.COM * set_newkeys(MODE_OUT) in the client. Note that in the 8527574SJan.Pechanec@Sun.COM * unprivileged child, set_newkeys() for MODE_OUT are set after 8537574SJan.Pechanec@Sun.COM * SSH2_MSG_NEWKEYS is read from the monitor and forwarded to 8547574SJan.Pechanec@Sun.COM * the client side. 8557574SJan.Pechanec@Sun.COM */ 8567574SJan.Pechanec@Sun.COM process_newkeys(MODE_OUT); 8577574SJan.Pechanec@Sun.COM } 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate 8607574SJan.Pechanec@Sun.COM /* 8617574SJan.Pechanec@Sun.COM * Packets we deal with here are plain until we encrypt them in 8627574SJan.Pechanec@Sun.COM * packet_send2_wrapped(). 8637574SJan.Pechanec@Sun.COM * 8647574SJan.Pechanec@Sun.COM * As already mentioned in a comment at process_newkeys() function we must not 8657574SJan.Pechanec@Sun.COM * fork() until both SSH2_MSG_NEWKEYS packets were processed. Until this is done 8667574SJan.Pechanec@Sun.COM * we must queue all packets so that they can be encrypted with the new keys and 8677574SJan.Pechanec@Sun.COM * then sent to the other side. However, what can happen here is that we get 8687574SJan.Pechanec@Sun.COM * SSH2_MSG_NEWKEYS after we sent it. In that situation we must call 8697574SJan.Pechanec@Sun.COM * packet_send2() anyway to empty the queue, and set the rekey flag to the 8707574SJan.Pechanec@Sun.COM * finished state. If we didn't do that we would just hang and enqueue data. 8717574SJan.Pechanec@Sun.COM */ 8725562Sjp161948 static void 8735562Sjp161948 packet_send2(void) 8745562Sjp161948 { 8755562Sjp161948 static int rekeying = 0; 8765562Sjp161948 struct packet *p; 8775562Sjp161948 u_char type, *cp; 8785562Sjp161948 8797574SJan.Pechanec@Sun.COM if (will_daemonize != SECOND_NEWKEYS_PROCESSED) { 8807574SJan.Pechanec@Sun.COM cp = buffer_ptr(&outgoing_packet); 8817574SJan.Pechanec@Sun.COM type = cp[5]; 8825562Sjp161948 8837574SJan.Pechanec@Sun.COM /* during rekeying we can only send key exchange messages */ 8847574SJan.Pechanec@Sun.COM if (rekeying) { 8857574SJan.Pechanec@Sun.COM if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 8867574SJan.Pechanec@Sun.COM (type <= SSH2_MSG_TRANSPORT_MAX))) { 8877574SJan.Pechanec@Sun.COM debug("enqueue a plain packet because rekex in " 8887574SJan.Pechanec@Sun.COM "progress [type %u]", type); 8897574SJan.Pechanec@Sun.COM p = xmalloc(sizeof(*p)); 8907574SJan.Pechanec@Sun.COM p->type = type; 8917574SJan.Pechanec@Sun.COM memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 8927574SJan.Pechanec@Sun.COM buffer_init(&outgoing_packet); 8937574SJan.Pechanec@Sun.COM TAILQ_INSERT_TAIL(&outgoing, p, next); 8947574SJan.Pechanec@Sun.COM return; 8957574SJan.Pechanec@Sun.COM } 8965562Sjp161948 } 8977574SJan.Pechanec@Sun.COM 8987574SJan.Pechanec@Sun.COM /* rekeying starts with sending KEXINIT */ 8997574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_KEXINIT) 9007574SJan.Pechanec@Sun.COM rekeying = 1; 9017574SJan.Pechanec@Sun.COM 9027574SJan.Pechanec@Sun.COM packet_send2_wrapped(); 9035562Sjp161948 } 9045562Sjp161948 9057574SJan.Pechanec@Sun.COM /* after rekex is done we can process the queue of plain packets */ 9067574SJan.Pechanec@Sun.COM if (will_daemonize == SECOND_NEWKEYS_PROCESSED || 9077574SJan.Pechanec@Sun.COM (will_daemonize == NOT_DAEMONIZING && type == SSH2_MSG_NEWKEYS)) { 9085562Sjp161948 rekeying = 0; 9097574SJan.Pechanec@Sun.COM will_daemonize = NOT_DAEMONIZING; 9105562Sjp161948 while ((p = TAILQ_FIRST(&outgoing)) != NULL) { 9115562Sjp161948 type = p->type; 9127574SJan.Pechanec@Sun.COM debug("dequeuing a plain packet since rekex is over " 9137574SJan.Pechanec@Sun.COM "[type %u]", type); 9145562Sjp161948 buffer_free(&outgoing_packet); 9155562Sjp161948 memcpy(&outgoing_packet, &p->payload, sizeof(Buffer)); 9165562Sjp161948 TAILQ_REMOVE(&outgoing, p, next); 9175562Sjp161948 xfree(p); 9185562Sjp161948 packet_send2_wrapped(); 9195562Sjp161948 } 9205562Sjp161948 } 9215562Sjp161948 } 9225562Sjp161948 9230Sstevel@tonic-gate void 9240Sstevel@tonic-gate packet_send(void) 9250Sstevel@tonic-gate { 9260Sstevel@tonic-gate if (compat20) 9270Sstevel@tonic-gate packet_send2(); 9280Sstevel@tonic-gate else 9290Sstevel@tonic-gate packet_send1(); 9300Sstevel@tonic-gate DBG(debug("packet_send done")); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate /* 9340Sstevel@tonic-gate * Waits until a packet has been received, and returns its type. Note that 9350Sstevel@tonic-gate * no other data is processed until this returns, so this function should not 9360Sstevel@tonic-gate * be used during the interactive session. 9370Sstevel@tonic-gate */ 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate int 9400Sstevel@tonic-gate packet_read_seqnr(u_int32_t *seqnr_p) 9410Sstevel@tonic-gate { 9420Sstevel@tonic-gate int type, len; 9430Sstevel@tonic-gate fd_set *setp; 9440Sstevel@tonic-gate char buf[8192]; 9450Sstevel@tonic-gate DBG(debug("packet_read()")); 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 9480Sstevel@tonic-gate sizeof(fd_mask)); 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate /* Since we are blocking, ensure that all written packets have been sent. */ 9510Sstevel@tonic-gate packet_write_wait(); 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate /* Stay in the loop until we have received a complete packet. */ 9540Sstevel@tonic-gate for (;;) { 9550Sstevel@tonic-gate /* Try to read a packet from the buffer. */ 9560Sstevel@tonic-gate type = packet_read_poll_seqnr(seqnr_p); 9570Sstevel@tonic-gate if (!compat20 && ( 9580Sstevel@tonic-gate type == SSH_SMSG_SUCCESS 9590Sstevel@tonic-gate || type == SSH_SMSG_FAILURE 9600Sstevel@tonic-gate || type == SSH_CMSG_EOF 9610Sstevel@tonic-gate || type == SSH_CMSG_EXIT_CONFIRMATION)) 9620Sstevel@tonic-gate packet_check_eom(); 9630Sstevel@tonic-gate /* If we got a packet, return it. */ 9640Sstevel@tonic-gate if (type != SSH_MSG_NONE) { 9650Sstevel@tonic-gate xfree(setp); 9660Sstevel@tonic-gate return type; 9670Sstevel@tonic-gate } 9680Sstevel@tonic-gate /* 9690Sstevel@tonic-gate * Otherwise, wait for some data to arrive, add it to the 9700Sstevel@tonic-gate * buffer, and try again. 9710Sstevel@tonic-gate */ 9720Sstevel@tonic-gate memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 9730Sstevel@tonic-gate sizeof(fd_mask)); 9740Sstevel@tonic-gate FD_SET(connection_in, setp); 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate /* Wait for some data to arrive. */ 9770Sstevel@tonic-gate while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 9780Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 9790Sstevel@tonic-gate ; 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate /* Read data from the socket. */ 9820Sstevel@tonic-gate len = read(connection_in, buf, sizeof(buf)); 9830Sstevel@tonic-gate if (len == 0) { 9840Sstevel@tonic-gate log("Connection closed by %.200s", get_remote_ipaddr()); 9850Sstevel@tonic-gate fatal_cleanup(); 9860Sstevel@tonic-gate } 9870Sstevel@tonic-gate if (len < 0) 9880Sstevel@tonic-gate fatal("Read from socket failed: %.100s", strerror(errno)); 9890Sstevel@tonic-gate /* Append it to the buffer. */ 9900Sstevel@tonic-gate packet_process_incoming(buf, len); 9910Sstevel@tonic-gate } 9920Sstevel@tonic-gate /* NOTREACHED */ 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate int 9960Sstevel@tonic-gate packet_read(void) 9970Sstevel@tonic-gate { 9980Sstevel@tonic-gate return packet_read_seqnr(NULL); 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate /* 10020Sstevel@tonic-gate * Waits until a packet has been received, verifies that its type matches 10030Sstevel@tonic-gate * that given, and gives a fatal error and exits if there is a mismatch. 10040Sstevel@tonic-gate */ 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate void 10070Sstevel@tonic-gate packet_read_expect(int expected_type) 10080Sstevel@tonic-gate { 10090Sstevel@tonic-gate int type; 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate type = packet_read(); 10120Sstevel@tonic-gate if (type != expected_type) 10130Sstevel@tonic-gate packet_disconnect("Protocol error: expected packet type %d, got %d", 10140Sstevel@tonic-gate expected_type, type); 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate /* Checks if a full packet is available in the data received so far via 10180Sstevel@tonic-gate * packet_process_incoming. If so, reads the packet; otherwise returns 10190Sstevel@tonic-gate * SSH_MSG_NONE. This does not wait for data from the connection. 10200Sstevel@tonic-gate * 10210Sstevel@tonic-gate * SSH_MSG_DISCONNECT is handled specially here. Also, 10220Sstevel@tonic-gate * SSH_MSG_IGNORE messages are skipped by this function and are never returned 10230Sstevel@tonic-gate * to higher levels. 10240Sstevel@tonic-gate */ 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate static int 10270Sstevel@tonic-gate packet_read_poll1(void) 10280Sstevel@tonic-gate { 10290Sstevel@tonic-gate u_int len, padded_len; 10300Sstevel@tonic-gate u_char *cp, type; 10310Sstevel@tonic-gate u_int checksum, stored_checksum; 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate /* Check if input size is less than minimum packet size. */ 10340Sstevel@tonic-gate if (buffer_len(&input) < 4 + 8) 10350Sstevel@tonic-gate return SSH_MSG_NONE; 10360Sstevel@tonic-gate /* Get length of incoming packet. */ 10370Sstevel@tonic-gate cp = buffer_ptr(&input); 10380Sstevel@tonic-gate len = GET_32BIT(cp); 10390Sstevel@tonic-gate if (len < 1 + 2 + 2 || len > 256 * 1024) 10400Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", len); 10410Sstevel@tonic-gate padded_len = (len + 8) & ~7; 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate /* Check if the packet has been entirely received. */ 10440Sstevel@tonic-gate if (buffer_len(&input) < 4 + padded_len) 10450Sstevel@tonic-gate return SSH_MSG_NONE; 10460Sstevel@tonic-gate 10470Sstevel@tonic-gate /* The entire packet is in buffer. */ 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate /* Consume packet length. */ 10500Sstevel@tonic-gate buffer_consume(&input, 4); 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate /* 10530Sstevel@tonic-gate * Cryptographic attack detector for ssh 10540Sstevel@tonic-gate * (C)1998 CORE-SDI, Buenos Aires Argentina 10550Sstevel@tonic-gate * Ariel Futoransky(futo@core-sdi.com) 10560Sstevel@tonic-gate */ 10573102Sjp161948 if (!receive_context.plaintext) { 10583102Sjp161948 switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) { 10593102Sjp161948 case DEATTACK_DETECTED: 10603102Sjp161948 packet_disconnect("crc32 compensation attack: " 10613102Sjp161948 "network attack detected"); 10623102Sjp161948 break; 10633102Sjp161948 case DEATTACK_DOS_DETECTED: 10643102Sjp161948 packet_disconnect("deattack denial of " 10653102Sjp161948 "service detected"); 10663102Sjp161948 break; 10673102Sjp161948 } 10683102Sjp161948 } 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate /* Decrypt data to incoming_packet. */ 10710Sstevel@tonic-gate buffer_clear(&incoming_packet); 10720Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, padded_len); 10730Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate buffer_consume(&input, padded_len); 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate #ifdef PACKET_DEBUG 10787574SJan.Pechanec@Sun.COM debug("read_poll plain/full:\n"); 10790Sstevel@tonic-gate buffer_dump(&incoming_packet); 10800Sstevel@tonic-gate #endif 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate /* Compute packet checksum. */ 10830Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&incoming_packet), 10840Sstevel@tonic-gate buffer_len(&incoming_packet) - 4); 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate /* Skip padding. */ 10870Sstevel@tonic-gate buffer_consume(&incoming_packet, 8 - len % 8); 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate /* Test check bytes. */ 10900Sstevel@tonic-gate if (len != buffer_len(&incoming_packet)) 10910Sstevel@tonic-gate packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 10920Sstevel@tonic-gate len, buffer_len(&incoming_packet)); 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 10950Sstevel@tonic-gate stored_checksum = GET_32BIT(cp); 10960Sstevel@tonic-gate if (checksum != stored_checksum) 10970Sstevel@tonic-gate packet_disconnect("Corrupted check bytes on input."); 10980Sstevel@tonic-gate buffer_consume_end(&incoming_packet, 4); 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate if (packet_compression) { 11010Sstevel@tonic-gate buffer_clear(&compression_buffer); 11020Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 11030Sstevel@tonic-gate buffer_clear(&incoming_packet); 11040Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 11050Sstevel@tonic-gate buffer_len(&compression_buffer)); 11060Sstevel@tonic-gate } 11070Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 11080Sstevel@tonic-gate return type; 11090Sstevel@tonic-gate } 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate static int 11120Sstevel@tonic-gate packet_read_poll2(u_int32_t *seqnr_p) 11130Sstevel@tonic-gate { 11140Sstevel@tonic-gate static u_int packet_length = 0; 11150Sstevel@tonic-gate u_int padlen, need; 11160Sstevel@tonic-gate u_char *macbuf, *cp, type; 11170Sstevel@tonic-gate int maclen, block_size; 11180Sstevel@tonic-gate Enc *enc = NULL; 11190Sstevel@tonic-gate Mac *mac = NULL; 11200Sstevel@tonic-gate Comp *comp = NULL; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate if (newkeys[MODE_IN] != NULL) { 11230Sstevel@tonic-gate enc = &newkeys[MODE_IN]->enc; 11240Sstevel@tonic-gate mac = &newkeys[MODE_IN]->mac; 11250Sstevel@tonic-gate comp = &newkeys[MODE_IN]->comp; 11260Sstevel@tonic-gate } 11270Sstevel@tonic-gate maclen = mac && mac->enabled ? mac->mac_len : 0; 11280Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate if (packet_length == 0) { 11310Sstevel@tonic-gate /* 11320Sstevel@tonic-gate * check if input size is less than the cipher block size, 11330Sstevel@tonic-gate * decrypt first block and extract length of incoming packet 11340Sstevel@tonic-gate */ 11350Sstevel@tonic-gate if (buffer_len(&input) < block_size) 11360Sstevel@tonic-gate return SSH_MSG_NONE; 11377574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 11387574SJan.Pechanec@Sun.COM debug("encrypted data we have in read queue (%d bytes):\n", 11397574SJan.Pechanec@Sun.COM buffer_len(&input)); 11407574SJan.Pechanec@Sun.COM buffer_dump(&input); 11417574SJan.Pechanec@Sun.COM #endif 11420Sstevel@tonic-gate buffer_clear(&incoming_packet); 11430Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, block_size); 11440Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), 11450Sstevel@tonic-gate block_size); 11460Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 11470Sstevel@tonic-gate packet_length = GET_32BIT(cp); 11480Sstevel@tonic-gate if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 11497574SJan.Pechanec@Sun.COM error("bad packet length %d; i/o counters " 11507574SJan.Pechanec@Sun.COM "%llu/%llu", packet_length, 11517574SJan.Pechanec@Sun.COM p_read.blocks * block_size, 11527574SJan.Pechanec@Sun.COM p_send.blocks * block_size); 11537574SJan.Pechanec@Sun.COM error("decrypted %d bytes follows:\n", block_size); 11540Sstevel@tonic-gate buffer_dump(&incoming_packet); 11557574SJan.Pechanec@Sun.COM packet_disconnect("Bad packet length %d, i/o counters " 11567574SJan.Pechanec@Sun.COM "%llu/%llu.", packet_length, 11577574SJan.Pechanec@Sun.COM p_read.blocks * block_size, 11587574SJan.Pechanec@Sun.COM p_send.blocks * block_size); 11590Sstevel@tonic-gate } 11605562Sjp161948 DBG(debug("input: packet len %u", packet_length + 4)); 11610Sstevel@tonic-gate buffer_consume(&input, block_size); 11620Sstevel@tonic-gate } 11630Sstevel@tonic-gate /* we have a partial packet of block_size bytes */ 11640Sstevel@tonic-gate need = 4 + packet_length - block_size; 11657574SJan.Pechanec@Sun.COM DBG(debug("partial packet %d, still need %d, maclen %d", block_size, 11660Sstevel@tonic-gate need, maclen)); 11670Sstevel@tonic-gate if (need % block_size != 0) 11680Sstevel@tonic-gate fatal("padding error: need %d block %d mod %d", 11690Sstevel@tonic-gate need, block_size, need % block_size); 11700Sstevel@tonic-gate /* 11710Sstevel@tonic-gate * check if the entire packet has been received and 11720Sstevel@tonic-gate * decrypt into incoming_packet 11730Sstevel@tonic-gate */ 11740Sstevel@tonic-gate if (buffer_len(&input) < need + maclen) 11750Sstevel@tonic-gate return SSH_MSG_NONE; 11760Sstevel@tonic-gate #ifdef PACKET_DEBUG 11777574SJan.Pechanec@Sun.COM debug("in read_poll, the encrypted input queue now contains " 11787574SJan.Pechanec@Sun.COM "(%d bytes):\n", buffer_len(&input)); 11790Sstevel@tonic-gate buffer_dump(&input); 11800Sstevel@tonic-gate #endif 11810Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, need); 11820Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 11830Sstevel@tonic-gate buffer_consume(&input, need); 11840Sstevel@tonic-gate /* 11850Sstevel@tonic-gate * compute MAC over seqnr and packet, 11860Sstevel@tonic-gate * increment sequence number for incoming packet 11870Sstevel@tonic-gate */ 11880Sstevel@tonic-gate if (mac && mac->enabled) { 11895562Sjp161948 macbuf = mac_compute(mac, p_read.seqnr, 11900Sstevel@tonic-gate buffer_ptr(&incoming_packet), 11910Sstevel@tonic-gate buffer_len(&incoming_packet)); 11920Sstevel@tonic-gate if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 11930Sstevel@tonic-gate packet_disconnect("Corrupted MAC on input."); 11945562Sjp161948 DBG(debug("MAC #%d ok", p_read.seqnr)); 11950Sstevel@tonic-gate buffer_consume(&input, mac->mac_len); 11960Sstevel@tonic-gate } 11970Sstevel@tonic-gate if (seqnr_p != NULL) 11985562Sjp161948 *seqnr_p = p_read.seqnr; 11995562Sjp161948 if (++p_read.seqnr == 0) 12000Sstevel@tonic-gate log("incoming seqnr wraps around"); 12010Sstevel@tonic-gate 12025562Sjp161948 /* see above for the comment on "First Rekeying Recommendation" */ 12035562Sjp161948 if (++p_read.packets == 0) 12045562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 12055562Sjp161948 fatal("too many packets with same key"); 12065562Sjp161948 p_read.blocks += (packet_length + 4) / block_size; 12075562Sjp161948 12080Sstevel@tonic-gate /* get padlen */ 12090Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 12100Sstevel@tonic-gate padlen = cp[4]; 12110Sstevel@tonic-gate DBG(debug("input: padlen %d", padlen)); 12120Sstevel@tonic-gate if (padlen < 4) 12130Sstevel@tonic-gate packet_disconnect("Corrupted padlen %d on input.", padlen); 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate /* skip packet size + padlen, discard padding */ 12160Sstevel@tonic-gate buffer_consume(&incoming_packet, 4 + 1); 12170Sstevel@tonic-gate buffer_consume_end(&incoming_packet, padlen); 12180Sstevel@tonic-gate 12190Sstevel@tonic-gate DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 12200Sstevel@tonic-gate if (comp && comp->enabled) { 12210Sstevel@tonic-gate buffer_clear(&compression_buffer); 12220Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 12230Sstevel@tonic-gate buffer_clear(&incoming_packet); 12240Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 12250Sstevel@tonic-gate buffer_len(&compression_buffer)); 12260Sstevel@tonic-gate DBG(debug("input: len after de-compress %d", 12270Sstevel@tonic-gate buffer_len(&incoming_packet))); 12280Sstevel@tonic-gate } 12290Sstevel@tonic-gate /* 12300Sstevel@tonic-gate * get packet type, implies consume. 12310Sstevel@tonic-gate * return length of payload (without type field) 12320Sstevel@tonic-gate */ 12330Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 12347574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_NEWKEYS) { 12357574SJan.Pechanec@Sun.COM /* 12367574SJan.Pechanec@Sun.COM * set_newkeys(MODE_IN) in the client because it doesn't have a 12377574SJan.Pechanec@Sun.COM * dispatch function for SSH2_MSG_NEWKEYS in contrast to the 12387574SJan.Pechanec@Sun.COM * server processes. Note that in the unprivileged child, 12397574SJan.Pechanec@Sun.COM * set_newkeys() for MODE_IN are set in dispatch function 12407574SJan.Pechanec@Sun.COM * altprivsep_rekey() after SSH2_MSG_NEWKEYS packet is received 12417574SJan.Pechanec@Sun.COM * from the client. 12427574SJan.Pechanec@Sun.COM */ 12437574SJan.Pechanec@Sun.COM process_newkeys(MODE_IN); 12447574SJan.Pechanec@Sun.COM } 12457574SJan.Pechanec@Sun.COM 12460Sstevel@tonic-gate #ifdef PACKET_DEBUG 12477574SJan.Pechanec@Sun.COM debug("decrypted input packet [type %d]:\n", type); 12480Sstevel@tonic-gate buffer_dump(&incoming_packet); 12490Sstevel@tonic-gate #endif 12500Sstevel@tonic-gate /* reset for next packet */ 12510Sstevel@tonic-gate packet_length = 0; 12520Sstevel@tonic-gate return type; 12530Sstevel@tonic-gate } 12540Sstevel@tonic-gate 12557574SJan.Pechanec@Sun.COM /* 12567574SJan.Pechanec@Sun.COM * This tries to read a packet from the buffer of received data. Note that it 12577574SJan.Pechanec@Sun.COM * doesn't read() anything from the network socket. 12587574SJan.Pechanec@Sun.COM */ 12590Sstevel@tonic-gate int 12600Sstevel@tonic-gate packet_read_poll_seqnr(u_int32_t *seqnr_p) 12610Sstevel@tonic-gate { 12620Sstevel@tonic-gate u_int reason, seqnr; 12630Sstevel@tonic-gate u_char type; 12640Sstevel@tonic-gate char *msg; 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate for (;;) { 12670Sstevel@tonic-gate if (compat20) { 12680Sstevel@tonic-gate type = packet_read_poll2(seqnr_p); 12690Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 12700Sstevel@tonic-gate switch (type) { 12710Sstevel@tonic-gate case SSH2_MSG_IGNORE: 12720Sstevel@tonic-gate break; 12730Sstevel@tonic-gate case SSH2_MSG_DEBUG: 12740Sstevel@tonic-gate packet_get_char(); 12750Sstevel@tonic-gate msg = packet_get_string(NULL); 12760Sstevel@tonic-gate debug("Remote: %.900s", msg); 12770Sstevel@tonic-gate xfree(msg); 12780Sstevel@tonic-gate msg = packet_get_string(NULL); 12790Sstevel@tonic-gate xfree(msg); 12800Sstevel@tonic-gate break; 12810Sstevel@tonic-gate case SSH2_MSG_DISCONNECT: 12820Sstevel@tonic-gate reason = packet_get_int(); 12830Sstevel@tonic-gate msg = packet_get_string(NULL); 12840Sstevel@tonic-gate log("Received disconnect from %s: %u: %.400s", 12850Sstevel@tonic-gate get_remote_ipaddr(), reason, msg); 12860Sstevel@tonic-gate xfree(msg); 12870Sstevel@tonic-gate fatal_cleanup(); 12880Sstevel@tonic-gate break; 12890Sstevel@tonic-gate case SSH2_MSG_UNIMPLEMENTED: 12900Sstevel@tonic-gate seqnr = packet_get_int(); 12910Sstevel@tonic-gate debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 12920Sstevel@tonic-gate seqnr); 12930Sstevel@tonic-gate break; 12940Sstevel@tonic-gate default: 12950Sstevel@tonic-gate return type; 12960Sstevel@tonic-gate break; 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate } else { 12990Sstevel@tonic-gate type = packet_read_poll1(); 13000Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 13010Sstevel@tonic-gate switch (type) { 13020Sstevel@tonic-gate case SSH_MSG_IGNORE: 13030Sstevel@tonic-gate break; 13040Sstevel@tonic-gate case SSH_MSG_DEBUG: 13050Sstevel@tonic-gate msg = packet_get_string(NULL); 13060Sstevel@tonic-gate debug("Remote: %.900s", msg); 13070Sstevel@tonic-gate xfree(msg); 13080Sstevel@tonic-gate break; 13090Sstevel@tonic-gate case SSH_MSG_DISCONNECT: 13100Sstevel@tonic-gate msg = packet_get_string(NULL); 13110Sstevel@tonic-gate log("Received disconnect from %s: %.400s", 13120Sstevel@tonic-gate get_remote_ipaddr(), msg); 13130Sstevel@tonic-gate fatal_cleanup(); 13140Sstevel@tonic-gate xfree(msg); 13150Sstevel@tonic-gate break; 13160Sstevel@tonic-gate default: 13170Sstevel@tonic-gate return type; 13180Sstevel@tonic-gate break; 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate } 13220Sstevel@tonic-gate } 13230Sstevel@tonic-gate 13240Sstevel@tonic-gate int 13250Sstevel@tonic-gate packet_read_poll(void) 13260Sstevel@tonic-gate { 13270Sstevel@tonic-gate return packet_read_poll_seqnr(NULL); 13280Sstevel@tonic-gate } 13290Sstevel@tonic-gate 13300Sstevel@tonic-gate /* 13310Sstevel@tonic-gate * Buffers the given amount of input characters. This is intended to be used 13320Sstevel@tonic-gate * together with packet_read_poll. 13330Sstevel@tonic-gate */ 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate void 13360Sstevel@tonic-gate packet_process_incoming(const char *buf, u_int len) 13370Sstevel@tonic-gate { 13380Sstevel@tonic-gate buffer_append(&input, buf, len); 13390Sstevel@tonic-gate } 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate /* Returns a character from the packet. */ 13420Sstevel@tonic-gate 13430Sstevel@tonic-gate u_int 13440Sstevel@tonic-gate packet_get_char(void) 13450Sstevel@tonic-gate { 13460Sstevel@tonic-gate char ch; 13470Sstevel@tonic-gate 13480Sstevel@tonic-gate buffer_get(&incoming_packet, &ch, 1); 13490Sstevel@tonic-gate return (u_char) ch; 13500Sstevel@tonic-gate } 13510Sstevel@tonic-gate 13520Sstevel@tonic-gate /* Returns an integer from the packet data. */ 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate u_int 13550Sstevel@tonic-gate packet_get_int(void) 13560Sstevel@tonic-gate { 13570Sstevel@tonic-gate return buffer_get_int(&incoming_packet); 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate /* 13610Sstevel@tonic-gate * Returns an arbitrary precision integer from the packet data. The integer 13620Sstevel@tonic-gate * must have been initialized before this call. 13630Sstevel@tonic-gate */ 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate void 13660Sstevel@tonic-gate packet_get_bignum(BIGNUM * value) 13670Sstevel@tonic-gate { 13680Sstevel@tonic-gate buffer_get_bignum(&incoming_packet, value); 13690Sstevel@tonic-gate } 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate void 13720Sstevel@tonic-gate packet_get_bignum2(BIGNUM * value) 13730Sstevel@tonic-gate { 13740Sstevel@tonic-gate buffer_get_bignum2(&incoming_packet, value); 13750Sstevel@tonic-gate } 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate void * 13780Sstevel@tonic-gate packet_get_raw(u_int *length_ptr) 13790Sstevel@tonic-gate { 13800Sstevel@tonic-gate u_int bytes = buffer_len(&incoming_packet); 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate if (length_ptr != NULL) 13830Sstevel@tonic-gate *length_ptr = bytes; 13840Sstevel@tonic-gate return buffer_ptr(&incoming_packet); 13850Sstevel@tonic-gate } 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate int 13880Sstevel@tonic-gate packet_remaining(void) 13890Sstevel@tonic-gate { 13900Sstevel@tonic-gate return buffer_len(&incoming_packet); 13910Sstevel@tonic-gate } 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate /* 13940Sstevel@tonic-gate * Returns a string from the packet data. The string is allocated using 13950Sstevel@tonic-gate * xmalloc; it is the responsibility of the calling program to free it when 13960Sstevel@tonic-gate * no longer needed. The length_ptr argument may be NULL, or point to an 13970Sstevel@tonic-gate * integer into which the length of the string is stored. 13980Sstevel@tonic-gate */ 13990Sstevel@tonic-gate 14000Sstevel@tonic-gate void * 14010Sstevel@tonic-gate packet_get_string(u_int *length_ptr) 14020Sstevel@tonic-gate { 14030Sstevel@tonic-gate return buffer_get_string(&incoming_packet, length_ptr); 14040Sstevel@tonic-gate } 14050Sstevel@tonic-gate char * 14060Sstevel@tonic-gate packet_get_ascii_cstring() 14070Sstevel@tonic-gate { 14080Sstevel@tonic-gate return buffer_get_ascii_cstring(&incoming_packet); 14090Sstevel@tonic-gate } 14100Sstevel@tonic-gate u_char * 14110Sstevel@tonic-gate packet_get_utf8_cstring() 14120Sstevel@tonic-gate { 14130Sstevel@tonic-gate return buffer_get_utf8_cstring(&incoming_packet); 14140Sstevel@tonic-gate } 14150Sstevel@tonic-gate 14160Sstevel@tonic-gate /* 14170Sstevel@tonic-gate * Sends a diagnostic message from the server to the client. This message 14180Sstevel@tonic-gate * can be sent at any time (but not while constructing another message). The 14190Sstevel@tonic-gate * message is printed immediately, but only if the client is being executed 14200Sstevel@tonic-gate * in verbose mode. These messages are primarily intended to ease debugging 14210Sstevel@tonic-gate * authentication problems. The length of the formatted message must not 14220Sstevel@tonic-gate * exceed 1024 bytes. This will automatically call packet_write_wait. 14230Sstevel@tonic-gate */ 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate void 14260Sstevel@tonic-gate packet_send_debug(const char *fmt,...) 14270Sstevel@tonic-gate { 14280Sstevel@tonic-gate char buf[1024]; 14290Sstevel@tonic-gate va_list args; 14300Sstevel@tonic-gate 14310Sstevel@tonic-gate if (compat20 && (datafellows & SSH_BUG_DEBUG)) 14320Sstevel@tonic-gate return; 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate va_start(args, fmt); 14350Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), gettext(fmt), args); 14360Sstevel@tonic-gate va_end(args); 14370Sstevel@tonic-gate 14380Sstevel@tonic-gate #ifdef ALTPRIVSEP 14390Sstevel@tonic-gate /* shouldn't happen */ 14400Sstevel@tonic-gate if (packet_monitor) { 14410Sstevel@tonic-gate debug("packet_send_debug: %s", buf); 14420Sstevel@tonic-gate return; 14430Sstevel@tonic-gate } 14440Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 14450Sstevel@tonic-gate 14460Sstevel@tonic-gate if (compat20) { 14470Sstevel@tonic-gate packet_start(SSH2_MSG_DEBUG); 14480Sstevel@tonic-gate packet_put_char(0); /* bool: always display */ 14490Sstevel@tonic-gate packet_put_cstring(buf); 14500Sstevel@tonic-gate packet_put_cstring(""); 14510Sstevel@tonic-gate } else { 14520Sstevel@tonic-gate packet_start(SSH_MSG_DEBUG); 14530Sstevel@tonic-gate packet_put_cstring(buf); 14540Sstevel@tonic-gate } 14550Sstevel@tonic-gate packet_send(); 14560Sstevel@tonic-gate packet_write_wait(); 14570Sstevel@tonic-gate } 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate /* 14600Sstevel@tonic-gate * Logs the error plus constructs and sends a disconnect packet, closes the 14610Sstevel@tonic-gate * connection, and exits. This function never returns. The error message 14620Sstevel@tonic-gate * should not contain a newline. The length of the formatted message must 14630Sstevel@tonic-gate * not exceed 1024 bytes. 14640Sstevel@tonic-gate */ 14650Sstevel@tonic-gate 14660Sstevel@tonic-gate void 14670Sstevel@tonic-gate packet_disconnect(const char *fmt,...) 14680Sstevel@tonic-gate { 14690Sstevel@tonic-gate char buf[1024]; 14700Sstevel@tonic-gate va_list args; 14710Sstevel@tonic-gate static int disconnecting = 0; 14720Sstevel@tonic-gate 14730Sstevel@tonic-gate if (disconnecting) /* Guard against recursive invocations. */ 14740Sstevel@tonic-gate fatal("packet_disconnect called recursively."); 14750Sstevel@tonic-gate disconnecting = 1; 14760Sstevel@tonic-gate 14770Sstevel@tonic-gate /* 14780Sstevel@tonic-gate * Format the message. Note that the caller must make sure the 14790Sstevel@tonic-gate * message is of limited size. 14800Sstevel@tonic-gate */ 14810Sstevel@tonic-gate va_start(args, fmt); 14820Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), fmt, args); 14830Sstevel@tonic-gate va_end(args); 14840Sstevel@tonic-gate 14850Sstevel@tonic-gate #ifdef ALTPRIVSEP 14860Sstevel@tonic-gate /* 14870Sstevel@tonic-gate * If we packet_disconnect() in the monitor the fatal cleanups will take 14880Sstevel@tonic-gate * care of the child. See main() in sshd.c. We don't send the packet 14890Sstevel@tonic-gate * disconnect message here because: a) the child might not be looking 14900Sstevel@tonic-gate * for it and b) because we don't really know if the child is compat20 14910Sstevel@tonic-gate * or not as we lost that information when packet_set_monitor() was 14920Sstevel@tonic-gate * called. 14930Sstevel@tonic-gate */ 14940Sstevel@tonic-gate if (packet_monitor) 14950Sstevel@tonic-gate goto close_stuff; 14960Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 14970Sstevel@tonic-gate 14980Sstevel@tonic-gate /* Send the disconnect message to the other side, and wait for it to get sent. */ 14990Sstevel@tonic-gate if (compat20) { 15000Sstevel@tonic-gate packet_start(SSH2_MSG_DISCONNECT); 15010Sstevel@tonic-gate packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 15020Sstevel@tonic-gate packet_put_cstring(buf); 15030Sstevel@tonic-gate packet_put_cstring(""); 15040Sstevel@tonic-gate } else { 15050Sstevel@tonic-gate packet_start(SSH_MSG_DISCONNECT); 15060Sstevel@tonic-gate packet_put_cstring(buf); 15070Sstevel@tonic-gate } 15080Sstevel@tonic-gate packet_send(); 15090Sstevel@tonic-gate packet_write_wait(); 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate #ifdef ALTPRIVSEP 15120Sstevel@tonic-gate close_stuff: 15130Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 15140Sstevel@tonic-gate /* Stop listening for connections. */ 15150Sstevel@tonic-gate channel_close_all(); 15160Sstevel@tonic-gate 15170Sstevel@tonic-gate /* Close the connection. */ 15180Sstevel@tonic-gate packet_close(); 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate /* Display the error locally and exit. */ 15210Sstevel@tonic-gate log("Disconnecting: %.100s", buf); 15220Sstevel@tonic-gate fatal_cleanup(); 15230Sstevel@tonic-gate } 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate /* Checks if there is any buffered output, and tries to write some of the output. */ 15260Sstevel@tonic-gate 15270Sstevel@tonic-gate void 15280Sstevel@tonic-gate packet_write_poll(void) 15290Sstevel@tonic-gate { 15300Sstevel@tonic-gate int len = buffer_len(&output); 15310Sstevel@tonic-gate 15320Sstevel@tonic-gate if (len > 0) { 15330Sstevel@tonic-gate len = write(connection_out, buffer_ptr(&output), len); 15340Sstevel@tonic-gate if (len <= 0) { 15350Sstevel@tonic-gate if (errno == EAGAIN) 15360Sstevel@tonic-gate return; 15370Sstevel@tonic-gate else 15380Sstevel@tonic-gate fatal("Write failed: %.100s", strerror(errno)); 15390Sstevel@tonic-gate } 15407574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 15417574SJan.Pechanec@Sun.COM debug("in packet_write_poll, %d bytes just sent to the " 15427574SJan.Pechanec@Sun.COM "remote side", len); 15437574SJan.Pechanec@Sun.COM #endif 15440Sstevel@tonic-gate buffer_consume(&output, len); 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate } 15470Sstevel@tonic-gate 15480Sstevel@tonic-gate /* 15490Sstevel@tonic-gate * Calls packet_write_poll repeatedly until all pending output data has been 15500Sstevel@tonic-gate * written. 15510Sstevel@tonic-gate */ 15520Sstevel@tonic-gate 15530Sstevel@tonic-gate void 15540Sstevel@tonic-gate packet_write_wait(void) 15550Sstevel@tonic-gate { 15560Sstevel@tonic-gate fd_set *setp; 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 15590Sstevel@tonic-gate sizeof(fd_mask)); 15600Sstevel@tonic-gate packet_write_poll(); 15610Sstevel@tonic-gate while (packet_have_data_to_write()) { 15620Sstevel@tonic-gate memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 15630Sstevel@tonic-gate sizeof(fd_mask)); 15640Sstevel@tonic-gate FD_SET(connection_out, setp); 15650Sstevel@tonic-gate while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 15660Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 15670Sstevel@tonic-gate ; 15680Sstevel@tonic-gate packet_write_poll(); 15690Sstevel@tonic-gate } 15700Sstevel@tonic-gate xfree(setp); 15710Sstevel@tonic-gate } 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate /* Returns true if there is buffered data to write to the connection. */ 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate int 15760Sstevel@tonic-gate packet_have_data_to_write(void) 15770Sstevel@tonic-gate { 15780Sstevel@tonic-gate return buffer_len(&output) != 0; 15790Sstevel@tonic-gate } 15800Sstevel@tonic-gate 15810Sstevel@tonic-gate /* Returns true if there is not too much data to write to the connection. */ 15820Sstevel@tonic-gate 15830Sstevel@tonic-gate int 15840Sstevel@tonic-gate packet_not_very_much_data_to_write(void) 15850Sstevel@tonic-gate { 15860Sstevel@tonic-gate if (interactive_mode) 15870Sstevel@tonic-gate return buffer_len(&output) < 16384; 15880Sstevel@tonic-gate else 15890Sstevel@tonic-gate return buffer_len(&output) < 128 * 1024; 15900Sstevel@tonic-gate } 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate /* Informs that the current session is interactive. Sets IP flags for that. */ 15930Sstevel@tonic-gate 15940Sstevel@tonic-gate void 15950Sstevel@tonic-gate packet_set_interactive(int interactive) 15960Sstevel@tonic-gate { 15970Sstevel@tonic-gate static int called = 0; 15980Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 15990Sstevel@tonic-gate int lowdelay = IPTOS_LOWDELAY; 16000Sstevel@tonic-gate int throughput = IPTOS_THROUGHPUT; 16010Sstevel@tonic-gate #endif 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate if (called) 16040Sstevel@tonic-gate return; 16050Sstevel@tonic-gate called = 1; 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate /* Record that we are in interactive mode. */ 16080Sstevel@tonic-gate interactive_mode = interactive; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate /* Only set socket options if using a socket. */ 16110Sstevel@tonic-gate if (!packet_connection_is_on_socket()) 16120Sstevel@tonic-gate return; 16130Sstevel@tonic-gate /* 16140Sstevel@tonic-gate * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only 16150Sstevel@tonic-gate */ 16160Sstevel@tonic-gate if (interactive) { 16170Sstevel@tonic-gate /* 16180Sstevel@tonic-gate * Set IP options for an interactive connection. Use 16190Sstevel@tonic-gate * IPTOS_LOWDELAY and TCP_NODELAY. 16200Sstevel@tonic-gate */ 16210Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 16220Sstevel@tonic-gate if (packet_connection_is_ipv4()) { 16230Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, 16240Sstevel@tonic-gate &lowdelay, sizeof(lowdelay)) < 0) 16250Sstevel@tonic-gate error("setsockopt IPTOS_LOWDELAY: %.100s", 16260Sstevel@tonic-gate strerror(errno)); 16270Sstevel@tonic-gate } 16280Sstevel@tonic-gate #endif 16290Sstevel@tonic-gate set_nodelay(connection_in); 16300Sstevel@tonic-gate } 16310Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 16320Sstevel@tonic-gate else if (packet_connection_is_ipv4()) { 16330Sstevel@tonic-gate /* 16340Sstevel@tonic-gate * Set IP options for a non-interactive connection. Use 16350Sstevel@tonic-gate * IPTOS_THROUGHPUT. 16360Sstevel@tonic-gate */ 16370Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, 16380Sstevel@tonic-gate sizeof(throughput)) < 0) 16390Sstevel@tonic-gate error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); 16400Sstevel@tonic-gate } 16410Sstevel@tonic-gate #endif 16420Sstevel@tonic-gate } 16430Sstevel@tonic-gate 16440Sstevel@tonic-gate /* Returns true if the current connection is interactive. */ 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate int 16470Sstevel@tonic-gate packet_is_interactive(void) 16480Sstevel@tonic-gate { 16490Sstevel@tonic-gate return interactive_mode; 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate 16520Sstevel@tonic-gate int 16530Sstevel@tonic-gate packet_set_maxsize(int s) 16540Sstevel@tonic-gate { 16550Sstevel@tonic-gate static int called = 0; 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate if (called) { 16580Sstevel@tonic-gate log("packet_set_maxsize: called twice: old %d new %d", 16590Sstevel@tonic-gate max_packet_size, s); 16600Sstevel@tonic-gate return -1; 16610Sstevel@tonic-gate } 16620Sstevel@tonic-gate if (s < 4 * 1024 || s > 1024 * 1024) { 16630Sstevel@tonic-gate log("packet_set_maxsize: bad size %d", s); 16640Sstevel@tonic-gate return -1; 16650Sstevel@tonic-gate } 16660Sstevel@tonic-gate called = 1; 16670Sstevel@tonic-gate debug("packet_set_maxsize: setting to %d", s); 16680Sstevel@tonic-gate max_packet_size = s; 16690Sstevel@tonic-gate return s; 16700Sstevel@tonic-gate } 16710Sstevel@tonic-gate 16720Sstevel@tonic-gate /* roundup current message to pad bytes */ 16730Sstevel@tonic-gate void 16740Sstevel@tonic-gate packet_add_padding(u_char pad) 16750Sstevel@tonic-gate { 16760Sstevel@tonic-gate extra_pad = pad; 16770Sstevel@tonic-gate } 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate /* 16800Sstevel@tonic-gate * 9.2. Ignored Data Message 16810Sstevel@tonic-gate * 16820Sstevel@tonic-gate * byte SSH_MSG_IGNORE 16830Sstevel@tonic-gate * string data 16840Sstevel@tonic-gate * 16850Sstevel@tonic-gate * All implementations MUST understand (and ignore) this message at any 16860Sstevel@tonic-gate * time (after receiving the protocol version). No implementation is 16870Sstevel@tonic-gate * required to send them. This message can be used as an additional 16880Sstevel@tonic-gate * protection measure against advanced traffic analysis techniques. 16890Sstevel@tonic-gate */ 16900Sstevel@tonic-gate void 16910Sstevel@tonic-gate packet_send_ignore(int nbytes) 16920Sstevel@tonic-gate { 16935562Sjp161948 u_int32_t rnd = 0; 16940Sstevel@tonic-gate int i; 16950Sstevel@tonic-gate 16960Sstevel@tonic-gate #ifdef ALTPRIVSEP 16970Sstevel@tonic-gate /* shouldn't happen -- see packet_set_monitor() */ 16980Sstevel@tonic-gate if (packet_monitor) 16990Sstevel@tonic-gate return; 17000Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 17010Sstevel@tonic-gate 17020Sstevel@tonic-gate packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 17030Sstevel@tonic-gate packet_put_int(nbytes); 17040Sstevel@tonic-gate for (i = 0; i < nbytes; i++) { 17050Sstevel@tonic-gate if (i % 4 == 0) 17065562Sjp161948 rnd = arc4random(); 17075562Sjp161948 packet_put_char((u_char)rnd & 0xff); 17085562Sjp161948 rnd >>= 8; 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate } 17110Sstevel@tonic-gate 17125562Sjp161948 #define MAX_PACKETS (1U<<31) 17135562Sjp161948 int 17145562Sjp161948 packet_need_rekeying(void) 17155562Sjp161948 { 17165562Sjp161948 if (datafellows & SSH_BUG_NOREKEY) 17175562Sjp161948 return 0; 17185562Sjp161948 return 17195562Sjp161948 (p_send.packets > MAX_PACKETS) || 17205562Sjp161948 (p_read.packets > MAX_PACKETS) || 17215562Sjp161948 (max_blocks_out && (p_send.blocks > max_blocks_out)) || 17225562Sjp161948 (max_blocks_in && (p_read.blocks > max_blocks_in)); 17235562Sjp161948 } 17245562Sjp161948 17255562Sjp161948 void 17265562Sjp161948 packet_set_rekey_limit(u_int32_t bytes) 17275562Sjp161948 { 17285562Sjp161948 rekey_limit = bytes; 17295562Sjp161948 } 17305562Sjp161948 17310Sstevel@tonic-gate #ifdef ALTPRIVSEP 17320Sstevel@tonic-gate void 17330Sstevel@tonic-gate packet_set_server(void) 17340Sstevel@tonic-gate { 17350Sstevel@tonic-gate packet_server = 1; 17360Sstevel@tonic-gate } 17370Sstevel@tonic-gate 17380Sstevel@tonic-gate int 17390Sstevel@tonic-gate packet_is_server(void) 17400Sstevel@tonic-gate { 17410Sstevel@tonic-gate return (packet_server); 17420Sstevel@tonic-gate } 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate void 17450Sstevel@tonic-gate packet_set_monitor(int pipe) 17460Sstevel@tonic-gate { 17470Sstevel@tonic-gate int dup_fd; 17480Sstevel@tonic-gate 17490Sstevel@tonic-gate packet_server = 1; 17500Sstevel@tonic-gate packet_monitor = 1; 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate /* 17530Sstevel@tonic-gate * Awful hack follows. 17540Sstevel@tonic-gate * 17550Sstevel@tonic-gate * For SSHv1 the monitor does not process any SSHv1 packets, only 17560Sstevel@tonic-gate * ALTPRIVSEP packets. We take advantage of that here to keep changes 17570Sstevel@tonic-gate * to packet.c to a minimum by using the SSHv2 binary packet protocol, 17580Sstevel@tonic-gate * with cipher "none," mac "none" and compression alg "none," as the 17590Sstevel@tonic-gate * basis for the monitor protocol. And so to force packet.c to treat 17600Sstevel@tonic-gate * packets as SSHv2 we force compat20 == 1 here. 17610Sstevel@tonic-gate * 17620Sstevel@tonic-gate * For completeness and to help future developers catch this we also 17630Sstevel@tonic-gate * force compat20 == 1 in the monitor loop, in serverloop.c. 17640Sstevel@tonic-gate */ 17650Sstevel@tonic-gate compat20 = 1; 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate /* 17680Sstevel@tonic-gate * NOTE: Assumptions below! 17690Sstevel@tonic-gate * 17700Sstevel@tonic-gate * - lots of packet.c code assumes that (connection_in == 17710Sstevel@tonic-gate * connection_out) -> connection is socket 17720Sstevel@tonic-gate * 17730Sstevel@tonic-gate * - packet_close() does not shutdown() the connection fildes 17740Sstevel@tonic-gate * if connection_in != connection_out 17750Sstevel@tonic-gate * 17760Sstevel@tonic-gate * - other code assumes the connection is a socket if 17770Sstevel@tonic-gate * connection_in == connection_out 17780Sstevel@tonic-gate */ 17790Sstevel@tonic-gate 17800Sstevel@tonic-gate if ((dup_fd = dup(pipe)) < 0) 17810Sstevel@tonic-gate fatal("Monitor failed to start: %s", strerror(errno)); 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate /* 17840Sstevel@tonic-gate * make sure that the monitor's child's socket is not shutdown(3SOCKET) 17857574SJan.Pechanec@Sun.COM * when we packet_close(). Setting connection_out to -1 will take care 17867574SJan.Pechanec@Sun.COM * of that. 17870Sstevel@tonic-gate */ 17880Sstevel@tonic-gate if (packet_connection_is_on_socket()) 17890Sstevel@tonic-gate connection_out = -1; 17900Sstevel@tonic-gate 17917574SJan.Pechanec@Sun.COM /* 17927574SJan.Pechanec@Sun.COM * Now clean up the state related to the server socket. As a side 17937574SJan.Pechanec@Sun.COM * effect, we also clean up existing cipher contexts that were 17947574SJan.Pechanec@Sun.COM * initialized with 'none' cipher in packet_set_connection(). That 17957574SJan.Pechanec@Sun.COM * function was called in the child server process shortly after the 17967574SJan.Pechanec@Sun.COM * master SSH process forked. However, all of that is reinialized again 17977574SJan.Pechanec@Sun.COM * by another packet_set_connection() call right below. 17987574SJan.Pechanec@Sun.COM */ 17990Sstevel@tonic-gate packet_close(); 18000Sstevel@tonic-gate 18017574SJan.Pechanec@Sun.COM /* 18027574SJan.Pechanec@Sun.COM * Now make the monitor pipe look like the ssh connection which means 18037574SJan.Pechanec@Sun.COM * that connection_in and connection_out will be set to the 18047574SJan.Pechanec@Sun.COM * communication pipe descriptors. 18057574SJan.Pechanec@Sun.COM */ 18060Sstevel@tonic-gate packet_set_connection(pipe, dup_fd); 18070Sstevel@tonic-gate } 18080Sstevel@tonic-gate 18097574SJan.Pechanec@Sun.COM /* 18107574SJan.Pechanec@Sun.COM * We temporarily need to set connection_in and connection_out descriptors so 18117574SJan.Pechanec@Sun.COM * that we can make use of existing code that gets the IP address and hostname 18127574SJan.Pechanec@Sun.COM * of the peer to write a login/logout record. It's not nice but we would have 18137574SJan.Pechanec@Sun.COM * to change more code when implementing the PKCS#11 engine support. 18147574SJan.Pechanec@Sun.COM */ 18157574SJan.Pechanec@Sun.COM void 18167574SJan.Pechanec@Sun.COM packet_set_fds(int fd, int restore) 18177574SJan.Pechanec@Sun.COM { 18187574SJan.Pechanec@Sun.COM static int stored_fd; 18197574SJan.Pechanec@Sun.COM 18207574SJan.Pechanec@Sun.COM if (stored_fd == 0 && restore == 0) { 18217574SJan.Pechanec@Sun.COM debug3("packet_set_fds: saving %d, installing %d", 18227574SJan.Pechanec@Sun.COM connection_in, fd); 18237574SJan.Pechanec@Sun.COM stored_fd = connection_in; 18247574SJan.Pechanec@Sun.COM /* we don't have a socket in inetd mode */ 18257574SJan.Pechanec@Sun.COM if (fd != -1) 18267574SJan.Pechanec@Sun.COM connection_in = connection_out = fd; 18277574SJan.Pechanec@Sun.COM return; 18287574SJan.Pechanec@Sun.COM } 18297574SJan.Pechanec@Sun.COM 18307574SJan.Pechanec@Sun.COM if (restore == 1) { 18317574SJan.Pechanec@Sun.COM debug3("restoring %d to connection_in/out", stored_fd); 18327574SJan.Pechanec@Sun.COM connection_in = connection_out = stored_fd; 18337574SJan.Pechanec@Sun.COM } 18347574SJan.Pechanec@Sun.COM } 18357574SJan.Pechanec@Sun.COM 18360Sstevel@tonic-gate int 18370Sstevel@tonic-gate packet_is_monitor(void) 18380Sstevel@tonic-gate { 18390Sstevel@tonic-gate return (packet_monitor); 18400Sstevel@tonic-gate } 18410Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1842