packet.c revision 181111
1181111Sdes/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 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 8757429Smarkm/* 8857429Smarkm * This variable contains the file descriptors used for communicating with 8957429Smarkm * the other side. connection_in is used for reading; connection_out for 9057429Smarkm * writing. These can be the same descriptor, in which case it is assumed to 9157429Smarkm * be a socket. 9257429Smarkm */ 9357429Smarkmstatic int connection_in = -1; 9457429Smarkmstatic int connection_out = -1; 9557429Smarkm 9657429Smarkm/* Protocol flags for the remote side. */ 9776259Sgreenstatic u_int remote_protocol_flags = 0; 9857429Smarkm 9957429Smarkm/* Encryption context for receiving data. This is only used for decryption. */ 10057429Smarkmstatic CipherContext receive_context; 10157429Smarkm 10257429Smarkm/* Encryption context for sending data. This is only used for encryption. */ 10357429Smarkmstatic CipherContext send_context; 10457429Smarkm 10557429Smarkm/* Buffer for raw input data from the socket. */ 10698675SdesBuffer input; 10757429Smarkm 10857429Smarkm/* Buffer for raw output data going to the socket. */ 10998675SdesBuffer output; 11057429Smarkm 11157429Smarkm/* Buffer for the partial outgoing packet being constructed. */ 11257429Smarkmstatic Buffer outgoing_packet; 11357429Smarkm 11457429Smarkm/* Buffer for the incoming packet currently being processed. */ 11557429Smarkmstatic Buffer incoming_packet; 11657429Smarkm 11757429Smarkm/* Scratch buffer for packet compression/decompression. */ 11857429Smarkmstatic Buffer compression_buffer; 11976259Sgreenstatic int compression_buffer_ready = 0; 12057429Smarkm 12157429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */ 12257429Smarkmstatic int packet_compression = 0; 12357429Smarkm 12457429Smarkm/* default maximum packet size */ 125124208Sdesu_int max_packet_size = 32768; 12657429Smarkm 12757429Smarkm/* Flag indicating whether this module has been initialized. */ 12857429Smarkmstatic int initialized = 0; 12957429Smarkm 13057429Smarkm/* Set to true if the connection is interactive. */ 13157429Smarkmstatic int interactive_mode = 0; 13257429Smarkm 133149749Sdes/* Set to true if we are the server side. */ 134149749Sdesstatic int server_side = 0; 135149749Sdes 136149749Sdes/* Set to true if we are authenticated. */ 137149749Sdesstatic int after_authentication = 0; 138149749Sdes 139181111Sdesint keep_alive_timeouts = 0; 140181111Sdes 141181111Sdes/* Set to the maximum time that we will wait to send or receive a packet */ 142181111Sdesstatic int packet_timeout_ms = -1; 143181111Sdes 14460573Skris/* Session key information for Encryption and MAC */ 14576259SgreenNewkeys *newkeys[MODE_MAX]; 146124208Sdesstatic struct packet_state { 147124208Sdes u_int32_t seqnr; 148124208Sdes u_int32_t packets; 149124208Sdes u_int64_t blocks; 150181111Sdes u_int64_t bytes; 151124208Sdes} p_read, p_send; 15260573Skris 153124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out; 154124208Sdesstatic u_int32_t rekey_limit; 155124208Sdes 15698675Sdes/* Session key for protocol v1 */ 15798675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 15898675Sdesstatic u_int ssh1_keylen; 15998675Sdes 16092555Sdes/* roundup current message to extra_pad bytes */ 16192555Sdesstatic u_char extra_pad = 0; 16260573Skris 163124208Sdesstruct packet { 164124208Sdes TAILQ_ENTRY(packet) next; 165124208Sdes u_char type; 166124208Sdes Buffer payload; 167124208Sdes}; 168124208SdesTAILQ_HEAD(, packet) outgoing; 169124208Sdes 17057429Smarkm/* 17157429Smarkm * Sets the descriptors used for communication. Disables encryption until 17257429Smarkm * packet_set_encryption_key is called. 17357429Smarkm */ 17457429Smarkmvoid 17557429Smarkmpacket_set_connection(int fd_in, int fd_out) 17657429Smarkm{ 17769587Sgreen Cipher *none = cipher_by_name("none"); 178106121Sdes 17969587Sgreen if (none == NULL) 18069587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 18157429Smarkm connection_in = fd_in; 18257429Smarkm connection_out = fd_out; 183137015Sdes cipher_init(&send_context, none, (const u_char *)"", 184137015Sdes 0, NULL, 0, CIPHER_ENCRYPT); 185137015Sdes cipher_init(&receive_context, none, (const u_char *)"", 186137015Sdes 0, NULL, 0, CIPHER_DECRYPT); 18792555Sdes newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 18857429Smarkm if (!initialized) { 18957429Smarkm initialized = 1; 19057429Smarkm buffer_init(&input); 19157429Smarkm buffer_init(&output); 19257429Smarkm buffer_init(&outgoing_packet); 19357429Smarkm buffer_init(&incoming_packet); 194124208Sdes TAILQ_INIT(&outgoing); 195181111Sdes p_send.packets = p_read.packets = 0; 19657429Smarkm } 19757429Smarkm} 19857429Smarkm 199181111Sdesvoid 200181111Sdespacket_set_timeout(int timeout, int count) 201181111Sdes{ 202181111Sdes if (timeout == 0 || count == 0) { 203181111Sdes packet_timeout_ms = -1; 204181111Sdes return; 205181111Sdes } 206181111Sdes if ((INT_MAX / 1000) / count < timeout) 207181111Sdes packet_timeout_ms = INT_MAX; 208181111Sdes else 209181111Sdes packet_timeout_ms = timeout * count * 1000; 210181111Sdes} 211181111Sdes 21257429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 21357429Smarkm 21457429Smarkmint 21592555Sdespacket_connection_is_on_socket(void) 21657429Smarkm{ 21757429Smarkm struct sockaddr_storage from, to; 21857429Smarkm socklen_t fromlen, tolen; 21957429Smarkm 22057429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 22157429Smarkm if (connection_in == connection_out) 22257429Smarkm return 1; 22357429Smarkm fromlen = sizeof(from); 22457429Smarkm memset(&from, 0, sizeof(from)); 22557429Smarkm if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 22657429Smarkm return 0; 22757429Smarkm tolen = sizeof(to); 22857429Smarkm memset(&to, 0, sizeof(to)); 22957429Smarkm if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 23057429Smarkm return 0; 23157429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 23257429Smarkm return 0; 23357429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 23457429Smarkm return 0; 23557429Smarkm return 1; 23657429Smarkm} 23757429Smarkm 23898675Sdes/* 23998675Sdes * Exports an IV from the CipherContext required to export the key 24098675Sdes * state back from the unprivileged child to the privileged parent 24198675Sdes * process. 24298675Sdes */ 24398675Sdes 24498675Sdesvoid 24598675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 24698675Sdes{ 24798675Sdes CipherContext *cc; 24898675Sdes 24998675Sdes if (mode == MODE_OUT) 25098675Sdes cc = &send_context; 25198675Sdes else 25298675Sdes cc = &receive_context; 25398675Sdes 25498675Sdes cipher_get_keyiv(cc, iv, len); 25598675Sdes} 25698675Sdes 25798675Sdesint 25898675Sdespacket_get_keycontext(int mode, u_char *dat) 25998675Sdes{ 26098675Sdes CipherContext *cc; 26198675Sdes 26298675Sdes if (mode == MODE_OUT) 26398675Sdes cc = &send_context; 26498675Sdes else 26598675Sdes cc = &receive_context; 26698675Sdes 26798675Sdes return (cipher_get_keycontext(cc, dat)); 26898675Sdes} 26998675Sdes 27098675Sdesvoid 27198675Sdespacket_set_keycontext(int mode, u_char *dat) 27298675Sdes{ 27398675Sdes CipherContext *cc; 27498675Sdes 27598675Sdes if (mode == MODE_OUT) 27698675Sdes cc = &send_context; 27798675Sdes else 27898675Sdes cc = &receive_context; 27998675Sdes 28098675Sdes cipher_set_keycontext(cc, dat); 28198675Sdes} 28298675Sdes 28398675Sdesint 28498675Sdespacket_get_keyiv_len(int mode) 28598675Sdes{ 28698675Sdes CipherContext *cc; 28798675Sdes 28898675Sdes if (mode == MODE_OUT) 28998675Sdes cc = &send_context; 29098675Sdes else 29198675Sdes cc = &receive_context; 29298675Sdes 29398675Sdes return (cipher_get_keyiv_len(cc)); 29498675Sdes} 295162852Sdes 29698675Sdesvoid 29798675Sdespacket_set_iv(int mode, u_char *dat) 29898675Sdes{ 29998675Sdes CipherContext *cc; 30098675Sdes 30198675Sdes if (mode == MODE_OUT) 30298675Sdes cc = &send_context; 30398675Sdes else 30498675Sdes cc = &receive_context; 30598675Sdes 30698675Sdes cipher_set_keyiv(cc, dat); 30798675Sdes} 308162852Sdes 30998675Sdesint 310124208Sdespacket_get_ssh1_cipher(void) 31198675Sdes{ 31298675Sdes return (cipher_get_number(receive_context.cipher)); 31398675Sdes} 31498675Sdes 315124208Sdesvoid 316181111Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets, 317181111Sdes u_int64_t *bytes) 318124208Sdes{ 319124208Sdes struct packet_state *state; 32098675Sdes 321124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 322181111Sdes if (seqnr) 323181111Sdes *seqnr = state->seqnr; 324181111Sdes if (blocks) 325181111Sdes *blocks = state->blocks; 326181111Sdes if (packets) 327181111Sdes *packets = state->packets; 328181111Sdes if (bytes) 329181111Sdes *bytes = state->bytes; 33098675Sdes} 33198675Sdes 33298675Sdesvoid 333181111Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, 334181111Sdes u_int64_t bytes) 33598675Sdes{ 336124208Sdes struct packet_state *state; 337124208Sdes 338124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 339124208Sdes state->seqnr = seqnr; 340124208Sdes state->blocks = blocks; 341124208Sdes state->packets = packets; 342181111Sdes state->bytes = bytes; 34398675Sdes} 34498675Sdes 34557429Smarkm/* returns 1 if connection is via ipv4 */ 34657429Smarkm 34757429Smarkmint 34892555Sdespacket_connection_is_ipv4(void) 34957429Smarkm{ 35057429Smarkm struct sockaddr_storage to; 35157429Smarkm socklen_t tolen = sizeof(to); 35257429Smarkm 35357429Smarkm memset(&to, 0, sizeof(to)); 35457429Smarkm if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 35557429Smarkm return 0; 35698937Sdes if (to.ss_family == AF_INET) 35798937Sdes return 1; 35898937Sdes#ifdef IPV4_IN_IPV6 359126274Sdes if (to.ss_family == AF_INET6 && 36098937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 36198937Sdes return 1; 36298937Sdes#endif 36398937Sdes return 0; 36457429Smarkm} 36557429Smarkm 36657429Smarkm/* Sets the connection into non-blocking mode. */ 36757429Smarkm 36857429Smarkmvoid 36992555Sdespacket_set_nonblocking(void) 37057429Smarkm{ 37157429Smarkm /* Set the socket into non-blocking mode. */ 372137015Sdes set_nonblock(connection_in); 37357429Smarkm 374137015Sdes if (connection_out != connection_in) 375137015Sdes set_nonblock(connection_out); 37657429Smarkm} 37757429Smarkm 37857429Smarkm/* Returns the socket used for reading. */ 37957429Smarkm 38057429Smarkmint 38192555Sdespacket_get_connection_in(void) 38257429Smarkm{ 38357429Smarkm return connection_in; 38457429Smarkm} 38557429Smarkm 38657429Smarkm/* Returns the descriptor used for writing. */ 38757429Smarkm 38857429Smarkmint 38992555Sdespacket_get_connection_out(void) 39057429Smarkm{ 39157429Smarkm return connection_out; 39257429Smarkm} 39357429Smarkm 39457429Smarkm/* Closes the connection and clears and frees internal data structures. */ 39557429Smarkm 39657429Smarkmvoid 39792555Sdespacket_close(void) 39857429Smarkm{ 39957429Smarkm if (!initialized) 40057429Smarkm return; 40157429Smarkm initialized = 0; 40257429Smarkm if (connection_in == connection_out) { 40357429Smarkm shutdown(connection_out, SHUT_RDWR); 40457429Smarkm close(connection_out); 40557429Smarkm } else { 40657429Smarkm close(connection_in); 40757429Smarkm close(connection_out); 40857429Smarkm } 40957429Smarkm buffer_free(&input); 41057429Smarkm buffer_free(&output); 41157429Smarkm buffer_free(&outgoing_packet); 41257429Smarkm buffer_free(&incoming_packet); 41376259Sgreen if (compression_buffer_ready) { 41457429Smarkm buffer_free(&compression_buffer); 41557429Smarkm buffer_compress_uninit(); 41657429Smarkm } 41792555Sdes cipher_cleanup(&send_context); 41892555Sdes cipher_cleanup(&receive_context); 41957429Smarkm} 42057429Smarkm 42157429Smarkm/* Sets remote side protocol flags. */ 42257429Smarkm 42357429Smarkmvoid 42476259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 42557429Smarkm{ 42657429Smarkm remote_protocol_flags = protocol_flags; 42757429Smarkm} 42857429Smarkm 42957429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 43057429Smarkm 43176259Sgreenu_int 43292555Sdespacket_get_protocol_flags(void) 43357429Smarkm{ 43457429Smarkm return remote_protocol_flags; 43557429Smarkm} 43657429Smarkm 43757429Smarkm/* 43857429Smarkm * Starts packet compression from the next packet on in both directions. 43957429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 44057429Smarkm */ 44157429Smarkm 44292555Sdesstatic void 44392555Sdespacket_init_compression(void) 44476259Sgreen{ 44576259Sgreen if (compression_buffer_ready == 1) 44676259Sgreen return; 44776259Sgreen compression_buffer_ready = 1; 44876259Sgreen buffer_init(&compression_buffer); 44976259Sgreen} 45076259Sgreen 45176259Sgreenvoid 45257429Smarkmpacket_start_compression(int level) 45357429Smarkm{ 45492555Sdes if (packet_compression && !compat20) 45557429Smarkm fatal("Compression already enabled."); 45657429Smarkm packet_compression = 1; 45776259Sgreen packet_init_compression(); 45876259Sgreen buffer_compress_init_send(level); 45976259Sgreen buffer_compress_init_recv(); 46057429Smarkm} 46157429Smarkm 46257429Smarkm/* 46357429Smarkm * Causes any further packets to be encrypted using the given key. The same 46457429Smarkm * key is used for both sending and reception. However, both directions are 46557429Smarkm * encrypted independently of each other. 46657429Smarkm */ 46798675Sdes 46857429Smarkmvoid 46976259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen, 47069587Sgreen int number) 47157429Smarkm{ 47269587Sgreen Cipher *cipher = cipher_by_number(number); 473106121Sdes 47469587Sgreen if (cipher == NULL) 47569587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 47660573Skris if (keylen < 20) 47769587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 47898675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 47998675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 48098675Sdes memcpy(ssh1_key, key, keylen); 48198675Sdes ssh1_keylen = keylen; 48292555Sdes cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 48392555Sdes cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 48457429Smarkm} 48557429Smarkm 48698675Sdesu_int 48798675Sdespacket_get_encryption_key(u_char *key) 48898675Sdes{ 48998675Sdes if (key == NULL) 49098675Sdes return (ssh1_keylen); 49198675Sdes memcpy(key, ssh1_key, ssh1_keylen); 49298675Sdes return (ssh1_keylen); 49398675Sdes} 49498675Sdes 49592555Sdes/* Start constructing a packet to send. */ 49657429Smarkmvoid 49792555Sdespacket_start(u_char type) 49857429Smarkm{ 49992555Sdes u_char buf[9]; 50092555Sdes int len; 50157429Smarkm 50292555Sdes DBG(debug("packet_start[%d]", type)); 50392555Sdes len = compat20 ? 6 : 9; 50492555Sdes memset(buf, 0, len - 1); 50592555Sdes buf[len - 1] = type; 50657429Smarkm buffer_clear(&outgoing_packet); 50792555Sdes buffer_append(&outgoing_packet, buf, len); 50857429Smarkm} 50957429Smarkm 51092555Sdes/* Append payload. */ 51160573Skrisvoid 51257429Smarkmpacket_put_char(int value) 51357429Smarkm{ 51457429Smarkm char ch = value; 515106121Sdes 51657429Smarkm buffer_append(&outgoing_packet, &ch, 1); 51757429Smarkm} 518162852Sdes 51957429Smarkmvoid 52076259Sgreenpacket_put_int(u_int value) 52157429Smarkm{ 52257429Smarkm buffer_put_int(&outgoing_packet, value); 52357429Smarkm} 524162852Sdes 52557429Smarkmvoid 52692555Sdespacket_put_string(const void *buf, u_int len) 52757429Smarkm{ 52857429Smarkm buffer_put_string(&outgoing_packet, buf, len); 52957429Smarkm} 530162852Sdes 53160573Skrisvoid 53260573Skrispacket_put_cstring(const char *str) 53360573Skris{ 53492555Sdes buffer_put_cstring(&outgoing_packet, str); 53560573Skris} 536162852Sdes 53760573Skrisvoid 53892555Sdespacket_put_raw(const void *buf, u_int len) 53960573Skris{ 54060573Skris buffer_append(&outgoing_packet, buf, len); 54160573Skris} 542162852Sdes 54357429Smarkmvoid 54457429Smarkmpacket_put_bignum(BIGNUM * value) 54557429Smarkm{ 54657429Smarkm buffer_put_bignum(&outgoing_packet, value); 54757429Smarkm} 548162852Sdes 54960573Skrisvoid 55060573Skrispacket_put_bignum2(BIGNUM * value) 55160573Skris{ 55260573Skris buffer_put_bignum2(&outgoing_packet, value); 55360573Skris} 55457429Smarkm 55557429Smarkm/* 55657429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 55757429Smarkm * encrypts the packet before sending. 55857429Smarkm */ 55957429Smarkm 56092555Sdesstatic void 56176259Sgreenpacket_send1(void) 56257429Smarkm{ 56392555Sdes u_char buf[8], *cp; 56457429Smarkm int i, padding, len; 56576259Sgreen u_int checksum; 566137015Sdes u_int32_t rnd = 0; 56757429Smarkm 56857429Smarkm /* 56957429Smarkm * If using packet compression, compress the payload of the outgoing 57057429Smarkm * packet. 57157429Smarkm */ 57257429Smarkm if (packet_compression) { 57357429Smarkm buffer_clear(&compression_buffer); 57457429Smarkm /* Skip padding. */ 57557429Smarkm buffer_consume(&outgoing_packet, 8); 57657429Smarkm /* padding */ 57757429Smarkm buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 57857429Smarkm buffer_compress(&outgoing_packet, &compression_buffer); 57957429Smarkm buffer_clear(&outgoing_packet); 58057429Smarkm buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 58192555Sdes buffer_len(&compression_buffer)); 58257429Smarkm } 58357429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 58457429Smarkm len = buffer_len(&outgoing_packet) + 4 - 8; 58557429Smarkm 58660573Skris /* Insert padding. Initialized to zero in packet_start1() */ 58757429Smarkm padding = 8 - len % 8; 58892555Sdes if (!send_context.plaintext) { 58957429Smarkm cp = buffer_ptr(&outgoing_packet); 59057429Smarkm for (i = 0; i < padding; i++) { 59157429Smarkm if (i % 4 == 0) 592137015Sdes rnd = arc4random(); 593137015Sdes cp[7 - i] = rnd & 0xff; 594137015Sdes rnd >>= 8; 59557429Smarkm } 59657429Smarkm } 59757429Smarkm buffer_consume(&outgoing_packet, 8 - padding); 59857429Smarkm 59957429Smarkm /* Add check bytes. */ 60092555Sdes checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 60165668Skris buffer_len(&outgoing_packet)); 602162852Sdes put_u32(buf, checksum); 60357429Smarkm buffer_append(&outgoing_packet, buf, 4); 60457429Smarkm 60557429Smarkm#ifdef PACKET_DEBUG 60657429Smarkm fprintf(stderr, "packet_send plain: "); 60757429Smarkm buffer_dump(&outgoing_packet); 60857429Smarkm#endif 60957429Smarkm 61057429Smarkm /* Append to output. */ 611162852Sdes put_u32(buf, len); 61257429Smarkm buffer_append(&output, buf, 4); 61392555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 61492555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 61592555Sdes buffer_len(&outgoing_packet)); 61657429Smarkm 61757429Smarkm#ifdef PACKET_DEBUG 61857429Smarkm fprintf(stderr, "encrypted: "); 61957429Smarkm buffer_dump(&output); 62057429Smarkm#endif 621181111Sdes p_send.packets++; 622181111Sdes p_send.bytes += len + buffer_len(&outgoing_packet); 62357429Smarkm buffer_clear(&outgoing_packet); 62457429Smarkm 62557429Smarkm /* 626157016Sdes * Note that the packet is now only buffered in output. It won't be 62757429Smarkm * actually sent until packet_write_wait or packet_write_poll is 62857429Smarkm * called. 62957429Smarkm */ 63057429Smarkm} 63157429Smarkm 63298675Sdesvoid 63376259Sgreenset_newkeys(int mode) 63476259Sgreen{ 63576259Sgreen Enc *enc; 63676259Sgreen Mac *mac; 63776259Sgreen Comp *comp; 63876259Sgreen CipherContext *cc; 639124208Sdes u_int64_t *max_blocks; 640137015Sdes int crypt_type; 64176259Sgreen 642113908Sdes debug2("set_newkeys: mode %d", mode); 64376259Sgreen 64492555Sdes if (mode == MODE_OUT) { 64592555Sdes cc = &send_context; 646137015Sdes crypt_type = CIPHER_ENCRYPT; 647124208Sdes p_send.packets = p_send.blocks = 0; 648124208Sdes max_blocks = &max_blocks_out; 64992555Sdes } else { 65092555Sdes cc = &receive_context; 651137015Sdes crypt_type = CIPHER_DECRYPT; 652124208Sdes p_read.packets = p_read.blocks = 0; 653124208Sdes max_blocks = &max_blocks_in; 65492555Sdes } 65576259Sgreen if (newkeys[mode] != NULL) { 656113908Sdes debug("set_newkeys: rekeying"); 65792555Sdes cipher_cleanup(cc); 65876259Sgreen enc = &newkeys[mode]->enc; 65976259Sgreen mac = &newkeys[mode]->mac; 66076259Sgreen comp = &newkeys[mode]->comp; 661181111Sdes mac_clear(mac); 66276259Sgreen xfree(enc->name); 66376259Sgreen xfree(enc->iv); 66476259Sgreen xfree(enc->key); 66576259Sgreen xfree(mac->name); 66676259Sgreen xfree(mac->key); 66776259Sgreen xfree(comp->name); 66876259Sgreen xfree(newkeys[mode]); 66976259Sgreen } 67076259Sgreen newkeys[mode] = kex_get_newkeys(mode); 67176259Sgreen if (newkeys[mode] == NULL) 67276259Sgreen fatal("newkeys: no keys for mode %d", mode); 67376259Sgreen enc = &newkeys[mode]->enc; 67476259Sgreen mac = &newkeys[mode]->mac; 67576259Sgreen comp = &newkeys[mode]->comp; 676181111Sdes if (mac_init(mac) == 0) 67776259Sgreen mac->enabled = 1; 67876259Sgreen DBG(debug("cipher_init_context: %d", mode)); 67992555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 680137015Sdes enc->iv, enc->block_size, crypt_type); 68198675Sdes /* Deleting the keys does not gain extra security */ 68298675Sdes /* memset(enc->iv, 0, enc->block_size); 683181111Sdes memset(enc->key, 0, enc->key_len); 684181111Sdes memset(mac->key, 0, mac->key_len); */ 685149749Sdes if ((comp->type == COMP_ZLIB || 686149749Sdes (comp->type == COMP_DELAYED && after_authentication)) && 687149749Sdes comp->enabled == 0) { 68876259Sgreen packet_init_compression(); 68976259Sgreen if (mode == MODE_OUT) 69076259Sgreen buffer_compress_init_send(6); 69176259Sgreen else 69276259Sgreen buffer_compress_init_recv(); 69376259Sgreen comp->enabled = 1; 69476259Sgreen } 695124208Sdes /* 696124208Sdes * The 2^(blocksize*2) limit is too expensive for 3DES, 697124208Sdes * blowfish, etc, so enforce a 1GB limit for small blocksizes. 698124208Sdes */ 699124208Sdes if (enc->block_size >= 16) 700124208Sdes *max_blocks = (u_int64_t)1 << (enc->block_size*2); 701124208Sdes else 702124208Sdes *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 703124208Sdes if (rekey_limit) 704124208Sdes *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 70576259Sgreen} 70676259Sgreen 70757429Smarkm/* 708149749Sdes * Delayed compression for SSH2 is enabled after authentication: 709162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, 710149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. 711149749Sdes */ 712149749Sdesstatic void 713149749Sdespacket_enable_delayed_compress(void) 714149749Sdes{ 715149749Sdes Comp *comp = NULL; 716149749Sdes int mode; 717149749Sdes 718149749Sdes /* 719149749Sdes * Remember that we are past the authentication step, so rekeying 720149749Sdes * with COMP_DELAYED will turn on compression immediately. 721149749Sdes */ 722149749Sdes after_authentication = 1; 723149749Sdes for (mode = 0; mode < MODE_MAX; mode++) { 724162852Sdes /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ 725162852Sdes if (newkeys[mode] == NULL) 726162852Sdes continue; 727149749Sdes comp = &newkeys[mode]->comp; 728149749Sdes if (comp && !comp->enabled && comp->type == COMP_DELAYED) { 729149749Sdes packet_init_compression(); 730149749Sdes if (mode == MODE_OUT) 731149749Sdes buffer_compress_init_send(6); 732149749Sdes else 733149749Sdes buffer_compress_init_recv(); 734149749Sdes comp->enabled = 1; 735149749Sdes } 736149749Sdes } 737149749Sdes} 738149749Sdes 739149749Sdes/* 74060573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 74160573Skris */ 74292555Sdesstatic void 743124208Sdespacket_send2_wrapped(void) 74460573Skris{ 74592555Sdes u_char type, *cp, *macbuf = NULL; 74692555Sdes u_char padlen, pad; 74776259Sgreen u_int packet_length = 0; 74892555Sdes u_int i, len; 749137015Sdes u_int32_t rnd = 0; 75060573Skris Enc *enc = NULL; 75160573Skris Mac *mac = NULL; 75260573Skris Comp *comp = NULL; 75360573Skris int block_size; 75460573Skris 75576259Sgreen if (newkeys[MODE_OUT] != NULL) { 75676259Sgreen enc = &newkeys[MODE_OUT]->enc; 75776259Sgreen mac = &newkeys[MODE_OUT]->mac; 75876259Sgreen comp = &newkeys[MODE_OUT]->comp; 75960573Skris } 76092555Sdes block_size = enc ? enc->block_size : 8; 76160573Skris 76260573Skris cp = buffer_ptr(&outgoing_packet); 76392555Sdes type = cp[5]; 76460573Skris 76560573Skris#ifdef PACKET_DEBUG 76660573Skris fprintf(stderr, "plain: "); 76760573Skris buffer_dump(&outgoing_packet); 76860573Skris#endif 76960573Skris 77060573Skris if (comp && comp->enabled) { 77160573Skris len = buffer_len(&outgoing_packet); 77260573Skris /* skip header, compress only payload */ 77360573Skris buffer_consume(&outgoing_packet, 5); 77460573Skris buffer_clear(&compression_buffer); 77560573Skris buffer_compress(&outgoing_packet, &compression_buffer); 77660573Skris buffer_clear(&outgoing_packet); 77760573Skris buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 77860573Skris buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 77960573Skris buffer_len(&compression_buffer)); 78060573Skris DBG(debug("compression: raw %d compressed %d", len, 78160573Skris buffer_len(&outgoing_packet))); 78260573Skris } 78360573Skris 78460573Skris /* sizeof (packet_len + pad_len + payload) */ 78560573Skris len = buffer_len(&outgoing_packet); 78660573Skris 78760573Skris /* 78860573Skris * calc size of padding, alloc space, get random data, 78960573Skris * minimum padding is 4 bytes 79060573Skris */ 79160573Skris padlen = block_size - (len % block_size); 79260573Skris if (padlen < 4) 79360573Skris padlen += block_size; 79492555Sdes if (extra_pad) { 79592555Sdes /* will wrap if extra_pad+padlen > 255 */ 79692555Sdes extra_pad = roundup(extra_pad, block_size); 79792555Sdes pad = extra_pad - ((len + padlen) % extra_pad); 79898675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 79992555Sdes pad, len, padlen, extra_pad); 80092555Sdes padlen += pad; 80192555Sdes extra_pad = 0; 80292555Sdes } 80392555Sdes cp = buffer_append_space(&outgoing_packet, padlen); 80492555Sdes if (enc && !send_context.plaintext) { 80560573Skris /* random padding */ 80660573Skris for (i = 0; i < padlen; i++) { 80760573Skris if (i % 4 == 0) 808137015Sdes rnd = arc4random(); 809137015Sdes cp[i] = rnd & 0xff; 810137015Sdes rnd >>= 8; 81160573Skris } 81260573Skris } else { 81360573Skris /* clear padding */ 81460573Skris memset(cp, 0, padlen); 81560573Skris } 81660573Skris /* packet_length includes payload, padding and padding length field */ 81760573Skris packet_length = buffer_len(&outgoing_packet) - 4; 81860573Skris cp = buffer_ptr(&outgoing_packet); 819162852Sdes put_u32(cp, packet_length); 82092555Sdes cp[4] = padlen; 82160573Skris DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 82260573Skris 82360573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 82460573Skris if (mac && mac->enabled) { 825124208Sdes macbuf = mac_compute(mac, p_send.seqnr, 82692555Sdes buffer_ptr(&outgoing_packet), 82776259Sgreen buffer_len(&outgoing_packet)); 828124208Sdes DBG(debug("done calc MAC out #%d", p_send.seqnr)); 82960573Skris } 83060573Skris /* encrypt packet and append to output buffer. */ 83192555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 83292555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 83360573Skris buffer_len(&outgoing_packet)); 83460573Skris /* append unencrypted MAC */ 83560573Skris if (mac && mac->enabled) 836162852Sdes buffer_append(&output, macbuf, mac->mac_len); 83760573Skris#ifdef PACKET_DEBUG 83860573Skris fprintf(stderr, "encrypted: "); 83960573Skris buffer_dump(&output); 84060573Skris#endif 84160573Skris /* increment sequence number for outgoing packets */ 842124208Sdes if (++p_send.seqnr == 0) 843124208Sdes logit("outgoing seqnr wraps around"); 844124208Sdes if (++p_send.packets == 0) 845124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 846124208Sdes fatal("XXX too many packets with same key"); 847124208Sdes p_send.blocks += (packet_length + 4) / block_size; 848181111Sdes p_send.bytes += packet_length + 4; 84960573Skris buffer_clear(&outgoing_packet); 85060573Skris 85176259Sgreen if (type == SSH2_MSG_NEWKEYS) 85276259Sgreen set_newkeys(MODE_OUT); 853149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) 854149749Sdes packet_enable_delayed_compress(); 85560573Skris} 85660573Skris 857124208Sdesstatic void 858124208Sdespacket_send2(void) 859124208Sdes{ 860124208Sdes static int rekeying = 0; 861124208Sdes struct packet *p; 862124208Sdes u_char type, *cp; 863124208Sdes 864124208Sdes cp = buffer_ptr(&outgoing_packet); 865124208Sdes type = cp[5]; 866124208Sdes 867124208Sdes /* during rekeying we can only send key exchange messages */ 868124208Sdes if (rekeying) { 869124208Sdes if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 870124208Sdes (type <= SSH2_MSG_TRANSPORT_MAX))) { 871124208Sdes debug("enqueue packet: %u", type); 872124208Sdes p = xmalloc(sizeof(*p)); 873124208Sdes p->type = type; 874124208Sdes memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 875124208Sdes buffer_init(&outgoing_packet); 876124208Sdes TAILQ_INSERT_TAIL(&outgoing, p, next); 877124208Sdes return; 878124208Sdes } 879124208Sdes } 880124208Sdes 881124208Sdes /* rekeying starts with sending KEXINIT */ 882124208Sdes if (type == SSH2_MSG_KEXINIT) 883124208Sdes rekeying = 1; 884124208Sdes 885124208Sdes packet_send2_wrapped(); 886124208Sdes 887124208Sdes /* after a NEWKEYS message we can send the complete queue */ 888124208Sdes if (type == SSH2_MSG_NEWKEYS) { 889124208Sdes rekeying = 0; 890124208Sdes while ((p = TAILQ_FIRST(&outgoing))) { 891124208Sdes type = p->type; 892124208Sdes debug("dequeue packet: %u", type); 893124208Sdes buffer_free(&outgoing_packet); 894124208Sdes memcpy(&outgoing_packet, &p->payload, 895124208Sdes sizeof(Buffer)); 896124208Sdes TAILQ_REMOVE(&outgoing, p, next); 897124208Sdes xfree(p); 898124208Sdes packet_send2_wrapped(); 899124208Sdes } 900124208Sdes } 901124208Sdes} 902124208Sdes 90360573Skrisvoid 90492555Sdespacket_send(void) 90560573Skris{ 90692555Sdes if (compat20) 90760573Skris packet_send2(); 90860573Skris else 90960573Skris packet_send1(); 91060573Skris DBG(debug("packet_send done")); 91160573Skris} 91260573Skris 91360573Skris/* 91457429Smarkm * Waits until a packet has been received, and returns its type. Note that 91557429Smarkm * no other data is processed until this returns, so this function should not 91657429Smarkm * be used during the interactive session. 91757429Smarkm */ 91857429Smarkm 91957429Smarkmint 92092555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 92157429Smarkm{ 922181111Sdes int type, len, ret, ms_remain; 92376259Sgreen fd_set *setp; 92457429Smarkm char buf[8192]; 925181111Sdes struct timeval timeout, start, *timeoutp = NULL; 926181111Sdes 92760573Skris DBG(debug("packet_read()")); 92857429Smarkm 929162852Sdes setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), 93076259Sgreen sizeof(fd_mask)); 93176259Sgreen 93257429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 93357429Smarkm packet_write_wait(); 93457429Smarkm 93557429Smarkm /* Stay in the loop until we have received a complete packet. */ 93657429Smarkm for (;;) { 93757429Smarkm /* Try to read a packet from the buffer. */ 93892555Sdes type = packet_read_poll_seqnr(seqnr_p); 93992555Sdes if (!compat20 && ( 94060573Skris type == SSH_SMSG_SUCCESS 94157429Smarkm || type == SSH_SMSG_FAILURE 94257429Smarkm || type == SSH_CMSG_EOF 94360573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 94492555Sdes packet_check_eom(); 94557429Smarkm /* If we got a packet, return it. */ 94676259Sgreen if (type != SSH_MSG_NONE) { 94776259Sgreen xfree(setp); 94857429Smarkm return type; 94976259Sgreen } 95057429Smarkm /* 95157429Smarkm * Otherwise, wait for some data to arrive, add it to the 95257429Smarkm * buffer, and try again. 95357429Smarkm */ 95476259Sgreen memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 95576259Sgreen sizeof(fd_mask)); 95676259Sgreen FD_SET(connection_in, setp); 95757429Smarkm 958181111Sdes if (packet_timeout_ms > 0) { 959181111Sdes ms_remain = packet_timeout_ms; 960181111Sdes timeoutp = &timeout; 961181111Sdes } 96257429Smarkm /* Wait for some data to arrive. */ 963181111Sdes for (;;) { 964181111Sdes if (packet_timeout_ms != -1) { 965181111Sdes ms_to_timeval(&timeout, ms_remain); 966181111Sdes gettimeofday(&start, NULL); 967181111Sdes } 968181111Sdes if ((ret = select(connection_in + 1, setp, NULL, 969181111Sdes NULL, timeoutp)) >= 0) 970181111Sdes break; 971181111Sdes if (errno != EAGAIN && errno != EINTR && 972181111Sdes errno != EWOULDBLOCK) 973181111Sdes break; 974181111Sdes if (packet_timeout_ms == -1) 975181111Sdes continue; 976181111Sdes ms_subtract_diff(&start, &ms_remain); 977181111Sdes if (ms_remain <= 0) { 978181111Sdes ret = 0; 979181111Sdes break; 980181111Sdes } 981181111Sdes } 982181111Sdes if (ret == 0) { 983181111Sdes logit("Connection to %.200s timed out while " 984181111Sdes "waiting to read", get_remote_ipaddr()); 985181111Sdes cleanup_exit(255); 986181111Sdes } 98757429Smarkm /* Read data from the socket. */ 98857429Smarkm len = read(connection_in, buf, sizeof(buf)); 98957429Smarkm if (len == 0) { 990124208Sdes logit("Connection closed by %.200s", get_remote_ipaddr()); 991126274Sdes cleanup_exit(255); 99257429Smarkm } 99357429Smarkm if (len < 0) 99457429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 99557429Smarkm /* Append it to the buffer. */ 99657429Smarkm packet_process_incoming(buf, len); 99757429Smarkm } 99857429Smarkm /* NOTREACHED */ 99957429Smarkm} 100057429Smarkm 100192555Sdesint 100292555Sdespacket_read(void) 100392555Sdes{ 100492555Sdes return packet_read_seqnr(NULL); 100592555Sdes} 100692555Sdes 100757429Smarkm/* 100857429Smarkm * Waits until a packet has been received, verifies that its type matches 100957429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 101057429Smarkm */ 101157429Smarkm 101257429Smarkmvoid 101392555Sdespacket_read_expect(int expected_type) 101457429Smarkm{ 101557429Smarkm int type; 101657429Smarkm 101792555Sdes type = packet_read(); 101857429Smarkm if (type != expected_type) 101957429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 102060573Skris expected_type, type); 102157429Smarkm} 102257429Smarkm 102357429Smarkm/* Checks if a full packet is available in the data received so far via 102457429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 102557429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 102657429Smarkm * 102757429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 102857429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 102957429Smarkm * to higher levels. 103057429Smarkm */ 103157429Smarkm 103292555Sdesstatic int 103392555Sdespacket_read_poll1(void) 103457429Smarkm{ 103576259Sgreen u_int len, padded_len; 103692555Sdes u_char *cp, type; 103776259Sgreen u_int checksum, stored_checksum; 103857429Smarkm 103957429Smarkm /* Check if input size is less than minimum packet size. */ 104057429Smarkm if (buffer_len(&input) < 4 + 8) 104157429Smarkm return SSH_MSG_NONE; 104257429Smarkm /* Get length of incoming packet. */ 104392555Sdes cp = buffer_ptr(&input); 1044162852Sdes len = get_u32(cp); 104557429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 1046113908Sdes packet_disconnect("Bad packet length %u.", len); 104757429Smarkm padded_len = (len + 8) & ~7; 104857429Smarkm 104957429Smarkm /* Check if the packet has been entirely received. */ 105057429Smarkm if (buffer_len(&input) < 4 + padded_len) 105157429Smarkm return SSH_MSG_NONE; 105257429Smarkm 105357429Smarkm /* The entire packet is in buffer. */ 105457429Smarkm 105557429Smarkm /* Consume packet length. */ 105657429Smarkm buffer_consume(&input, 4); 105757429Smarkm 105892555Sdes /* 105992555Sdes * Cryptographic attack detector for ssh 106092555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 106192555Sdes * Ariel Futoransky(futo@core-sdi.com) 106292555Sdes */ 1063162852Sdes if (!receive_context.plaintext) { 1064162852Sdes switch (detect_attack(buffer_ptr(&input), padded_len)) { 1065162852Sdes case DEATTACK_DETECTED: 1066162852Sdes packet_disconnect("crc32 compensation attack: " 1067162852Sdes "network attack detected"); 1068162852Sdes case DEATTACK_DOS_DETECTED: 1069162852Sdes packet_disconnect("deattack denial of " 1070162852Sdes "service detected"); 1071162852Sdes } 1072162852Sdes } 107392555Sdes 107492555Sdes /* Decrypt data to incoming_packet. */ 107557429Smarkm buffer_clear(&incoming_packet); 107692555Sdes cp = buffer_append_space(&incoming_packet, padded_len); 107792555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 107892555Sdes 107957429Smarkm buffer_consume(&input, padded_len); 108057429Smarkm 108157429Smarkm#ifdef PACKET_DEBUG 108257429Smarkm fprintf(stderr, "read_poll plain: "); 108357429Smarkm buffer_dump(&incoming_packet); 108457429Smarkm#endif 108557429Smarkm 108657429Smarkm /* Compute packet checksum. */ 108792555Sdes checksum = ssh_crc32(buffer_ptr(&incoming_packet), 108860573Skris buffer_len(&incoming_packet) - 4); 108957429Smarkm 109057429Smarkm /* Skip padding. */ 109157429Smarkm buffer_consume(&incoming_packet, 8 - len % 8); 109257429Smarkm 109357429Smarkm /* Test check bytes. */ 109457429Smarkm if (len != buffer_len(&incoming_packet)) 109592555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 109660573Skris len, buffer_len(&incoming_packet)); 109757429Smarkm 109892555Sdes cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 1099162852Sdes stored_checksum = get_u32(cp); 110057429Smarkm if (checksum != stored_checksum) 110157429Smarkm packet_disconnect("Corrupted check bytes on input."); 110257429Smarkm buffer_consume_end(&incoming_packet, 4); 110357429Smarkm 110457429Smarkm if (packet_compression) { 110557429Smarkm buffer_clear(&compression_buffer); 110657429Smarkm buffer_uncompress(&incoming_packet, &compression_buffer); 110757429Smarkm buffer_clear(&incoming_packet); 110857429Smarkm buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 110960573Skris buffer_len(&compression_buffer)); 111057429Smarkm } 1111181111Sdes p_read.packets++; 1112181111Sdes p_read.bytes += padded_len + 4; 111392555Sdes type = buffer_get_char(&incoming_packet); 1114146998Sdes if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1115146998Sdes packet_disconnect("Invalid ssh1 packet type: %d", type); 111692555Sdes return type; 111760573Skris} 111857429Smarkm 111992555Sdesstatic int 112092555Sdespacket_read_poll2(u_int32_t *seqnr_p) 112160573Skris{ 112276259Sgreen static u_int packet_length = 0; 112376259Sgreen u_int padlen, need; 112492555Sdes u_char *macbuf, *cp, type; 1125149749Sdes u_int maclen, block_size; 112660573Skris Enc *enc = NULL; 112760573Skris Mac *mac = NULL; 112860573Skris Comp *comp = NULL; 112957429Smarkm 113076259Sgreen if (newkeys[MODE_IN] != NULL) { 113176259Sgreen enc = &newkeys[MODE_IN]->enc; 113276259Sgreen mac = &newkeys[MODE_IN]->mac; 113376259Sgreen comp = &newkeys[MODE_IN]->comp; 113457429Smarkm } 113560573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 113692555Sdes block_size = enc ? enc->block_size : 8; 113760573Skris 113860573Skris if (packet_length == 0) { 113960573Skris /* 114060573Skris * check if input size is less than the cipher block size, 114160573Skris * decrypt first block and extract length of incoming packet 114260573Skris */ 114360573Skris if (buffer_len(&input) < block_size) 114460573Skris return SSH_MSG_NONE; 114560573Skris buffer_clear(&incoming_packet); 114692555Sdes cp = buffer_append_space(&incoming_packet, block_size); 114792555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), 114860573Skris block_size); 114992555Sdes cp = buffer_ptr(&incoming_packet); 1150162852Sdes packet_length = get_u32(cp); 115160573Skris if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1152124208Sdes#ifdef PACKET_DEBUG 115360573Skris buffer_dump(&incoming_packet); 1154124208Sdes#endif 1155113908Sdes packet_disconnect("Bad packet length %u.", packet_length); 115660573Skris } 1157113908Sdes DBG(debug("input: packet len %u", packet_length+4)); 115860573Skris buffer_consume(&input, block_size); 115960573Skris } 116060573Skris /* we have a partial packet of block_size bytes */ 116160573Skris need = 4 + packet_length - block_size; 116260573Skris DBG(debug("partial packet %d, need %d, maclen %d", block_size, 116360573Skris need, maclen)); 116460573Skris if (need % block_size != 0) 116560573Skris fatal("padding error: need %d block %d mod %d", 116660573Skris need, block_size, need % block_size); 116760573Skris /* 116860573Skris * check if the entire packet has been received and 116960573Skris * decrypt into incoming_packet 117060573Skris */ 117160573Skris if (buffer_len(&input) < need + maclen) 117260573Skris return SSH_MSG_NONE; 117360573Skris#ifdef PACKET_DEBUG 117460573Skris fprintf(stderr, "read_poll enc/full: "); 117560573Skris buffer_dump(&input); 117660573Skris#endif 117792555Sdes cp = buffer_append_space(&incoming_packet, need); 117892555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 117960573Skris buffer_consume(&input, need); 118060573Skris /* 118160573Skris * compute MAC over seqnr and packet, 118260573Skris * increment sequence number for incoming packet 118360573Skris */ 118460573Skris if (mac && mac->enabled) { 1185124208Sdes macbuf = mac_compute(mac, p_read.seqnr, 118692555Sdes buffer_ptr(&incoming_packet), 118776259Sgreen buffer_len(&incoming_packet)); 118860573Skris if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 118969587Sgreen packet_disconnect("Corrupted MAC on input."); 1190124208Sdes DBG(debug("MAC #%d ok", p_read.seqnr)); 119160573Skris buffer_consume(&input, mac->mac_len); 119260573Skris } 119392555Sdes if (seqnr_p != NULL) 1194124208Sdes *seqnr_p = p_read.seqnr; 1195124208Sdes if (++p_read.seqnr == 0) 1196124208Sdes logit("incoming seqnr wraps around"); 1197124208Sdes if (++p_read.packets == 0) 1198124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 1199124208Sdes fatal("XXX too many packets with same key"); 1200124208Sdes p_read.blocks += (packet_length + 4) / block_size; 1201181111Sdes p_read.bytes += packet_length + 4; 120260573Skris 120360573Skris /* get padlen */ 120492555Sdes cp = buffer_ptr(&incoming_packet); 120592555Sdes padlen = cp[4]; 120660573Skris DBG(debug("input: padlen %d", padlen)); 120760573Skris if (padlen < 4) 120860573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 120960573Skris 121060573Skris /* skip packet size + padlen, discard padding */ 121160573Skris buffer_consume(&incoming_packet, 4 + 1); 121260573Skris buffer_consume_end(&incoming_packet, padlen); 121360573Skris 121460573Skris DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 121560573Skris if (comp && comp->enabled) { 121660573Skris buffer_clear(&compression_buffer); 121760573Skris buffer_uncompress(&incoming_packet, &compression_buffer); 121860573Skris buffer_clear(&incoming_packet); 121960573Skris buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 122060573Skris buffer_len(&compression_buffer)); 1221106121Sdes DBG(debug("input: len after de-compress %d", 1222106121Sdes buffer_len(&incoming_packet))); 122360573Skris } 122460573Skris /* 122560573Skris * get packet type, implies consume. 122660573Skris * return length of payload (without type field) 122760573Skris */ 122892555Sdes type = buffer_get_char(&incoming_packet); 1229146998Sdes if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) 1230146998Sdes packet_disconnect("Invalid ssh2 packet type: %d", type); 123176259Sgreen if (type == SSH2_MSG_NEWKEYS) 123276259Sgreen set_newkeys(MODE_IN); 1233149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side) 1234149749Sdes packet_enable_delayed_compress(); 123560573Skris#ifdef PACKET_DEBUG 123676259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 123760573Skris buffer_dump(&incoming_packet); 123860573Skris#endif 123992555Sdes /* reset for next packet */ 124092555Sdes packet_length = 0; 124192555Sdes return type; 124257429Smarkm} 124357429Smarkm 124460573Skrisint 124592555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 124660573Skris{ 124799060Sdes u_int reason, seqnr; 124892555Sdes u_char type; 124960573Skris char *msg; 125092555Sdes 125160573Skris for (;;) { 125292555Sdes if (compat20) { 125392555Sdes type = packet_read_poll2(seqnr_p); 1254181111Sdes if (type) { 1255181111Sdes keep_alive_timeouts = 0; 125660573Skris DBG(debug("received packet type %d", type)); 1257181111Sdes } 125892555Sdes switch (type) { 125960573Skris case SSH2_MSG_IGNORE: 1260181111Sdes debug3("Received SSH2_MSG_IGNORE"); 126160573Skris break; 126260573Skris case SSH2_MSG_DEBUG: 126360573Skris packet_get_char(); 126460573Skris msg = packet_get_string(NULL); 126560573Skris debug("Remote: %.900s", msg); 126660573Skris xfree(msg); 126760573Skris msg = packet_get_string(NULL); 126860573Skris xfree(msg); 126960573Skris break; 127060573Skris case SSH2_MSG_DISCONNECT: 127160573Skris reason = packet_get_int(); 127260573Skris msg = packet_get_string(NULL); 1273124208Sdes logit("Received disconnect from %s: %u: %.400s", 127499060Sdes get_remote_ipaddr(), reason, msg); 127560573Skris xfree(msg); 1276126274Sdes cleanup_exit(255); 127760573Skris break; 127892555Sdes case SSH2_MSG_UNIMPLEMENTED: 127992555Sdes seqnr = packet_get_int(); 128099060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 128199060Sdes seqnr); 128292555Sdes break; 128360573Skris default: 128460573Skris return type; 128576259Sgreen } 128660573Skris } else { 128792555Sdes type = packet_read_poll1(); 128892555Sdes switch (type) { 128960573Skris case SSH_MSG_IGNORE: 129060573Skris break; 129160573Skris case SSH_MSG_DEBUG: 129260573Skris msg = packet_get_string(NULL); 129360573Skris debug("Remote: %.900s", msg); 129460573Skris xfree(msg); 129560573Skris break; 129660573Skris case SSH_MSG_DISCONNECT: 129760573Skris msg = packet_get_string(NULL); 1298124208Sdes logit("Received disconnect from %s: %.400s", 129999060Sdes get_remote_ipaddr(), msg); 1300126274Sdes cleanup_exit(255); 130160573Skris break; 130260573Skris default: 130392555Sdes if (type) 130460573Skris DBG(debug("received packet type %d", type)); 130560573Skris return type; 130676259Sgreen } 130760573Skris } 130860573Skris } 130960573Skris} 131060573Skris 131192555Sdesint 131292555Sdespacket_read_poll(void) 131392555Sdes{ 131492555Sdes return packet_read_poll_seqnr(NULL); 131592555Sdes} 131692555Sdes 131757429Smarkm/* 131857429Smarkm * Buffers the given amount of input characters. This is intended to be used 131957429Smarkm * together with packet_read_poll. 132057429Smarkm */ 132157429Smarkm 132257429Smarkmvoid 132376259Sgreenpacket_process_incoming(const char *buf, u_int len) 132457429Smarkm{ 132557429Smarkm buffer_append(&input, buf, len); 132657429Smarkm} 132757429Smarkm 132857429Smarkm/* Returns a character from the packet. */ 132957429Smarkm 133076259Sgreenu_int 133192555Sdespacket_get_char(void) 133257429Smarkm{ 133357429Smarkm char ch; 1334106121Sdes 133557429Smarkm buffer_get(&incoming_packet, &ch, 1); 133676259Sgreen return (u_char) ch; 133757429Smarkm} 133857429Smarkm 133957429Smarkm/* Returns an integer from the packet data. */ 134057429Smarkm 134176259Sgreenu_int 134292555Sdespacket_get_int(void) 134357429Smarkm{ 134457429Smarkm return buffer_get_int(&incoming_packet); 134557429Smarkm} 134657429Smarkm 134757429Smarkm/* 134857429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 134957429Smarkm * must have been initialized before this call. 135057429Smarkm */ 135157429Smarkm 135257429Smarkmvoid 135392555Sdespacket_get_bignum(BIGNUM * value) 135457429Smarkm{ 135592555Sdes buffer_get_bignum(&incoming_packet, value); 135657429Smarkm} 135757429Smarkm 135860573Skrisvoid 135992555Sdespacket_get_bignum2(BIGNUM * value) 136060573Skris{ 136192555Sdes buffer_get_bignum2(&incoming_packet, value); 136260573Skris} 136360573Skris 136492555Sdesvoid * 1365149749Sdespacket_get_raw(u_int *length_ptr) 136660573Skris{ 1367149749Sdes u_int bytes = buffer_len(&incoming_packet); 1368106121Sdes 136960573Skris if (length_ptr != NULL) 137060573Skris *length_ptr = bytes; 137160573Skris return buffer_ptr(&incoming_packet); 137260573Skris} 137360573Skris 137460573Skrisint 137560573Skrispacket_remaining(void) 137660573Skris{ 137760573Skris return buffer_len(&incoming_packet); 137860573Skris} 137960573Skris 138057429Smarkm/* 138157429Smarkm * Returns a string from the packet data. The string is allocated using 138257429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 138357429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 138457429Smarkm * integer into which the length of the string is stored. 138557429Smarkm */ 138657429Smarkm 138792555Sdesvoid * 138876259Sgreenpacket_get_string(u_int *length_ptr) 138957429Smarkm{ 139057429Smarkm return buffer_get_string(&incoming_packet, length_ptr); 139157429Smarkm} 139257429Smarkm 1393181111Sdesvoid * 1394181111Sdespacket_get_string_ptr(u_int *length_ptr) 1395181111Sdes{ 1396181111Sdes return buffer_get_string_ptr(&incoming_packet, length_ptr); 1397181111Sdes} 1398181111Sdes 139957429Smarkm/* 140057429Smarkm * Sends a diagnostic message from the server to the client. This message 140157429Smarkm * can be sent at any time (but not while constructing another message). The 140257429Smarkm * message is printed immediately, but only if the client is being executed 140357429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 140457429Smarkm * authentication problems. The length of the formatted message must not 140557429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 140657429Smarkm */ 140757429Smarkm 140857429Smarkmvoid 140957429Smarkmpacket_send_debug(const char *fmt,...) 141057429Smarkm{ 141157429Smarkm char buf[1024]; 141257429Smarkm va_list args; 141357429Smarkm 141476259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 141576259Sgreen return; 141676259Sgreen 141757429Smarkm va_start(args, fmt); 141857429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 141957429Smarkm va_end(args); 142057429Smarkm 142160573Skris if (compat20) { 142260573Skris packet_start(SSH2_MSG_DEBUG); 142360573Skris packet_put_char(0); /* bool: always display */ 142460573Skris packet_put_cstring(buf); 142560573Skris packet_put_cstring(""); 142660573Skris } else { 142760573Skris packet_start(SSH_MSG_DEBUG); 142860573Skris packet_put_cstring(buf); 142960573Skris } 143057429Smarkm packet_send(); 143157429Smarkm packet_write_wait(); 143257429Smarkm} 143357429Smarkm 143457429Smarkm/* 143557429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 143657429Smarkm * connection, and exits. This function never returns. The error message 143757429Smarkm * should not contain a newline. The length of the formatted message must 143857429Smarkm * not exceed 1024 bytes. 143957429Smarkm */ 144057429Smarkm 144157429Smarkmvoid 144257429Smarkmpacket_disconnect(const char *fmt,...) 144357429Smarkm{ 144457429Smarkm char buf[1024]; 144557429Smarkm va_list args; 144657429Smarkm static int disconnecting = 0; 1447106121Sdes 144857429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 144957429Smarkm fatal("packet_disconnect called recursively."); 145057429Smarkm disconnecting = 1; 145157429Smarkm 145257429Smarkm /* 145357429Smarkm * Format the message. Note that the caller must make sure the 145457429Smarkm * message is of limited size. 145557429Smarkm */ 145657429Smarkm va_start(args, fmt); 145757429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 145857429Smarkm va_end(args); 145957429Smarkm 1460113908Sdes /* Display the error locally */ 1461124208Sdes logit("Disconnecting: %.100s", buf); 1462113908Sdes 146357429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 146460573Skris if (compat20) { 146560573Skris packet_start(SSH2_MSG_DISCONNECT); 146660573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 146760573Skris packet_put_cstring(buf); 146860573Skris packet_put_cstring(""); 146960573Skris } else { 147060573Skris packet_start(SSH_MSG_DISCONNECT); 147192555Sdes packet_put_cstring(buf); 147260573Skris } 147357429Smarkm packet_send(); 147457429Smarkm packet_write_wait(); 147557429Smarkm 147657429Smarkm /* Stop listening for connections. */ 147792555Sdes channel_close_all(); 147857429Smarkm 147957429Smarkm /* Close the connection. */ 148057429Smarkm packet_close(); 1481126274Sdes cleanup_exit(255); 148257429Smarkm} 148357429Smarkm 148457429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 148557429Smarkm 148657429Smarkmvoid 148792555Sdespacket_write_poll(void) 148857429Smarkm{ 148957429Smarkm int len = buffer_len(&output); 1490106121Sdes 149157429Smarkm if (len > 0) { 149257429Smarkm len = write(connection_out, buffer_ptr(&output), len); 1493181111Sdes if (len == -1) { 1494181111Sdes if (errno == EINTR || errno == EAGAIN || 1495181111Sdes errno == EWOULDBLOCK) 149657429Smarkm return; 1497181111Sdes fatal("Write failed: %.100s", strerror(errno)); 149857429Smarkm } 1499181111Sdes if (len == 0) 1500181111Sdes fatal("Write connection closed"); 150157429Smarkm buffer_consume(&output, len); 150257429Smarkm } 150357429Smarkm} 150457429Smarkm 1505181111Sdes 150657429Smarkm/* 150757429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 150857429Smarkm * written. 150957429Smarkm */ 151057429Smarkm 151157429Smarkmvoid 151292555Sdespacket_write_wait(void) 151357429Smarkm{ 151476259Sgreen fd_set *setp; 1515181111Sdes int ret, ms_remain; 1516181111Sdes struct timeval start, timeout, *timeoutp = NULL; 151776259Sgreen 1518162852Sdes setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), 151976259Sgreen sizeof(fd_mask)); 152057429Smarkm packet_write_poll(); 152157429Smarkm while (packet_have_data_to_write()) { 152276259Sgreen memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 152376259Sgreen sizeof(fd_mask)); 152476259Sgreen FD_SET(connection_out, setp); 1525181111Sdes 1526181111Sdes if (packet_timeout_ms > 0) { 1527181111Sdes ms_remain = packet_timeout_ms; 1528181111Sdes timeoutp = &timeout; 1529181111Sdes } 1530181111Sdes for (;;) { 1531181111Sdes if (packet_timeout_ms != -1) { 1532181111Sdes ms_to_timeval(&timeout, ms_remain); 1533181111Sdes gettimeofday(&start, NULL); 1534181111Sdes } 1535181111Sdes if ((ret = select(connection_out + 1, NULL, setp, 1536181111Sdes NULL, timeoutp)) >= 0) 1537181111Sdes break; 1538181111Sdes if (errno != EAGAIN && errno != EINTR && 1539181111Sdes errno != EWOULDBLOCK) 1540181111Sdes break; 1541181111Sdes if (packet_timeout_ms == -1) 1542181111Sdes continue; 1543181111Sdes ms_subtract_diff(&start, &ms_remain); 1544181111Sdes if (ms_remain <= 0) { 1545181111Sdes ret = 0; 1546181111Sdes break; 1547181111Sdes } 1548181111Sdes } 1549181111Sdes if (ret == 0) { 1550181111Sdes logit("Connection to %.200s timed out while " 1551181111Sdes "waiting to write", get_remote_ipaddr()); 1552181111Sdes cleanup_exit(255); 1553181111Sdes } 155457429Smarkm packet_write_poll(); 155557429Smarkm } 155676259Sgreen xfree(setp); 155757429Smarkm} 155857429Smarkm 155957429Smarkm/* Returns true if there is buffered data to write to the connection. */ 156057429Smarkm 156157429Smarkmint 156292555Sdespacket_have_data_to_write(void) 156357429Smarkm{ 156457429Smarkm return buffer_len(&output) != 0; 156557429Smarkm} 156657429Smarkm 156757429Smarkm/* Returns true if there is not too much data to write to the connection. */ 156857429Smarkm 156957429Smarkmint 157092555Sdespacket_not_very_much_data_to_write(void) 157157429Smarkm{ 157257429Smarkm if (interactive_mode) 157357429Smarkm return buffer_len(&output) < 16384; 157457429Smarkm else 157557429Smarkm return buffer_len(&output) < 128 * 1024; 157657429Smarkm} 157757429Smarkm 1578124208Sdes 1579113908Sdesstatic void 1580113908Sdespacket_set_tos(int interactive) 1581113908Sdes{ 1582126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1583113908Sdes int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT; 1584113908Sdes 1585113908Sdes if (!packet_connection_is_on_socket() || 1586113908Sdes !packet_connection_is_ipv4()) 1587113908Sdes return; 1588113908Sdes if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos, 1589113908Sdes sizeof(tos)) < 0) 1590113908Sdes error("setsockopt IP_TOS %d: %.100s:", 1591113908Sdes tos, strerror(errno)); 1592126274Sdes#endif 1593113908Sdes} 1594113908Sdes 159557429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 159657429Smarkm 159757429Smarkmvoid 159876259Sgreenpacket_set_interactive(int interactive) 159957429Smarkm{ 160076259Sgreen static int called = 0; 160157429Smarkm 160276259Sgreen if (called) 160376259Sgreen return; 160476259Sgreen called = 1; 160576259Sgreen 160657429Smarkm /* Record that we are in interactive mode. */ 160757429Smarkm interactive_mode = interactive; 160857429Smarkm 160957429Smarkm /* Only set socket options if using a socket. */ 161057429Smarkm if (!packet_connection_is_on_socket()) 1611116791Sdes return; 1612162852Sdes set_nodelay(connection_in); 1613113908Sdes packet_set_tos(interactive); 161457429Smarkm} 161557429Smarkm 161657429Smarkm/* Returns true if the current connection is interactive. */ 161757429Smarkm 161857429Smarkmint 161992555Sdespacket_is_interactive(void) 162057429Smarkm{ 162157429Smarkm return interactive_mode; 162257429Smarkm} 162357429Smarkm 1624137015Sdesint 1625124208Sdespacket_set_maxsize(u_int s) 162657429Smarkm{ 162757429Smarkm static int called = 0; 1628106121Sdes 162957429Smarkm if (called) { 1630124208Sdes logit("packet_set_maxsize: called twice: old %d new %d", 163160573Skris max_packet_size, s); 163257429Smarkm return -1; 163357429Smarkm } 163457429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 1635124208Sdes logit("packet_set_maxsize: bad size %d", s); 163657429Smarkm return -1; 163757429Smarkm } 163892555Sdes called = 1; 163992555Sdes debug("packet_set_maxsize: setting to %d", s); 164057429Smarkm max_packet_size = s; 164157429Smarkm return s; 164257429Smarkm} 164376259Sgreen 164492555Sdes/* roundup current message to pad bytes */ 164592555Sdesvoid 164692555Sdespacket_add_padding(u_char pad) 164792555Sdes{ 164892555Sdes extra_pad = pad; 164992555Sdes} 165092555Sdes 165176259Sgreen/* 165276259Sgreen * 9.2. Ignored Data Message 165376259Sgreen * 165476259Sgreen * byte SSH_MSG_IGNORE 165576259Sgreen * string data 165676259Sgreen * 165776259Sgreen * All implementations MUST understand (and ignore) this message at any 165876259Sgreen * time (after receiving the protocol version). No implementation is 165976259Sgreen * required to send them. This message can be used as an additional 166076259Sgreen * protection measure against advanced traffic analysis techniques. 166176259Sgreen */ 166276259Sgreenvoid 166376259Sgreenpacket_send_ignore(int nbytes) 166476259Sgreen{ 1665137015Sdes u_int32_t rnd = 0; 166676259Sgreen int i; 166776259Sgreen 166876259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 166976259Sgreen packet_put_int(nbytes); 167092555Sdes for (i = 0; i < nbytes; i++) { 167176259Sgreen if (i % 4 == 0) 1672137015Sdes rnd = arc4random(); 1673162852Sdes packet_put_char((u_char)rnd & 0xff); 1674137015Sdes rnd >>= 8; 167576259Sgreen } 167676259Sgreen} 1677124208Sdes 1678137015Sdes#define MAX_PACKETS (1U<<31) 1679124208Sdesint 1680124208Sdespacket_need_rekeying(void) 1681124208Sdes{ 1682124208Sdes if (datafellows & SSH_BUG_NOREKEY) 1683124208Sdes return 0; 1684124208Sdes return 1685124208Sdes (p_send.packets > MAX_PACKETS) || 1686124208Sdes (p_read.packets > MAX_PACKETS) || 1687124208Sdes (max_blocks_out && (p_send.blocks > max_blocks_out)) || 1688124208Sdes (max_blocks_in && (p_read.blocks > max_blocks_in)); 1689124208Sdes} 1690124208Sdes 1691124208Sdesvoid 1692124208Sdespacket_set_rekey_limit(u_int32_t bytes) 1693124208Sdes{ 1694124208Sdes rekey_limit = bytes; 1695124208Sdes} 1696149749Sdes 1697149749Sdesvoid 1698149749Sdespacket_set_server(void) 1699149749Sdes{ 1700149749Sdes server_side = 1; 1701149749Sdes} 1702149749Sdes 1703149749Sdesvoid 1704149749Sdespacket_set_authenticated(void) 1705149749Sdes{ 1706149749Sdes after_authentication = 1; 1707149749Sdes} 1708