packet.c revision 192595
1192595Sdes/* $OpenBSD: packet.c,v 1.160 2009/02/13 11:50:21 markus Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 657429Smarkm * This file contains code implementing the packet protocol and communication 757429Smarkm * with the other side. This same code is used both on client and server side. 860573Skris * 965668Skris * As far as I am concerned, the code I have written for this software 1065668Skris * can be used freely for any purpose. Any derived versions of this 1165668Skris * software must be clearly marked as such, and if the derived work is 1265668Skris * incompatible with the protocol description in the RFC file, it must be 1365668Skris * called by a name other than "ssh" or "Secure Shell". 1465668Skris * 1565668Skris * 1660573Skris * SSH2 packet format added by Markus Friedl. 1792555Sdes * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 1860573Skris * 1965668Skris * Redistribution and use in source and binary forms, with or without 2065668Skris * modification, are permitted provided that the following conditions 2165668Skris * are met: 2265668Skris * 1. Redistributions of source code must retain the above copyright 2365668Skris * notice, this list of conditions and the following disclaimer. 2465668Skris * 2. Redistributions in binary form must reproduce the above copyright 2565668Skris * notice, this list of conditions and the following disclaimer in the 2665668Skris * documentation and/or other materials provided with the distribution. 2765668Skris * 2865668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2965668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 3065668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 3165668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 3265668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3365668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3465668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3565668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3665668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3765668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3857429Smarkm */ 3957429Smarkm 4057429Smarkm#include "includes.h" 41162852Sdes 42162852Sdes#include <sys/types.h> 43124208Sdes#include "openbsd-compat/sys-queue.h" 44162852Sdes#include <sys/param.h> 45162852Sdes#include <sys/socket.h> 46162852Sdes#ifdef HAVE_SYS_TIME_H 47162852Sdes# include <sys/time.h> 48162852Sdes#endif 49124208Sdes 50162852Sdes#include <netinet/in.h> 51162852Sdes#include <netinet/ip.h> 52162852Sdes#include <arpa/inet.h> 53162852Sdes 54162852Sdes#include <errno.h> 55162852Sdes#include <stdarg.h> 56162852Sdes#include <stdio.h> 57162852Sdes#include <stdlib.h> 58162852Sdes#include <string.h> 59162852Sdes#include <unistd.h> 60162852Sdes#include <signal.h> 61162852Sdes 6257429Smarkm#include "xmalloc.h" 6357429Smarkm#include "buffer.h" 6457429Smarkm#include "packet.h" 6557429Smarkm#include "crc32.h" 6657429Smarkm#include "compress.h" 6757429Smarkm#include "deattack.h" 6860573Skris#include "channels.h" 6960573Skris#include "compat.h" 7076259Sgreen#include "ssh1.h" 7160573Skris#include "ssh2.h" 7269587Sgreen#include "cipher.h" 73162852Sdes#include "key.h" 7460573Skris#include "kex.h" 7576259Sgreen#include "mac.h" 7676259Sgreen#include "log.h" 7776259Sgreen#include "canohost.h" 7892555Sdes#include "misc.h" 7998675Sdes#include "ssh.h" 8060573Skris 8160573Skris#ifdef PACKET_DEBUG 8260573Skris#define DBG(x) x 8360573Skris#else 8460573Skris#define DBG(x) 8560573Skris#endif 8660573Skris 87192595Sdes#define PACKET_MAX_SIZE (256 * 1024) 88192595Sdes 8957429Smarkm/* 9057429Smarkm * This variable contains the file descriptors used for communicating with 9157429Smarkm * the other side. connection_in is used for reading; connection_out for 9257429Smarkm * writing. These can be the same descriptor, in which case it is assumed to 9357429Smarkm * be a socket. 9457429Smarkm */ 9557429Smarkmstatic int connection_in = -1; 9657429Smarkmstatic int connection_out = -1; 9757429Smarkm 9857429Smarkm/* Protocol flags for the remote side. */ 9976259Sgreenstatic u_int remote_protocol_flags = 0; 10057429Smarkm 10157429Smarkm/* Encryption context for receiving data. This is only used for decryption. */ 10257429Smarkmstatic CipherContext receive_context; 10357429Smarkm 10457429Smarkm/* Encryption context for sending data. This is only used for encryption. */ 10557429Smarkmstatic CipherContext send_context; 10657429Smarkm 10757429Smarkm/* Buffer for raw input data from the socket. */ 10898675SdesBuffer input; 10957429Smarkm 11057429Smarkm/* Buffer for raw output data going to the socket. */ 11198675SdesBuffer output; 11257429Smarkm 11357429Smarkm/* Buffer for the partial outgoing packet being constructed. */ 11457429Smarkmstatic Buffer outgoing_packet; 11557429Smarkm 11657429Smarkm/* Buffer for the incoming packet currently being processed. */ 11757429Smarkmstatic Buffer incoming_packet; 11857429Smarkm 11957429Smarkm/* Scratch buffer for packet compression/decompression. */ 12057429Smarkmstatic Buffer compression_buffer; 12176259Sgreenstatic int compression_buffer_ready = 0; 12257429Smarkm 12357429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */ 12457429Smarkmstatic int packet_compression = 0; 12557429Smarkm 12657429Smarkm/* default maximum packet size */ 127124208Sdesu_int max_packet_size = 32768; 12857429Smarkm 12957429Smarkm/* Flag indicating whether this module has been initialized. */ 13057429Smarkmstatic int initialized = 0; 13157429Smarkm 13257429Smarkm/* Set to true if the connection is interactive. */ 13357429Smarkmstatic int interactive_mode = 0; 13457429Smarkm 135149749Sdes/* Set to true if we are the server side. */ 136149749Sdesstatic int server_side = 0; 137149749Sdes 138149749Sdes/* Set to true if we are authenticated. */ 139149749Sdesstatic int after_authentication = 0; 140149749Sdes 141181111Sdesint keep_alive_timeouts = 0; 142181111Sdes 143181111Sdes/* Set to the maximum time that we will wait to send or receive a packet */ 144181111Sdesstatic int packet_timeout_ms = -1; 145181111Sdes 14660573Skris/* Session key information for Encryption and MAC */ 14776259SgreenNewkeys *newkeys[MODE_MAX]; 148124208Sdesstatic struct packet_state { 149124208Sdes u_int32_t seqnr; 150124208Sdes u_int32_t packets; 151124208Sdes u_int64_t blocks; 152181111Sdes u_int64_t bytes; 153124208Sdes} p_read, p_send; 15460573Skris 155124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out; 156124208Sdesstatic u_int32_t rekey_limit; 157124208Sdes 15898675Sdes/* Session key for protocol v1 */ 15998675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 16098675Sdesstatic u_int ssh1_keylen; 16198675Sdes 16292555Sdes/* roundup current message to extra_pad bytes */ 16392555Sdesstatic u_char extra_pad = 0; 16460573Skris 165192595Sdes/* XXX discard incoming data after MAC error */ 166192595Sdesstatic u_int packet_discard = 0; 167192595Sdesstatic Mac *packet_discard_mac = NULL; 168192595Sdes 169124208Sdesstruct packet { 170124208Sdes TAILQ_ENTRY(packet) next; 171124208Sdes u_char type; 172124208Sdes Buffer payload; 173124208Sdes}; 174124208SdesTAILQ_HEAD(, packet) outgoing; 175124208Sdes 17657429Smarkm/* 17757429Smarkm * Sets the descriptors used for communication. Disables encryption until 17857429Smarkm * packet_set_encryption_key is called. 17957429Smarkm */ 18057429Smarkmvoid 18157429Smarkmpacket_set_connection(int fd_in, int fd_out) 18257429Smarkm{ 18369587Sgreen Cipher *none = cipher_by_name("none"); 184106121Sdes 18569587Sgreen if (none == NULL) 18669587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 18757429Smarkm connection_in = fd_in; 18857429Smarkm connection_out = fd_out; 189137015Sdes cipher_init(&send_context, none, (const u_char *)"", 190137015Sdes 0, NULL, 0, CIPHER_ENCRYPT); 191137015Sdes cipher_init(&receive_context, none, (const u_char *)"", 192137015Sdes 0, NULL, 0, CIPHER_DECRYPT); 19392555Sdes newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 19457429Smarkm if (!initialized) { 19557429Smarkm initialized = 1; 19657429Smarkm buffer_init(&input); 19757429Smarkm buffer_init(&output); 19857429Smarkm buffer_init(&outgoing_packet); 19957429Smarkm buffer_init(&incoming_packet); 200124208Sdes TAILQ_INIT(&outgoing); 201181111Sdes p_send.packets = p_read.packets = 0; 20257429Smarkm } 20357429Smarkm} 20457429Smarkm 205181111Sdesvoid 206181111Sdespacket_set_timeout(int timeout, int count) 207181111Sdes{ 208181111Sdes if (timeout == 0 || count == 0) { 209181111Sdes packet_timeout_ms = -1; 210181111Sdes return; 211181111Sdes } 212181111Sdes if ((INT_MAX / 1000) / count < timeout) 213181111Sdes packet_timeout_ms = INT_MAX; 214181111Sdes else 215181111Sdes packet_timeout_ms = timeout * count * 1000; 216181111Sdes} 217181111Sdes 218192595Sdesstatic void 219192595Sdespacket_stop_discard(void) 220192595Sdes{ 221192595Sdes if (packet_discard_mac) { 222192595Sdes char buf[1024]; 223192595Sdes 224192595Sdes memset(buf, 'a', sizeof(buf)); 225192595Sdes while (buffer_len(&incoming_packet) < PACKET_MAX_SIZE) 226192595Sdes buffer_append(&incoming_packet, buf, sizeof(buf)); 227192595Sdes (void) mac_compute(packet_discard_mac, 228192595Sdes p_read.seqnr, 229192595Sdes buffer_ptr(&incoming_packet), 230192595Sdes PACKET_MAX_SIZE); 231192595Sdes } 232192595Sdes logit("Finished discarding for %.200s", get_remote_ipaddr()); 233192595Sdes cleanup_exit(255); 234192595Sdes} 235192595Sdes 236192595Sdesstatic void 237192595Sdespacket_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) 238192595Sdes{ 239192595Sdes if (enc == NULL || !cipher_is_cbc(enc->cipher)) 240192595Sdes packet_disconnect("Packet corrupt"); 241192595Sdes if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) 242192595Sdes packet_discard_mac = mac; 243192595Sdes if (buffer_len(&input) >= discard) 244192595Sdes packet_stop_discard(); 245192595Sdes packet_discard = discard - buffer_len(&input); 246192595Sdes} 247192595Sdes 24857429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 24957429Smarkm 25057429Smarkmint 25192555Sdespacket_connection_is_on_socket(void) 25257429Smarkm{ 25357429Smarkm struct sockaddr_storage from, to; 25457429Smarkm socklen_t fromlen, tolen; 25557429Smarkm 25657429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 25757429Smarkm if (connection_in == connection_out) 25857429Smarkm return 1; 25957429Smarkm fromlen = sizeof(from); 26057429Smarkm memset(&from, 0, sizeof(from)); 26157429Smarkm if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 26257429Smarkm return 0; 26357429Smarkm tolen = sizeof(to); 26457429Smarkm memset(&to, 0, sizeof(to)); 26557429Smarkm if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 26657429Smarkm return 0; 26757429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 26857429Smarkm return 0; 26957429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 27057429Smarkm return 0; 27157429Smarkm return 1; 27257429Smarkm} 27357429Smarkm 27498675Sdes/* 27598675Sdes * Exports an IV from the CipherContext required to export the key 27698675Sdes * state back from the unprivileged child to the privileged parent 27798675Sdes * process. 27898675Sdes */ 27998675Sdes 28098675Sdesvoid 28198675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 28298675Sdes{ 28398675Sdes CipherContext *cc; 28498675Sdes 28598675Sdes if (mode == MODE_OUT) 28698675Sdes cc = &send_context; 28798675Sdes else 28898675Sdes cc = &receive_context; 28998675Sdes 29098675Sdes cipher_get_keyiv(cc, iv, len); 29198675Sdes} 29298675Sdes 29398675Sdesint 29498675Sdespacket_get_keycontext(int mode, u_char *dat) 29598675Sdes{ 29698675Sdes CipherContext *cc; 29798675Sdes 29898675Sdes if (mode == MODE_OUT) 29998675Sdes cc = &send_context; 30098675Sdes else 30198675Sdes cc = &receive_context; 30298675Sdes 30398675Sdes return (cipher_get_keycontext(cc, dat)); 30498675Sdes} 30598675Sdes 30698675Sdesvoid 30798675Sdespacket_set_keycontext(int mode, u_char *dat) 30898675Sdes{ 30998675Sdes CipherContext *cc; 31098675Sdes 31198675Sdes if (mode == MODE_OUT) 31298675Sdes cc = &send_context; 31398675Sdes else 31498675Sdes cc = &receive_context; 31598675Sdes 31698675Sdes cipher_set_keycontext(cc, dat); 31798675Sdes} 31898675Sdes 31998675Sdesint 32098675Sdespacket_get_keyiv_len(int mode) 32198675Sdes{ 32298675Sdes CipherContext *cc; 32398675Sdes 32498675Sdes if (mode == MODE_OUT) 32598675Sdes cc = &send_context; 32698675Sdes else 32798675Sdes cc = &receive_context; 32898675Sdes 32998675Sdes return (cipher_get_keyiv_len(cc)); 33098675Sdes} 331162852Sdes 33298675Sdesvoid 33398675Sdespacket_set_iv(int mode, u_char *dat) 33498675Sdes{ 33598675Sdes CipherContext *cc; 33698675Sdes 33798675Sdes if (mode == MODE_OUT) 33898675Sdes cc = &send_context; 33998675Sdes else 34098675Sdes cc = &receive_context; 34198675Sdes 34298675Sdes cipher_set_keyiv(cc, dat); 34398675Sdes} 344162852Sdes 34598675Sdesint 346124208Sdespacket_get_ssh1_cipher(void) 34798675Sdes{ 34898675Sdes return (cipher_get_number(receive_context.cipher)); 34998675Sdes} 35098675Sdes 351124208Sdesvoid 352181111Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets, 353181111Sdes u_int64_t *bytes) 354124208Sdes{ 355124208Sdes struct packet_state *state; 35698675Sdes 357124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 358181111Sdes if (seqnr) 359181111Sdes *seqnr = state->seqnr; 360181111Sdes if (blocks) 361181111Sdes *blocks = state->blocks; 362181111Sdes if (packets) 363181111Sdes *packets = state->packets; 364181111Sdes if (bytes) 365181111Sdes *bytes = state->bytes; 36698675Sdes} 36798675Sdes 36898675Sdesvoid 369181111Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, 370181111Sdes u_int64_t bytes) 37198675Sdes{ 372124208Sdes struct packet_state *state; 373124208Sdes 374124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 375124208Sdes state->seqnr = seqnr; 376124208Sdes state->blocks = blocks; 377124208Sdes state->packets = packets; 378181111Sdes state->bytes = bytes; 37998675Sdes} 38098675Sdes 38157429Smarkm/* returns 1 if connection is via ipv4 */ 38257429Smarkm 38357429Smarkmint 38492555Sdespacket_connection_is_ipv4(void) 38557429Smarkm{ 38657429Smarkm struct sockaddr_storage to; 38757429Smarkm socklen_t tolen = sizeof(to); 38857429Smarkm 38957429Smarkm memset(&to, 0, sizeof(to)); 39057429Smarkm if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 39157429Smarkm return 0; 39298937Sdes if (to.ss_family == AF_INET) 39398937Sdes return 1; 39498937Sdes#ifdef IPV4_IN_IPV6 395126274Sdes if (to.ss_family == AF_INET6 && 39698937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 39798937Sdes return 1; 39898937Sdes#endif 39998937Sdes return 0; 40057429Smarkm} 40157429Smarkm 40257429Smarkm/* Sets the connection into non-blocking mode. */ 40357429Smarkm 40457429Smarkmvoid 40592555Sdespacket_set_nonblocking(void) 40657429Smarkm{ 40757429Smarkm /* Set the socket into non-blocking mode. */ 408137015Sdes set_nonblock(connection_in); 40957429Smarkm 410137015Sdes if (connection_out != connection_in) 411137015Sdes set_nonblock(connection_out); 41257429Smarkm} 41357429Smarkm 41457429Smarkm/* Returns the socket used for reading. */ 41557429Smarkm 41657429Smarkmint 41792555Sdespacket_get_connection_in(void) 41857429Smarkm{ 41957429Smarkm return connection_in; 42057429Smarkm} 42157429Smarkm 42257429Smarkm/* Returns the descriptor used for writing. */ 42357429Smarkm 42457429Smarkmint 42592555Sdespacket_get_connection_out(void) 42657429Smarkm{ 42757429Smarkm return connection_out; 42857429Smarkm} 42957429Smarkm 43057429Smarkm/* Closes the connection and clears and frees internal data structures. */ 43157429Smarkm 43257429Smarkmvoid 43392555Sdespacket_close(void) 43457429Smarkm{ 43557429Smarkm if (!initialized) 43657429Smarkm return; 43757429Smarkm initialized = 0; 43857429Smarkm if (connection_in == connection_out) { 43957429Smarkm shutdown(connection_out, SHUT_RDWR); 44057429Smarkm close(connection_out); 44157429Smarkm } else { 44257429Smarkm close(connection_in); 44357429Smarkm close(connection_out); 44457429Smarkm } 44557429Smarkm buffer_free(&input); 44657429Smarkm buffer_free(&output); 44757429Smarkm buffer_free(&outgoing_packet); 44857429Smarkm buffer_free(&incoming_packet); 44976259Sgreen if (compression_buffer_ready) { 45057429Smarkm buffer_free(&compression_buffer); 45157429Smarkm buffer_compress_uninit(); 45257429Smarkm } 45392555Sdes cipher_cleanup(&send_context); 45492555Sdes cipher_cleanup(&receive_context); 45557429Smarkm} 45657429Smarkm 45757429Smarkm/* Sets remote side protocol flags. */ 45857429Smarkm 45957429Smarkmvoid 46076259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 46157429Smarkm{ 46257429Smarkm remote_protocol_flags = protocol_flags; 46357429Smarkm} 46457429Smarkm 46557429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 46657429Smarkm 46776259Sgreenu_int 46892555Sdespacket_get_protocol_flags(void) 46957429Smarkm{ 47057429Smarkm return remote_protocol_flags; 47157429Smarkm} 47257429Smarkm 47357429Smarkm/* 47457429Smarkm * Starts packet compression from the next packet on in both directions. 47557429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 47657429Smarkm */ 47757429Smarkm 47892555Sdesstatic void 47992555Sdespacket_init_compression(void) 48076259Sgreen{ 48176259Sgreen if (compression_buffer_ready == 1) 48276259Sgreen return; 48376259Sgreen compression_buffer_ready = 1; 48476259Sgreen buffer_init(&compression_buffer); 48576259Sgreen} 48676259Sgreen 48776259Sgreenvoid 48857429Smarkmpacket_start_compression(int level) 48957429Smarkm{ 49092555Sdes if (packet_compression && !compat20) 49157429Smarkm fatal("Compression already enabled."); 49257429Smarkm packet_compression = 1; 49376259Sgreen packet_init_compression(); 49476259Sgreen buffer_compress_init_send(level); 49576259Sgreen buffer_compress_init_recv(); 49657429Smarkm} 49757429Smarkm 49857429Smarkm/* 49957429Smarkm * Causes any further packets to be encrypted using the given key. The same 50057429Smarkm * key is used for both sending and reception. However, both directions are 50157429Smarkm * encrypted independently of each other. 50257429Smarkm */ 50398675Sdes 50457429Smarkmvoid 50576259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen, 50669587Sgreen int number) 50757429Smarkm{ 50869587Sgreen Cipher *cipher = cipher_by_number(number); 509106121Sdes 51069587Sgreen if (cipher == NULL) 51169587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 51260573Skris if (keylen < 20) 51369587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 51498675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 51598675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 51698675Sdes memcpy(ssh1_key, key, keylen); 51798675Sdes ssh1_keylen = keylen; 51892555Sdes cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 51992555Sdes cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 52057429Smarkm} 52157429Smarkm 52298675Sdesu_int 52398675Sdespacket_get_encryption_key(u_char *key) 52498675Sdes{ 52598675Sdes if (key == NULL) 52698675Sdes return (ssh1_keylen); 52798675Sdes memcpy(key, ssh1_key, ssh1_keylen); 52898675Sdes return (ssh1_keylen); 52998675Sdes} 53098675Sdes 53192555Sdes/* Start constructing a packet to send. */ 53257429Smarkmvoid 53392555Sdespacket_start(u_char type) 53457429Smarkm{ 53592555Sdes u_char buf[9]; 53692555Sdes int len; 53757429Smarkm 53892555Sdes DBG(debug("packet_start[%d]", type)); 53992555Sdes len = compat20 ? 6 : 9; 54092555Sdes memset(buf, 0, len - 1); 54192555Sdes buf[len - 1] = type; 54257429Smarkm buffer_clear(&outgoing_packet); 54392555Sdes buffer_append(&outgoing_packet, buf, len); 54457429Smarkm} 54557429Smarkm 54692555Sdes/* Append payload. */ 54760573Skrisvoid 54857429Smarkmpacket_put_char(int value) 54957429Smarkm{ 55057429Smarkm char ch = value; 551106121Sdes 55257429Smarkm buffer_append(&outgoing_packet, &ch, 1); 55357429Smarkm} 554162852Sdes 55557429Smarkmvoid 55676259Sgreenpacket_put_int(u_int value) 55757429Smarkm{ 55857429Smarkm buffer_put_int(&outgoing_packet, value); 55957429Smarkm} 560162852Sdes 56157429Smarkmvoid 56292555Sdespacket_put_string(const void *buf, u_int len) 56357429Smarkm{ 56457429Smarkm buffer_put_string(&outgoing_packet, buf, len); 56557429Smarkm} 566162852Sdes 56760573Skrisvoid 56860573Skrispacket_put_cstring(const char *str) 56960573Skris{ 57092555Sdes buffer_put_cstring(&outgoing_packet, str); 57160573Skris} 572162852Sdes 57360573Skrisvoid 57492555Sdespacket_put_raw(const void *buf, u_int len) 57560573Skris{ 57660573Skris buffer_append(&outgoing_packet, buf, len); 57760573Skris} 578162852Sdes 57957429Smarkmvoid 58057429Smarkmpacket_put_bignum(BIGNUM * value) 58157429Smarkm{ 58257429Smarkm buffer_put_bignum(&outgoing_packet, value); 58357429Smarkm} 584162852Sdes 58560573Skrisvoid 58660573Skrispacket_put_bignum2(BIGNUM * value) 58760573Skris{ 58860573Skris buffer_put_bignum2(&outgoing_packet, value); 58960573Skris} 59057429Smarkm 59157429Smarkm/* 59257429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 59357429Smarkm * encrypts the packet before sending. 59457429Smarkm */ 59557429Smarkm 59692555Sdesstatic void 59776259Sgreenpacket_send1(void) 59857429Smarkm{ 59992555Sdes u_char buf[8], *cp; 60057429Smarkm int i, padding, len; 60176259Sgreen u_int checksum; 602137015Sdes u_int32_t rnd = 0; 60357429Smarkm 60457429Smarkm /* 60557429Smarkm * If using packet compression, compress the payload of the outgoing 60657429Smarkm * packet. 60757429Smarkm */ 60857429Smarkm if (packet_compression) { 60957429Smarkm buffer_clear(&compression_buffer); 61057429Smarkm /* Skip padding. */ 61157429Smarkm buffer_consume(&outgoing_packet, 8); 61257429Smarkm /* padding */ 61357429Smarkm buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 61457429Smarkm buffer_compress(&outgoing_packet, &compression_buffer); 61557429Smarkm buffer_clear(&outgoing_packet); 61657429Smarkm buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 61792555Sdes buffer_len(&compression_buffer)); 61857429Smarkm } 61957429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 62057429Smarkm len = buffer_len(&outgoing_packet) + 4 - 8; 62157429Smarkm 62260573Skris /* Insert padding. Initialized to zero in packet_start1() */ 62357429Smarkm padding = 8 - len % 8; 62492555Sdes if (!send_context.plaintext) { 62557429Smarkm cp = buffer_ptr(&outgoing_packet); 62657429Smarkm for (i = 0; i < padding; i++) { 62757429Smarkm if (i % 4 == 0) 628137015Sdes rnd = arc4random(); 629137015Sdes cp[7 - i] = rnd & 0xff; 630137015Sdes rnd >>= 8; 63157429Smarkm } 63257429Smarkm } 63357429Smarkm buffer_consume(&outgoing_packet, 8 - padding); 63457429Smarkm 63557429Smarkm /* Add check bytes. */ 63692555Sdes checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 63765668Skris buffer_len(&outgoing_packet)); 638162852Sdes put_u32(buf, checksum); 63957429Smarkm buffer_append(&outgoing_packet, buf, 4); 64057429Smarkm 64157429Smarkm#ifdef PACKET_DEBUG 64257429Smarkm fprintf(stderr, "packet_send plain: "); 64357429Smarkm buffer_dump(&outgoing_packet); 64457429Smarkm#endif 64557429Smarkm 64657429Smarkm /* Append to output. */ 647162852Sdes put_u32(buf, len); 64857429Smarkm buffer_append(&output, buf, 4); 64992555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 65092555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 65192555Sdes buffer_len(&outgoing_packet)); 65257429Smarkm 65357429Smarkm#ifdef PACKET_DEBUG 65457429Smarkm fprintf(stderr, "encrypted: "); 65557429Smarkm buffer_dump(&output); 65657429Smarkm#endif 657181111Sdes p_send.packets++; 658181111Sdes p_send.bytes += len + buffer_len(&outgoing_packet); 65957429Smarkm buffer_clear(&outgoing_packet); 66057429Smarkm 66157429Smarkm /* 662157016Sdes * Note that the packet is now only buffered in output. It won't be 66357429Smarkm * actually sent until packet_write_wait or packet_write_poll is 66457429Smarkm * called. 66557429Smarkm */ 66657429Smarkm} 66757429Smarkm 66898675Sdesvoid 66976259Sgreenset_newkeys(int mode) 67076259Sgreen{ 67176259Sgreen Enc *enc; 67276259Sgreen Mac *mac; 67376259Sgreen Comp *comp; 67476259Sgreen CipherContext *cc; 675124208Sdes u_int64_t *max_blocks; 676137015Sdes int crypt_type; 67776259Sgreen 678113908Sdes debug2("set_newkeys: mode %d", mode); 67976259Sgreen 68092555Sdes if (mode == MODE_OUT) { 68192555Sdes cc = &send_context; 682137015Sdes crypt_type = CIPHER_ENCRYPT; 683124208Sdes p_send.packets = p_send.blocks = 0; 684124208Sdes max_blocks = &max_blocks_out; 68592555Sdes } else { 68692555Sdes cc = &receive_context; 687137015Sdes crypt_type = CIPHER_DECRYPT; 688124208Sdes p_read.packets = p_read.blocks = 0; 689124208Sdes max_blocks = &max_blocks_in; 69092555Sdes } 69176259Sgreen if (newkeys[mode] != NULL) { 692113908Sdes debug("set_newkeys: rekeying"); 69392555Sdes cipher_cleanup(cc); 69476259Sgreen enc = &newkeys[mode]->enc; 69576259Sgreen mac = &newkeys[mode]->mac; 69676259Sgreen comp = &newkeys[mode]->comp; 697181111Sdes mac_clear(mac); 69876259Sgreen xfree(enc->name); 69976259Sgreen xfree(enc->iv); 70076259Sgreen xfree(enc->key); 70176259Sgreen xfree(mac->name); 70276259Sgreen xfree(mac->key); 70376259Sgreen xfree(comp->name); 70476259Sgreen xfree(newkeys[mode]); 70576259Sgreen } 70676259Sgreen newkeys[mode] = kex_get_newkeys(mode); 70776259Sgreen if (newkeys[mode] == NULL) 70876259Sgreen fatal("newkeys: no keys for mode %d", mode); 70976259Sgreen enc = &newkeys[mode]->enc; 71076259Sgreen mac = &newkeys[mode]->mac; 71176259Sgreen comp = &newkeys[mode]->comp; 712181111Sdes if (mac_init(mac) == 0) 71376259Sgreen mac->enabled = 1; 71476259Sgreen DBG(debug("cipher_init_context: %d", mode)); 71592555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 716137015Sdes enc->iv, enc->block_size, crypt_type); 71798675Sdes /* Deleting the keys does not gain extra security */ 71898675Sdes /* memset(enc->iv, 0, enc->block_size); 719181111Sdes memset(enc->key, 0, enc->key_len); 720181111Sdes memset(mac->key, 0, mac->key_len); */ 721149749Sdes if ((comp->type == COMP_ZLIB || 722149749Sdes (comp->type == COMP_DELAYED && after_authentication)) && 723149749Sdes comp->enabled == 0) { 72476259Sgreen packet_init_compression(); 72576259Sgreen if (mode == MODE_OUT) 72676259Sgreen buffer_compress_init_send(6); 72776259Sgreen else 72876259Sgreen buffer_compress_init_recv(); 72976259Sgreen comp->enabled = 1; 73076259Sgreen } 731124208Sdes /* 732124208Sdes * The 2^(blocksize*2) limit is too expensive for 3DES, 733124208Sdes * blowfish, etc, so enforce a 1GB limit for small blocksizes. 734124208Sdes */ 735124208Sdes if (enc->block_size >= 16) 736124208Sdes *max_blocks = (u_int64_t)1 << (enc->block_size*2); 737124208Sdes else 738124208Sdes *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 739124208Sdes if (rekey_limit) 740124208Sdes *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 74176259Sgreen} 74276259Sgreen 74357429Smarkm/* 744149749Sdes * Delayed compression for SSH2 is enabled after authentication: 745162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, 746149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. 747149749Sdes */ 748149749Sdesstatic void 749149749Sdespacket_enable_delayed_compress(void) 750149749Sdes{ 751149749Sdes Comp *comp = NULL; 752149749Sdes int mode; 753149749Sdes 754149749Sdes /* 755149749Sdes * Remember that we are past the authentication step, so rekeying 756149749Sdes * with COMP_DELAYED will turn on compression immediately. 757149749Sdes */ 758149749Sdes after_authentication = 1; 759149749Sdes for (mode = 0; mode < MODE_MAX; mode++) { 760162852Sdes /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ 761162852Sdes if (newkeys[mode] == NULL) 762162852Sdes continue; 763149749Sdes comp = &newkeys[mode]->comp; 764149749Sdes if (comp && !comp->enabled && comp->type == COMP_DELAYED) { 765149749Sdes packet_init_compression(); 766149749Sdes if (mode == MODE_OUT) 767149749Sdes buffer_compress_init_send(6); 768149749Sdes else 769149749Sdes buffer_compress_init_recv(); 770149749Sdes comp->enabled = 1; 771149749Sdes } 772149749Sdes } 773149749Sdes} 774149749Sdes 775149749Sdes/* 77660573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 77760573Skris */ 77892555Sdesstatic void 779124208Sdespacket_send2_wrapped(void) 78060573Skris{ 78192555Sdes u_char type, *cp, *macbuf = NULL; 78292555Sdes u_char padlen, pad; 78376259Sgreen u_int packet_length = 0; 78492555Sdes u_int i, len; 785137015Sdes u_int32_t rnd = 0; 78660573Skris Enc *enc = NULL; 78760573Skris Mac *mac = NULL; 78860573Skris Comp *comp = NULL; 78960573Skris int block_size; 79060573Skris 79176259Sgreen if (newkeys[MODE_OUT] != NULL) { 79276259Sgreen enc = &newkeys[MODE_OUT]->enc; 79376259Sgreen mac = &newkeys[MODE_OUT]->mac; 79476259Sgreen comp = &newkeys[MODE_OUT]->comp; 79560573Skris } 79692555Sdes block_size = enc ? enc->block_size : 8; 79760573Skris 79860573Skris cp = buffer_ptr(&outgoing_packet); 79992555Sdes type = cp[5]; 80060573Skris 80160573Skris#ifdef PACKET_DEBUG 80260573Skris fprintf(stderr, "plain: "); 80360573Skris buffer_dump(&outgoing_packet); 80460573Skris#endif 80560573Skris 80660573Skris if (comp && comp->enabled) { 80760573Skris len = buffer_len(&outgoing_packet); 80860573Skris /* skip header, compress only payload */ 80960573Skris buffer_consume(&outgoing_packet, 5); 81060573Skris buffer_clear(&compression_buffer); 81160573Skris buffer_compress(&outgoing_packet, &compression_buffer); 81260573Skris buffer_clear(&outgoing_packet); 81360573Skris buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 81460573Skris buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 81560573Skris buffer_len(&compression_buffer)); 81660573Skris DBG(debug("compression: raw %d compressed %d", len, 81760573Skris buffer_len(&outgoing_packet))); 81860573Skris } 81960573Skris 82060573Skris /* sizeof (packet_len + pad_len + payload) */ 82160573Skris len = buffer_len(&outgoing_packet); 82260573Skris 82360573Skris /* 82460573Skris * calc size of padding, alloc space, get random data, 82560573Skris * minimum padding is 4 bytes 82660573Skris */ 82760573Skris padlen = block_size - (len % block_size); 82860573Skris if (padlen < 4) 82960573Skris padlen += block_size; 83092555Sdes if (extra_pad) { 83192555Sdes /* will wrap if extra_pad+padlen > 255 */ 83292555Sdes extra_pad = roundup(extra_pad, block_size); 83392555Sdes pad = extra_pad - ((len + padlen) % extra_pad); 83498675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 83592555Sdes pad, len, padlen, extra_pad); 83692555Sdes padlen += pad; 83792555Sdes extra_pad = 0; 83892555Sdes } 83992555Sdes cp = buffer_append_space(&outgoing_packet, padlen); 84092555Sdes if (enc && !send_context.plaintext) { 84160573Skris /* random padding */ 84260573Skris for (i = 0; i < padlen; i++) { 84360573Skris if (i % 4 == 0) 844137015Sdes rnd = arc4random(); 845137015Sdes cp[i] = rnd & 0xff; 846137015Sdes rnd >>= 8; 84760573Skris } 84860573Skris } else { 84960573Skris /* clear padding */ 85060573Skris memset(cp, 0, padlen); 85160573Skris } 85260573Skris /* packet_length includes payload, padding and padding length field */ 85360573Skris packet_length = buffer_len(&outgoing_packet) - 4; 85460573Skris cp = buffer_ptr(&outgoing_packet); 855162852Sdes put_u32(cp, packet_length); 85692555Sdes cp[4] = padlen; 85760573Skris DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 85860573Skris 85960573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 86060573Skris if (mac && mac->enabled) { 861124208Sdes macbuf = mac_compute(mac, p_send.seqnr, 86292555Sdes buffer_ptr(&outgoing_packet), 86376259Sgreen buffer_len(&outgoing_packet)); 864124208Sdes DBG(debug("done calc MAC out #%d", p_send.seqnr)); 86560573Skris } 86660573Skris /* encrypt packet and append to output buffer. */ 86792555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 86892555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 86960573Skris buffer_len(&outgoing_packet)); 87060573Skris /* append unencrypted MAC */ 87160573Skris if (mac && mac->enabled) 872162852Sdes buffer_append(&output, macbuf, mac->mac_len); 87360573Skris#ifdef PACKET_DEBUG 87460573Skris fprintf(stderr, "encrypted: "); 87560573Skris buffer_dump(&output); 87660573Skris#endif 87760573Skris /* increment sequence number for outgoing packets */ 878124208Sdes if (++p_send.seqnr == 0) 879124208Sdes logit("outgoing seqnr wraps around"); 880124208Sdes if (++p_send.packets == 0) 881124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 882124208Sdes fatal("XXX too many packets with same key"); 883124208Sdes p_send.blocks += (packet_length + 4) / block_size; 884181111Sdes p_send.bytes += packet_length + 4; 88560573Skris buffer_clear(&outgoing_packet); 88660573Skris 88776259Sgreen if (type == SSH2_MSG_NEWKEYS) 88876259Sgreen set_newkeys(MODE_OUT); 889149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) 890149749Sdes packet_enable_delayed_compress(); 89160573Skris} 89260573Skris 893124208Sdesstatic void 894124208Sdespacket_send2(void) 895124208Sdes{ 896124208Sdes static int rekeying = 0; 897124208Sdes struct packet *p; 898124208Sdes u_char type, *cp; 899124208Sdes 900124208Sdes cp = buffer_ptr(&outgoing_packet); 901124208Sdes type = cp[5]; 902124208Sdes 903124208Sdes /* during rekeying we can only send key exchange messages */ 904124208Sdes if (rekeying) { 905124208Sdes if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 906124208Sdes (type <= SSH2_MSG_TRANSPORT_MAX))) { 907124208Sdes debug("enqueue packet: %u", type); 908124208Sdes p = xmalloc(sizeof(*p)); 909124208Sdes p->type = type; 910124208Sdes memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 911124208Sdes buffer_init(&outgoing_packet); 912124208Sdes TAILQ_INSERT_TAIL(&outgoing, p, next); 913124208Sdes return; 914124208Sdes } 915124208Sdes } 916124208Sdes 917124208Sdes /* rekeying starts with sending KEXINIT */ 918124208Sdes if (type == SSH2_MSG_KEXINIT) 919124208Sdes rekeying = 1; 920124208Sdes 921124208Sdes packet_send2_wrapped(); 922124208Sdes 923124208Sdes /* after a NEWKEYS message we can send the complete queue */ 924124208Sdes if (type == SSH2_MSG_NEWKEYS) { 925124208Sdes rekeying = 0; 926124208Sdes while ((p = TAILQ_FIRST(&outgoing))) { 927124208Sdes type = p->type; 928124208Sdes debug("dequeue packet: %u", type); 929124208Sdes buffer_free(&outgoing_packet); 930124208Sdes memcpy(&outgoing_packet, &p->payload, 931124208Sdes sizeof(Buffer)); 932124208Sdes TAILQ_REMOVE(&outgoing, p, next); 933124208Sdes xfree(p); 934124208Sdes packet_send2_wrapped(); 935124208Sdes } 936124208Sdes } 937124208Sdes} 938124208Sdes 93960573Skrisvoid 94092555Sdespacket_send(void) 94160573Skris{ 94292555Sdes if (compat20) 94360573Skris packet_send2(); 94460573Skris else 94560573Skris packet_send1(); 94660573Skris DBG(debug("packet_send done")); 94760573Skris} 94860573Skris 94960573Skris/* 95057429Smarkm * Waits until a packet has been received, and returns its type. Note that 95157429Smarkm * no other data is processed until this returns, so this function should not 95257429Smarkm * be used during the interactive session. 95357429Smarkm */ 95457429Smarkm 95557429Smarkmint 95692555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 95757429Smarkm{ 958181111Sdes int type, len, ret, ms_remain; 95976259Sgreen fd_set *setp; 96057429Smarkm char buf[8192]; 961181111Sdes struct timeval timeout, start, *timeoutp = NULL; 962181111Sdes 96360573Skris DBG(debug("packet_read()")); 96457429Smarkm 965162852Sdes setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), 96676259Sgreen sizeof(fd_mask)); 96776259Sgreen 96857429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 96957429Smarkm packet_write_wait(); 97057429Smarkm 97157429Smarkm /* Stay in the loop until we have received a complete packet. */ 97257429Smarkm for (;;) { 97357429Smarkm /* Try to read a packet from the buffer. */ 97492555Sdes type = packet_read_poll_seqnr(seqnr_p); 97592555Sdes if (!compat20 && ( 97660573Skris type == SSH_SMSG_SUCCESS 97757429Smarkm || type == SSH_SMSG_FAILURE 97857429Smarkm || type == SSH_CMSG_EOF 97960573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 98092555Sdes packet_check_eom(); 98157429Smarkm /* If we got a packet, return it. */ 98276259Sgreen if (type != SSH_MSG_NONE) { 98376259Sgreen xfree(setp); 98457429Smarkm return type; 98576259Sgreen } 98657429Smarkm /* 98757429Smarkm * Otherwise, wait for some data to arrive, add it to the 98857429Smarkm * buffer, and try again. 98957429Smarkm */ 99076259Sgreen memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 99176259Sgreen sizeof(fd_mask)); 99276259Sgreen FD_SET(connection_in, setp); 99357429Smarkm 994181111Sdes if (packet_timeout_ms > 0) { 995181111Sdes ms_remain = packet_timeout_ms; 996181111Sdes timeoutp = &timeout; 997181111Sdes } 99857429Smarkm /* Wait for some data to arrive. */ 999181111Sdes for (;;) { 1000181111Sdes if (packet_timeout_ms != -1) { 1001181111Sdes ms_to_timeval(&timeout, ms_remain); 1002181111Sdes gettimeofday(&start, NULL); 1003181111Sdes } 1004181111Sdes if ((ret = select(connection_in + 1, setp, NULL, 1005181111Sdes NULL, timeoutp)) >= 0) 1006181111Sdes break; 1007181111Sdes if (errno != EAGAIN && errno != EINTR && 1008181111Sdes errno != EWOULDBLOCK) 1009181111Sdes break; 1010181111Sdes if (packet_timeout_ms == -1) 1011181111Sdes continue; 1012181111Sdes ms_subtract_diff(&start, &ms_remain); 1013181111Sdes if (ms_remain <= 0) { 1014181111Sdes ret = 0; 1015181111Sdes break; 1016181111Sdes } 1017181111Sdes } 1018181111Sdes if (ret == 0) { 1019181111Sdes logit("Connection to %.200s timed out while " 1020181111Sdes "waiting to read", get_remote_ipaddr()); 1021181111Sdes cleanup_exit(255); 1022181111Sdes } 102357429Smarkm /* Read data from the socket. */ 102457429Smarkm len = read(connection_in, buf, sizeof(buf)); 102557429Smarkm if (len == 0) { 1026124208Sdes logit("Connection closed by %.200s", get_remote_ipaddr()); 1027126274Sdes cleanup_exit(255); 102857429Smarkm } 102957429Smarkm if (len < 0) 103057429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 103157429Smarkm /* Append it to the buffer. */ 103257429Smarkm packet_process_incoming(buf, len); 103357429Smarkm } 103457429Smarkm /* NOTREACHED */ 103557429Smarkm} 103657429Smarkm 103792555Sdesint 103892555Sdespacket_read(void) 103992555Sdes{ 104092555Sdes return packet_read_seqnr(NULL); 104192555Sdes} 104292555Sdes 104357429Smarkm/* 104457429Smarkm * Waits until a packet has been received, verifies that its type matches 104557429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 104657429Smarkm */ 104757429Smarkm 104857429Smarkmvoid 104992555Sdespacket_read_expect(int expected_type) 105057429Smarkm{ 105157429Smarkm int type; 105257429Smarkm 105392555Sdes type = packet_read(); 105457429Smarkm if (type != expected_type) 105557429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 105660573Skris expected_type, type); 105757429Smarkm} 105857429Smarkm 105957429Smarkm/* Checks if a full packet is available in the data received so far via 106057429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 106157429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 106257429Smarkm * 106357429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 106457429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 106557429Smarkm * to higher levels. 106657429Smarkm */ 106757429Smarkm 106892555Sdesstatic int 106992555Sdespacket_read_poll1(void) 107057429Smarkm{ 107176259Sgreen u_int len, padded_len; 107292555Sdes u_char *cp, type; 107376259Sgreen u_int checksum, stored_checksum; 107457429Smarkm 107557429Smarkm /* Check if input size is less than minimum packet size. */ 107657429Smarkm if (buffer_len(&input) < 4 + 8) 107757429Smarkm return SSH_MSG_NONE; 107857429Smarkm /* Get length of incoming packet. */ 107992555Sdes cp = buffer_ptr(&input); 1080162852Sdes len = get_u32(cp); 108157429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 1082113908Sdes packet_disconnect("Bad packet length %u.", len); 108357429Smarkm padded_len = (len + 8) & ~7; 108457429Smarkm 108557429Smarkm /* Check if the packet has been entirely received. */ 108657429Smarkm if (buffer_len(&input) < 4 + padded_len) 108757429Smarkm return SSH_MSG_NONE; 108857429Smarkm 108957429Smarkm /* The entire packet is in buffer. */ 109057429Smarkm 109157429Smarkm /* Consume packet length. */ 109257429Smarkm buffer_consume(&input, 4); 109357429Smarkm 109492555Sdes /* 109592555Sdes * Cryptographic attack detector for ssh 109692555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 109792555Sdes * Ariel Futoransky(futo@core-sdi.com) 109892555Sdes */ 1099162852Sdes if (!receive_context.plaintext) { 1100162852Sdes switch (detect_attack(buffer_ptr(&input), padded_len)) { 1101162852Sdes case DEATTACK_DETECTED: 1102162852Sdes packet_disconnect("crc32 compensation attack: " 1103162852Sdes "network attack detected"); 1104162852Sdes case DEATTACK_DOS_DETECTED: 1105162852Sdes packet_disconnect("deattack denial of " 1106162852Sdes "service detected"); 1107162852Sdes } 1108162852Sdes } 110992555Sdes 111092555Sdes /* Decrypt data to incoming_packet. */ 111157429Smarkm buffer_clear(&incoming_packet); 111292555Sdes cp = buffer_append_space(&incoming_packet, padded_len); 111392555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 111492555Sdes 111557429Smarkm buffer_consume(&input, padded_len); 111657429Smarkm 111757429Smarkm#ifdef PACKET_DEBUG 111857429Smarkm fprintf(stderr, "read_poll plain: "); 111957429Smarkm buffer_dump(&incoming_packet); 112057429Smarkm#endif 112157429Smarkm 112257429Smarkm /* Compute packet checksum. */ 112392555Sdes checksum = ssh_crc32(buffer_ptr(&incoming_packet), 112460573Skris buffer_len(&incoming_packet) - 4); 112557429Smarkm 112657429Smarkm /* Skip padding. */ 112757429Smarkm buffer_consume(&incoming_packet, 8 - len % 8); 112857429Smarkm 112957429Smarkm /* Test check bytes. */ 113057429Smarkm if (len != buffer_len(&incoming_packet)) 113192555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 113260573Skris len, buffer_len(&incoming_packet)); 113357429Smarkm 113492555Sdes cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 1135162852Sdes stored_checksum = get_u32(cp); 113657429Smarkm if (checksum != stored_checksum) 113757429Smarkm packet_disconnect("Corrupted check bytes on input."); 113857429Smarkm buffer_consume_end(&incoming_packet, 4); 113957429Smarkm 114057429Smarkm if (packet_compression) { 114157429Smarkm buffer_clear(&compression_buffer); 114257429Smarkm buffer_uncompress(&incoming_packet, &compression_buffer); 114357429Smarkm buffer_clear(&incoming_packet); 114457429Smarkm buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 114560573Skris buffer_len(&compression_buffer)); 114657429Smarkm } 1147181111Sdes p_read.packets++; 1148181111Sdes p_read.bytes += padded_len + 4; 114992555Sdes type = buffer_get_char(&incoming_packet); 1150146998Sdes if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1151146998Sdes packet_disconnect("Invalid ssh1 packet type: %d", type); 115292555Sdes return type; 115360573Skris} 115457429Smarkm 115592555Sdesstatic int 115692555Sdespacket_read_poll2(u_int32_t *seqnr_p) 115760573Skris{ 115876259Sgreen static u_int packet_length = 0; 115976259Sgreen u_int padlen, need; 116092555Sdes u_char *macbuf, *cp, type; 1161149749Sdes u_int maclen, block_size; 116260573Skris Enc *enc = NULL; 116360573Skris Mac *mac = NULL; 116460573Skris Comp *comp = NULL; 116557429Smarkm 1166192595Sdes if (packet_discard) 1167192595Sdes return SSH_MSG_NONE; 1168192595Sdes 116976259Sgreen if (newkeys[MODE_IN] != NULL) { 117076259Sgreen enc = &newkeys[MODE_IN]->enc; 117176259Sgreen mac = &newkeys[MODE_IN]->mac; 117276259Sgreen comp = &newkeys[MODE_IN]->comp; 117357429Smarkm } 117460573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 117592555Sdes block_size = enc ? enc->block_size : 8; 117660573Skris 117760573Skris if (packet_length == 0) { 117860573Skris /* 117960573Skris * check if input size is less than the cipher block size, 118060573Skris * decrypt first block and extract length of incoming packet 118160573Skris */ 118260573Skris if (buffer_len(&input) < block_size) 118360573Skris return SSH_MSG_NONE; 118460573Skris buffer_clear(&incoming_packet); 118592555Sdes cp = buffer_append_space(&incoming_packet, block_size); 118692555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), 118760573Skris block_size); 118892555Sdes cp = buffer_ptr(&incoming_packet); 1189162852Sdes packet_length = get_u32(cp); 1190192595Sdes if (packet_length < 1 + 4 || packet_length > PACKET_MAX_SIZE) { 1191124208Sdes#ifdef PACKET_DEBUG 119260573Skris buffer_dump(&incoming_packet); 1193124208Sdes#endif 1194192595Sdes logit("Bad packet length %u.", packet_length); 1195192595Sdes packet_start_discard(enc, mac, packet_length, 1196192595Sdes PACKET_MAX_SIZE); 1197192595Sdes return SSH_MSG_NONE; 119860573Skris } 1199113908Sdes DBG(debug("input: packet len %u", packet_length+4)); 120060573Skris buffer_consume(&input, block_size); 120160573Skris } 120260573Skris /* we have a partial packet of block_size bytes */ 120360573Skris need = 4 + packet_length - block_size; 120460573Skris DBG(debug("partial packet %d, need %d, maclen %d", block_size, 120560573Skris need, maclen)); 1206192595Sdes if (need % block_size != 0) { 1207192595Sdes logit("padding error: need %d block %d mod %d", 120860573Skris need, block_size, need % block_size); 1209192595Sdes packet_start_discard(enc, mac, packet_length, 1210192595Sdes PACKET_MAX_SIZE - block_size); 1211192595Sdes return SSH_MSG_NONE; 1212192595Sdes } 121360573Skris /* 121460573Skris * check if the entire packet has been received and 121560573Skris * decrypt into incoming_packet 121660573Skris */ 121760573Skris if (buffer_len(&input) < need + maclen) 121860573Skris return SSH_MSG_NONE; 121960573Skris#ifdef PACKET_DEBUG 122060573Skris fprintf(stderr, "read_poll enc/full: "); 122160573Skris buffer_dump(&input); 122260573Skris#endif 122392555Sdes cp = buffer_append_space(&incoming_packet, need); 122492555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 122560573Skris buffer_consume(&input, need); 122660573Skris /* 122760573Skris * compute MAC over seqnr and packet, 122860573Skris * increment sequence number for incoming packet 122960573Skris */ 123060573Skris if (mac && mac->enabled) { 1231124208Sdes macbuf = mac_compute(mac, p_read.seqnr, 123292555Sdes buffer_ptr(&incoming_packet), 123376259Sgreen buffer_len(&incoming_packet)); 1234192595Sdes if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) { 1235192595Sdes logit("Corrupted MAC on input."); 1236192595Sdes if (need > PACKET_MAX_SIZE) 1237192595Sdes fatal("internal error need %d", need); 1238192595Sdes packet_start_discard(enc, mac, packet_length, 1239192595Sdes PACKET_MAX_SIZE - need); 1240192595Sdes return SSH_MSG_NONE; 1241192595Sdes } 1242192595Sdes 1243124208Sdes DBG(debug("MAC #%d ok", p_read.seqnr)); 124460573Skris buffer_consume(&input, mac->mac_len); 124560573Skris } 1246192595Sdes /* XXX now it's safe to use fatal/packet_disconnect */ 124792555Sdes if (seqnr_p != NULL) 1248124208Sdes *seqnr_p = p_read.seqnr; 1249124208Sdes if (++p_read.seqnr == 0) 1250124208Sdes logit("incoming seqnr wraps around"); 1251124208Sdes if (++p_read.packets == 0) 1252124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 1253124208Sdes fatal("XXX too many packets with same key"); 1254124208Sdes p_read.blocks += (packet_length + 4) / block_size; 1255181111Sdes p_read.bytes += packet_length + 4; 125660573Skris 125760573Skris /* get padlen */ 125892555Sdes cp = buffer_ptr(&incoming_packet); 125992555Sdes padlen = cp[4]; 126060573Skris DBG(debug("input: padlen %d", padlen)); 126160573Skris if (padlen < 4) 126260573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 126360573Skris 126460573Skris /* skip packet size + padlen, discard padding */ 126560573Skris buffer_consume(&incoming_packet, 4 + 1); 126660573Skris buffer_consume_end(&incoming_packet, padlen); 126760573Skris 126860573Skris DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 126960573Skris if (comp && comp->enabled) { 127060573Skris buffer_clear(&compression_buffer); 127160573Skris buffer_uncompress(&incoming_packet, &compression_buffer); 127260573Skris buffer_clear(&incoming_packet); 127360573Skris buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 127460573Skris buffer_len(&compression_buffer)); 1275106121Sdes DBG(debug("input: len after de-compress %d", 1276106121Sdes buffer_len(&incoming_packet))); 127760573Skris } 127860573Skris /* 127960573Skris * get packet type, implies consume. 128060573Skris * return length of payload (without type field) 128160573Skris */ 128292555Sdes type = buffer_get_char(&incoming_packet); 1283146998Sdes if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) 1284146998Sdes packet_disconnect("Invalid ssh2 packet type: %d", type); 128576259Sgreen if (type == SSH2_MSG_NEWKEYS) 128676259Sgreen set_newkeys(MODE_IN); 1287149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side) 1288149749Sdes packet_enable_delayed_compress(); 128960573Skris#ifdef PACKET_DEBUG 129076259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 129160573Skris buffer_dump(&incoming_packet); 129260573Skris#endif 129392555Sdes /* reset for next packet */ 129492555Sdes packet_length = 0; 129592555Sdes return type; 129657429Smarkm} 129757429Smarkm 129860573Skrisint 129992555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 130060573Skris{ 130199060Sdes u_int reason, seqnr; 130292555Sdes u_char type; 130360573Skris char *msg; 130492555Sdes 130560573Skris for (;;) { 130692555Sdes if (compat20) { 130792555Sdes type = packet_read_poll2(seqnr_p); 1308181111Sdes if (type) { 1309181111Sdes keep_alive_timeouts = 0; 131060573Skris DBG(debug("received packet type %d", type)); 1311181111Sdes } 131292555Sdes switch (type) { 131360573Skris case SSH2_MSG_IGNORE: 1314181111Sdes debug3("Received SSH2_MSG_IGNORE"); 131560573Skris break; 131660573Skris case SSH2_MSG_DEBUG: 131760573Skris packet_get_char(); 131860573Skris msg = packet_get_string(NULL); 131960573Skris debug("Remote: %.900s", msg); 132060573Skris xfree(msg); 132160573Skris msg = packet_get_string(NULL); 132260573Skris xfree(msg); 132360573Skris break; 132460573Skris case SSH2_MSG_DISCONNECT: 132560573Skris reason = packet_get_int(); 132660573Skris msg = packet_get_string(NULL); 1327124208Sdes logit("Received disconnect from %s: %u: %.400s", 132899060Sdes get_remote_ipaddr(), reason, msg); 132960573Skris xfree(msg); 1330126274Sdes cleanup_exit(255); 133160573Skris break; 133292555Sdes case SSH2_MSG_UNIMPLEMENTED: 133392555Sdes seqnr = packet_get_int(); 133499060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 133599060Sdes seqnr); 133692555Sdes break; 133760573Skris default: 133860573Skris return type; 133976259Sgreen } 134060573Skris } else { 134192555Sdes type = packet_read_poll1(); 134292555Sdes switch (type) { 134360573Skris case SSH_MSG_IGNORE: 134460573Skris break; 134560573Skris case SSH_MSG_DEBUG: 134660573Skris msg = packet_get_string(NULL); 134760573Skris debug("Remote: %.900s", msg); 134860573Skris xfree(msg); 134960573Skris break; 135060573Skris case SSH_MSG_DISCONNECT: 135160573Skris msg = packet_get_string(NULL); 1352124208Sdes logit("Received disconnect from %s: %.400s", 135399060Sdes get_remote_ipaddr(), msg); 1354126274Sdes cleanup_exit(255); 135560573Skris break; 135660573Skris default: 135792555Sdes if (type) 135860573Skris DBG(debug("received packet type %d", type)); 135960573Skris return type; 136076259Sgreen } 136160573Skris } 136260573Skris } 136360573Skris} 136460573Skris 136592555Sdesint 136692555Sdespacket_read_poll(void) 136792555Sdes{ 136892555Sdes return packet_read_poll_seqnr(NULL); 136992555Sdes} 137092555Sdes 137157429Smarkm/* 137257429Smarkm * Buffers the given amount of input characters. This is intended to be used 137357429Smarkm * together with packet_read_poll. 137457429Smarkm */ 137557429Smarkm 137657429Smarkmvoid 137776259Sgreenpacket_process_incoming(const char *buf, u_int len) 137857429Smarkm{ 1379192595Sdes if (packet_discard) { 1380192595Sdes keep_alive_timeouts = 0; /* ?? */ 1381192595Sdes if (len >= packet_discard) 1382192595Sdes packet_stop_discard(); 1383192595Sdes packet_discard -= len; 1384192595Sdes return; 1385192595Sdes } 138657429Smarkm buffer_append(&input, buf, len); 138757429Smarkm} 138857429Smarkm 138957429Smarkm/* Returns a character from the packet. */ 139057429Smarkm 139176259Sgreenu_int 139292555Sdespacket_get_char(void) 139357429Smarkm{ 139457429Smarkm char ch; 1395106121Sdes 139657429Smarkm buffer_get(&incoming_packet, &ch, 1); 139776259Sgreen return (u_char) ch; 139857429Smarkm} 139957429Smarkm 140057429Smarkm/* Returns an integer from the packet data. */ 140157429Smarkm 140276259Sgreenu_int 140392555Sdespacket_get_int(void) 140457429Smarkm{ 140557429Smarkm return buffer_get_int(&incoming_packet); 140657429Smarkm} 140757429Smarkm 140857429Smarkm/* 140957429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 141057429Smarkm * must have been initialized before this call. 141157429Smarkm */ 141257429Smarkm 141357429Smarkmvoid 141492555Sdespacket_get_bignum(BIGNUM * value) 141557429Smarkm{ 141692555Sdes buffer_get_bignum(&incoming_packet, value); 141757429Smarkm} 141857429Smarkm 141960573Skrisvoid 142092555Sdespacket_get_bignum2(BIGNUM * value) 142160573Skris{ 142292555Sdes buffer_get_bignum2(&incoming_packet, value); 142360573Skris} 142460573Skris 142592555Sdesvoid * 1426149749Sdespacket_get_raw(u_int *length_ptr) 142760573Skris{ 1428149749Sdes u_int bytes = buffer_len(&incoming_packet); 1429106121Sdes 143060573Skris if (length_ptr != NULL) 143160573Skris *length_ptr = bytes; 143260573Skris return buffer_ptr(&incoming_packet); 143360573Skris} 143460573Skris 143560573Skrisint 143660573Skrispacket_remaining(void) 143760573Skris{ 143860573Skris return buffer_len(&incoming_packet); 143960573Skris} 144060573Skris 144157429Smarkm/* 144257429Smarkm * Returns a string from the packet data. The string is allocated using 144357429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 144457429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 144557429Smarkm * integer into which the length of the string is stored. 144657429Smarkm */ 144757429Smarkm 144892555Sdesvoid * 144976259Sgreenpacket_get_string(u_int *length_ptr) 145057429Smarkm{ 145157429Smarkm return buffer_get_string(&incoming_packet, length_ptr); 145257429Smarkm} 145357429Smarkm 1454181111Sdesvoid * 1455181111Sdespacket_get_string_ptr(u_int *length_ptr) 1456181111Sdes{ 1457181111Sdes return buffer_get_string_ptr(&incoming_packet, length_ptr); 1458181111Sdes} 1459181111Sdes 146057429Smarkm/* 146157429Smarkm * Sends a diagnostic message from the server to the client. This message 146257429Smarkm * can be sent at any time (but not while constructing another message). The 146357429Smarkm * message is printed immediately, but only if the client is being executed 146457429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 146557429Smarkm * authentication problems. The length of the formatted message must not 146657429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 146757429Smarkm */ 146857429Smarkm 146957429Smarkmvoid 147057429Smarkmpacket_send_debug(const char *fmt,...) 147157429Smarkm{ 147257429Smarkm char buf[1024]; 147357429Smarkm va_list args; 147457429Smarkm 147576259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 147676259Sgreen return; 147776259Sgreen 147857429Smarkm va_start(args, fmt); 147957429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 148057429Smarkm va_end(args); 148157429Smarkm 148260573Skris if (compat20) { 148360573Skris packet_start(SSH2_MSG_DEBUG); 148460573Skris packet_put_char(0); /* bool: always display */ 148560573Skris packet_put_cstring(buf); 148660573Skris packet_put_cstring(""); 148760573Skris } else { 148860573Skris packet_start(SSH_MSG_DEBUG); 148960573Skris packet_put_cstring(buf); 149060573Skris } 149157429Smarkm packet_send(); 149257429Smarkm packet_write_wait(); 149357429Smarkm} 149457429Smarkm 149557429Smarkm/* 149657429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 149757429Smarkm * connection, and exits. This function never returns. The error message 149857429Smarkm * should not contain a newline. The length of the formatted message must 149957429Smarkm * not exceed 1024 bytes. 150057429Smarkm */ 150157429Smarkm 150257429Smarkmvoid 150357429Smarkmpacket_disconnect(const char *fmt,...) 150457429Smarkm{ 150557429Smarkm char buf[1024]; 150657429Smarkm va_list args; 150757429Smarkm static int disconnecting = 0; 1508106121Sdes 150957429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 151057429Smarkm fatal("packet_disconnect called recursively."); 151157429Smarkm disconnecting = 1; 151257429Smarkm 151357429Smarkm /* 151457429Smarkm * Format the message. Note that the caller must make sure the 151557429Smarkm * message is of limited size. 151657429Smarkm */ 151757429Smarkm va_start(args, fmt); 151857429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 151957429Smarkm va_end(args); 152057429Smarkm 1521113908Sdes /* Display the error locally */ 1522124208Sdes logit("Disconnecting: %.100s", buf); 1523113908Sdes 152457429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 152560573Skris if (compat20) { 152660573Skris packet_start(SSH2_MSG_DISCONNECT); 152760573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 152860573Skris packet_put_cstring(buf); 152960573Skris packet_put_cstring(""); 153060573Skris } else { 153160573Skris packet_start(SSH_MSG_DISCONNECT); 153292555Sdes packet_put_cstring(buf); 153360573Skris } 153457429Smarkm packet_send(); 153557429Smarkm packet_write_wait(); 153657429Smarkm 153757429Smarkm /* Stop listening for connections. */ 153892555Sdes channel_close_all(); 153957429Smarkm 154057429Smarkm /* Close the connection. */ 154157429Smarkm packet_close(); 1542126274Sdes cleanup_exit(255); 154357429Smarkm} 154457429Smarkm 154557429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 154657429Smarkm 154757429Smarkmvoid 154892555Sdespacket_write_poll(void) 154957429Smarkm{ 155057429Smarkm int len = buffer_len(&output); 1551106121Sdes 155257429Smarkm if (len > 0) { 155357429Smarkm len = write(connection_out, buffer_ptr(&output), len); 1554181111Sdes if (len == -1) { 1555181111Sdes if (errno == EINTR || errno == EAGAIN || 1556181111Sdes errno == EWOULDBLOCK) 155757429Smarkm return; 1558181111Sdes fatal("Write failed: %.100s", strerror(errno)); 155957429Smarkm } 1560181111Sdes if (len == 0) 1561181111Sdes fatal("Write connection closed"); 156257429Smarkm buffer_consume(&output, len); 156357429Smarkm } 156457429Smarkm} 156557429Smarkm 1566181111Sdes 156757429Smarkm/* 156857429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 156957429Smarkm * written. 157057429Smarkm */ 157157429Smarkm 157257429Smarkmvoid 157392555Sdespacket_write_wait(void) 157457429Smarkm{ 157576259Sgreen fd_set *setp; 1576181111Sdes int ret, ms_remain; 1577181111Sdes struct timeval start, timeout, *timeoutp = NULL; 157876259Sgreen 1579162852Sdes setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), 158076259Sgreen sizeof(fd_mask)); 158157429Smarkm packet_write_poll(); 158257429Smarkm while (packet_have_data_to_write()) { 158376259Sgreen memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 158476259Sgreen sizeof(fd_mask)); 158576259Sgreen FD_SET(connection_out, setp); 1586181111Sdes 1587181111Sdes if (packet_timeout_ms > 0) { 1588181111Sdes ms_remain = packet_timeout_ms; 1589181111Sdes timeoutp = &timeout; 1590181111Sdes } 1591181111Sdes for (;;) { 1592181111Sdes if (packet_timeout_ms != -1) { 1593181111Sdes ms_to_timeval(&timeout, ms_remain); 1594181111Sdes gettimeofday(&start, NULL); 1595181111Sdes } 1596181111Sdes if ((ret = select(connection_out + 1, NULL, setp, 1597181111Sdes NULL, timeoutp)) >= 0) 1598181111Sdes break; 1599181111Sdes if (errno != EAGAIN && errno != EINTR && 1600181111Sdes errno != EWOULDBLOCK) 1601181111Sdes break; 1602181111Sdes if (packet_timeout_ms == -1) 1603181111Sdes continue; 1604181111Sdes ms_subtract_diff(&start, &ms_remain); 1605181111Sdes if (ms_remain <= 0) { 1606181111Sdes ret = 0; 1607181111Sdes break; 1608181111Sdes } 1609181111Sdes } 1610181111Sdes if (ret == 0) { 1611181111Sdes logit("Connection to %.200s timed out while " 1612181111Sdes "waiting to write", get_remote_ipaddr()); 1613181111Sdes cleanup_exit(255); 1614181111Sdes } 161557429Smarkm packet_write_poll(); 161657429Smarkm } 161776259Sgreen xfree(setp); 161857429Smarkm} 161957429Smarkm 162057429Smarkm/* Returns true if there is buffered data to write to the connection. */ 162157429Smarkm 162257429Smarkmint 162392555Sdespacket_have_data_to_write(void) 162457429Smarkm{ 162557429Smarkm return buffer_len(&output) != 0; 162657429Smarkm} 162757429Smarkm 162857429Smarkm/* Returns true if there is not too much data to write to the connection. */ 162957429Smarkm 163057429Smarkmint 163192555Sdespacket_not_very_much_data_to_write(void) 163257429Smarkm{ 163357429Smarkm if (interactive_mode) 163457429Smarkm return buffer_len(&output) < 16384; 163557429Smarkm else 163657429Smarkm return buffer_len(&output) < 128 * 1024; 163757429Smarkm} 163857429Smarkm 1639124208Sdes 1640113908Sdesstatic void 1641113908Sdespacket_set_tos(int interactive) 1642113908Sdes{ 1643126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1644113908Sdes int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT; 1645113908Sdes 1646113908Sdes if (!packet_connection_is_on_socket() || 1647113908Sdes !packet_connection_is_ipv4()) 1648113908Sdes return; 1649113908Sdes if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos, 1650113908Sdes sizeof(tos)) < 0) 1651113908Sdes error("setsockopt IP_TOS %d: %.100s:", 1652113908Sdes tos, strerror(errno)); 1653126274Sdes#endif 1654113908Sdes} 1655113908Sdes 165657429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 165757429Smarkm 165857429Smarkmvoid 165976259Sgreenpacket_set_interactive(int interactive) 166057429Smarkm{ 166176259Sgreen static int called = 0; 166257429Smarkm 166376259Sgreen if (called) 166476259Sgreen return; 166576259Sgreen called = 1; 166676259Sgreen 166757429Smarkm /* Record that we are in interactive mode. */ 166857429Smarkm interactive_mode = interactive; 166957429Smarkm 167057429Smarkm /* Only set socket options if using a socket. */ 167157429Smarkm if (!packet_connection_is_on_socket()) 1672116791Sdes return; 1673162852Sdes set_nodelay(connection_in); 1674113908Sdes packet_set_tos(interactive); 167557429Smarkm} 167657429Smarkm 167757429Smarkm/* Returns true if the current connection is interactive. */ 167857429Smarkm 167957429Smarkmint 168092555Sdespacket_is_interactive(void) 168157429Smarkm{ 168257429Smarkm return interactive_mode; 168357429Smarkm} 168457429Smarkm 1685137015Sdesint 1686124208Sdespacket_set_maxsize(u_int s) 168757429Smarkm{ 168857429Smarkm static int called = 0; 1689106121Sdes 169057429Smarkm if (called) { 1691124208Sdes logit("packet_set_maxsize: called twice: old %d new %d", 169260573Skris max_packet_size, s); 169357429Smarkm return -1; 169457429Smarkm } 169557429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 1696124208Sdes logit("packet_set_maxsize: bad size %d", s); 169757429Smarkm return -1; 169857429Smarkm } 169992555Sdes called = 1; 170092555Sdes debug("packet_set_maxsize: setting to %d", s); 170157429Smarkm max_packet_size = s; 170257429Smarkm return s; 170357429Smarkm} 170476259Sgreen 170592555Sdes/* roundup current message to pad bytes */ 170692555Sdesvoid 170792555Sdespacket_add_padding(u_char pad) 170892555Sdes{ 170992555Sdes extra_pad = pad; 171092555Sdes} 171192555Sdes 171276259Sgreen/* 171376259Sgreen * 9.2. Ignored Data Message 171476259Sgreen * 171576259Sgreen * byte SSH_MSG_IGNORE 171676259Sgreen * string data 171776259Sgreen * 171876259Sgreen * All implementations MUST understand (and ignore) this message at any 171976259Sgreen * time (after receiving the protocol version). No implementation is 172076259Sgreen * required to send them. This message can be used as an additional 172176259Sgreen * protection measure against advanced traffic analysis techniques. 172276259Sgreen */ 172376259Sgreenvoid 172476259Sgreenpacket_send_ignore(int nbytes) 172576259Sgreen{ 1726137015Sdes u_int32_t rnd = 0; 172776259Sgreen int i; 172876259Sgreen 172976259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 173076259Sgreen packet_put_int(nbytes); 173192555Sdes for (i = 0; i < nbytes; i++) { 173276259Sgreen if (i % 4 == 0) 1733137015Sdes rnd = arc4random(); 1734162852Sdes packet_put_char((u_char)rnd & 0xff); 1735137015Sdes rnd >>= 8; 173676259Sgreen } 173776259Sgreen} 1738124208Sdes 1739137015Sdes#define MAX_PACKETS (1U<<31) 1740124208Sdesint 1741124208Sdespacket_need_rekeying(void) 1742124208Sdes{ 1743124208Sdes if (datafellows & SSH_BUG_NOREKEY) 1744124208Sdes return 0; 1745124208Sdes return 1746124208Sdes (p_send.packets > MAX_PACKETS) || 1747124208Sdes (p_read.packets > MAX_PACKETS) || 1748124208Sdes (max_blocks_out && (p_send.blocks > max_blocks_out)) || 1749124208Sdes (max_blocks_in && (p_read.blocks > max_blocks_in)); 1750124208Sdes} 1751124208Sdes 1752124208Sdesvoid 1753124208Sdespacket_set_rekey_limit(u_int32_t bytes) 1754124208Sdes{ 1755124208Sdes rekey_limit = bytes; 1756124208Sdes} 1757149749Sdes 1758149749Sdesvoid 1759149749Sdespacket_set_server(void) 1760149749Sdes{ 1761149749Sdes server_side = 1; 1762149749Sdes} 1763149749Sdes 1764149749Sdesvoid 1765149749Sdespacket_set_authenticated(void) 1766149749Sdes{ 1767149749Sdes after_authentication = 1; 1768149749Sdes} 1769