1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 3*0Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4*0Sstevel@tonic-gate * All rights reserved 5*0Sstevel@tonic-gate * This file contains code implementing the packet protocol and communication 6*0Sstevel@tonic-gate * with the other side. This same code is used both on client and server side. 7*0Sstevel@tonic-gate * 8*0Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 9*0Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 10*0Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 11*0Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 12*0Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * SSH2 packet format added by Markus Friedl. 16*0Sstevel@tonic-gate * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 17*0Sstevel@tonic-gate * 18*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 19*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 20*0Sstevel@tonic-gate * are met: 21*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 22*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 23*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 24*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 25*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 26*0Sstevel@tonic-gate * 27*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 32*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 36*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37*0Sstevel@tonic-gate */ 38*0Sstevel@tonic-gate /* 39*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 40*0Sstevel@tonic-gate * Use is subject to license terms. 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include "includes.h" 44*0Sstevel@tonic-gate RCSID("$OpenBSD: packet.c,v 1.97 2002/07/04 08:12:15 deraadt Exp $"); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include "xmalloc.h" 49*0Sstevel@tonic-gate #include "buffer.h" 50*0Sstevel@tonic-gate #include "packet.h" 51*0Sstevel@tonic-gate #include "bufaux.h" 52*0Sstevel@tonic-gate #include "crc32.h" 53*0Sstevel@tonic-gate #include "getput.h" 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate #include "compress.h" 56*0Sstevel@tonic-gate #include "deattack.h" 57*0Sstevel@tonic-gate #include "channels.h" 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include "compat.h" 60*0Sstevel@tonic-gate #include "ssh1.h" 61*0Sstevel@tonic-gate #include "ssh2.h" 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #include "cipher.h" 64*0Sstevel@tonic-gate #include "kex.h" 65*0Sstevel@tonic-gate #include "mac.h" 66*0Sstevel@tonic-gate #include "log.h" 67*0Sstevel@tonic-gate #include "canohost.h" 68*0Sstevel@tonic-gate #include "misc.h" 69*0Sstevel@tonic-gate #include "ssh.h" 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 72*0Sstevel@tonic-gate static int packet_server = 0; 73*0Sstevel@tonic-gate static int packet_monitor = 0; 74*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 77*0Sstevel@tonic-gate #define DBG(x) x 78*0Sstevel@tonic-gate #else 79*0Sstevel@tonic-gate #define DBG(x) 80*0Sstevel@tonic-gate #endif 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * This variable contains the file descriptors used for communicating with 84*0Sstevel@tonic-gate * the other side. connection_in is used for reading; connection_out for 85*0Sstevel@tonic-gate * writing. These can be the same descriptor, in which case it is assumed to 86*0Sstevel@tonic-gate * be a socket. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate static int connection_in = -1; 89*0Sstevel@tonic-gate static int connection_out = -1; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* Protocol flags for the remote side. */ 92*0Sstevel@tonic-gate static u_int remote_protocol_flags = 0; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* Encryption context for receiving data. This is only used for decryption. */ 95*0Sstevel@tonic-gate static CipherContext receive_context; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* Encryption context for sending data. This is only used for encryption. */ 98*0Sstevel@tonic-gate static CipherContext send_context; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* Buffer for raw input data from the socket. */ 101*0Sstevel@tonic-gate Buffer input; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* Buffer for raw output data going to the socket. */ 104*0Sstevel@tonic-gate Buffer output; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* Buffer for the partial outgoing packet being constructed. */ 107*0Sstevel@tonic-gate static Buffer outgoing_packet; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* Buffer for the incoming packet currently being processed. */ 110*0Sstevel@tonic-gate static Buffer incoming_packet; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* Scratch buffer for packet compression/decompression. */ 113*0Sstevel@tonic-gate static Buffer compression_buffer; 114*0Sstevel@tonic-gate static int compression_buffer_ready = 0; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* Flag indicating whether packet compression/decompression is enabled. */ 117*0Sstevel@tonic-gate static int packet_compression = 0; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* default maximum packet size */ 120*0Sstevel@tonic-gate int max_packet_size = 32768; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate /* Flag indicating whether this module has been initialized. */ 123*0Sstevel@tonic-gate static int initialized = 0; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* Set to true if the connection is interactive. */ 126*0Sstevel@tonic-gate static int interactive_mode = 0; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* Session key information for Encryption and MAC */ 129*0Sstevel@tonic-gate Newkeys *newkeys[MODE_MAX]; 130*0Sstevel@tonic-gate static u_int32_t read_seqnr = 0; 131*0Sstevel@tonic-gate static u_int32_t send_seqnr = 0; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* Session key for protocol v1 */ 134*0Sstevel@tonic-gate static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 135*0Sstevel@tonic-gate static u_int ssh1_keylen; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* roundup current message to extra_pad bytes */ 138*0Sstevel@tonic-gate static u_char extra_pad = 0; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* 141*0Sstevel@tonic-gate * Sets the descriptors used for communication. Disables encryption until 142*0Sstevel@tonic-gate * packet_set_encryption_key is called. 143*0Sstevel@tonic-gate */ 144*0Sstevel@tonic-gate void 145*0Sstevel@tonic-gate packet_set_connection(int fd_in, int fd_out) 146*0Sstevel@tonic-gate { 147*0Sstevel@tonic-gate Cipher *none = cipher_by_name("none"); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if (none == NULL) 150*0Sstevel@tonic-gate fatal("packet_set_connection: cannot load cipher 'none'"); 151*0Sstevel@tonic-gate connection_in = fd_in; 152*0Sstevel@tonic-gate connection_out = fd_out; 153*0Sstevel@tonic-gate cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT); 154*0Sstevel@tonic-gate cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT); 155*0Sstevel@tonic-gate newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 156*0Sstevel@tonic-gate if (!initialized) { 157*0Sstevel@tonic-gate initialized = 1; 158*0Sstevel@tonic-gate buffer_init(&input); 159*0Sstevel@tonic-gate buffer_init(&output); 160*0Sstevel@tonic-gate buffer_init(&outgoing_packet); 161*0Sstevel@tonic-gate buffer_init(&incoming_packet); 162*0Sstevel@tonic-gate } else { 163*0Sstevel@tonic-gate buffer_clear(&input); 164*0Sstevel@tonic-gate buffer_clear(&output); 165*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 166*0Sstevel@tonic-gate buffer_clear(&incoming_packet); 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* 170*0Sstevel@tonic-gate * Prime the cache for get_remote_ipaddr() while we have a 171*0Sstevel@tonic-gate * socket on which to do a getpeername(). 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate (void) get_remote_ipaddr(); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* Kludge: arrange the close function to be called from fatal(). */ 176*0Sstevel@tonic-gate fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* Returns 1 if remote host is connected via socket, 0 if not. */ 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate int 182*0Sstevel@tonic-gate packet_connection_is_on_socket(void) 183*0Sstevel@tonic-gate { 184*0Sstevel@tonic-gate struct sockaddr_storage from, to; 185*0Sstevel@tonic-gate socklen_t fromlen, tolen; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* filedescriptors in and out are the same, so it's a socket */ 188*0Sstevel@tonic-gate if (connection_in != -1 && connection_in == connection_out) 189*0Sstevel@tonic-gate return 1; 190*0Sstevel@tonic-gate fromlen = sizeof(from); 191*0Sstevel@tonic-gate memset(&from, 0, sizeof(from)); 192*0Sstevel@tonic-gate if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 193*0Sstevel@tonic-gate return 0; 194*0Sstevel@tonic-gate tolen = sizeof(to); 195*0Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 196*0Sstevel@tonic-gate if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 197*0Sstevel@tonic-gate return 0; 198*0Sstevel@tonic-gate if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 199*0Sstevel@tonic-gate return 0; 200*0Sstevel@tonic-gate if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 201*0Sstevel@tonic-gate return 0; 202*0Sstevel@tonic-gate return 1; 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate /* 206*0Sstevel@tonic-gate * Exports an IV from the CipherContext required to export the key 207*0Sstevel@tonic-gate * state back from the unprivileged child to the privileged parent 208*0Sstevel@tonic-gate * process. 209*0Sstevel@tonic-gate */ 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate void 212*0Sstevel@tonic-gate packet_get_keyiv(int mode, u_char *iv, u_int len) 213*0Sstevel@tonic-gate { 214*0Sstevel@tonic-gate CipherContext *cc; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (mode == MODE_OUT) 217*0Sstevel@tonic-gate cc = &send_context; 218*0Sstevel@tonic-gate else 219*0Sstevel@tonic-gate cc = &receive_context; 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate cipher_get_keyiv(cc, iv, len); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate int 225*0Sstevel@tonic-gate packet_get_keycontext(int mode, u_char *dat) 226*0Sstevel@tonic-gate { 227*0Sstevel@tonic-gate CipherContext *cc; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate if (mode == MODE_OUT) 230*0Sstevel@tonic-gate cc = &send_context; 231*0Sstevel@tonic-gate else 232*0Sstevel@tonic-gate cc = &receive_context; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate return (cipher_get_keycontext(cc, dat)); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate void 238*0Sstevel@tonic-gate packet_set_keycontext(int mode, u_char *dat) 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate CipherContext *cc; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (mode == MODE_OUT) 243*0Sstevel@tonic-gate cc = &send_context; 244*0Sstevel@tonic-gate else 245*0Sstevel@tonic-gate cc = &receive_context; 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate cipher_set_keycontext(cc, dat); 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate int 251*0Sstevel@tonic-gate packet_get_keyiv_len(int mode) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate CipherContext *cc; 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate if (mode == MODE_OUT) 256*0Sstevel@tonic-gate cc = &send_context; 257*0Sstevel@tonic-gate else 258*0Sstevel@tonic-gate cc = &receive_context; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate return (cipher_get_keyiv_len(cc)); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate void 263*0Sstevel@tonic-gate packet_set_iv(int mode, u_char *dat) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate CipherContext *cc; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate if (mode == MODE_OUT) 268*0Sstevel@tonic-gate cc = &send_context; 269*0Sstevel@tonic-gate else 270*0Sstevel@tonic-gate cc = &receive_context; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate cipher_set_keyiv(cc, dat); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate int 275*0Sstevel@tonic-gate packet_get_ssh1_cipher() 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate return (cipher_get_number(receive_context.cipher)); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate u_int32_t 282*0Sstevel@tonic-gate packet_get_seqnr(int mode) 283*0Sstevel@tonic-gate { 284*0Sstevel@tonic-gate return (mode == MODE_IN ? read_seqnr : send_seqnr); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate void 288*0Sstevel@tonic-gate packet_set_seqnr(int mode, u_int32_t seqnr) 289*0Sstevel@tonic-gate { 290*0Sstevel@tonic-gate if (mode == MODE_IN) 291*0Sstevel@tonic-gate read_seqnr = seqnr; 292*0Sstevel@tonic-gate else if (mode == MODE_OUT) 293*0Sstevel@tonic-gate send_seqnr = seqnr; 294*0Sstevel@tonic-gate else 295*0Sstevel@tonic-gate fatal("packet_set_seqnr: bad mode %d", mode); 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate /* returns 1 if connection is via ipv4 */ 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate int 301*0Sstevel@tonic-gate packet_connection_is_ipv4(void) 302*0Sstevel@tonic-gate { 303*0Sstevel@tonic-gate struct sockaddr_storage to; 304*0Sstevel@tonic-gate socklen_t tolen = sizeof(to); 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate memset(&to, 0, sizeof(to)); 307*0Sstevel@tonic-gate if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 308*0Sstevel@tonic-gate return 0; 309*0Sstevel@tonic-gate if (to.ss_family == AF_INET) 310*0Sstevel@tonic-gate return 1; 311*0Sstevel@tonic-gate #ifdef IPV4_IN_IPV6 312*0Sstevel@tonic-gate if (to.ss_family == AF_INET6 && 313*0Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 314*0Sstevel@tonic-gate return 1; 315*0Sstevel@tonic-gate #endif 316*0Sstevel@tonic-gate return 0; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* Sets the connection into non-blocking mode. */ 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate void 322*0Sstevel@tonic-gate packet_set_nonblocking(void) 323*0Sstevel@tonic-gate { 324*0Sstevel@tonic-gate /* Set the socket into non-blocking mode. */ 325*0Sstevel@tonic-gate if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) 326*0Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate if (connection_out != connection_in) { 329*0Sstevel@tonic-gate if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) 330*0Sstevel@tonic-gate error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate /* Returns the socket used for reading. */ 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate int 337*0Sstevel@tonic-gate packet_get_connection_in(void) 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate return connection_in; 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* Returns the descriptor used for writing. */ 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate int 345*0Sstevel@tonic-gate packet_get_connection_out(void) 346*0Sstevel@tonic-gate { 347*0Sstevel@tonic-gate return connection_out; 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate /* Closes the connection and clears and frees internal data structures. */ 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate void 353*0Sstevel@tonic-gate packet_close(void) 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate if (!initialized) 356*0Sstevel@tonic-gate return; 357*0Sstevel@tonic-gate initialized = 0; 358*0Sstevel@tonic-gate if (connection_in == connection_out) { 359*0Sstevel@tonic-gate shutdown(connection_out, SHUT_RDWR); 360*0Sstevel@tonic-gate close(connection_out); 361*0Sstevel@tonic-gate } else { 362*0Sstevel@tonic-gate close(connection_in); 363*0Sstevel@tonic-gate close(connection_out); 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate buffer_free(&input); 366*0Sstevel@tonic-gate buffer_free(&output); 367*0Sstevel@tonic-gate buffer_free(&outgoing_packet); 368*0Sstevel@tonic-gate buffer_free(&incoming_packet); 369*0Sstevel@tonic-gate if (compression_buffer_ready) { 370*0Sstevel@tonic-gate buffer_free(&compression_buffer); 371*0Sstevel@tonic-gate buffer_compress_uninit(); 372*0Sstevel@tonic-gate compression_buffer_ready = 0; 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate cipher_cleanup(&send_context); 375*0Sstevel@tonic-gate cipher_cleanup(&receive_context); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate /* Sets remote side protocol flags. */ 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate void 381*0Sstevel@tonic-gate packet_set_protocol_flags(u_int protocol_flags) 382*0Sstevel@tonic-gate { 383*0Sstevel@tonic-gate remote_protocol_flags = protocol_flags; 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* Returns the remote protocol flags set earlier by the above function. */ 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate u_int 389*0Sstevel@tonic-gate packet_get_protocol_flags(void) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate return remote_protocol_flags; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * Starts packet compression from the next packet on in both directions. 396*0Sstevel@tonic-gate * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 397*0Sstevel@tonic-gate */ 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate static void 400*0Sstevel@tonic-gate packet_init_compression(void) 401*0Sstevel@tonic-gate { 402*0Sstevel@tonic-gate if (compression_buffer_ready == 1) 403*0Sstevel@tonic-gate return; 404*0Sstevel@tonic-gate compression_buffer_ready = 1; 405*0Sstevel@tonic-gate buffer_init(&compression_buffer); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate void 409*0Sstevel@tonic-gate packet_start_compression(int level) 410*0Sstevel@tonic-gate { 411*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 412*0Sstevel@tonic-gate /* shouldn't happen! */ 413*0Sstevel@tonic-gate if (packet_monitor) 414*0Sstevel@tonic-gate fatal("INTERNAL ERROR: The monitor cannot compress."); 415*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate if (packet_compression && !compat20) 418*0Sstevel@tonic-gate fatal("Compression already enabled."); 419*0Sstevel@tonic-gate packet_compression = 1; 420*0Sstevel@tonic-gate packet_init_compression(); 421*0Sstevel@tonic-gate buffer_compress_init_send(level); 422*0Sstevel@tonic-gate buffer_compress_init_recv(); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * Causes any further packets to be encrypted using the given key. The same 427*0Sstevel@tonic-gate * key is used for both sending and reception. However, both directions are 428*0Sstevel@tonic-gate * encrypted independently of each other. 429*0Sstevel@tonic-gate */ 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate void 432*0Sstevel@tonic-gate packet_set_encryption_key(const u_char *key, u_int keylen, 433*0Sstevel@tonic-gate int number) 434*0Sstevel@tonic-gate { 435*0Sstevel@tonic-gate Cipher *cipher = cipher_by_number(number); 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if (cipher == NULL) 438*0Sstevel@tonic-gate fatal("packet_set_encryption_key: unknown cipher number %d", number); 439*0Sstevel@tonic-gate if (keylen < 20) 440*0Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too small: %d", keylen); 441*0Sstevel@tonic-gate if (keylen > SSH_SESSION_KEY_LENGTH) 442*0Sstevel@tonic-gate fatal("packet_set_encryption_key: keylen too big: %d", keylen); 443*0Sstevel@tonic-gate memcpy(ssh1_key, key, keylen); 444*0Sstevel@tonic-gate ssh1_keylen = keylen; 445*0Sstevel@tonic-gate cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 446*0Sstevel@tonic-gate cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 447*0Sstevel@tonic-gate } 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate u_int 450*0Sstevel@tonic-gate packet_get_encryption_key(u_char *key) 451*0Sstevel@tonic-gate { 452*0Sstevel@tonic-gate if (key == NULL) 453*0Sstevel@tonic-gate return (ssh1_keylen); 454*0Sstevel@tonic-gate memcpy(key, ssh1_key, ssh1_keylen); 455*0Sstevel@tonic-gate return (ssh1_keylen); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate /* Start constructing a packet to send. */ 459*0Sstevel@tonic-gate void 460*0Sstevel@tonic-gate packet_start(u_char type) 461*0Sstevel@tonic-gate { 462*0Sstevel@tonic-gate u_char buf[9]; 463*0Sstevel@tonic-gate int len; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate DBG(debug("packet_start[%d]", type)); 466*0Sstevel@tonic-gate len = compat20 ? 6 : 9; 467*0Sstevel@tonic-gate memset(buf, 0, len - 1); 468*0Sstevel@tonic-gate buf[len - 1] = type; 469*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 470*0Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate /* Append payload. */ 474*0Sstevel@tonic-gate void 475*0Sstevel@tonic-gate packet_put_char(int value) 476*0Sstevel@tonic-gate { 477*0Sstevel@tonic-gate char ch = value; 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate buffer_append(&outgoing_packet, &ch, 1); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate void 482*0Sstevel@tonic-gate packet_put_int(u_int value) 483*0Sstevel@tonic-gate { 484*0Sstevel@tonic-gate buffer_put_int(&outgoing_packet, value); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate void 487*0Sstevel@tonic-gate packet_put_string(const void *buf, u_int len) 488*0Sstevel@tonic-gate { 489*0Sstevel@tonic-gate buffer_put_string(&outgoing_packet, buf, len); 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate void 492*0Sstevel@tonic-gate packet_put_cstring(const char *str) 493*0Sstevel@tonic-gate { 494*0Sstevel@tonic-gate buffer_put_cstring(&outgoing_packet, str); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate void 497*0Sstevel@tonic-gate packet_put_ascii_cstring(const char *str) 498*0Sstevel@tonic-gate { 499*0Sstevel@tonic-gate buffer_put_ascii_cstring(&outgoing_packet, str); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate void 502*0Sstevel@tonic-gate packet_put_utf8_cstring(const u_char *str) 503*0Sstevel@tonic-gate { 504*0Sstevel@tonic-gate buffer_put_utf8_cstring(&outgoing_packet, str); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate #if 0 507*0Sstevel@tonic-gate void 508*0Sstevel@tonic-gate packet_put_ascii_string(const void *buf, u_int len) 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate buffer_put_ascii_string(&outgoing_packet, buf, len); 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate void 513*0Sstevel@tonic-gate packet_put_utf8_string(const void *buf, u_int len) 514*0Sstevel@tonic-gate { 515*0Sstevel@tonic-gate buffer_put_utf8_string(&outgoing_packet, buf, len); 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate #endif 518*0Sstevel@tonic-gate void 519*0Sstevel@tonic-gate packet_put_raw(const void *buf, u_int len) 520*0Sstevel@tonic-gate { 521*0Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, len); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate void 524*0Sstevel@tonic-gate packet_put_bignum(BIGNUM * value) 525*0Sstevel@tonic-gate { 526*0Sstevel@tonic-gate buffer_put_bignum(&outgoing_packet, value); 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate void 529*0Sstevel@tonic-gate packet_put_bignum2(BIGNUM * value) 530*0Sstevel@tonic-gate { 531*0Sstevel@tonic-gate buffer_put_bignum2(&outgoing_packet, value); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate /* 535*0Sstevel@tonic-gate * Finalizes and sends the packet. If the encryption key has been set, 536*0Sstevel@tonic-gate * encrypts the packet before sending. 537*0Sstevel@tonic-gate */ 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate static void 540*0Sstevel@tonic-gate packet_send1(void) 541*0Sstevel@tonic-gate { 542*0Sstevel@tonic-gate u_char buf[8], *cp; 543*0Sstevel@tonic-gate int i, padding, len; 544*0Sstevel@tonic-gate u_int checksum; 545*0Sstevel@tonic-gate u_int32_t rand = 0; 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate /* 548*0Sstevel@tonic-gate * If using packet compression, compress the payload of the outgoing 549*0Sstevel@tonic-gate * packet. 550*0Sstevel@tonic-gate */ 551*0Sstevel@tonic-gate if (packet_compression) { 552*0Sstevel@tonic-gate buffer_clear(&compression_buffer); 553*0Sstevel@tonic-gate /* Skip padding. */ 554*0Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8); 555*0Sstevel@tonic-gate /* padding */ 556*0Sstevel@tonic-gate buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 557*0Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 558*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 559*0Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 560*0Sstevel@tonic-gate buffer_len(&compression_buffer)); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate /* Compute packet length without padding (add checksum, remove padding). */ 563*0Sstevel@tonic-gate len = buffer_len(&outgoing_packet) + 4 - 8; 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* Insert padding. Initialized to zero in packet_start1() */ 566*0Sstevel@tonic-gate padding = 8 - len % 8; 567*0Sstevel@tonic-gate if (!send_context.plaintext) { 568*0Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 569*0Sstevel@tonic-gate for (i = 0; i < padding; i++) { 570*0Sstevel@tonic-gate if (i % 4 == 0) 571*0Sstevel@tonic-gate rand = arc4random(); 572*0Sstevel@tonic-gate cp[7 - i] = rand & 0xff; 573*0Sstevel@tonic-gate rand >>= 8; 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate buffer_consume(&outgoing_packet, 8 - padding); 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate /* Add check bytes. */ 579*0Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 580*0Sstevel@tonic-gate buffer_len(&outgoing_packet)); 581*0Sstevel@tonic-gate PUT_32BIT(buf, checksum); 582*0Sstevel@tonic-gate buffer_append(&outgoing_packet, buf, 4); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 585*0Sstevel@tonic-gate fprintf(stderr, "packet_send plain: "); 586*0Sstevel@tonic-gate buffer_dump(&outgoing_packet); 587*0Sstevel@tonic-gate #endif 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* Append to output. */ 590*0Sstevel@tonic-gate PUT_32BIT(buf, len); 591*0Sstevel@tonic-gate buffer_append(&output, buf, 4); 592*0Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 593*0Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 594*0Sstevel@tonic-gate buffer_len(&outgoing_packet)); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 597*0Sstevel@tonic-gate fprintf(stderr, "encrypted: "); 598*0Sstevel@tonic-gate buffer_dump(&output); 599*0Sstevel@tonic-gate #endif 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* 604*0Sstevel@tonic-gate * Note that the packet is now only buffered in output. It won\'t be 605*0Sstevel@tonic-gate * actually sent until packet_write_wait or packet_write_poll is 606*0Sstevel@tonic-gate * called. 607*0Sstevel@tonic-gate */ 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate void 611*0Sstevel@tonic-gate set_newkeys(int mode) 612*0Sstevel@tonic-gate { 613*0Sstevel@tonic-gate Enc *enc; 614*0Sstevel@tonic-gate Mac *mac; 615*0Sstevel@tonic-gate Comp *comp; 616*0Sstevel@tonic-gate CipherContext *cc; 617*0Sstevel@tonic-gate int encrypt; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate debug("newkeys: mode %d", mode); 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate if (mode == MODE_OUT) { 622*0Sstevel@tonic-gate cc = &send_context; 623*0Sstevel@tonic-gate encrypt = CIPHER_ENCRYPT; 624*0Sstevel@tonic-gate } else { 625*0Sstevel@tonic-gate cc = &receive_context; 626*0Sstevel@tonic-gate encrypt = CIPHER_DECRYPT; 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate if (newkeys[mode] != NULL) { 629*0Sstevel@tonic-gate debug("newkeys: rekeying"); 630*0Sstevel@tonic-gate cipher_cleanup(cc); 631*0Sstevel@tonic-gate enc = &newkeys[mode]->enc; 632*0Sstevel@tonic-gate mac = &newkeys[mode]->mac; 633*0Sstevel@tonic-gate comp = &newkeys[mode]->comp; 634*0Sstevel@tonic-gate memset(mac->key, 0, mac->key_len); 635*0Sstevel@tonic-gate xfree(enc->name); 636*0Sstevel@tonic-gate xfree(enc->iv); 637*0Sstevel@tonic-gate xfree(enc->key); 638*0Sstevel@tonic-gate xfree(mac->name); 639*0Sstevel@tonic-gate xfree(mac->key); 640*0Sstevel@tonic-gate xfree(comp->name); 641*0Sstevel@tonic-gate xfree(newkeys[mode]); 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate newkeys[mode] = kex_get_newkeys(mode); 644*0Sstevel@tonic-gate if (newkeys[mode] == NULL) 645*0Sstevel@tonic-gate fatal("newkeys: no keys for mode %d", mode); 646*0Sstevel@tonic-gate enc = &newkeys[mode]->enc; 647*0Sstevel@tonic-gate mac = &newkeys[mode]->mac; 648*0Sstevel@tonic-gate comp = &newkeys[mode]->comp; 649*0Sstevel@tonic-gate if (mac->md != NULL) 650*0Sstevel@tonic-gate mac->enabled = 1; 651*0Sstevel@tonic-gate DBG(debug("cipher_init_context: %d", mode)); 652*0Sstevel@tonic-gate cipher_init(cc, enc->cipher, enc->key, enc->key_len, 653*0Sstevel@tonic-gate enc->iv, enc->block_size, encrypt); 654*0Sstevel@tonic-gate /* Deleting the keys does not gain extra security */ 655*0Sstevel@tonic-gate /* memset(enc->iv, 0, enc->block_size); 656*0Sstevel@tonic-gate memset(enc->key, 0, enc->key_len); */ 657*0Sstevel@tonic-gate if (comp->type != 0 && comp->enabled == 0) { 658*0Sstevel@tonic-gate packet_init_compression(); 659*0Sstevel@tonic-gate if (mode == MODE_OUT) 660*0Sstevel@tonic-gate buffer_compress_init_send(6); 661*0Sstevel@tonic-gate else 662*0Sstevel@tonic-gate buffer_compress_init_recv(); 663*0Sstevel@tonic-gate comp->enabled = 1; 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* 668*0Sstevel@tonic-gate * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 669*0Sstevel@tonic-gate */ 670*0Sstevel@tonic-gate static void 671*0Sstevel@tonic-gate packet_send2(void) 672*0Sstevel@tonic-gate { 673*0Sstevel@tonic-gate u_char type, *cp, *macbuf = NULL; 674*0Sstevel@tonic-gate u_char padlen, pad; 675*0Sstevel@tonic-gate u_int packet_length = 0; 676*0Sstevel@tonic-gate u_int i, len; 677*0Sstevel@tonic-gate u_int32_t rand = 0; 678*0Sstevel@tonic-gate Enc *enc = NULL; 679*0Sstevel@tonic-gate Mac *mac = NULL; 680*0Sstevel@tonic-gate Comp *comp = NULL; 681*0Sstevel@tonic-gate int block_size; 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate if (newkeys[MODE_OUT] != NULL) { 684*0Sstevel@tonic-gate enc = &newkeys[MODE_OUT]->enc; 685*0Sstevel@tonic-gate mac = &newkeys[MODE_OUT]->mac; 686*0Sstevel@tonic-gate comp = &newkeys[MODE_OUT]->comp; 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 691*0Sstevel@tonic-gate type = cp[5]; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 694*0Sstevel@tonic-gate fprintf(stderr, "plain: "); 695*0Sstevel@tonic-gate buffer_dump(&outgoing_packet); 696*0Sstevel@tonic-gate #endif 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate if (comp && comp->enabled) { 699*0Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 700*0Sstevel@tonic-gate /* skip header, compress only payload */ 701*0Sstevel@tonic-gate buffer_consume(&outgoing_packet, 5); 702*0Sstevel@tonic-gate buffer_clear(&compression_buffer); 703*0Sstevel@tonic-gate buffer_compress(&outgoing_packet, &compression_buffer); 704*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 705*0Sstevel@tonic-gate buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 706*0Sstevel@tonic-gate buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 707*0Sstevel@tonic-gate buffer_len(&compression_buffer)); 708*0Sstevel@tonic-gate DBG(debug("compression: raw %d compressed %d", len, 709*0Sstevel@tonic-gate buffer_len(&outgoing_packet))); 710*0Sstevel@tonic-gate } 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate /* sizeof (packet_len + pad_len + payload) */ 713*0Sstevel@tonic-gate len = buffer_len(&outgoing_packet); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate /* 716*0Sstevel@tonic-gate * calc size of padding, alloc space, get random data, 717*0Sstevel@tonic-gate * minimum padding is 4 bytes 718*0Sstevel@tonic-gate */ 719*0Sstevel@tonic-gate padlen = block_size - (len % block_size); 720*0Sstevel@tonic-gate if (padlen < 4) 721*0Sstevel@tonic-gate padlen += block_size; 722*0Sstevel@tonic-gate if (extra_pad) { 723*0Sstevel@tonic-gate /* will wrap if extra_pad+padlen > 255 */ 724*0Sstevel@tonic-gate extra_pad = roundup(extra_pad, block_size); 725*0Sstevel@tonic-gate pad = extra_pad - ((len + padlen) % extra_pad); 726*0Sstevel@tonic-gate debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 727*0Sstevel@tonic-gate pad, len, padlen, extra_pad); 728*0Sstevel@tonic-gate padlen += pad; 729*0Sstevel@tonic-gate extra_pad = 0; 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate cp = buffer_append_space(&outgoing_packet, padlen); 732*0Sstevel@tonic-gate if (enc && !send_context.plaintext) { 733*0Sstevel@tonic-gate /* random padding */ 734*0Sstevel@tonic-gate for (i = 0; i < padlen; i++) { 735*0Sstevel@tonic-gate if (i % 4 == 0) 736*0Sstevel@tonic-gate rand = arc4random(); 737*0Sstevel@tonic-gate cp[i] = rand & 0xff; 738*0Sstevel@tonic-gate rand >>= 8; 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate } else { 741*0Sstevel@tonic-gate /* clear padding */ 742*0Sstevel@tonic-gate memset(cp, 0, padlen); 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate /* packet_length includes payload, padding and padding length field */ 745*0Sstevel@tonic-gate packet_length = buffer_len(&outgoing_packet) - 4; 746*0Sstevel@tonic-gate cp = buffer_ptr(&outgoing_packet); 747*0Sstevel@tonic-gate PUT_32BIT(cp, packet_length); 748*0Sstevel@tonic-gate cp[4] = padlen; 749*0Sstevel@tonic-gate DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate /* compute MAC over seqnr and packet(length fields, payload, padding) */ 752*0Sstevel@tonic-gate if (mac && mac->enabled) { 753*0Sstevel@tonic-gate macbuf = mac_compute(mac, send_seqnr, 754*0Sstevel@tonic-gate buffer_ptr(&outgoing_packet), 755*0Sstevel@tonic-gate buffer_len(&outgoing_packet)); 756*0Sstevel@tonic-gate DBG(debug("done calc MAC out #%d", send_seqnr)); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate /* encrypt packet and append to output buffer. */ 759*0Sstevel@tonic-gate cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 760*0Sstevel@tonic-gate cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 761*0Sstevel@tonic-gate buffer_len(&outgoing_packet)); 762*0Sstevel@tonic-gate /* append unencrypted MAC */ 763*0Sstevel@tonic-gate if (mac && mac->enabled) 764*0Sstevel@tonic-gate buffer_append(&output, (char *)macbuf, mac->mac_len); 765*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 766*0Sstevel@tonic-gate fprintf(stderr, "encrypted: "); 767*0Sstevel@tonic-gate buffer_dump(&output); 768*0Sstevel@tonic-gate #endif 769*0Sstevel@tonic-gate /* increment sequence number for outgoing packets */ 770*0Sstevel@tonic-gate if (++send_seqnr == 0) 771*0Sstevel@tonic-gate log("outgoing seqnr wraps around"); 772*0Sstevel@tonic-gate buffer_clear(&outgoing_packet); 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 775*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 776*0Sstevel@tonic-gate /* set_newkeys(MODE_OUT) in client, server, but not monitor */ 777*0Sstevel@tonic-gate if (!packet_is_server() && !packet_is_monitor()) 778*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 779*0Sstevel@tonic-gate set_newkeys(MODE_OUT); 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate void 783*0Sstevel@tonic-gate packet_send(void) 784*0Sstevel@tonic-gate { 785*0Sstevel@tonic-gate if (compat20) 786*0Sstevel@tonic-gate packet_send2(); 787*0Sstevel@tonic-gate else 788*0Sstevel@tonic-gate packet_send1(); 789*0Sstevel@tonic-gate DBG(debug("packet_send done")); 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate /* 793*0Sstevel@tonic-gate * Waits until a packet has been received, and returns its type. Note that 794*0Sstevel@tonic-gate * no other data is processed until this returns, so this function should not 795*0Sstevel@tonic-gate * be used during the interactive session. 796*0Sstevel@tonic-gate */ 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate int 799*0Sstevel@tonic-gate packet_read_seqnr(u_int32_t *seqnr_p) 800*0Sstevel@tonic-gate { 801*0Sstevel@tonic-gate int type, len; 802*0Sstevel@tonic-gate fd_set *setp; 803*0Sstevel@tonic-gate char buf[8192]; 804*0Sstevel@tonic-gate DBG(debug("packet_read()")); 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 807*0Sstevel@tonic-gate sizeof(fd_mask)); 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate /* Since we are blocking, ensure that all written packets have been sent. */ 810*0Sstevel@tonic-gate packet_write_wait(); 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate /* Stay in the loop until we have received a complete packet. */ 813*0Sstevel@tonic-gate for (;;) { 814*0Sstevel@tonic-gate /* Try to read a packet from the buffer. */ 815*0Sstevel@tonic-gate type = packet_read_poll_seqnr(seqnr_p); 816*0Sstevel@tonic-gate if (!compat20 && ( 817*0Sstevel@tonic-gate type == SSH_SMSG_SUCCESS 818*0Sstevel@tonic-gate || type == SSH_SMSG_FAILURE 819*0Sstevel@tonic-gate || type == SSH_CMSG_EOF 820*0Sstevel@tonic-gate || type == SSH_CMSG_EXIT_CONFIRMATION)) 821*0Sstevel@tonic-gate packet_check_eom(); 822*0Sstevel@tonic-gate /* If we got a packet, return it. */ 823*0Sstevel@tonic-gate if (type != SSH_MSG_NONE) { 824*0Sstevel@tonic-gate xfree(setp); 825*0Sstevel@tonic-gate return type; 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate /* 828*0Sstevel@tonic-gate * Otherwise, wait for some data to arrive, add it to the 829*0Sstevel@tonic-gate * buffer, and try again. 830*0Sstevel@tonic-gate */ 831*0Sstevel@tonic-gate memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 832*0Sstevel@tonic-gate sizeof(fd_mask)); 833*0Sstevel@tonic-gate FD_SET(connection_in, setp); 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate /* Wait for some data to arrive. */ 836*0Sstevel@tonic-gate while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 837*0Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 838*0Sstevel@tonic-gate ; 839*0Sstevel@tonic-gate 840*0Sstevel@tonic-gate /* Read data from the socket. */ 841*0Sstevel@tonic-gate len = read(connection_in, buf, sizeof(buf)); 842*0Sstevel@tonic-gate if (len == 0) { 843*0Sstevel@tonic-gate log("Connection closed by %.200s", get_remote_ipaddr()); 844*0Sstevel@tonic-gate fatal_cleanup(); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate if (len < 0) 847*0Sstevel@tonic-gate fatal("Read from socket failed: %.100s", strerror(errno)); 848*0Sstevel@tonic-gate /* Append it to the buffer. */ 849*0Sstevel@tonic-gate packet_process_incoming(buf, len); 850*0Sstevel@tonic-gate } 851*0Sstevel@tonic-gate /* NOTREACHED */ 852*0Sstevel@tonic-gate } 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gate int 855*0Sstevel@tonic-gate packet_read(void) 856*0Sstevel@tonic-gate { 857*0Sstevel@tonic-gate return packet_read_seqnr(NULL); 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate /* 861*0Sstevel@tonic-gate * Waits until a packet has been received, verifies that its type matches 862*0Sstevel@tonic-gate * that given, and gives a fatal error and exits if there is a mismatch. 863*0Sstevel@tonic-gate */ 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate void 866*0Sstevel@tonic-gate packet_read_expect(int expected_type) 867*0Sstevel@tonic-gate { 868*0Sstevel@tonic-gate int type; 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate type = packet_read(); 871*0Sstevel@tonic-gate if (type != expected_type) 872*0Sstevel@tonic-gate packet_disconnect("Protocol error: expected packet type %d, got %d", 873*0Sstevel@tonic-gate expected_type, type); 874*0Sstevel@tonic-gate } 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate /* Checks if a full packet is available in the data received so far via 877*0Sstevel@tonic-gate * packet_process_incoming. If so, reads the packet; otherwise returns 878*0Sstevel@tonic-gate * SSH_MSG_NONE. This does not wait for data from the connection. 879*0Sstevel@tonic-gate * 880*0Sstevel@tonic-gate * SSH_MSG_DISCONNECT is handled specially here. Also, 881*0Sstevel@tonic-gate * SSH_MSG_IGNORE messages are skipped by this function and are never returned 882*0Sstevel@tonic-gate * to higher levels. 883*0Sstevel@tonic-gate */ 884*0Sstevel@tonic-gate 885*0Sstevel@tonic-gate static int 886*0Sstevel@tonic-gate packet_read_poll1(void) 887*0Sstevel@tonic-gate { 888*0Sstevel@tonic-gate u_int len, padded_len; 889*0Sstevel@tonic-gate u_char *cp, type; 890*0Sstevel@tonic-gate u_int checksum, stored_checksum; 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate /* Check if input size is less than minimum packet size. */ 893*0Sstevel@tonic-gate if (buffer_len(&input) < 4 + 8) 894*0Sstevel@tonic-gate return SSH_MSG_NONE; 895*0Sstevel@tonic-gate /* Get length of incoming packet. */ 896*0Sstevel@tonic-gate cp = buffer_ptr(&input); 897*0Sstevel@tonic-gate len = GET_32BIT(cp); 898*0Sstevel@tonic-gate if (len < 1 + 2 + 2 || len > 256 * 1024) 899*0Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", len); 900*0Sstevel@tonic-gate padded_len = (len + 8) & ~7; 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate /* Check if the packet has been entirely received. */ 903*0Sstevel@tonic-gate if (buffer_len(&input) < 4 + padded_len) 904*0Sstevel@tonic-gate return SSH_MSG_NONE; 905*0Sstevel@tonic-gate 906*0Sstevel@tonic-gate /* The entire packet is in buffer. */ 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate /* Consume packet length. */ 909*0Sstevel@tonic-gate buffer_consume(&input, 4); 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * Cryptographic attack detector for ssh 913*0Sstevel@tonic-gate * (C)1998 CORE-SDI, Buenos Aires Argentina 914*0Sstevel@tonic-gate * Ariel Futoransky(futo@core-sdi.com) 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate if (!receive_context.plaintext && 917*0Sstevel@tonic-gate detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED) 918*0Sstevel@tonic-gate packet_disconnect("crc32 compensation attack: network attack detected"); 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate /* Decrypt data to incoming_packet. */ 921*0Sstevel@tonic-gate buffer_clear(&incoming_packet); 922*0Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, padded_len); 923*0Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate buffer_consume(&input, padded_len); 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 928*0Sstevel@tonic-gate fprintf(stderr, "read_poll plain: "); 929*0Sstevel@tonic-gate buffer_dump(&incoming_packet); 930*0Sstevel@tonic-gate #endif 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate /* Compute packet checksum. */ 933*0Sstevel@tonic-gate checksum = ssh_crc32(buffer_ptr(&incoming_packet), 934*0Sstevel@tonic-gate buffer_len(&incoming_packet) - 4); 935*0Sstevel@tonic-gate 936*0Sstevel@tonic-gate /* Skip padding. */ 937*0Sstevel@tonic-gate buffer_consume(&incoming_packet, 8 - len % 8); 938*0Sstevel@tonic-gate 939*0Sstevel@tonic-gate /* Test check bytes. */ 940*0Sstevel@tonic-gate if (len != buffer_len(&incoming_packet)) 941*0Sstevel@tonic-gate packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 942*0Sstevel@tonic-gate len, buffer_len(&incoming_packet)); 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 945*0Sstevel@tonic-gate stored_checksum = GET_32BIT(cp); 946*0Sstevel@tonic-gate if (checksum != stored_checksum) 947*0Sstevel@tonic-gate packet_disconnect("Corrupted check bytes on input."); 948*0Sstevel@tonic-gate buffer_consume_end(&incoming_packet, 4); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate if (packet_compression) { 951*0Sstevel@tonic-gate buffer_clear(&compression_buffer); 952*0Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 953*0Sstevel@tonic-gate buffer_clear(&incoming_packet); 954*0Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 955*0Sstevel@tonic-gate buffer_len(&compression_buffer)); 956*0Sstevel@tonic-gate } 957*0Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 958*0Sstevel@tonic-gate return type; 959*0Sstevel@tonic-gate } 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate static int 962*0Sstevel@tonic-gate packet_read_poll2(u_int32_t *seqnr_p) 963*0Sstevel@tonic-gate { 964*0Sstevel@tonic-gate static u_int packet_length = 0; 965*0Sstevel@tonic-gate u_int padlen, need; 966*0Sstevel@tonic-gate u_char *macbuf, *cp, type; 967*0Sstevel@tonic-gate int maclen, block_size; 968*0Sstevel@tonic-gate Enc *enc = NULL; 969*0Sstevel@tonic-gate Mac *mac = NULL; 970*0Sstevel@tonic-gate Comp *comp = NULL; 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate if (newkeys[MODE_IN] != NULL) { 973*0Sstevel@tonic-gate enc = &newkeys[MODE_IN]->enc; 974*0Sstevel@tonic-gate mac = &newkeys[MODE_IN]->mac; 975*0Sstevel@tonic-gate comp = &newkeys[MODE_IN]->comp; 976*0Sstevel@tonic-gate } 977*0Sstevel@tonic-gate maclen = mac && mac->enabled ? mac->mac_len : 0; 978*0Sstevel@tonic-gate block_size = enc ? enc->block_size : 8; 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate if (packet_length == 0) { 981*0Sstevel@tonic-gate /* 982*0Sstevel@tonic-gate * check if input size is less than the cipher block size, 983*0Sstevel@tonic-gate * decrypt first block and extract length of incoming packet 984*0Sstevel@tonic-gate */ 985*0Sstevel@tonic-gate if (buffer_len(&input) < block_size) 986*0Sstevel@tonic-gate return SSH_MSG_NONE; 987*0Sstevel@tonic-gate buffer_clear(&incoming_packet); 988*0Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, block_size); 989*0Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), 990*0Sstevel@tonic-gate block_size); 991*0Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 992*0Sstevel@tonic-gate packet_length = GET_32BIT(cp); 993*0Sstevel@tonic-gate if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 994*0Sstevel@tonic-gate buffer_dump(&incoming_packet); 995*0Sstevel@tonic-gate packet_disconnect("Bad packet length %d.", packet_length); 996*0Sstevel@tonic-gate } 997*0Sstevel@tonic-gate DBG(debug("input: packet len %d", packet_length+4)); 998*0Sstevel@tonic-gate buffer_consume(&input, block_size); 999*0Sstevel@tonic-gate } 1000*0Sstevel@tonic-gate /* we have a partial packet of block_size bytes */ 1001*0Sstevel@tonic-gate need = 4 + packet_length - block_size; 1002*0Sstevel@tonic-gate DBG(debug("partial packet %d, need %d, maclen %d", block_size, 1003*0Sstevel@tonic-gate need, maclen)); 1004*0Sstevel@tonic-gate if (need % block_size != 0) 1005*0Sstevel@tonic-gate fatal("padding error: need %d block %d mod %d", 1006*0Sstevel@tonic-gate need, block_size, need % block_size); 1007*0Sstevel@tonic-gate /* 1008*0Sstevel@tonic-gate * check if the entire packet has been received and 1009*0Sstevel@tonic-gate * decrypt into incoming_packet 1010*0Sstevel@tonic-gate */ 1011*0Sstevel@tonic-gate if (buffer_len(&input) < need + maclen) 1012*0Sstevel@tonic-gate return SSH_MSG_NONE; 1013*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 1014*0Sstevel@tonic-gate fprintf(stderr, "read_poll enc/full: "); 1015*0Sstevel@tonic-gate buffer_dump(&input); 1016*0Sstevel@tonic-gate #endif 1017*0Sstevel@tonic-gate cp = buffer_append_space(&incoming_packet, need); 1018*0Sstevel@tonic-gate cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 1019*0Sstevel@tonic-gate buffer_consume(&input, need); 1020*0Sstevel@tonic-gate /* 1021*0Sstevel@tonic-gate * compute MAC over seqnr and packet, 1022*0Sstevel@tonic-gate * increment sequence number for incoming packet 1023*0Sstevel@tonic-gate */ 1024*0Sstevel@tonic-gate if (mac && mac->enabled) { 1025*0Sstevel@tonic-gate macbuf = mac_compute(mac, read_seqnr, 1026*0Sstevel@tonic-gate buffer_ptr(&incoming_packet), 1027*0Sstevel@tonic-gate buffer_len(&incoming_packet)); 1028*0Sstevel@tonic-gate if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 1029*0Sstevel@tonic-gate packet_disconnect("Corrupted MAC on input."); 1030*0Sstevel@tonic-gate DBG(debug("MAC #%d ok", read_seqnr)); 1031*0Sstevel@tonic-gate buffer_consume(&input, mac->mac_len); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate if (seqnr_p != NULL) 1034*0Sstevel@tonic-gate *seqnr_p = read_seqnr; 1035*0Sstevel@tonic-gate if (++read_seqnr == 0) 1036*0Sstevel@tonic-gate log("incoming seqnr wraps around"); 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate /* get padlen */ 1039*0Sstevel@tonic-gate cp = buffer_ptr(&incoming_packet); 1040*0Sstevel@tonic-gate padlen = cp[4]; 1041*0Sstevel@tonic-gate DBG(debug("input: padlen %d", padlen)); 1042*0Sstevel@tonic-gate if (padlen < 4) 1043*0Sstevel@tonic-gate packet_disconnect("Corrupted padlen %d on input.", padlen); 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate /* skip packet size + padlen, discard padding */ 1046*0Sstevel@tonic-gate buffer_consume(&incoming_packet, 4 + 1); 1047*0Sstevel@tonic-gate buffer_consume_end(&incoming_packet, padlen); 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 1050*0Sstevel@tonic-gate if (comp && comp->enabled) { 1051*0Sstevel@tonic-gate buffer_clear(&compression_buffer); 1052*0Sstevel@tonic-gate buffer_uncompress(&incoming_packet, &compression_buffer); 1053*0Sstevel@tonic-gate buffer_clear(&incoming_packet); 1054*0Sstevel@tonic-gate buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 1055*0Sstevel@tonic-gate buffer_len(&compression_buffer)); 1056*0Sstevel@tonic-gate DBG(debug("input: len after de-compress %d", 1057*0Sstevel@tonic-gate buffer_len(&incoming_packet))); 1058*0Sstevel@tonic-gate } 1059*0Sstevel@tonic-gate /* 1060*0Sstevel@tonic-gate * get packet type, implies consume. 1061*0Sstevel@tonic-gate * return length of payload (without type field) 1062*0Sstevel@tonic-gate */ 1063*0Sstevel@tonic-gate type = buffer_get_char(&incoming_packet); 1064*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1065*0Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 1066*0Sstevel@tonic-gate /* set_newkeys(MODE_OUT) in client, server, but not monitor */ 1067*0Sstevel@tonic-gate if (!packet_is_server() && !packet_is_monitor()) 1068*0Sstevel@tonic-gate set_newkeys(MODE_IN); 1069*0Sstevel@tonic-gate #else /* ALTPRIVSEP */ 1070*0Sstevel@tonic-gate if (type == SSH2_MSG_NEWKEYS) 1071*0Sstevel@tonic-gate set_newkeys(MODE_IN); 1072*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1073*0Sstevel@tonic-gate #ifdef PACKET_DEBUG 1074*0Sstevel@tonic-gate fprintf(stderr, "read/plain[%d]:\r\n", type); 1075*0Sstevel@tonic-gate buffer_dump(&incoming_packet); 1076*0Sstevel@tonic-gate #endif 1077*0Sstevel@tonic-gate /* reset for next packet */ 1078*0Sstevel@tonic-gate packet_length = 0; 1079*0Sstevel@tonic-gate return type; 1080*0Sstevel@tonic-gate } 1081*0Sstevel@tonic-gate 1082*0Sstevel@tonic-gate int 1083*0Sstevel@tonic-gate packet_read_poll_seqnr(u_int32_t *seqnr_p) 1084*0Sstevel@tonic-gate { 1085*0Sstevel@tonic-gate u_int reason, seqnr; 1086*0Sstevel@tonic-gate u_char type; 1087*0Sstevel@tonic-gate char *msg; 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate for (;;) { 1090*0Sstevel@tonic-gate if (compat20) { 1091*0Sstevel@tonic-gate type = packet_read_poll2(seqnr_p); 1092*0Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 1093*0Sstevel@tonic-gate switch (type) { 1094*0Sstevel@tonic-gate case SSH2_MSG_IGNORE: 1095*0Sstevel@tonic-gate break; 1096*0Sstevel@tonic-gate case SSH2_MSG_DEBUG: 1097*0Sstevel@tonic-gate packet_get_char(); 1098*0Sstevel@tonic-gate msg = packet_get_string(NULL); 1099*0Sstevel@tonic-gate debug("Remote: %.900s", msg); 1100*0Sstevel@tonic-gate xfree(msg); 1101*0Sstevel@tonic-gate msg = packet_get_string(NULL); 1102*0Sstevel@tonic-gate xfree(msg); 1103*0Sstevel@tonic-gate break; 1104*0Sstevel@tonic-gate case SSH2_MSG_DISCONNECT: 1105*0Sstevel@tonic-gate reason = packet_get_int(); 1106*0Sstevel@tonic-gate msg = packet_get_string(NULL); 1107*0Sstevel@tonic-gate log("Received disconnect from %s: %u: %.400s", 1108*0Sstevel@tonic-gate get_remote_ipaddr(), reason, msg); 1109*0Sstevel@tonic-gate xfree(msg); 1110*0Sstevel@tonic-gate fatal_cleanup(); 1111*0Sstevel@tonic-gate break; 1112*0Sstevel@tonic-gate case SSH2_MSG_UNIMPLEMENTED: 1113*0Sstevel@tonic-gate seqnr = packet_get_int(); 1114*0Sstevel@tonic-gate debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 1115*0Sstevel@tonic-gate seqnr); 1116*0Sstevel@tonic-gate break; 1117*0Sstevel@tonic-gate default: 1118*0Sstevel@tonic-gate return type; 1119*0Sstevel@tonic-gate break; 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate } else { 1122*0Sstevel@tonic-gate type = packet_read_poll1(); 1123*0Sstevel@tonic-gate DBG(debug("received packet type %d", type)); 1124*0Sstevel@tonic-gate switch (type) { 1125*0Sstevel@tonic-gate case SSH_MSG_IGNORE: 1126*0Sstevel@tonic-gate break; 1127*0Sstevel@tonic-gate case SSH_MSG_DEBUG: 1128*0Sstevel@tonic-gate msg = packet_get_string(NULL); 1129*0Sstevel@tonic-gate debug("Remote: %.900s", msg); 1130*0Sstevel@tonic-gate xfree(msg); 1131*0Sstevel@tonic-gate break; 1132*0Sstevel@tonic-gate case SSH_MSG_DISCONNECT: 1133*0Sstevel@tonic-gate msg = packet_get_string(NULL); 1134*0Sstevel@tonic-gate log("Received disconnect from %s: %.400s", 1135*0Sstevel@tonic-gate get_remote_ipaddr(), msg); 1136*0Sstevel@tonic-gate fatal_cleanup(); 1137*0Sstevel@tonic-gate xfree(msg); 1138*0Sstevel@tonic-gate break; 1139*0Sstevel@tonic-gate default: 1140*0Sstevel@tonic-gate return type; 1141*0Sstevel@tonic-gate break; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate int 1148*0Sstevel@tonic-gate packet_read_poll(void) 1149*0Sstevel@tonic-gate { 1150*0Sstevel@tonic-gate return packet_read_poll_seqnr(NULL); 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate 1153*0Sstevel@tonic-gate /* 1154*0Sstevel@tonic-gate * Buffers the given amount of input characters. This is intended to be used 1155*0Sstevel@tonic-gate * together with packet_read_poll. 1156*0Sstevel@tonic-gate */ 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate void 1159*0Sstevel@tonic-gate packet_process_incoming(const char *buf, u_int len) 1160*0Sstevel@tonic-gate { 1161*0Sstevel@tonic-gate buffer_append(&input, buf, len); 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate /* Returns a character from the packet. */ 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate u_int 1167*0Sstevel@tonic-gate packet_get_char(void) 1168*0Sstevel@tonic-gate { 1169*0Sstevel@tonic-gate char ch; 1170*0Sstevel@tonic-gate 1171*0Sstevel@tonic-gate buffer_get(&incoming_packet, &ch, 1); 1172*0Sstevel@tonic-gate return (u_char) ch; 1173*0Sstevel@tonic-gate } 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* Returns an integer from the packet data. */ 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate u_int 1178*0Sstevel@tonic-gate packet_get_int(void) 1179*0Sstevel@tonic-gate { 1180*0Sstevel@tonic-gate return buffer_get_int(&incoming_packet); 1181*0Sstevel@tonic-gate } 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate /* 1184*0Sstevel@tonic-gate * Returns an arbitrary precision integer from the packet data. The integer 1185*0Sstevel@tonic-gate * must have been initialized before this call. 1186*0Sstevel@tonic-gate */ 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate void 1189*0Sstevel@tonic-gate packet_get_bignum(BIGNUM * value) 1190*0Sstevel@tonic-gate { 1191*0Sstevel@tonic-gate buffer_get_bignum(&incoming_packet, value); 1192*0Sstevel@tonic-gate } 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate void 1195*0Sstevel@tonic-gate packet_get_bignum2(BIGNUM * value) 1196*0Sstevel@tonic-gate { 1197*0Sstevel@tonic-gate buffer_get_bignum2(&incoming_packet, value); 1198*0Sstevel@tonic-gate } 1199*0Sstevel@tonic-gate 1200*0Sstevel@tonic-gate void * 1201*0Sstevel@tonic-gate packet_get_raw(u_int *length_ptr) 1202*0Sstevel@tonic-gate { 1203*0Sstevel@tonic-gate u_int bytes = buffer_len(&incoming_packet); 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate if (length_ptr != NULL) 1206*0Sstevel@tonic-gate *length_ptr = bytes; 1207*0Sstevel@tonic-gate return buffer_ptr(&incoming_packet); 1208*0Sstevel@tonic-gate } 1209*0Sstevel@tonic-gate 1210*0Sstevel@tonic-gate int 1211*0Sstevel@tonic-gate packet_remaining(void) 1212*0Sstevel@tonic-gate { 1213*0Sstevel@tonic-gate return buffer_len(&incoming_packet); 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate /* 1217*0Sstevel@tonic-gate * Returns a string from the packet data. The string is allocated using 1218*0Sstevel@tonic-gate * xmalloc; it is the responsibility of the calling program to free it when 1219*0Sstevel@tonic-gate * no longer needed. The length_ptr argument may be NULL, or point to an 1220*0Sstevel@tonic-gate * integer into which the length of the string is stored. 1221*0Sstevel@tonic-gate */ 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate void * 1224*0Sstevel@tonic-gate packet_get_string(u_int *length_ptr) 1225*0Sstevel@tonic-gate { 1226*0Sstevel@tonic-gate return buffer_get_string(&incoming_packet, length_ptr); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate char * 1229*0Sstevel@tonic-gate packet_get_ascii_cstring() 1230*0Sstevel@tonic-gate { 1231*0Sstevel@tonic-gate return buffer_get_ascii_cstring(&incoming_packet); 1232*0Sstevel@tonic-gate } 1233*0Sstevel@tonic-gate u_char * 1234*0Sstevel@tonic-gate packet_get_utf8_cstring() 1235*0Sstevel@tonic-gate { 1236*0Sstevel@tonic-gate return buffer_get_utf8_cstring(&incoming_packet); 1237*0Sstevel@tonic-gate } 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gate /* 1240*0Sstevel@tonic-gate * Sends a diagnostic message from the server to the client. This message 1241*0Sstevel@tonic-gate * can be sent at any time (but not while constructing another message). The 1242*0Sstevel@tonic-gate * message is printed immediately, but only if the client is being executed 1243*0Sstevel@tonic-gate * in verbose mode. These messages are primarily intended to ease debugging 1244*0Sstevel@tonic-gate * authentication problems. The length of the formatted message must not 1245*0Sstevel@tonic-gate * exceed 1024 bytes. This will automatically call packet_write_wait. 1246*0Sstevel@tonic-gate */ 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate void 1249*0Sstevel@tonic-gate packet_send_debug(const char *fmt,...) 1250*0Sstevel@tonic-gate { 1251*0Sstevel@tonic-gate char buf[1024]; 1252*0Sstevel@tonic-gate va_list args; 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate if (compat20 && (datafellows & SSH_BUG_DEBUG)) 1255*0Sstevel@tonic-gate return; 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate va_start(args, fmt); 1258*0Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), gettext(fmt), args); 1259*0Sstevel@tonic-gate va_end(args); 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1262*0Sstevel@tonic-gate /* shouldn't happen */ 1263*0Sstevel@tonic-gate if (packet_monitor) { 1264*0Sstevel@tonic-gate debug("packet_send_debug: %s", buf); 1265*0Sstevel@tonic-gate return; 1266*0Sstevel@tonic-gate } 1267*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate if (compat20) { 1270*0Sstevel@tonic-gate packet_start(SSH2_MSG_DEBUG); 1271*0Sstevel@tonic-gate packet_put_char(0); /* bool: always display */ 1272*0Sstevel@tonic-gate packet_put_cstring(buf); 1273*0Sstevel@tonic-gate packet_put_cstring(""); 1274*0Sstevel@tonic-gate } else { 1275*0Sstevel@tonic-gate packet_start(SSH_MSG_DEBUG); 1276*0Sstevel@tonic-gate packet_put_cstring(buf); 1277*0Sstevel@tonic-gate } 1278*0Sstevel@tonic-gate packet_send(); 1279*0Sstevel@tonic-gate packet_write_wait(); 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate /* 1283*0Sstevel@tonic-gate * Logs the error plus constructs and sends a disconnect packet, closes the 1284*0Sstevel@tonic-gate * connection, and exits. This function never returns. The error message 1285*0Sstevel@tonic-gate * should not contain a newline. The length of the formatted message must 1286*0Sstevel@tonic-gate * not exceed 1024 bytes. 1287*0Sstevel@tonic-gate */ 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate void 1290*0Sstevel@tonic-gate packet_disconnect(const char *fmt,...) 1291*0Sstevel@tonic-gate { 1292*0Sstevel@tonic-gate char buf[1024]; 1293*0Sstevel@tonic-gate va_list args; 1294*0Sstevel@tonic-gate static int disconnecting = 0; 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate if (disconnecting) /* Guard against recursive invocations. */ 1297*0Sstevel@tonic-gate fatal("packet_disconnect called recursively."); 1298*0Sstevel@tonic-gate disconnecting = 1; 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate /* 1301*0Sstevel@tonic-gate * Format the message. Note that the caller must make sure the 1302*0Sstevel@tonic-gate * message is of limited size. 1303*0Sstevel@tonic-gate */ 1304*0Sstevel@tonic-gate va_start(args, fmt); 1305*0Sstevel@tonic-gate vsnprintf(buf, sizeof(buf), fmt, args); 1306*0Sstevel@tonic-gate va_end(args); 1307*0Sstevel@tonic-gate 1308*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1309*0Sstevel@tonic-gate /* 1310*0Sstevel@tonic-gate * If we packet_disconnect() in the monitor the fatal cleanups will take 1311*0Sstevel@tonic-gate * care of the child. See main() in sshd.c. We don't send the packet 1312*0Sstevel@tonic-gate * disconnect message here because: a) the child might not be looking 1313*0Sstevel@tonic-gate * for it and b) because we don't really know if the child is compat20 1314*0Sstevel@tonic-gate * or not as we lost that information when packet_set_monitor() was 1315*0Sstevel@tonic-gate * called. 1316*0Sstevel@tonic-gate */ 1317*0Sstevel@tonic-gate if (packet_monitor) 1318*0Sstevel@tonic-gate goto close_stuff; 1319*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1320*0Sstevel@tonic-gate 1321*0Sstevel@tonic-gate /* Send the disconnect message to the other side, and wait for it to get sent. */ 1322*0Sstevel@tonic-gate if (compat20) { 1323*0Sstevel@tonic-gate packet_start(SSH2_MSG_DISCONNECT); 1324*0Sstevel@tonic-gate packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 1325*0Sstevel@tonic-gate packet_put_cstring(buf); 1326*0Sstevel@tonic-gate packet_put_cstring(""); 1327*0Sstevel@tonic-gate } else { 1328*0Sstevel@tonic-gate packet_start(SSH_MSG_DISCONNECT); 1329*0Sstevel@tonic-gate packet_put_cstring(buf); 1330*0Sstevel@tonic-gate } 1331*0Sstevel@tonic-gate packet_send(); 1332*0Sstevel@tonic-gate packet_write_wait(); 1333*0Sstevel@tonic-gate 1334*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1335*0Sstevel@tonic-gate close_stuff: 1336*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1337*0Sstevel@tonic-gate /* Stop listening for connections. */ 1338*0Sstevel@tonic-gate channel_close_all(); 1339*0Sstevel@tonic-gate 1340*0Sstevel@tonic-gate /* Close the connection. */ 1341*0Sstevel@tonic-gate packet_close(); 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gate /* Display the error locally and exit. */ 1344*0Sstevel@tonic-gate log("Disconnecting: %.100s", buf); 1345*0Sstevel@tonic-gate fatal_cleanup(); 1346*0Sstevel@tonic-gate } 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate /* Checks if there is any buffered output, and tries to write some of the output. */ 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate void 1351*0Sstevel@tonic-gate packet_write_poll(void) 1352*0Sstevel@tonic-gate { 1353*0Sstevel@tonic-gate int len = buffer_len(&output); 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gate if (len > 0) { 1356*0Sstevel@tonic-gate len = write(connection_out, buffer_ptr(&output), len); 1357*0Sstevel@tonic-gate if (len <= 0) { 1358*0Sstevel@tonic-gate if (errno == EAGAIN) 1359*0Sstevel@tonic-gate return; 1360*0Sstevel@tonic-gate else 1361*0Sstevel@tonic-gate fatal("Write failed: %.100s", strerror(errno)); 1362*0Sstevel@tonic-gate } 1363*0Sstevel@tonic-gate buffer_consume(&output, len); 1364*0Sstevel@tonic-gate } 1365*0Sstevel@tonic-gate } 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate /* 1368*0Sstevel@tonic-gate * Calls packet_write_poll repeatedly until all pending output data has been 1369*0Sstevel@tonic-gate * written. 1370*0Sstevel@tonic-gate */ 1371*0Sstevel@tonic-gate 1372*0Sstevel@tonic-gate void 1373*0Sstevel@tonic-gate packet_write_wait(void) 1374*0Sstevel@tonic-gate { 1375*0Sstevel@tonic-gate fd_set *setp; 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 1378*0Sstevel@tonic-gate sizeof(fd_mask)); 1379*0Sstevel@tonic-gate packet_write_poll(); 1380*0Sstevel@tonic-gate while (packet_have_data_to_write()) { 1381*0Sstevel@tonic-gate memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 1382*0Sstevel@tonic-gate sizeof(fd_mask)); 1383*0Sstevel@tonic-gate FD_SET(connection_out, setp); 1384*0Sstevel@tonic-gate while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 1385*0Sstevel@tonic-gate (errno == EAGAIN || errno == EINTR)) 1386*0Sstevel@tonic-gate ; 1387*0Sstevel@tonic-gate packet_write_poll(); 1388*0Sstevel@tonic-gate } 1389*0Sstevel@tonic-gate xfree(setp); 1390*0Sstevel@tonic-gate } 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate /* Returns true if there is buffered data to write to the connection. */ 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gate int 1395*0Sstevel@tonic-gate packet_have_data_to_write(void) 1396*0Sstevel@tonic-gate { 1397*0Sstevel@tonic-gate return buffer_len(&output) != 0; 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate /* Returns true if there is not too much data to write to the connection. */ 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate int 1403*0Sstevel@tonic-gate packet_not_very_much_data_to_write(void) 1404*0Sstevel@tonic-gate { 1405*0Sstevel@tonic-gate if (interactive_mode) 1406*0Sstevel@tonic-gate return buffer_len(&output) < 16384; 1407*0Sstevel@tonic-gate else 1408*0Sstevel@tonic-gate return buffer_len(&output) < 128 * 1024; 1409*0Sstevel@tonic-gate } 1410*0Sstevel@tonic-gate 1411*0Sstevel@tonic-gate /* Informs that the current session is interactive. Sets IP flags for that. */ 1412*0Sstevel@tonic-gate 1413*0Sstevel@tonic-gate void 1414*0Sstevel@tonic-gate packet_set_interactive(int interactive) 1415*0Sstevel@tonic-gate { 1416*0Sstevel@tonic-gate static int called = 0; 1417*0Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1418*0Sstevel@tonic-gate int lowdelay = IPTOS_LOWDELAY; 1419*0Sstevel@tonic-gate int throughput = IPTOS_THROUGHPUT; 1420*0Sstevel@tonic-gate #endif 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate if (called) 1423*0Sstevel@tonic-gate return; 1424*0Sstevel@tonic-gate called = 1; 1425*0Sstevel@tonic-gate 1426*0Sstevel@tonic-gate /* Record that we are in interactive mode. */ 1427*0Sstevel@tonic-gate interactive_mode = interactive; 1428*0Sstevel@tonic-gate 1429*0Sstevel@tonic-gate /* Only set socket options if using a socket. */ 1430*0Sstevel@tonic-gate if (!packet_connection_is_on_socket()) 1431*0Sstevel@tonic-gate return; 1432*0Sstevel@tonic-gate /* 1433*0Sstevel@tonic-gate * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only 1434*0Sstevel@tonic-gate */ 1435*0Sstevel@tonic-gate if (interactive) { 1436*0Sstevel@tonic-gate /* 1437*0Sstevel@tonic-gate * Set IP options for an interactive connection. Use 1438*0Sstevel@tonic-gate * IPTOS_LOWDELAY and TCP_NODELAY. 1439*0Sstevel@tonic-gate */ 1440*0Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1441*0Sstevel@tonic-gate if (packet_connection_is_ipv4()) { 1442*0Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, 1443*0Sstevel@tonic-gate &lowdelay, sizeof(lowdelay)) < 0) 1444*0Sstevel@tonic-gate error("setsockopt IPTOS_LOWDELAY: %.100s", 1445*0Sstevel@tonic-gate strerror(errno)); 1446*0Sstevel@tonic-gate } 1447*0Sstevel@tonic-gate #endif 1448*0Sstevel@tonic-gate set_nodelay(connection_in); 1449*0Sstevel@tonic-gate } 1450*0Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1451*0Sstevel@tonic-gate else if (packet_connection_is_ipv4()) { 1452*0Sstevel@tonic-gate /* 1453*0Sstevel@tonic-gate * Set IP options for a non-interactive connection. Use 1454*0Sstevel@tonic-gate * IPTOS_THROUGHPUT. 1455*0Sstevel@tonic-gate */ 1456*0Sstevel@tonic-gate if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, 1457*0Sstevel@tonic-gate sizeof(throughput)) < 0) 1458*0Sstevel@tonic-gate error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); 1459*0Sstevel@tonic-gate } 1460*0Sstevel@tonic-gate #endif 1461*0Sstevel@tonic-gate } 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate /* Returns true if the current connection is interactive. */ 1464*0Sstevel@tonic-gate 1465*0Sstevel@tonic-gate int 1466*0Sstevel@tonic-gate packet_is_interactive(void) 1467*0Sstevel@tonic-gate { 1468*0Sstevel@tonic-gate return interactive_mode; 1469*0Sstevel@tonic-gate } 1470*0Sstevel@tonic-gate 1471*0Sstevel@tonic-gate int 1472*0Sstevel@tonic-gate packet_set_maxsize(int s) 1473*0Sstevel@tonic-gate { 1474*0Sstevel@tonic-gate static int called = 0; 1475*0Sstevel@tonic-gate 1476*0Sstevel@tonic-gate if (called) { 1477*0Sstevel@tonic-gate log("packet_set_maxsize: called twice: old %d new %d", 1478*0Sstevel@tonic-gate max_packet_size, s); 1479*0Sstevel@tonic-gate return -1; 1480*0Sstevel@tonic-gate } 1481*0Sstevel@tonic-gate if (s < 4 * 1024 || s > 1024 * 1024) { 1482*0Sstevel@tonic-gate log("packet_set_maxsize: bad size %d", s); 1483*0Sstevel@tonic-gate return -1; 1484*0Sstevel@tonic-gate } 1485*0Sstevel@tonic-gate called = 1; 1486*0Sstevel@tonic-gate debug("packet_set_maxsize: setting to %d", s); 1487*0Sstevel@tonic-gate max_packet_size = s; 1488*0Sstevel@tonic-gate return s; 1489*0Sstevel@tonic-gate } 1490*0Sstevel@tonic-gate 1491*0Sstevel@tonic-gate /* roundup current message to pad bytes */ 1492*0Sstevel@tonic-gate void 1493*0Sstevel@tonic-gate packet_add_padding(u_char pad) 1494*0Sstevel@tonic-gate { 1495*0Sstevel@tonic-gate extra_pad = pad; 1496*0Sstevel@tonic-gate } 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gate /* 1499*0Sstevel@tonic-gate * 9.2. Ignored Data Message 1500*0Sstevel@tonic-gate * 1501*0Sstevel@tonic-gate * byte SSH_MSG_IGNORE 1502*0Sstevel@tonic-gate * string data 1503*0Sstevel@tonic-gate * 1504*0Sstevel@tonic-gate * All implementations MUST understand (and ignore) this message at any 1505*0Sstevel@tonic-gate * time (after receiving the protocol version). No implementation is 1506*0Sstevel@tonic-gate * required to send them. This message can be used as an additional 1507*0Sstevel@tonic-gate * protection measure against advanced traffic analysis techniques. 1508*0Sstevel@tonic-gate */ 1509*0Sstevel@tonic-gate void 1510*0Sstevel@tonic-gate packet_send_ignore(int nbytes) 1511*0Sstevel@tonic-gate { 1512*0Sstevel@tonic-gate u_int32_t rand = 0; 1513*0Sstevel@tonic-gate int i; 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1516*0Sstevel@tonic-gate /* shouldn't happen -- see packet_set_monitor() */ 1517*0Sstevel@tonic-gate if (packet_monitor) 1518*0Sstevel@tonic-gate return; 1519*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 1522*0Sstevel@tonic-gate packet_put_int(nbytes); 1523*0Sstevel@tonic-gate for (i = 0; i < nbytes; i++) { 1524*0Sstevel@tonic-gate if (i % 4 == 0) 1525*0Sstevel@tonic-gate rand = arc4random(); 1526*0Sstevel@tonic-gate packet_put_char(rand & 0xff); 1527*0Sstevel@tonic-gate rand >>= 8; 1528*0Sstevel@tonic-gate } 1529*0Sstevel@tonic-gate } 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1532*0Sstevel@tonic-gate void 1533*0Sstevel@tonic-gate packet_set_server(void) 1534*0Sstevel@tonic-gate { 1535*0Sstevel@tonic-gate packet_server = 1; 1536*0Sstevel@tonic-gate } 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate void 1539*0Sstevel@tonic-gate packet_set_no_monitor(void) 1540*0Sstevel@tonic-gate { 1541*0Sstevel@tonic-gate packet_server = 0; 1542*0Sstevel@tonic-gate } 1543*0Sstevel@tonic-gate 1544*0Sstevel@tonic-gate int 1545*0Sstevel@tonic-gate packet_is_server(void) 1546*0Sstevel@tonic-gate { 1547*0Sstevel@tonic-gate return (packet_server); 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate void 1551*0Sstevel@tonic-gate packet_set_monitor(int pipe) 1552*0Sstevel@tonic-gate { 1553*0Sstevel@tonic-gate int dup_fd; 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate packet_server = 1; 1556*0Sstevel@tonic-gate packet_monitor = 1; 1557*0Sstevel@tonic-gate 1558*0Sstevel@tonic-gate /* 1559*0Sstevel@tonic-gate * Awful hack follows. 1560*0Sstevel@tonic-gate * 1561*0Sstevel@tonic-gate * For SSHv1 the monitor does not process any SSHv1 packets, only 1562*0Sstevel@tonic-gate * ALTPRIVSEP packets. We take advantage of that here to keep changes 1563*0Sstevel@tonic-gate * to packet.c to a minimum by using the SSHv2 binary packet protocol, 1564*0Sstevel@tonic-gate * with cipher "none," mac "none" and compression alg "none," as the 1565*0Sstevel@tonic-gate * basis for the monitor protocol. And so to force packet.c to treat 1566*0Sstevel@tonic-gate * packets as SSHv2 we force compat20 == 1 here. 1567*0Sstevel@tonic-gate * 1568*0Sstevel@tonic-gate * For completeness and to help future developers catch this we also 1569*0Sstevel@tonic-gate * force compat20 == 1 in the monitor loop, in serverloop.c. 1570*0Sstevel@tonic-gate */ 1571*0Sstevel@tonic-gate compat20 = 1; 1572*0Sstevel@tonic-gate 1573*0Sstevel@tonic-gate /* 1574*0Sstevel@tonic-gate * NOTE: Assumptions below! 1575*0Sstevel@tonic-gate * 1576*0Sstevel@tonic-gate * - lots of packet.c code assumes that (connection_in == 1577*0Sstevel@tonic-gate * connection_out) -> connection is socket 1578*0Sstevel@tonic-gate * 1579*0Sstevel@tonic-gate * - packet_close() does not shutdown() the connection fildes 1580*0Sstevel@tonic-gate * if connection_in != connection_out 1581*0Sstevel@tonic-gate * 1582*0Sstevel@tonic-gate * - other code assumes the connection is a socket if 1583*0Sstevel@tonic-gate * connection_in == connection_out 1584*0Sstevel@tonic-gate */ 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate if ((dup_fd = dup(pipe)) < 0) 1587*0Sstevel@tonic-gate fatal("Monitor failed to start: %s", strerror(errno)); 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate /* 1590*0Sstevel@tonic-gate * make sure that the monitor's child's socket is not shutdown(3SOCKET) 1591*0Sstevel@tonic-gate * when we packet_close() 1592*0Sstevel@tonic-gate */ 1593*0Sstevel@tonic-gate if (packet_connection_is_on_socket()) 1594*0Sstevel@tonic-gate connection_out = -1; 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate /* now cleanup state related to ssh socket */ 1597*0Sstevel@tonic-gate packet_close(); 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate /* now make the monitor pipe look like the ssh connection */ 1600*0Sstevel@tonic-gate packet_set_connection(pipe, dup_fd); 1601*0Sstevel@tonic-gate } 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate int 1604*0Sstevel@tonic-gate packet_is_monitor(void) 1605*0Sstevel@tonic-gate { 1606*0Sstevel@tonic-gate return (packet_monitor); 1607*0Sstevel@tonic-gate } 1608*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1609