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" 67*7574SJan.Pechanec@Sun.COM #include "engine.h" 68*7574SJan.Pechanec@Sun.COM 69*7574SJan.Pechanec@Sun.COM /* PKCS#11 engine */ 70*7574SJan.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 83*7574SJan.Pechanec@Sun.COM static void packet_send2(void); 84*7574SJan.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 /* 157*7574SJan.Pechanec@Sun.COM * Part of what -f option and ~& escape sequence do in the client is that they 158*7574SJan.Pechanec@Sun.COM * will force it to daemonize itself. Due to the fork safety rules inherent in 159*7574SJan.Pechanec@Sun.COM * any PKCS#11 environment, if the engine is used we must do a key re-exchange 160*7574SJan.Pechanec@Sun.COM * before forking a child to negotiate the new keys. Those keys will be used to 161*7574SJan.Pechanec@Sun.COM * inicialize the new crypto contexts. This involves finishing the engine in the 162*7574SJan.Pechanec@Sun.COM * parent and reinitializing it again in both processes after fork() returns. 163*7574SJan.Pechanec@Sun.COM * This approach also leaves protocol 1 out since it doesn't support rekeying. 164*7574SJan.Pechanec@Sun.COM */ 165*7574SJan.Pechanec@Sun.COM int will_daemonize; 166*7574SJan.Pechanec@Sun.COM 167*7574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 168*7574SJan.Pechanec@Sun.COM /* This function dumps data onto stderr. This is for debugging only. */ 169*7574SJan.Pechanec@Sun.COM void 170*7574SJan.Pechanec@Sun.COM data_dump(void *data, u_int len) 171*7574SJan.Pechanec@Sun.COM { 172*7574SJan.Pechanec@Sun.COM Buffer buf; 173*7574SJan.Pechanec@Sun.COM 174*7574SJan.Pechanec@Sun.COM buffer_init(&buf); 175*7574SJan.Pechanec@Sun.COM buffer_append(&buf, data, len); 176*7574SJan.Pechanec@Sun.COM buffer_dump(&buf); 177*7574SJan.Pechanec@Sun.COM buffer_free(&buf); 178*7574SJan.Pechanec@Sun.COM } 179*7574SJan.Pechanec@Sun.COM #endif 180*7574SJan.Pechanec@Sun.COM 181*7574SJan.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 552*7574SJan.Pechanec@Sun.COM debug("encrypted output queue now contains (%d bytes):\n", 553*7574SJan.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 } 589*7574SJan.Pechanec@Sun.COM 590*7574SJan.Pechanec@Sun.COM debug("set_newkeys: setting new keys for '%s' mode", 591*7574SJan.Pechanec@Sun.COM mode == MODE_IN ? "in" : "out"); 592*7574SJan.Pechanec@Sun.COM 5930Sstevel@tonic-gate if (newkeys[mode] != NULL) { 5940Sstevel@tonic-gate cipher_cleanup(cc); 5955562Sjp161948 free_keys(newkeys[mode]); 5960Sstevel@tonic-gate } 597*7574SJan.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; 606*7574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 607*7574SJan.Pechanec@Sun.COM debug("new encryption key:\n"); 608*7574SJan.Pechanec@Sun.COM data_dump(enc->key, enc->key_len); 609*7574SJan.Pechanec@Sun.COM debug("new encryption IV:\n"); 610*7574SJan.Pechanec@Sun.COM data_dump(enc->iv, enc->block_size); 611*7574SJan.Pechanec@Sun.COM debug("new MAC key:\n"); 612*7574SJan.Pechanec@Sun.COM data_dump(mac->key, mac->key_len); 613*7574SJan.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 /* 685*7574SJan.Pechanec@Sun.COM * Process SSH2_MSG_NEWKEYS message. If we are using the engine we must have 686*7574SJan.Pechanec@Sun.COM * both SSH2_MSG_NEWKEYS processed before we can finish the engine, fork, and 687*7574SJan.Pechanec@Sun.COM * reinitialize the crypto contexts. We can't fork before processing the 2nd 688*7574SJan.Pechanec@Sun.COM * message otherwise we couldn't encrypt/decrypt that message at all - note that 689*7574SJan.Pechanec@Sun.COM * parent's PKCS#11 sessions are useless after the fork and we must process 690*7574SJan.Pechanec@Sun.COM * both SSH2_MSG_NEWKEYS messages using the old keys. 691*7574SJan.Pechanec@Sun.COM */ 692*7574SJan.Pechanec@Sun.COM void 693*7574SJan.Pechanec@Sun.COM process_newkeys(int mode) 694*7574SJan.Pechanec@Sun.COM { 695*7574SJan.Pechanec@Sun.COM if (packet_is_server() != 0) 696*7574SJan.Pechanec@Sun.COM return; 697*7574SJan.Pechanec@Sun.COM 698*7574SJan.Pechanec@Sun.COM if (will_daemonize == FIRST_NEWKEYS_PROCESSED) { 699*7574SJan.Pechanec@Sun.COM debug3("both SSH2_MSG_NEWKEYS processed, will daemonize now"); 700*7574SJan.Pechanec@Sun.COM cipher_cleanup(&send_context); 701*7574SJan.Pechanec@Sun.COM cipher_cleanup(&receive_context); 702*7574SJan.Pechanec@Sun.COM pkcs11_engine_finish(e); 703*7574SJan.Pechanec@Sun.COM if (daemon(1, 1) < 0) { 704*7574SJan.Pechanec@Sun.COM fatal("daemon() failed: %.200s", 705*7574SJan.Pechanec@Sun.COM strerror(errno)); 706*7574SJan.Pechanec@Sun.COM } 707*7574SJan.Pechanec@Sun.COM e = pkcs11_engine_load(e != NULL ? 1 : 0); 708*7574SJan.Pechanec@Sun.COM 709*7574SJan.Pechanec@Sun.COM set_newkeys(MODE_OUT); 710*7574SJan.Pechanec@Sun.COM set_newkeys(MODE_IN); 711*7574SJan.Pechanec@Sun.COM will_daemonize = SECOND_NEWKEYS_PROCESSED; 712*7574SJan.Pechanec@Sun.COM packet_send2(); 713*7574SJan.Pechanec@Sun.COM } else { 714*7574SJan.Pechanec@Sun.COM if (will_daemonize == DAEMONIZING_REQUESTED) 715*7574SJan.Pechanec@Sun.COM will_daemonize = FIRST_NEWKEYS_PROCESSED; 716*7574SJan.Pechanec@Sun.COM else 717*7574SJan.Pechanec@Sun.COM set_newkeys(mode); 718*7574SJan.Pechanec@Sun.COM } 719*7574SJan.Pechanec@Sun.COM } 720*7574SJan.Pechanec@Sun.COM 721*7574SJan.Pechanec@Sun.COM /* 7220Sstevel@tonic-gate * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 7230Sstevel@tonic-gate */ 7240Sstevel@tonic-gate static void 7255562Sjp161948 packet_send2_wrapped(void) 7260Sstevel@tonic-gate { 7270Sstevel@tonic-gate u_char type, *cp, *macbuf = NULL; 7280Sstevel@tonic-gate u_char padlen, pad; 7290Sstevel@tonic-gate u_int packet_length = 0; 7300Sstevel@tonic-gate u_int i, len; 7315562Sjp161948 u_int32_t rnd = 0; 7320Sstevel@tonic-gate Enc *enc = NULL; 7330Sstevel@tonic-gate Mac *mac = NULL; 7340Sstevel@tonic-gate Comp *comp = NULL; 7350Sstevel@tonic-gate int block_size; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate if (newkeys[MODE_OUT] != NULL) { 7380Sstevel@tonic-gate enc = &newkeys[MODE_OUT]->enc; 7390Sstevel@tonic-gate mac = &newkeys[MODE_OUT]->mac; 7400Sstevel@tonic-gate comp = &newkeys[MODE_OUT]->comp; 7410Sstevel@tonic-gate } 7420Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 7450Sstevel@tonic-gate type = cp[5]; 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate #ifdef PACKET_DEBUG 748*7574SJan.Pechanec@Sun.COM debug("plain output packet to be processed (%d bytes):\n", 749*7574SJan.Pechanec@Sun.COM buffer_len(&outgoing_packet)); 7500Sstevel@tonic-gate buffer_dump(&outgoing_packet); 7510Sstevel@tonic-gate #endif 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate if (comp && comp->enabled) { 7540Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 7550Sstevel@tonic-gate /* skip header, compress only payload */ 7560Sstevel@tonic-gate buffer_consume(&outgoing_packet, 5); 7570Sstevel@tonic-gate buffer_clear(&compression_buffer); 7580Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 7590Sstevel@tonic-gate buffer_clear(&outgoing_packet); 7600Sstevel@tonic-gate buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 7610Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 7620Sstevel@tonic-gate buffer_len(&compression_buffer)); 7630Sstevel@tonic-gate DBG(debug("compression: raw %d compressed %d", len, 7640Sstevel@tonic-gate buffer_len(&outgoing_packet))); 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate /* sizeof (packet_len + pad_len + payload) */ 7680Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* 7710Sstevel@tonic-gate * calc size of padding, alloc space, get random data, 7720Sstevel@tonic-gate * minimum padding is 4 bytes 7730Sstevel@tonic-gate */ 7740Sstevel@tonic-gate padlen = block_size - (len % block_size); 7750Sstevel@tonic-gate if (padlen < 4) 7760Sstevel@tonic-gate padlen += block_size; 7770Sstevel@tonic-gate if (extra_pad) { 7780Sstevel@tonic-gate /* will wrap if extra_pad+padlen > 255 */ 7790Sstevel@tonic-gate extra_pad = roundup(extra_pad, block_size); 7800Sstevel@tonic-gate pad = extra_pad - ((len + padlen) % extra_pad); 7810Sstevel@tonic-gate debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 7820Sstevel@tonic-gate pad, len, padlen, extra_pad); 7830Sstevel@tonic-gate padlen += pad; 7840Sstevel@tonic-gate extra_pad = 0; 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate cp = buffer_append_space(&outgoing_packet, padlen); 7870Sstevel@tonic-gate if (enc && !send_context.plaintext) { 7880Sstevel@tonic-gate /* random padding */ 7890Sstevel@tonic-gate for (i = 0; i < padlen; i++) { 7900Sstevel@tonic-gate if (i % 4 == 0) 7915562Sjp161948 rnd = arc4random(); 7925562Sjp161948 cp[i] = rnd & 0xff; 7935562Sjp161948 rnd >>= 8; 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate } else { 7960Sstevel@tonic-gate /* clear padding */ 7970Sstevel@tonic-gate memset(cp, 0, padlen); 7980Sstevel@tonic-gate } 7990Sstevel@tonic-gate /* packet_length includes payload, padding and padding length field */ 8000Sstevel@tonic-gate packet_length = buffer_len(&outgoing_packet) - 4; 8010Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 8020Sstevel@tonic-gate PUT_32BIT(cp, packet_length); 8030Sstevel@tonic-gate cp[4] = padlen; 804*7574SJan.Pechanec@Sun.COM DBG(debug("will send %d bytes (includes padlen %d)", 805*7574SJan.Pechanec@Sun.COM packet_length + 4, padlen)); 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate /* compute MAC over seqnr and packet(length fields, payload, padding) */ 8080Sstevel@tonic-gate if (mac && mac->enabled) { 8095562Sjp161948 macbuf = mac_compute(mac, p_send.seqnr, 8100Sstevel@tonic-gate buffer_ptr(&outgoing_packet), 8110Sstevel@tonic-gate buffer_len(&outgoing_packet)); 8125562Sjp161948 DBG(debug("done calc MAC out #%d", p_send.seqnr)); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate /* encrypt packet and append to output buffer. */ 8150Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 8160Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 8170Sstevel@tonic-gate buffer_len(&outgoing_packet)); 8180Sstevel@tonic-gate /* append unencrypted MAC */ 8190Sstevel@tonic-gate if (mac && mac->enabled) 8200Sstevel@tonic-gate buffer_append(&output, (char *)macbuf, mac->mac_len); 8210Sstevel@tonic-gate #ifdef PACKET_DEBUG 822*7574SJan.Pechanec@Sun.COM debug("encrypted output queue now contains (%d bytes):\n", 823*7574SJan.Pechanec@Sun.COM buffer_len(&output)); 8240Sstevel@tonic-gate buffer_dump(&output); 8250Sstevel@tonic-gate #endif 8260Sstevel@tonic-gate /* increment sequence number for outgoing packets */ 8275562Sjp161948 if (++p_send.seqnr == 0) 8280Sstevel@tonic-gate log("outgoing seqnr wraps around"); 8295562Sjp161948 8305562Sjp161948 /* 8315562Sjp161948 * RFC 4344: 3.1. First Rekeying Recommendation 8325562Sjp161948 * 8335562Sjp161948 * "Because of possible information leakage through the MAC tag after a 8345562Sjp161948 * key exchange, .... an SSH implementation SHOULD NOT send more than 8355562Sjp161948 * 2**32 packets before rekeying again." 8365562Sjp161948 * 8375562Sjp161948 * The code below is a hard check so that we are sure we don't go across 8385562Sjp161948 * the suggestion. However, since the largest cipher block size we have 8395562Sjp161948 * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the 8405562Sjp161948 * same key while performing periodic rekeying. 8415562Sjp161948 */ 8425562Sjp161948 if (++p_send.packets == 0) 8435562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 8445562Sjp161948 fatal("too many packets encrypted with same key"); 8455562Sjp161948 p_send.blocks += (packet_length + 4) / block_size; 8460Sstevel@tonic-gate buffer_clear(&outgoing_packet); 8470Sstevel@tonic-gate 848*7574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_NEWKEYS) { 849*7574SJan.Pechanec@Sun.COM /* 850*7574SJan.Pechanec@Sun.COM * set_newkeys(MODE_OUT) in the client. Note that in the 851*7574SJan.Pechanec@Sun.COM * unprivileged child, set_newkeys() for MODE_OUT are set after 852*7574SJan.Pechanec@Sun.COM * SSH2_MSG_NEWKEYS is read from the monitor and forwarded to 853*7574SJan.Pechanec@Sun.COM * the client side. 854*7574SJan.Pechanec@Sun.COM */ 855*7574SJan.Pechanec@Sun.COM process_newkeys(MODE_OUT); 856*7574SJan.Pechanec@Sun.COM } 8570Sstevel@tonic-gate } 8580Sstevel@tonic-gate 859*7574SJan.Pechanec@Sun.COM /* 860*7574SJan.Pechanec@Sun.COM * Packets we deal with here are plain until we encrypt them in 861*7574SJan.Pechanec@Sun.COM * packet_send2_wrapped(). 862*7574SJan.Pechanec@Sun.COM * 863*7574SJan.Pechanec@Sun.COM * As already mentioned in a comment at process_newkeys() function we must not 864*7574SJan.Pechanec@Sun.COM * fork() until both SSH2_MSG_NEWKEYS packets were processed. Until this is done 865*7574SJan.Pechanec@Sun.COM * we must queue all packets so that they can be encrypted with the new keys and 866*7574SJan.Pechanec@Sun.COM * then sent to the other side. However, what can happen here is that we get 867*7574SJan.Pechanec@Sun.COM * SSH2_MSG_NEWKEYS after we sent it. In that situation we must call 868*7574SJan.Pechanec@Sun.COM * packet_send2() anyway to empty the queue, and set the rekey flag to the 869*7574SJan.Pechanec@Sun.COM * finished state. If we didn't do that we would just hang and enqueue data. 870*7574SJan.Pechanec@Sun.COM */ 8715562Sjp161948 static void 8725562Sjp161948 packet_send2(void) 8735562Sjp161948 { 8745562Sjp161948 static int rekeying = 0; 8755562Sjp161948 struct packet *p; 8765562Sjp161948 u_char type, *cp; 8775562Sjp161948 878*7574SJan.Pechanec@Sun.COM if (will_daemonize != SECOND_NEWKEYS_PROCESSED) { 879*7574SJan.Pechanec@Sun.COM cp = buffer_ptr(&outgoing_packet); 880*7574SJan.Pechanec@Sun.COM type = cp[5]; 8815562Sjp161948 882*7574SJan.Pechanec@Sun.COM /* during rekeying we can only send key exchange messages */ 883*7574SJan.Pechanec@Sun.COM if (rekeying) { 884*7574SJan.Pechanec@Sun.COM if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 885*7574SJan.Pechanec@Sun.COM (type <= SSH2_MSG_TRANSPORT_MAX))) { 886*7574SJan.Pechanec@Sun.COM debug("enqueue a plain packet because rekex in " 887*7574SJan.Pechanec@Sun.COM "progress [type %u]", type); 888*7574SJan.Pechanec@Sun.COM p = xmalloc(sizeof(*p)); 889*7574SJan.Pechanec@Sun.COM p->type = type; 890*7574SJan.Pechanec@Sun.COM memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 891*7574SJan.Pechanec@Sun.COM buffer_init(&outgoing_packet); 892*7574SJan.Pechanec@Sun.COM TAILQ_INSERT_TAIL(&outgoing, p, next); 893*7574SJan.Pechanec@Sun.COM return; 894*7574SJan.Pechanec@Sun.COM } 8955562Sjp161948 } 896*7574SJan.Pechanec@Sun.COM 897*7574SJan.Pechanec@Sun.COM /* rekeying starts with sending KEXINIT */ 898*7574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_KEXINIT) 899*7574SJan.Pechanec@Sun.COM rekeying = 1; 900*7574SJan.Pechanec@Sun.COM 901*7574SJan.Pechanec@Sun.COM packet_send2_wrapped(); 9025562Sjp161948 } 9035562Sjp161948 904*7574SJan.Pechanec@Sun.COM /* after rekex is done we can process the queue of plain packets */ 905*7574SJan.Pechanec@Sun.COM if (will_daemonize == SECOND_NEWKEYS_PROCESSED || 906*7574SJan.Pechanec@Sun.COM (will_daemonize == NOT_DAEMONIZING && type == SSH2_MSG_NEWKEYS)) { 9075562Sjp161948 rekeying = 0; 908*7574SJan.Pechanec@Sun.COM will_daemonize = NOT_DAEMONIZING; 9095562Sjp161948 while ((p = TAILQ_FIRST(&outgoing)) != NULL) { 9105562Sjp161948 type = p->type; 911*7574SJan.Pechanec@Sun.COM debug("dequeuing a plain packet since rekex is over " 912*7574SJan.Pechanec@Sun.COM "[type %u]", type); 9135562Sjp161948 buffer_free(&outgoing_packet); 9145562Sjp161948 memcpy(&outgoing_packet, &p->payload, sizeof(Buffer)); 9155562Sjp161948 TAILQ_REMOVE(&outgoing, p, next); 9165562Sjp161948 xfree(p); 9175562Sjp161948 packet_send2_wrapped(); 9185562Sjp161948 } 9195562Sjp161948 } 9205562Sjp161948 } 9215562Sjp161948 9220Sstevel@tonic-gate void 9230Sstevel@tonic-gate packet_send(void) 9240Sstevel@tonic-gate { 9250Sstevel@tonic-gate if (compat20) 9260Sstevel@tonic-gate packet_send2(); 9270Sstevel@tonic-gate else 9280Sstevel@tonic-gate packet_send1(); 9290Sstevel@tonic-gate DBG(debug("packet_send done")); 9300Sstevel@tonic-gate } 9310Sstevel@tonic-gate 9320Sstevel@tonic-gate /* 9330Sstevel@tonic-gate * Waits until a packet has been received, and returns its type. Note that 9340Sstevel@tonic-gate * no other data is processed until this returns, so this function should not 9350Sstevel@tonic-gate * be used during the interactive session. 9360Sstevel@tonic-gate */ 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate int 9390Sstevel@tonic-gate packet_read_seqnr(u_int32_t *seqnr_p) 9400Sstevel@tonic-gate { 9410Sstevel@tonic-gate int type, len; 9420Sstevel@tonic-gate fd_set *setp; 9430Sstevel@tonic-gate char buf[8192]; 9440Sstevel@tonic-gate DBG(debug("packet_read()")); 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 9470Sstevel@tonic-gate sizeof(fd_mask)); 9480Sstevel@tonic-gate 9490Sstevel@tonic-gate /* Since we are blocking, ensure that all written packets have been sent. */ 9500Sstevel@tonic-gate packet_write_wait(); 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate /* Stay in the loop until we have received a complete packet. */ 9530Sstevel@tonic-gate for (;;) { 9540Sstevel@tonic-gate /* Try to read a packet from the buffer. */ 9550Sstevel@tonic-gate type = packet_read_poll_seqnr(seqnr_p); 9560Sstevel@tonic-gate if (!compat20 && ( 9570Sstevel@tonic-gate type == SSH_SMSG_SUCCESS 9580Sstevel@tonic-gate || type == SSH_SMSG_FAILURE 9590Sstevel@tonic-gate || type == SSH_CMSG_EOF 9600Sstevel@tonic-gate || type == SSH_CMSG_EXIT_CONFIRMATION)) 9610Sstevel@tonic-gate packet_check_eom(); 9620Sstevel@tonic-gate /* If we got a packet, return it. */ 9630Sstevel@tonic-gate if (type != SSH_MSG_NONE) { 9640Sstevel@tonic-gate xfree(setp); 9650Sstevel@tonic-gate return type; 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate /* 9680Sstevel@tonic-gate * Otherwise, wait for some data to arrive, add it to the 9690Sstevel@tonic-gate * buffer, and try again. 9700Sstevel@tonic-gate */ 9710Sstevel@tonic-gate memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 9720Sstevel@tonic-gate sizeof(fd_mask)); 9730Sstevel@tonic-gate FD_SET(connection_in, setp); 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate /* Wait for some data to arrive. */ 9760Sstevel@tonic-gate while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 9770Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 9780Sstevel@tonic-gate ; 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate /* Read data from the socket. */ 9810Sstevel@tonic-gate len = read(connection_in, buf, sizeof(buf)); 9820Sstevel@tonic-gate if (len == 0) { 9830Sstevel@tonic-gate log("Connection closed by %.200s", get_remote_ipaddr()); 9840Sstevel@tonic-gate fatal_cleanup(); 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate if (len < 0) 9870Sstevel@tonic-gate fatal("Read from socket failed: %.100s", strerror(errno)); 9880Sstevel@tonic-gate /* Append it to the buffer. */ 9890Sstevel@tonic-gate packet_process_incoming(buf, len); 9900Sstevel@tonic-gate } 9910Sstevel@tonic-gate /* NOTREACHED */ 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate int 9950Sstevel@tonic-gate packet_read(void) 9960Sstevel@tonic-gate { 9970Sstevel@tonic-gate return packet_read_seqnr(NULL); 9980Sstevel@tonic-gate } 9990Sstevel@tonic-gate 10000Sstevel@tonic-gate /* 10010Sstevel@tonic-gate * Waits until a packet has been received, verifies that its type matches 10020Sstevel@tonic-gate * that given, and gives a fatal error and exits if there is a mismatch. 10030Sstevel@tonic-gate */ 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate void 10060Sstevel@tonic-gate packet_read_expect(int expected_type) 10070Sstevel@tonic-gate { 10080Sstevel@tonic-gate int type; 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate type = packet_read(); 10110Sstevel@tonic-gate if (type != expected_type) 10120Sstevel@tonic-gate packet_disconnect("Protocol error: expected packet type %d, got %d", 10130Sstevel@tonic-gate expected_type, type); 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate /* Checks if a full packet is available in the data received so far via 10170Sstevel@tonic-gate * packet_process_incoming. If so, reads the packet; otherwise returns 10180Sstevel@tonic-gate * SSH_MSG_NONE. This does not wait for data from the connection. 10190Sstevel@tonic-gate * 10200Sstevel@tonic-gate * SSH_MSG_DISCONNECT is handled specially here. Also, 10210Sstevel@tonic-gate * SSH_MSG_IGNORE messages are skipped by this function and are never returned 10220Sstevel@tonic-gate * to higher levels. 10230Sstevel@tonic-gate */ 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate static int 10260Sstevel@tonic-gate packet_read_poll1(void) 10270Sstevel@tonic-gate { 10280Sstevel@tonic-gate u_int len, padded_len; 10290Sstevel@tonic-gate u_char *cp, type; 10300Sstevel@tonic-gate u_int checksum, stored_checksum; 10310Sstevel@tonic-gate 10320Sstevel@tonic-gate /* Check if input size is less than minimum packet size. */ 10330Sstevel@tonic-gate if (buffer_len(&input) < 4 + 8) 10340Sstevel@tonic-gate return SSH_MSG_NONE; 10350Sstevel@tonic-gate /* Get length of incoming packet. */ 10360Sstevel@tonic-gate cp = buffer_ptr(&input); 10370Sstevel@tonic-gate len = GET_32BIT(cp); 10380Sstevel@tonic-gate if (len < 1 + 2 + 2 || len > 256 * 1024) 10390Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", len); 10400Sstevel@tonic-gate padded_len = (len + 8) & ~7; 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate /* Check if the packet has been entirely received. */ 10430Sstevel@tonic-gate if (buffer_len(&input) < 4 + padded_len) 10440Sstevel@tonic-gate return SSH_MSG_NONE; 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate /* The entire packet is in buffer. */ 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate /* Consume packet length. */ 10490Sstevel@tonic-gate buffer_consume(&input, 4); 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate /* 10520Sstevel@tonic-gate * Cryptographic attack detector for ssh 10530Sstevel@tonic-gate * (C)1998 CORE-SDI, Buenos Aires Argentina 10540Sstevel@tonic-gate * Ariel Futoransky(futo@core-sdi.com) 10550Sstevel@tonic-gate */ 10563102Sjp161948 if (!receive_context.plaintext) { 10573102Sjp161948 switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) { 10583102Sjp161948 case DEATTACK_DETECTED: 10593102Sjp161948 packet_disconnect("crc32 compensation attack: " 10603102Sjp161948 "network attack detected"); 10613102Sjp161948 break; 10623102Sjp161948 case DEATTACK_DOS_DETECTED: 10633102Sjp161948 packet_disconnect("deattack denial of " 10643102Sjp161948 "service detected"); 10653102Sjp161948 break; 10663102Sjp161948 } 10673102Sjp161948 } 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate /* Decrypt data to incoming_packet. */ 10700Sstevel@tonic-gate buffer_clear(&incoming_packet); 10710Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, padded_len); 10720Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate buffer_consume(&input, padded_len); 10750Sstevel@tonic-gate 10760Sstevel@tonic-gate #ifdef PACKET_DEBUG 1077*7574SJan.Pechanec@Sun.COM debug("read_poll plain/full:\n"); 10780Sstevel@tonic-gate buffer_dump(&incoming_packet); 10790Sstevel@tonic-gate #endif 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate /* Compute packet checksum. */ 10820Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&incoming_packet), 10830Sstevel@tonic-gate buffer_len(&incoming_packet) - 4); 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate /* Skip padding. */ 10860Sstevel@tonic-gate buffer_consume(&incoming_packet, 8 - len % 8); 10870Sstevel@tonic-gate 10880Sstevel@tonic-gate /* Test check bytes. */ 10890Sstevel@tonic-gate if (len != buffer_len(&incoming_packet)) 10900Sstevel@tonic-gate packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 10910Sstevel@tonic-gate len, buffer_len(&incoming_packet)); 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 10940Sstevel@tonic-gate stored_checksum = GET_32BIT(cp); 10950Sstevel@tonic-gate if (checksum != stored_checksum) 10960Sstevel@tonic-gate packet_disconnect("Corrupted check bytes on input."); 10970Sstevel@tonic-gate buffer_consume_end(&incoming_packet, 4); 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate if (packet_compression) { 11000Sstevel@tonic-gate buffer_clear(&compression_buffer); 11010Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 11020Sstevel@tonic-gate buffer_clear(&incoming_packet); 11030Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 11040Sstevel@tonic-gate buffer_len(&compression_buffer)); 11050Sstevel@tonic-gate } 11060Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 11070Sstevel@tonic-gate return type; 11080Sstevel@tonic-gate } 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate static int 11110Sstevel@tonic-gate packet_read_poll2(u_int32_t *seqnr_p) 11120Sstevel@tonic-gate { 11130Sstevel@tonic-gate static u_int packet_length = 0; 11140Sstevel@tonic-gate u_int padlen, need; 11150Sstevel@tonic-gate u_char *macbuf, *cp, type; 11160Sstevel@tonic-gate int maclen, block_size; 11170Sstevel@tonic-gate Enc *enc = NULL; 11180Sstevel@tonic-gate Mac *mac = NULL; 11190Sstevel@tonic-gate Comp *comp = NULL; 11200Sstevel@tonic-gate 11210Sstevel@tonic-gate if (newkeys[MODE_IN] != NULL) { 11220Sstevel@tonic-gate enc = &newkeys[MODE_IN]->enc; 11230Sstevel@tonic-gate mac = &newkeys[MODE_IN]->mac; 11240Sstevel@tonic-gate comp = &newkeys[MODE_IN]->comp; 11250Sstevel@tonic-gate } 11260Sstevel@tonic-gate maclen = mac && mac->enabled ? mac->mac_len : 0; 11270Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 11280Sstevel@tonic-gate 11290Sstevel@tonic-gate if (packet_length == 0) { 11300Sstevel@tonic-gate /* 11310Sstevel@tonic-gate * check if input size is less than the cipher block size, 11320Sstevel@tonic-gate * decrypt first block and extract length of incoming packet 11330Sstevel@tonic-gate */ 11340Sstevel@tonic-gate if (buffer_len(&input) < block_size) 11350Sstevel@tonic-gate return SSH_MSG_NONE; 1136*7574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 1137*7574SJan.Pechanec@Sun.COM debug("encrypted data we have in read queue (%d bytes):\n", 1138*7574SJan.Pechanec@Sun.COM buffer_len(&input)); 1139*7574SJan.Pechanec@Sun.COM buffer_dump(&input); 1140*7574SJan.Pechanec@Sun.COM #endif 11410Sstevel@tonic-gate buffer_clear(&incoming_packet); 11420Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, block_size); 11430Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), 11440Sstevel@tonic-gate block_size); 11450Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 11460Sstevel@tonic-gate packet_length = GET_32BIT(cp); 11470Sstevel@tonic-gate if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1148*7574SJan.Pechanec@Sun.COM error("bad packet length %d; i/o counters " 1149*7574SJan.Pechanec@Sun.COM "%llu/%llu", packet_length, 1150*7574SJan.Pechanec@Sun.COM p_read.blocks * block_size, 1151*7574SJan.Pechanec@Sun.COM p_send.blocks * block_size); 1152*7574SJan.Pechanec@Sun.COM error("decrypted %d bytes follows:\n", block_size); 11530Sstevel@tonic-gate buffer_dump(&incoming_packet); 1154*7574SJan.Pechanec@Sun.COM packet_disconnect("Bad packet length %d, i/o counters " 1155*7574SJan.Pechanec@Sun.COM "%llu/%llu.", packet_length, 1156*7574SJan.Pechanec@Sun.COM p_read.blocks * block_size, 1157*7574SJan.Pechanec@Sun.COM p_send.blocks * block_size); 11580Sstevel@tonic-gate } 11595562Sjp161948 DBG(debug("input: packet len %u", packet_length + 4)); 11600Sstevel@tonic-gate buffer_consume(&input, block_size); 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate /* we have a partial packet of block_size bytes */ 11630Sstevel@tonic-gate need = 4 + packet_length - block_size; 1164*7574SJan.Pechanec@Sun.COM DBG(debug("partial packet %d, still need %d, maclen %d", block_size, 11650Sstevel@tonic-gate need, maclen)); 11660Sstevel@tonic-gate if (need % block_size != 0) 11670Sstevel@tonic-gate fatal("padding error: need %d block %d mod %d", 11680Sstevel@tonic-gate need, block_size, need % block_size); 11690Sstevel@tonic-gate /* 11700Sstevel@tonic-gate * check if the entire packet has been received and 11710Sstevel@tonic-gate * decrypt into incoming_packet 11720Sstevel@tonic-gate */ 11730Sstevel@tonic-gate if (buffer_len(&input) < need + maclen) 11740Sstevel@tonic-gate return SSH_MSG_NONE; 11750Sstevel@tonic-gate #ifdef PACKET_DEBUG 1176*7574SJan.Pechanec@Sun.COM debug("in read_poll, the encrypted input queue now contains " 1177*7574SJan.Pechanec@Sun.COM "(%d bytes):\n", buffer_len(&input)); 11780Sstevel@tonic-gate buffer_dump(&input); 11790Sstevel@tonic-gate #endif 11800Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, need); 11810Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 11820Sstevel@tonic-gate buffer_consume(&input, need); 11830Sstevel@tonic-gate /* 11840Sstevel@tonic-gate * compute MAC over seqnr and packet, 11850Sstevel@tonic-gate * increment sequence number for incoming packet 11860Sstevel@tonic-gate */ 11870Sstevel@tonic-gate if (mac && mac->enabled) { 11885562Sjp161948 macbuf = mac_compute(mac, p_read.seqnr, 11890Sstevel@tonic-gate buffer_ptr(&incoming_packet), 11900Sstevel@tonic-gate buffer_len(&incoming_packet)); 11910Sstevel@tonic-gate if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 11920Sstevel@tonic-gate packet_disconnect("Corrupted MAC on input."); 11935562Sjp161948 DBG(debug("MAC #%d ok", p_read.seqnr)); 11940Sstevel@tonic-gate buffer_consume(&input, mac->mac_len); 11950Sstevel@tonic-gate } 11960Sstevel@tonic-gate if (seqnr_p != NULL) 11975562Sjp161948 *seqnr_p = p_read.seqnr; 11985562Sjp161948 if (++p_read.seqnr == 0) 11990Sstevel@tonic-gate log("incoming seqnr wraps around"); 12000Sstevel@tonic-gate 12015562Sjp161948 /* see above for the comment on "First Rekeying Recommendation" */ 12025562Sjp161948 if (++p_read.packets == 0) 12035562Sjp161948 if (!(datafellows & SSH_BUG_NOREKEY)) 12045562Sjp161948 fatal("too many packets with same key"); 12055562Sjp161948 p_read.blocks += (packet_length + 4) / block_size; 12065562Sjp161948 12070Sstevel@tonic-gate /* get padlen */ 12080Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 12090Sstevel@tonic-gate padlen = cp[4]; 12100Sstevel@tonic-gate DBG(debug("input: padlen %d", padlen)); 12110Sstevel@tonic-gate if (padlen < 4) 12120Sstevel@tonic-gate packet_disconnect("Corrupted padlen %d on input.", padlen); 12130Sstevel@tonic-gate 12140Sstevel@tonic-gate /* skip packet size + padlen, discard padding */ 12150Sstevel@tonic-gate buffer_consume(&incoming_packet, 4 + 1); 12160Sstevel@tonic-gate buffer_consume_end(&incoming_packet, padlen); 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 12190Sstevel@tonic-gate if (comp && comp->enabled) { 12200Sstevel@tonic-gate buffer_clear(&compression_buffer); 12210Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 12220Sstevel@tonic-gate buffer_clear(&incoming_packet); 12230Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 12240Sstevel@tonic-gate buffer_len(&compression_buffer)); 12250Sstevel@tonic-gate DBG(debug("input: len after de-compress %d", 12260Sstevel@tonic-gate buffer_len(&incoming_packet))); 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate /* 12290Sstevel@tonic-gate * get packet type, implies consume. 12300Sstevel@tonic-gate * return length of payload (without type field) 12310Sstevel@tonic-gate */ 12320Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 1233*7574SJan.Pechanec@Sun.COM if (type == SSH2_MSG_NEWKEYS) { 1234*7574SJan.Pechanec@Sun.COM /* 1235*7574SJan.Pechanec@Sun.COM * set_newkeys(MODE_IN) in the client because it doesn't have a 1236*7574SJan.Pechanec@Sun.COM * dispatch function for SSH2_MSG_NEWKEYS in contrast to the 1237*7574SJan.Pechanec@Sun.COM * server processes. Note that in the unprivileged child, 1238*7574SJan.Pechanec@Sun.COM * set_newkeys() for MODE_IN are set in dispatch function 1239*7574SJan.Pechanec@Sun.COM * altprivsep_rekey() after SSH2_MSG_NEWKEYS packet is received 1240*7574SJan.Pechanec@Sun.COM * from the client. 1241*7574SJan.Pechanec@Sun.COM */ 1242*7574SJan.Pechanec@Sun.COM process_newkeys(MODE_IN); 1243*7574SJan.Pechanec@Sun.COM } 1244*7574SJan.Pechanec@Sun.COM 12450Sstevel@tonic-gate #ifdef PACKET_DEBUG 1246*7574SJan.Pechanec@Sun.COM debug("decrypted input packet [type %d]:\n", type); 12470Sstevel@tonic-gate buffer_dump(&incoming_packet); 12480Sstevel@tonic-gate #endif 12490Sstevel@tonic-gate /* reset for next packet */ 12500Sstevel@tonic-gate packet_length = 0; 12510Sstevel@tonic-gate return type; 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 1254*7574SJan.Pechanec@Sun.COM /* 1255*7574SJan.Pechanec@Sun.COM * This tries to read a packet from the buffer of received data. Note that it 1256*7574SJan.Pechanec@Sun.COM * doesn't read() anything from the network socket. 1257*7574SJan.Pechanec@Sun.COM */ 12580Sstevel@tonic-gate int 12590Sstevel@tonic-gate packet_read_poll_seqnr(u_int32_t *seqnr_p) 12600Sstevel@tonic-gate { 12610Sstevel@tonic-gate u_int reason, seqnr; 12620Sstevel@tonic-gate u_char type; 12630Sstevel@tonic-gate char *msg; 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate for (;;) { 12660Sstevel@tonic-gate if (compat20) { 12670Sstevel@tonic-gate type = packet_read_poll2(seqnr_p); 12680Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 12690Sstevel@tonic-gate switch (type) { 12700Sstevel@tonic-gate case SSH2_MSG_IGNORE: 12710Sstevel@tonic-gate break; 12720Sstevel@tonic-gate case SSH2_MSG_DEBUG: 12730Sstevel@tonic-gate packet_get_char(); 12740Sstevel@tonic-gate msg = packet_get_string(NULL); 12750Sstevel@tonic-gate debug("Remote: %.900s", msg); 12760Sstevel@tonic-gate xfree(msg); 12770Sstevel@tonic-gate msg = packet_get_string(NULL); 12780Sstevel@tonic-gate xfree(msg); 12790Sstevel@tonic-gate break; 12800Sstevel@tonic-gate case SSH2_MSG_DISCONNECT: 12810Sstevel@tonic-gate reason = packet_get_int(); 12820Sstevel@tonic-gate msg = packet_get_string(NULL); 12830Sstevel@tonic-gate log("Received disconnect from %s: %u: %.400s", 12840Sstevel@tonic-gate get_remote_ipaddr(), reason, msg); 12850Sstevel@tonic-gate xfree(msg); 12860Sstevel@tonic-gate fatal_cleanup(); 12870Sstevel@tonic-gate break; 12880Sstevel@tonic-gate case SSH2_MSG_UNIMPLEMENTED: 12890Sstevel@tonic-gate seqnr = packet_get_int(); 12900Sstevel@tonic-gate debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 12910Sstevel@tonic-gate seqnr); 12920Sstevel@tonic-gate break; 12930Sstevel@tonic-gate default: 12940Sstevel@tonic-gate return type; 12950Sstevel@tonic-gate break; 12960Sstevel@tonic-gate } 12970Sstevel@tonic-gate } else { 12980Sstevel@tonic-gate type = packet_read_poll1(); 12990Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 13000Sstevel@tonic-gate switch (type) { 13010Sstevel@tonic-gate case SSH_MSG_IGNORE: 13020Sstevel@tonic-gate break; 13030Sstevel@tonic-gate case SSH_MSG_DEBUG: 13040Sstevel@tonic-gate msg = packet_get_string(NULL); 13050Sstevel@tonic-gate debug("Remote: %.900s", msg); 13060Sstevel@tonic-gate xfree(msg); 13070Sstevel@tonic-gate break; 13080Sstevel@tonic-gate case SSH_MSG_DISCONNECT: 13090Sstevel@tonic-gate msg = packet_get_string(NULL); 13100Sstevel@tonic-gate log("Received disconnect from %s: %.400s", 13110Sstevel@tonic-gate get_remote_ipaddr(), msg); 13120Sstevel@tonic-gate fatal_cleanup(); 13130Sstevel@tonic-gate xfree(msg); 13140Sstevel@tonic-gate break; 13150Sstevel@tonic-gate default: 13160Sstevel@tonic-gate return type; 13170Sstevel@tonic-gate break; 13180Sstevel@tonic-gate } 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate } 13220Sstevel@tonic-gate 13230Sstevel@tonic-gate int 13240Sstevel@tonic-gate packet_read_poll(void) 13250Sstevel@tonic-gate { 13260Sstevel@tonic-gate return packet_read_poll_seqnr(NULL); 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate /* 13300Sstevel@tonic-gate * Buffers the given amount of input characters. This is intended to be used 13310Sstevel@tonic-gate * together with packet_read_poll. 13320Sstevel@tonic-gate */ 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate void 13350Sstevel@tonic-gate packet_process_incoming(const char *buf, u_int len) 13360Sstevel@tonic-gate { 13370Sstevel@tonic-gate buffer_append(&input, buf, len); 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate /* Returns a character from the packet. */ 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate u_int 13430Sstevel@tonic-gate packet_get_char(void) 13440Sstevel@tonic-gate { 13450Sstevel@tonic-gate char ch; 13460Sstevel@tonic-gate 13470Sstevel@tonic-gate buffer_get(&incoming_packet, &ch, 1); 13480Sstevel@tonic-gate return (u_char) ch; 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate /* Returns an integer from the packet data. */ 13520Sstevel@tonic-gate 13530Sstevel@tonic-gate u_int 13540Sstevel@tonic-gate packet_get_int(void) 13550Sstevel@tonic-gate { 13560Sstevel@tonic-gate return buffer_get_int(&incoming_packet); 13570Sstevel@tonic-gate } 13580Sstevel@tonic-gate 13590Sstevel@tonic-gate /* 13600Sstevel@tonic-gate * Returns an arbitrary precision integer from the packet data. The integer 13610Sstevel@tonic-gate * must have been initialized before this call. 13620Sstevel@tonic-gate */ 13630Sstevel@tonic-gate 13640Sstevel@tonic-gate void 13650Sstevel@tonic-gate packet_get_bignum(BIGNUM * value) 13660Sstevel@tonic-gate { 13670Sstevel@tonic-gate buffer_get_bignum(&incoming_packet, value); 13680Sstevel@tonic-gate } 13690Sstevel@tonic-gate 13700Sstevel@tonic-gate void 13710Sstevel@tonic-gate packet_get_bignum2(BIGNUM * value) 13720Sstevel@tonic-gate { 13730Sstevel@tonic-gate buffer_get_bignum2(&incoming_packet, value); 13740Sstevel@tonic-gate } 13750Sstevel@tonic-gate 13760Sstevel@tonic-gate void * 13770Sstevel@tonic-gate packet_get_raw(u_int *length_ptr) 13780Sstevel@tonic-gate { 13790Sstevel@tonic-gate u_int bytes = buffer_len(&incoming_packet); 13800Sstevel@tonic-gate 13810Sstevel@tonic-gate if (length_ptr != NULL) 13820Sstevel@tonic-gate *length_ptr = bytes; 13830Sstevel@tonic-gate return buffer_ptr(&incoming_packet); 13840Sstevel@tonic-gate } 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate int 13870Sstevel@tonic-gate packet_remaining(void) 13880Sstevel@tonic-gate { 13890Sstevel@tonic-gate return buffer_len(&incoming_packet); 13900Sstevel@tonic-gate } 13910Sstevel@tonic-gate 13920Sstevel@tonic-gate /* 13930Sstevel@tonic-gate * Returns a string from the packet data. The string is allocated using 13940Sstevel@tonic-gate * xmalloc; it is the responsibility of the calling program to free it when 13950Sstevel@tonic-gate * no longer needed. The length_ptr argument may be NULL, or point to an 13960Sstevel@tonic-gate * integer into which the length of the string is stored. 13970Sstevel@tonic-gate */ 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate void * 14000Sstevel@tonic-gate packet_get_string(u_int *length_ptr) 14010Sstevel@tonic-gate { 14020Sstevel@tonic-gate return buffer_get_string(&incoming_packet, length_ptr); 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate char * 14050Sstevel@tonic-gate packet_get_ascii_cstring() 14060Sstevel@tonic-gate { 14070Sstevel@tonic-gate return buffer_get_ascii_cstring(&incoming_packet); 14080Sstevel@tonic-gate } 14090Sstevel@tonic-gate u_char * 14100Sstevel@tonic-gate packet_get_utf8_cstring() 14110Sstevel@tonic-gate { 14120Sstevel@tonic-gate return buffer_get_utf8_cstring(&incoming_packet); 14130Sstevel@tonic-gate } 14140Sstevel@tonic-gate 14150Sstevel@tonic-gate /* 14160Sstevel@tonic-gate * Sends a diagnostic message from the server to the client. This message 14170Sstevel@tonic-gate * can be sent at any time (but not while constructing another message). The 14180Sstevel@tonic-gate * message is printed immediately, but only if the client is being executed 14190Sstevel@tonic-gate * in verbose mode. These messages are primarily intended to ease debugging 14200Sstevel@tonic-gate * authentication problems. The length of the formatted message must not 14210Sstevel@tonic-gate * exceed 1024 bytes. This will automatically call packet_write_wait. 14220Sstevel@tonic-gate */ 14230Sstevel@tonic-gate 14240Sstevel@tonic-gate void 14250Sstevel@tonic-gate packet_send_debug(const char *fmt,...) 14260Sstevel@tonic-gate { 14270Sstevel@tonic-gate char buf[1024]; 14280Sstevel@tonic-gate va_list args; 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate if (compat20 && (datafellows & SSH_BUG_DEBUG)) 14310Sstevel@tonic-gate return; 14320Sstevel@tonic-gate 14330Sstevel@tonic-gate va_start(args, fmt); 14340Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), gettext(fmt), args); 14350Sstevel@tonic-gate va_end(args); 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate #ifdef ALTPRIVSEP 14380Sstevel@tonic-gate /* shouldn't happen */ 14390Sstevel@tonic-gate if (packet_monitor) { 14400Sstevel@tonic-gate debug("packet_send_debug: %s", buf); 14410Sstevel@tonic-gate return; 14420Sstevel@tonic-gate } 14430Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 14440Sstevel@tonic-gate 14450Sstevel@tonic-gate if (compat20) { 14460Sstevel@tonic-gate packet_start(SSH2_MSG_DEBUG); 14470Sstevel@tonic-gate packet_put_char(0); /* bool: always display */ 14480Sstevel@tonic-gate packet_put_cstring(buf); 14490Sstevel@tonic-gate packet_put_cstring(""); 14500Sstevel@tonic-gate } else { 14510Sstevel@tonic-gate packet_start(SSH_MSG_DEBUG); 14520Sstevel@tonic-gate packet_put_cstring(buf); 14530Sstevel@tonic-gate } 14540Sstevel@tonic-gate packet_send(); 14550Sstevel@tonic-gate packet_write_wait(); 14560Sstevel@tonic-gate } 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate /* 14590Sstevel@tonic-gate * Logs the error plus constructs and sends a disconnect packet, closes the 14600Sstevel@tonic-gate * connection, and exits. This function never returns. The error message 14610Sstevel@tonic-gate * should not contain a newline. The length of the formatted message must 14620Sstevel@tonic-gate * not exceed 1024 bytes. 14630Sstevel@tonic-gate */ 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate void 14660Sstevel@tonic-gate packet_disconnect(const char *fmt,...) 14670Sstevel@tonic-gate { 14680Sstevel@tonic-gate char buf[1024]; 14690Sstevel@tonic-gate va_list args; 14700Sstevel@tonic-gate static int disconnecting = 0; 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate if (disconnecting) /* Guard against recursive invocations. */ 14730Sstevel@tonic-gate fatal("packet_disconnect called recursively."); 14740Sstevel@tonic-gate disconnecting = 1; 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate /* 14770Sstevel@tonic-gate * Format the message. Note that the caller must make sure the 14780Sstevel@tonic-gate * message is of limited size. 14790Sstevel@tonic-gate */ 14800Sstevel@tonic-gate va_start(args, fmt); 14810Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), fmt, args); 14820Sstevel@tonic-gate va_end(args); 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate #ifdef ALTPRIVSEP 14850Sstevel@tonic-gate /* 14860Sstevel@tonic-gate * If we packet_disconnect() in the monitor the fatal cleanups will take 14870Sstevel@tonic-gate * care of the child. See main() in sshd.c. We don't send the packet 14880Sstevel@tonic-gate * disconnect message here because: a) the child might not be looking 14890Sstevel@tonic-gate * for it and b) because we don't really know if the child is compat20 14900Sstevel@tonic-gate * or not as we lost that information when packet_set_monitor() was 14910Sstevel@tonic-gate * called. 14920Sstevel@tonic-gate */ 14930Sstevel@tonic-gate if (packet_monitor) 14940Sstevel@tonic-gate goto close_stuff; 14950Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate /* Send the disconnect message to the other side, and wait for it to get sent. */ 14980Sstevel@tonic-gate if (compat20) { 14990Sstevel@tonic-gate packet_start(SSH2_MSG_DISCONNECT); 15000Sstevel@tonic-gate packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 15010Sstevel@tonic-gate packet_put_cstring(buf); 15020Sstevel@tonic-gate packet_put_cstring(""); 15030Sstevel@tonic-gate } else { 15040Sstevel@tonic-gate packet_start(SSH_MSG_DISCONNECT); 15050Sstevel@tonic-gate packet_put_cstring(buf); 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate packet_send(); 15080Sstevel@tonic-gate packet_write_wait(); 15090Sstevel@tonic-gate 15100Sstevel@tonic-gate #ifdef ALTPRIVSEP 15110Sstevel@tonic-gate close_stuff: 15120Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 15130Sstevel@tonic-gate /* Stop listening for connections. */ 15140Sstevel@tonic-gate channel_close_all(); 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate /* Close the connection. */ 15170Sstevel@tonic-gate packet_close(); 15180Sstevel@tonic-gate 15190Sstevel@tonic-gate /* Display the error locally and exit. */ 15200Sstevel@tonic-gate log("Disconnecting: %.100s", buf); 15210Sstevel@tonic-gate fatal_cleanup(); 15220Sstevel@tonic-gate } 15230Sstevel@tonic-gate 15240Sstevel@tonic-gate /* Checks if there is any buffered output, and tries to write some of the output. */ 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate void 15270Sstevel@tonic-gate packet_write_poll(void) 15280Sstevel@tonic-gate { 15290Sstevel@tonic-gate int len = buffer_len(&output); 15300Sstevel@tonic-gate 15310Sstevel@tonic-gate if (len > 0) { 15320Sstevel@tonic-gate len = write(connection_out, buffer_ptr(&output), len); 15330Sstevel@tonic-gate if (len <= 0) { 15340Sstevel@tonic-gate if (errno == EAGAIN) 15350Sstevel@tonic-gate return; 15360Sstevel@tonic-gate else 15370Sstevel@tonic-gate fatal("Write failed: %.100s", strerror(errno)); 15380Sstevel@tonic-gate } 1539*7574SJan.Pechanec@Sun.COM #ifdef PACKET_DEBUG 1540*7574SJan.Pechanec@Sun.COM debug("in packet_write_poll, %d bytes just sent to the " 1541*7574SJan.Pechanec@Sun.COM "remote side", len); 1542*7574SJan.Pechanec@Sun.COM #endif 15430Sstevel@tonic-gate buffer_consume(&output, len); 15440Sstevel@tonic-gate } 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate /* 15480Sstevel@tonic-gate * Calls packet_write_poll repeatedly until all pending output data has been 15490Sstevel@tonic-gate * written. 15500Sstevel@tonic-gate */ 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate void 15530Sstevel@tonic-gate packet_write_wait(void) 15540Sstevel@tonic-gate { 15550Sstevel@tonic-gate fd_set *setp; 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 15580Sstevel@tonic-gate sizeof(fd_mask)); 15590Sstevel@tonic-gate packet_write_poll(); 15600Sstevel@tonic-gate while (packet_have_data_to_write()) { 15610Sstevel@tonic-gate memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 15620Sstevel@tonic-gate sizeof(fd_mask)); 15630Sstevel@tonic-gate FD_SET(connection_out, setp); 15640Sstevel@tonic-gate while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 15650Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 15660Sstevel@tonic-gate ; 15670Sstevel@tonic-gate packet_write_poll(); 15680Sstevel@tonic-gate } 15690Sstevel@tonic-gate xfree(setp); 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate 15720Sstevel@tonic-gate /* Returns true if there is buffered data to write to the connection. */ 15730Sstevel@tonic-gate 15740Sstevel@tonic-gate int 15750Sstevel@tonic-gate packet_have_data_to_write(void) 15760Sstevel@tonic-gate { 15770Sstevel@tonic-gate return buffer_len(&output) != 0; 15780Sstevel@tonic-gate } 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate /* Returns true if there is not too much data to write to the connection. */ 15810Sstevel@tonic-gate 15820Sstevel@tonic-gate int 15830Sstevel@tonic-gate packet_not_very_much_data_to_write(void) 15840Sstevel@tonic-gate { 15850Sstevel@tonic-gate if (interactive_mode) 15860Sstevel@tonic-gate return buffer_len(&output) < 16384; 15870Sstevel@tonic-gate else 15880Sstevel@tonic-gate return buffer_len(&output) < 128 * 1024; 15890Sstevel@tonic-gate } 15900Sstevel@tonic-gate 15910Sstevel@tonic-gate /* Informs that the current session is interactive. Sets IP flags for that. */ 15920Sstevel@tonic-gate 15930Sstevel@tonic-gate void 15940Sstevel@tonic-gate packet_set_interactive(int interactive) 15950Sstevel@tonic-gate { 15960Sstevel@tonic-gate static int called = 0; 15970Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 15980Sstevel@tonic-gate int lowdelay = IPTOS_LOWDELAY; 15990Sstevel@tonic-gate int throughput = IPTOS_THROUGHPUT; 16000Sstevel@tonic-gate #endif 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate if (called) 16030Sstevel@tonic-gate return; 16040Sstevel@tonic-gate called = 1; 16050Sstevel@tonic-gate 16060Sstevel@tonic-gate /* Record that we are in interactive mode. */ 16070Sstevel@tonic-gate interactive_mode = interactive; 16080Sstevel@tonic-gate 16090Sstevel@tonic-gate /* Only set socket options if using a socket. */ 16100Sstevel@tonic-gate if (!packet_connection_is_on_socket()) 16110Sstevel@tonic-gate return; 16120Sstevel@tonic-gate /* 16130Sstevel@tonic-gate * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only 16140Sstevel@tonic-gate */ 16150Sstevel@tonic-gate if (interactive) { 16160Sstevel@tonic-gate /* 16170Sstevel@tonic-gate * Set IP options for an interactive connection. Use 16180Sstevel@tonic-gate * IPTOS_LOWDELAY and TCP_NODELAY. 16190Sstevel@tonic-gate */ 16200Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 16210Sstevel@tonic-gate if (packet_connection_is_ipv4()) { 16220Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, 16230Sstevel@tonic-gate &lowdelay, sizeof(lowdelay)) < 0) 16240Sstevel@tonic-gate error("setsockopt IPTOS_LOWDELAY: %.100s", 16250Sstevel@tonic-gate strerror(errno)); 16260Sstevel@tonic-gate } 16270Sstevel@tonic-gate #endif 16280Sstevel@tonic-gate set_nodelay(connection_in); 16290Sstevel@tonic-gate } 16300Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 16310Sstevel@tonic-gate else if (packet_connection_is_ipv4()) { 16320Sstevel@tonic-gate /* 16330Sstevel@tonic-gate * Set IP options for a non-interactive connection. Use 16340Sstevel@tonic-gate * IPTOS_THROUGHPUT. 16350Sstevel@tonic-gate */ 16360Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, 16370Sstevel@tonic-gate sizeof(throughput)) < 0) 16380Sstevel@tonic-gate error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); 16390Sstevel@tonic-gate } 16400Sstevel@tonic-gate #endif 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate 16430Sstevel@tonic-gate /* Returns true if the current connection is interactive. */ 16440Sstevel@tonic-gate 16450Sstevel@tonic-gate int 16460Sstevel@tonic-gate packet_is_interactive(void) 16470Sstevel@tonic-gate { 16480Sstevel@tonic-gate return interactive_mode; 16490Sstevel@tonic-gate } 16500Sstevel@tonic-gate 16510Sstevel@tonic-gate int 16520Sstevel@tonic-gate packet_set_maxsize(int s) 16530Sstevel@tonic-gate { 16540Sstevel@tonic-gate static int called = 0; 16550Sstevel@tonic-gate 16560Sstevel@tonic-gate if (called) { 16570Sstevel@tonic-gate log("packet_set_maxsize: called twice: old %d new %d", 16580Sstevel@tonic-gate max_packet_size, s); 16590Sstevel@tonic-gate return -1; 16600Sstevel@tonic-gate } 16610Sstevel@tonic-gate if (s < 4 * 1024 || s > 1024 * 1024) { 16620Sstevel@tonic-gate log("packet_set_maxsize: bad size %d", s); 16630Sstevel@tonic-gate return -1; 16640Sstevel@tonic-gate } 16650Sstevel@tonic-gate called = 1; 16660Sstevel@tonic-gate debug("packet_set_maxsize: setting to %d", s); 16670Sstevel@tonic-gate max_packet_size = s; 16680Sstevel@tonic-gate return s; 16690Sstevel@tonic-gate } 16700Sstevel@tonic-gate 16710Sstevel@tonic-gate /* roundup current message to pad bytes */ 16720Sstevel@tonic-gate void 16730Sstevel@tonic-gate packet_add_padding(u_char pad) 16740Sstevel@tonic-gate { 16750Sstevel@tonic-gate extra_pad = pad; 16760Sstevel@tonic-gate } 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate /* 16790Sstevel@tonic-gate * 9.2. Ignored Data Message 16800Sstevel@tonic-gate * 16810Sstevel@tonic-gate * byte SSH_MSG_IGNORE 16820Sstevel@tonic-gate * string data 16830Sstevel@tonic-gate * 16840Sstevel@tonic-gate * All implementations MUST understand (and ignore) this message at any 16850Sstevel@tonic-gate * time (after receiving the protocol version). No implementation is 16860Sstevel@tonic-gate * required to send them. This message can be used as an additional 16870Sstevel@tonic-gate * protection measure against advanced traffic analysis techniques. 16880Sstevel@tonic-gate */ 16890Sstevel@tonic-gate void 16900Sstevel@tonic-gate packet_send_ignore(int nbytes) 16910Sstevel@tonic-gate { 16925562Sjp161948 u_int32_t rnd = 0; 16930Sstevel@tonic-gate int i; 16940Sstevel@tonic-gate 16950Sstevel@tonic-gate #ifdef ALTPRIVSEP 16960Sstevel@tonic-gate /* shouldn't happen -- see packet_set_monitor() */ 16970Sstevel@tonic-gate if (packet_monitor) 16980Sstevel@tonic-gate return; 16990Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 17000Sstevel@tonic-gate 17010Sstevel@tonic-gate packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 17020Sstevel@tonic-gate packet_put_int(nbytes); 17030Sstevel@tonic-gate for (i = 0; i < nbytes; i++) { 17040Sstevel@tonic-gate if (i % 4 == 0) 17055562Sjp161948 rnd = arc4random(); 17065562Sjp161948 packet_put_char((u_char)rnd & 0xff); 17075562Sjp161948 rnd >>= 8; 17080Sstevel@tonic-gate } 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate 17115562Sjp161948 #define MAX_PACKETS (1U<<31) 17125562Sjp161948 int 17135562Sjp161948 packet_need_rekeying(void) 17145562Sjp161948 { 17155562Sjp161948 if (datafellows & SSH_BUG_NOREKEY) 17165562Sjp161948 return 0; 17175562Sjp161948 return 17185562Sjp161948 (p_send.packets > MAX_PACKETS) || 17195562Sjp161948 (p_read.packets > MAX_PACKETS) || 17205562Sjp161948 (max_blocks_out && (p_send.blocks > max_blocks_out)) || 17215562Sjp161948 (max_blocks_in && (p_read.blocks > max_blocks_in)); 17225562Sjp161948 } 17235562Sjp161948 17245562Sjp161948 void 17255562Sjp161948 packet_set_rekey_limit(u_int32_t bytes) 17265562Sjp161948 { 17275562Sjp161948 rekey_limit = bytes; 17285562Sjp161948 } 17295562Sjp161948 17300Sstevel@tonic-gate #ifdef ALTPRIVSEP 17310Sstevel@tonic-gate void 17320Sstevel@tonic-gate packet_set_server(void) 17330Sstevel@tonic-gate { 17340Sstevel@tonic-gate packet_server = 1; 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate 17370Sstevel@tonic-gate int 17380Sstevel@tonic-gate packet_is_server(void) 17390Sstevel@tonic-gate { 17400Sstevel@tonic-gate return (packet_server); 17410Sstevel@tonic-gate } 17420Sstevel@tonic-gate 17430Sstevel@tonic-gate void 17440Sstevel@tonic-gate packet_set_monitor(int pipe) 17450Sstevel@tonic-gate { 17460Sstevel@tonic-gate int dup_fd; 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate packet_server = 1; 17490Sstevel@tonic-gate packet_monitor = 1; 17500Sstevel@tonic-gate 17510Sstevel@tonic-gate /* 17520Sstevel@tonic-gate * Awful hack follows. 17530Sstevel@tonic-gate * 17540Sstevel@tonic-gate * For SSHv1 the monitor does not process any SSHv1 packets, only 17550Sstevel@tonic-gate * ALTPRIVSEP packets. We take advantage of that here to keep changes 17560Sstevel@tonic-gate * to packet.c to a minimum by using the SSHv2 binary packet protocol, 17570Sstevel@tonic-gate * with cipher "none," mac "none" and compression alg "none," as the 17580Sstevel@tonic-gate * basis for the monitor protocol. And so to force packet.c to treat 17590Sstevel@tonic-gate * packets as SSHv2 we force compat20 == 1 here. 17600Sstevel@tonic-gate * 17610Sstevel@tonic-gate * For completeness and to help future developers catch this we also 17620Sstevel@tonic-gate * force compat20 == 1 in the monitor loop, in serverloop.c. 17630Sstevel@tonic-gate */ 17640Sstevel@tonic-gate compat20 = 1; 17650Sstevel@tonic-gate 17660Sstevel@tonic-gate /* 17670Sstevel@tonic-gate * NOTE: Assumptions below! 17680Sstevel@tonic-gate * 17690Sstevel@tonic-gate * - lots of packet.c code assumes that (connection_in == 17700Sstevel@tonic-gate * connection_out) -> connection is socket 17710Sstevel@tonic-gate * 17720Sstevel@tonic-gate * - packet_close() does not shutdown() the connection fildes 17730Sstevel@tonic-gate * if connection_in != connection_out 17740Sstevel@tonic-gate * 17750Sstevel@tonic-gate * - other code assumes the connection is a socket if 17760Sstevel@tonic-gate * connection_in == connection_out 17770Sstevel@tonic-gate */ 17780Sstevel@tonic-gate 17790Sstevel@tonic-gate if ((dup_fd = dup(pipe)) < 0) 17800Sstevel@tonic-gate fatal("Monitor failed to start: %s", strerror(errno)); 17810Sstevel@tonic-gate 17820Sstevel@tonic-gate /* 17830Sstevel@tonic-gate * make sure that the monitor's child's socket is not shutdown(3SOCKET) 1784*7574SJan.Pechanec@Sun.COM * when we packet_close(). Setting connection_out to -1 will take care 1785*7574SJan.Pechanec@Sun.COM * of that. 17860Sstevel@tonic-gate */ 17870Sstevel@tonic-gate if (packet_connection_is_on_socket()) 17880Sstevel@tonic-gate connection_out = -1; 17890Sstevel@tonic-gate 1790*7574SJan.Pechanec@Sun.COM /* 1791*7574SJan.Pechanec@Sun.COM * Now clean up the state related to the server socket. As a side 1792*7574SJan.Pechanec@Sun.COM * effect, we also clean up existing cipher contexts that were 1793*7574SJan.Pechanec@Sun.COM * initialized with 'none' cipher in packet_set_connection(). That 1794*7574SJan.Pechanec@Sun.COM * function was called in the child server process shortly after the 1795*7574SJan.Pechanec@Sun.COM * master SSH process forked. However, all of that is reinialized again 1796*7574SJan.Pechanec@Sun.COM * by another packet_set_connection() call right below. 1797*7574SJan.Pechanec@Sun.COM */ 17980Sstevel@tonic-gate packet_close(); 17990Sstevel@tonic-gate 1800*7574SJan.Pechanec@Sun.COM /* 1801*7574SJan.Pechanec@Sun.COM * Now make the monitor pipe look like the ssh connection which means 1802*7574SJan.Pechanec@Sun.COM * that connection_in and connection_out will be set to the 1803*7574SJan.Pechanec@Sun.COM * communication pipe descriptors. 1804*7574SJan.Pechanec@Sun.COM */ 18050Sstevel@tonic-gate packet_set_connection(pipe, dup_fd); 18060Sstevel@tonic-gate } 18070Sstevel@tonic-gate 1808*7574SJan.Pechanec@Sun.COM /* 1809*7574SJan.Pechanec@Sun.COM * We temporarily need to set connection_in and connection_out descriptors so 1810*7574SJan.Pechanec@Sun.COM * that we can make use of existing code that gets the IP address and hostname 1811*7574SJan.Pechanec@Sun.COM * of the peer to write a login/logout record. It's not nice but we would have 1812*7574SJan.Pechanec@Sun.COM * to change more code when implementing the PKCS#11 engine support. 1813*7574SJan.Pechanec@Sun.COM */ 1814*7574SJan.Pechanec@Sun.COM void 1815*7574SJan.Pechanec@Sun.COM packet_set_fds(int fd, int restore) 1816*7574SJan.Pechanec@Sun.COM { 1817*7574SJan.Pechanec@Sun.COM static int stored_fd; 1818*7574SJan.Pechanec@Sun.COM 1819*7574SJan.Pechanec@Sun.COM if (stored_fd == 0 && restore == 0) { 1820*7574SJan.Pechanec@Sun.COM debug3("packet_set_fds: saving %d, installing %d", 1821*7574SJan.Pechanec@Sun.COM connection_in, fd); 1822*7574SJan.Pechanec@Sun.COM stored_fd = connection_in; 1823*7574SJan.Pechanec@Sun.COM /* we don't have a socket in inetd mode */ 1824*7574SJan.Pechanec@Sun.COM if (fd != -1) 1825*7574SJan.Pechanec@Sun.COM connection_in = connection_out = fd; 1826*7574SJan.Pechanec@Sun.COM return; 1827*7574SJan.Pechanec@Sun.COM } 1828*7574SJan.Pechanec@Sun.COM 1829*7574SJan.Pechanec@Sun.COM if (restore == 1) { 1830*7574SJan.Pechanec@Sun.COM debug3("restoring %d to connection_in/out", stored_fd); 1831*7574SJan.Pechanec@Sun.COM connection_in = connection_out = stored_fd; 1832*7574SJan.Pechanec@Sun.COM } 1833*7574SJan.Pechanec@Sun.COM } 1834*7574SJan.Pechanec@Sun.COM 18350Sstevel@tonic-gate int 18360Sstevel@tonic-gate packet_is_monitor(void) 18370Sstevel@tonic-gate { 18380Sstevel@tonic-gate return (packet_monitor); 18390Sstevel@tonic-gate } 18400Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1841